/* ==========================================================================
   TaskFlow — design system (Pass 1)
   Sections: tokens · base · auth · layout · sidebar · topbar · cards ·
             buttons · forms · alerts · toasts · skeleton · responsive
   ========================================================================== */

/* ------------------------------- Tokens -------------------------------- */

:root {
  --primary:        #4f46e5;
  --accent:         #4f7cff;
  --primary-hover:  #4338ca;
  --primary-soft:   rgba(79, 70, 229, .14);
  --bg:             #f3f4f6;
  --surface:        #ffffff;
  --surface-2:      #f9fafb;
  --text:           #111827;
  --text-muted:     #6b7280;
  --border:         #e5e7eb;
  --hover:          rgba(17, 24, 39, .06);
  --danger:         #dc2626;
  --danger-soft:    #fef2f2;
  --success:        #16a34a;
  --success-soft:   #f0fdf4;
  --warning:        #d97706;
  --warning-soft:   #fffbeb;
  --sidebar-bg:     linear-gradient(180deg, #1e2242 0%, #171a30 100%);
  --sidebar-text:   #c7cbef;
  --sidebar-muted:  #8b90bd;
  --band-bg:        linear-gradient(180deg, #e6e9ff 0%, #dfe3fd 100%);
  --band-edge:      rgba(79, 70, 229, .18);
  --band-surface:   rgba(255, 255, 255, .55);
  --band-border:    rgba(255, 255, 255, .7);
  --sidebar-w:      248px;
  --sidebar-wc:     68px;
  --radius:         12px;
  --radius-sm:      9px;
  --shadow-sm:      0 1px 2px rgba(16, 24, 40, .06);
  --shadow-md:      0 8px 24px rgba(16, 24, 40, .10);
  --ring:           0 0 0 3px var(--primary-soft);
  /* Module-theme enforcement aliases (Pass 77): the per-module override
     blocks consume these names instead of literals, so future COLOURED
     themes flow through automatically — redefine the app tokens and the
     aliases follow. Single definition on :root is enough: data-theme lives
     on <html>, so each var() resolves against the ACTIVE theme's token.
     The tiered extras (no app-token equivalent) are redefined per theme. */
  --mt-text:        var(--text);
  --mt-muted:       var(--text-muted);
  --mt-surface:     var(--surface);
  --mt-surface-2:   var(--surface-2);
  --mt-bg:          var(--bg);
  --mt-border:      var(--border);
  --mt-text-2:      #374151;
  --mt-faint:       #9ca3af;
  --mt-surface-3:   #eef1f5;
  --mt-border-strong: #d2d8e0;
  --mt-overlay:     rgba(17, 24, 39, .05);
  --mt-overlay-2:   rgba(17, 24, 39, .08);
  --mt-shadow:      rgba(16, 24, 40, .12);
  color-scheme: light;
}

[data-theme="dark"] {
  --primary:        #6366f1;
  --accent:         #4f7cff;
  --primary-hover:  #818cf8;
  --primary-soft:   rgba(99, 102, 241, .22);
  --bg:             #0f1115;
  --surface:        #171a21;
  --surface-2:      #1e222b;
  --text:           #e5e7eb;
  --text-muted:     #9ca3af;
  --border:         #2a2f3a;
  --hover:          rgba(229, 231, 235, .07);
  --danger:         #f87171;
  --danger-soft:    rgba(248, 113, 113, .12);
  --success:        #4ade80;
  --success-soft:   rgba(74, 222, 128, .12);
  --warning:        #fbbf24;
  --warning-soft:   rgba(251, 191, 36, .12);
  --sidebar-bg:     linear-gradient(180deg, #1e2242 0%, #171a30 100%);
  --sidebar-text:   #c7cbef;
  --sidebar-muted:  #8b90bd;
  --band-bg:        linear-gradient(180deg, #262244 0%, #1c1930 100%);
  --band-edge:      rgba(99, 102, 241, .28);
  --band-surface:   rgba(23, 26, 33, .55);
  --band-border:    rgba(255, 255, 255, .08);
  --shadow-sm:      0 1px 2px rgba(0, 0, 0, .4);
  --shadow-md:      0 8px 24px rgba(0, 0, 0, .45);
  /* Dark tiers for the module-theme aliases (the var()-backed ones above
     resolve on their own). */
  --mt-text-2:      #c3c9d4;
  --mt-faint:       #6b7280;
  --mt-surface-3:   #252b35;
  --mt-border-strong: #3a4150;
  --mt-overlay:     rgba(229, 231, 235, .06);
  --mt-overlay-2:   rgba(229, 231, 235, .09);
  --mt-shadow:      rgba(0, 0, 0, .4);
  color-scheme: dark;
}

/* -------------------------------- Base --------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  background: var(--bg);
  color: var(--text);
  transition: background-color .2s ease, color .2s ease;
}

a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { margin: 0; line-height: 1.25; }

button { font: inherit; color: inherit; }

svg { display: block; }

[hidden] { display: none !important; }

::selection { background: var(--primary-soft); }

.text-muted { color: var(--text-muted); }

/* -------------------------------- Auth ---------------------------------- */
/* Standalone centered-card pages (login / register).                       */

.auth-page {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px 16px;
}

.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--shadow-md);
  padding: 28px;
}

.auth-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-bottom: 4px;
  font-size: 20px;
  font-weight: 800;
}

.auth-sub {
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
  margin: 0 0 20px;
}

/* Friendly error pages (403.php / 404.php) */
.error-card { text-align: center; }
.error-code {
  font-size: 56px;
  font-weight: 800;
  letter-spacing: 0.04em;
  margin: 12px 0 4px;
  color: var(--primary, #4f46e5);
}

.auth-alt {
  text-align: center;
  font-size: 14px;
  color: var(--text-muted);
  margin: 18px 0 0;
}

.demo-hint {
  text-align: center;
  margin-top: 16px;
  padding: 10px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

/* -------------------------------- Layout -------------------------------- */

.app {
  display: flex;
  min-height: 100vh;
}

.main {
  flex: 1;
  min-width: 0;               /* lets grid children shrink properly */
  display: flex;
  flex-direction: column;
}

.content {
  flex: 1;
  min-height: 0;   /* lets the messages page cap itself at the window height */
  width: 100%;
  /* No max-width cap: on widescreen monitors the dashboard uses the full
     window width (the 24px side padding stays as the only gutter). */
  margin: 0 auto;
  padding: 24px;
}

/* ------------------------------- Sidebar -------------------------------- */

.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;           /* clips labels during the width transition */
  background: var(--sidebar-bg);
  border-right: 1px solid rgba(255,255,255,.06);
  transition: width .22s ease, transform .25s ease;
  z-index: 40;
}

.sidebar-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 12px 14px;
}
.sidebar-logo-link {
  display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0;
  color: var(--sidebar-text, var(--text));
}
.sidebar-logo-link:hover { text-decoration: none; }
.sidebar-logo-text { display: flex; flex-direction: column; min-width: 0; }
.sidebar-logo-name { font-size: 17px; font-weight: 800; color: #fff; }
.sidebar-logo-tag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; color: var(--sidebar-muted, var(--text-muted));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-transform: capitalize;
}
.sidebar-upgrade {
  padding: 1px 8px; border-radius: 999px;
  background: var(--accent, #4f7cff); color: #fff;
  font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em;
}
.sidebar-upgrade:hover { text-decoration: none; filter: brightness(1.1); color: #fff; }
.sidebar-chevron {
  flex-shrink: 0; width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 6px; background: none; cursor: pointer;
  color: var(--sidebar-muted, var(--text-muted));
}
.sidebar-chevron:hover { background: rgba(255,255,255,.08); color: #fff; }

.logo-mark {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--primary);
  color: #fff;
}
.logo-mark svg { width: 20px; height: 20px; }

.sidebar-nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  overflow-y: auto;
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--sidebar-muted, var(--text-muted));
  font-size: 14px;
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.nav-link svg { width: 20px; height: 20px; flex-shrink: 0; }
.nav-link:hover {
  background: rgba(255,255,255,.06); color: #fff; text-decoration: none;
}
.nav-link.active {
  background: var(--accent, #4f7cff); color: #fff;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent, #4f7cff) 45%, transparent);
}
/* Unread bubble on the Messages link (Pass 67). */
.nav-badge {
  margin-left: auto;
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 999px; background: #e5484d; color: #fff;
  font-size: 11px; font-weight: 800; line-height: 20px; text-align: center;
}
.nav-link.active .nav-badge { background: #fff; color: var(--accent, #4f7cff); }

.nav-text { transition: opacity .15s ease; }

.sidebar-footer {
  padding: 10px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  color: var(--sidebar-text, var(--text));
}
.sidebar-user .user-role { color: var(--sidebar-muted, var(--text-muted)); }
.sidebar-footer { border-top: 1px solid rgba(255,255,255,.08); }

.avatar {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary);
  font-weight: 800;
}

.user-meta { display: flex; flex-direction: column; min-width: 0; }
.user-name {
  font-size: 14px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-role {
  font-size: 12px;
  color: var(--text-muted);
  text-transform: capitalize;
}

.logout-form { margin: 0; }
.logout-btn { color: var(--text-muted); }
.logout-btn:hover { color: var(--danger); }

/* Collapsed sidebar — desktop only. State lives on <html> (set by JS and
   restored pre-paint from localStorage). The .nav-text span is REMOVED from
   the flex layout (not just faded): with gap:12px an invisible label still
   ate width and shoved every icon off-center. */
@media (min-width: 768px) {
  html.sidebar-collapsed .sidebar { width: var(--sidebar-wc); }
  html.sidebar-collapsed .nav-text { display: none; }
  html.sidebar-collapsed .nav-link {
    justify-content: center;
    gap: 0;
    padding-left: 0;
    padding-right: 0;
  }
  html.sidebar-collapsed .sidebar-logo {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
  html.sidebar-collapsed .sidebar-user { justify-content: center; padding: 6px 0; }

  /* Hover flyout: with the rail icon-only, the item name floats beside the
     icon. Both ancestors must stop clipping for the label to escape the
     68px rail (they only clip to animate the width transition, which the
     collapsed steady state doesn't need). */
  html.sidebar-collapsed .sidebar,
  html.sidebar-collapsed .sidebar-nav { overflow: visible; }
  html.sidebar-collapsed .nav-link { position: relative; }
  html.sidebar-collapsed .nav-link:hover .nav-text,
  html.sidebar-collapsed .nav-link:focus-visible .nav-text {
    display: block;
    position: absolute;
    left: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%);
    padding: 6px 10px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    font-size: 12.5px;
    white-space: nowrap;
    z-index: 60;
    pointer-events: none;
  }
}

/* Mobile: sidebar becomes an overlay drawer with a backdrop. */
.sidebar-backdrop { display: none; }

@media (max-width: 767.98px) {
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--sidebar-w) !important;
    transform: translateX(-105%);
    box-shadow: var(--shadow-md);
  }
  body.sidebar-open .sidebar { transform: translateX(0); }

  /* Ignore the collapsed state on mobile — the drawer is either open or closed. */
  html.sidebar-collapsed .nav-text { display: inline; }
  html.sidebar-collapsed .nav-link {
    justify-content: flex-start;
    gap: 12px;
    padding-left: 10px;
    padding-right: 10px;
  }
  html.sidebar-collapsed .sidebar-logo { justify-content: flex-start; padding: 16px; }

  .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .45);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
    z-index: 39;
  }
  body.sidebar-open .sidebar-backdrop { opacity: 1; pointer-events: auto; }
}

/* -------------------------------- Topbar -------------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.topbar-title { flex: 1; font-size: 18px; font-weight: 800; }

.topbar-actions { display: flex; align-items: center; gap: 6px; }

/* Theme toggle: show the icon for the theme you'd switch TO. */
[data-theme="light"] .icon-sun  { display: none; }
[data-theme="dark"]  .icon-moon { display: none; }

/* ------------------------------ Card grid ------------------------------- */

/* Free-form layout: cards sit DIRECTLY in a 3-column grid. Placement comes
   from inline grid-column-start (set per card by the layout editor), which
   is also what makes real spanning possible: a wide card's grid-column is
   clamped to the available room (span 2 from column 2, span 3 from columns
   1–2), so a card can never stretch past the grid or start a phantom row. */
.cards {
  display: grid;
  /* --cols is set inline by dashboard.php / share.php when the dashboard has
     a FIXED column count (1–9); otherwise the no-JS fallback stays 3-wide
     and the masonry engine guesses a good count from the screen width. */
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  gap: 16px;
  align-items: start;
  /* The column preview overlay (picker + drag highlight) anchors here. */
  position: relative;
  /* Dense packing: cards keep moving forward only when an explicitly-placed
     item conflicts with already-placed ones. Without it, a span-2 card in
     column 0 pushes every later single-column card a row down instead of
     letting them backfill the free track beside the wide card. */
  grid-auto-flow: dense;
}

/* The empty-state message spans the full width. */
.cards > .empty-state { grid-column: 1 / -1; }

/* Content pages (settings, plans, super, upload, module generator): cards
   pack in COLUMNS, not rows — with row grids, a tall card leaves a gap under
   its shorter row-mates. CSS multi-column stacks each column independently;
   cards never split across columns. The library (.lib-grid) keeps its own
   dense grid. */
.cards-align-start:not(.lib-grid) {
  display: block;
  columns: 340px;
  column-gap: 16px;
}
.cards-align-start:not(.lib-grid) > .card {
  break-inside: avoid;
  margin-bottom: 16px;
}

/* Two-column tablet fallback (no-JS only — the JS engine guesses the track
   count from the real width or uses the dashboard's fixed column count). */
@media (max-width: 1100px) {
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Phone fallback: single column — JS flattens placement to source order. */
@media (max-width: 640px) {
  .cards { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------------------
   Column preview overlay: purple dashed column tracks shown on top of the
   grid while picking a dashboard width, flashing after a change, and during
   card drag & drop (with the hovered column "hot"). Same look as the
   drop placeholder. Inserted by dashboard.js as the grid's last child.
   --------------------------------------------------------------------- */
.cols-preview {
  position: absolute;
  inset: 0;
  display: flex;
  pointer-events: none;
  z-index: 6;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.cols-preview.show { opacity: 1; }
.cols-preview > span {
  flex: 1 1 0;
  min-width: 0;
  border: 2px dashed var(--primary);
  background: var(--primary-soft);
  border-radius: var(--radius);
}
.cols-preview > span.hot {
  border-style: solid;
  background: rgba(79, 70, 229, 0.20);
}

/* ------------------------------------------------------------------------
   Dashboard columns picker (dashbar). Without JS it is a plain select +
   Apply button; with JS a toggle button + popover of numbered choices.
   --------------------------------------------------------------------- */
.dash-cols { position: relative; }
.dash-cols .dash-cols-label { font-size: 13px; color: var(--text-muted); }
.dash-cols select { width: auto; padding: 5px 8px; }
.dash-cols .cols-toggle { display: none; }
.dash-cols.dash-cols--js .cols-toggle { display: inline-flex; }
.dash-cols.dash-cols--js select,
.dash-cols.dash-cols--js [data-cols-apply],
.dash-cols.dash-cols--js .dash-cols-label { display: none; }

.cols-pop {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 1200;   /* dropdown tier: above cards, topbar, chatbot (200),
                      flash bar (900) and drag ghosts (1000); only toasts
                      (2000) and drag followers stay higher */
  width: 220px;
  padding: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.cols-pop-title {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.cols-pop-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
}
.cols-pop-grid button {
  height: 34px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  color: var(--text);
}
.cols-pop-grid button:hover { border-color: var(--primary); color: var(--primary); }
.cols-pop-grid button.active {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.cols-pop-grid .cols-auto { grid-column: 1 / -1; }

/* Small screens: anchor the popover to the form's LEFT edge so it never
   spills past the viewport. */
@media (max-width: 768px) {
  .cols-pop { right: auto; left: 0; }
}

/* Drag affordances (the layout editor uses pointer-based dragging). */
.drag-handle { cursor: grab; touch-action: none; }

.module-card.card-ghost {
  position: fixed;
  z-index: 1000;
  pointer-events: none;
  opacity: 0.92;
  margin: 0;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.28);
  transform: rotate(1.2deg);
}

.module-card.card-placeholder {
  border: 2px dashed var(--primary);
  background: var(--primary-soft);
  box-shadow: none;
  min-height: 56px;
}

.module-card.card-placeholder > * { visibility: hidden; }

/* ==========================================================================
   Masonry layout (JS-enhanced) — independent column stacks.
   The grid above remains the no-JS fallback; once dashboard.js measures the
   cards it switches the container to absolute positioning, where every
   column stacks its cards directly below each other (no cross-column row
   coupling) and wide cards form bands.
   ========================================================================== */

.cards--masonry {
  display: block;
  position: relative;
}

.cards--masonry .module-card {
  position: absolute;
  top: 0;
  margin: 0;
}

/* Enabled only after the first layout, so later reflows glide. */
.cards--animate .module-card {
  transition: top 0.18s ease, left 0.18s ease, width 0.18s ease;
}

.module-card.card-ghost { transition: none !important; }

.card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

/* Content containment: a card holds its allocated grid space — text wraps,
   code/URLs break, media scales down. Unbreakable leftovers are reported
   by the layout engine, which widens the card's span (or the layout's
   effective track count) instead of letting anything spill. */
.module-card .card-body { overflow-x: hidden; }
.module-card .card-body pre,
.module-card .card-body code { overflow-wrap: anywhere; white-space: pre-wrap; }
.module-card .card-body img,
.module-card .card-body video,
.module-card .card-body canvas { max-width: 100%; }

/* While the layout engine measures a card's min-content width, containment
   must not hide the spill it is measuring. Canvas stays clamped: a Chart.js
   canvas re-renders to fit any width (responsive), so its intrinsic size is
   just the last rendered pixel size — treating it as min-content would
   inflate the card's floor every time it grows. */
/* No transitions while measuring: .cards--animate transitions width, and a
   synchronous scrollWidth read would then see the OLD painted width (the
   transition's start value) instead of width:0 — and scrollWidth never
   reports less than the box itself. The measured floor could only ever
   ratchet up, so cards would widen but never shrink. */
.module-card.min-measure { transition: none !important; }
/* Whole-pass suppression: measuring flips a card's width to 0 and back
   inside layoutNow. Class-local suppression (min-measure) ends before the
   pass finishes, and Firefox then animates the restore — pass 2 measures
   heights at the transition's start width and the RO chases the animation
   frame by frame (a running pomodoro made the card wobble every second). */
.cards--noanim .module-card { transition: none !important; }
.module-card.min-measure .card-body { overflow: visible; }
.module-card.min-measure .card-body img,
.module-card.min-measure .card-body video { max-width: none; }

.card-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}

.card-icon {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--primary-soft);
  color: var(--primary);
}
.card-icon svg { width: 16px; height: 16px; }

.card-title {
  flex: 1;
  font-size: 15px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-actions { display: flex; gap: 2px; }
.card-actions .icon-btn { width: 28px; height: 28px; }
.card-actions .icon-btn svg { width: 15px; height: 15px; }

.card-body { flex: 1; padding: 14px; }

/* Empty state (also reused by placeholder pages) */
.empty-state {
  grid-column: 1 / -1;
  text-align: center;
  padding: 64px 24px;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}
.empty-state h2 { font-size: 18px; margin: 14px 0 6px; }
.empty-state p {
  max-width: 480px;
  margin: 0 auto 18px;
  color: var(--text-muted);
}
.empty-state .btn { text-decoration: none; }
.empty-icon {
  width: 52px;
  height: 52px;
  margin: 0 auto;
  display: grid;
  place-items: center;
  border-radius: 14px;
  background: var(--primary-soft);
  color: var(--primary);
}
.empty-icon svg { width: 26px; height: 26px; }

/* ------------------------------- Buttons -------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:hover { background: var(--primary-hover); text-decoration: none; }

.btn-ghost { background: transparent; border-color: var(--border); color: var(--text); }
.btn-ghost:hover { background: var(--hover); text-decoration: none; }

.btn-danger { background: var(--danger); color: #fff; }

.btn-block { width: 100%; }

.btn-sm {
  padding: 5px 10px;
  font-size: 12.5px;
  gap: 6px;
}

/* "keep data" checkbox next to uninstall buttons (library + admin) */
.keep-data { font-size: 12.5px; color: var(--text-muted); }

.icon-btn {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  display: inline-grid;
  place-items: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.icon-btn:hover { background: var(--hover); color: var(--text); }
/* Card embed link is live (Pass 32) — green so a public card stands out. */
.icon-btn.embed-live { background: var(--success-soft); color: var(--success); }
.icon-btn.embed-live:hover { background: var(--success-soft); color: var(--success); }
/* Width toggle pinned at full width by its own min-content floor. */
.icon-btn:disabled { opacity: 0.4; cursor: default; }
.icon-btn:disabled:hover { background: transparent; color: var(--text-muted); }
.icon-btn svg { width: 18px; height: 18px; }

.btn:focus-visible,
.icon-btn:focus-visible,
.nav-link:focus-visible,
.input:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}

/* -------------------------------- Forms --------------------------------- */

.field { margin-bottom: 14px; }

.label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 700;
}

.input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: var(--ring);
}

.form-error { margin: 5px 0 0; font-size: 12.5px; color: var(--danger); }
.form-hint  { margin: 5px 0 0; font-size: 12.5px; color: var(--text-muted); }

.radio-inline {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-right: 18px;
  cursor: pointer;
}
.radio-inline input { accent-color: var(--primary); }

/* -------------------------------- Alerts -------------------------------- */

.alert {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  margin-bottom: 14px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 14px;
  transition: opacity .3s ease;
}
.alert span { flex: 1; }

.alert-success {
  background: var(--success-soft);
  color: var(--success);
  border-color: color-mix(in srgb, var(--success) 30%, transparent);
}
.alert-error {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 30%, transparent);
}
.alert-info {
  background: var(--primary-soft);
  color: var(--primary);
  border-color: color-mix(in srgb, var(--primary) 30%, transparent);
}

.alert-close {
  border: 0;
  background: none;
  color: inherit;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  opacity: .7;
}
.alert-close:hover { opacity: 1; }

.alert-hide { opacity: 0; }

/* Flash alerts (rendered by includes/header.php) float over the page,
   centered under the topbar — they never push the content down. The wrapper
   is click-transparent; each alert re-enables pointer events. */
.flash-stack {
  position: fixed;
  top: 64px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 900;   /* above content, below the confirm modal (1000) */
  width: min(480px, calc(100vw - 32px));
  pointer-events: none;
}

.flash-stack .alert {
  pointer-events: auto;
  margin-bottom: 8px;
  box-shadow: var(--shadow-md);
  animation: flash-in .2s ease;
}

/* The soft type colors are translucent — layer them over the solid surface
   so page content doesn't bleed through the floating alert. */
.flash-stack .alert-success {
  background: linear-gradient(var(--success-soft), var(--success-soft)), var(--surface);
}
.flash-stack .alert-error {
  background: linear-gradient(var(--danger-soft), var(--danger-soft)), var(--surface);
}
.flash-stack .alert-info {
  background: linear-gradient(var(--primary-soft), var(--primary-soft)), var(--surface);
}

@keyframes flash-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* -------------------------------- Toasts -------------------------------- */

.toast-container {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 2000;   /* above drag ghosts (1000) and the chatbot (200) */
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: min(360px, calc(100vw - 32px));
  /* Never block clicks heading for what's underneath (call buttons live in
     this corner); only the visible toast card itself is clickable. */
  pointer-events: none;
}
.toast { pointer-events: auto; }

/* During a group call the overlay's buttons occupy the top-right corner —
   toasts start just BELOW them so they can never cover the buttons. */
body.gcall-open .toast-container { top: 76px; }

.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--primary);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-size: 14px;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity .25s ease, transform .25s ease;
}
.toast.show { opacity: 1; transform: translateY(0); }

.toast-success { border-left-color: var(--success); }
.toast-error   { border-left-color: var(--danger); }
.toast-info    { border-left-color: var(--primary); }

.toast-msg { flex: 1; }

.toast-close {
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: 16px;
  cursor: pointer;
}

/* ------------------------------- Skeleton ------------------------------- */
/* Shown while the card grid initializes. Without JS, the skeleton is hidden
   and the real grid is shown instead (see the html:not(.js) rules).        */

html:not(.js) .cards-skeleton { display: none; }
html.js .cards-swap { display: none; }

.skeleton-card .card-body { display: flex; flex-direction: column; gap: 10px; }

.sk-block {
  display: block;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--hover) 25%, var(--surface-2) 37%, var(--hover) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
}
.sk-icon { width: 28px; height: 28px; border-radius: 8px; }
.sk-line { height: 12px; }

.w-40 { width: 40%; }
.w-70 { width: 70%; }
.w-80 { width: 80%; }
.w-90 { width: 90%; }

@keyframes shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

/* ------------------------------ Responsive ------------------------------ */

@media (max-width: 640px) {
  .content { padding: 16px; }
  .topband { margin: -16px -16px 14px; padding: 12px 16px; }
  .topbar  { padding: 10px 14px; }
  .topbar-title { font-size: 16px; }
  .empty-state { padding: 48px 16px; }
}

/* ==========================================================================
   Pass 2 — module engine UI
   ========================================================================== */

/* Drag handle on module cards */
.drag-handle { cursor: grab; touch-action: none; }
.drag-handle:active { cursor: grabbing; }

/* Card being dragged */
.module-card.dragging {
  opacity: .45;
  border-style: dashed;
}

/* Minimized card: header only */
.module-card.minimized .card-body { display: none; }

/* Error card shown when a module crashes (never breaks the grid) */
.module-error {
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--danger-soft);
  color: var(--danger);
  font-size: 13.5px;
  line-height: 1.5;
}

/* Badges */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

/* "Shared by <name>" hover popover — reveals the owner's email. Pure CSS
   (share pages intentionally load no JS); same flyout pattern as the
   collapsed-sidebar tooltips. */
.share-by-pop { position: relative; cursor: help; }
.share-by-pop .share-by-pop-text {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  padding: 6px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-size: 12.5px;
  font-weight: 400;
  white-space: nowrap;
  z-index: 60;
  pointer-events: none;
}
.share-by-pop:hover .share-by-pop-text,
.share-by-pop:focus-visible .share-by-pop-text { display: block; }
/* Hosts near the page bottom (share footer) open upward instead. */
.share-by-pop--up .share-by-pop-text { top: auto; bottom: calc(100% + 8px); }
.badge-success {
  background: var(--success-soft);
  border-color: color-mix(in srgb, var(--success) 30%, transparent);
  color: var(--success);
}
.badge-disabled {
  background: var(--warning-soft);
  border-color: color-mix(in srgb, var(--warning) 30%, transparent);
  color: var(--warning);
}

/* Library cards */
.lib-body { display: flex; flex-direction: column; gap: 10px; }
.lib-desc { margin: 0; color: var(--text-muted); font-size: 14px; }
.lib-meta { margin: 0; font-size: 12.5px; color: var(--text-muted); }

.lib-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-top: 6px;
  border-top: 1px solid var(--border);
}
.lib-actions form {
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  max-width: 100%;
}
.lib-add select { min-width: 0; max-width: 100%; }
.lib-grid .lib-add { width: 100%; }
.lib-grid .lib-add select { flex: 1 1 110px; }
.lib-uninstall .keep-data { font-size: 12.5px; color: var(--text-muted); margin-right: 0; }

/* Stacked cards on plain content pages (admin, settings) get breathing room
   — the dashboard grid handles its own gaps, these siblings had none. */
.content > .card + .card { margin-top: 18px; }

/* ------------------------- Library refine toolbar ---------------------- */
.lib-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 0 14px;
}
.lib-toolbar [data-lib-search] { flex: 1 1 200px; max-width: 360px; }
.lib-toolbar [data-lib-filter] { width: auto; }
.lib-view-toggle span { display: inline-flex; align-items: center; gap: 6px; }
.lib-view-toggle svg { width: 14px; height: 14px; }

/* Compact library grid: auto-fill tracks of ≥280 px — about 6 across on an
   ultrawide, stepping down through desktop/tablet to a single column on
   phones (overrides the dashboard's fixed 3/2/1 .cards columns). */
.cards.lib-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

/* Cap the grid at 7 columns on very wide screens (7×280 + 6×16 px gaps). */
@media (min-width: 2056px) {
  .cards.lib-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
}
.lib-grid .card-body { padding: 12px 14px; }
.lib-grid .lib-body { gap: 8px; }
.lib-grid .lib-desc { font-size: 13px; }

/* Smaller library controls (both views). */
.lib-actions .btn { padding: 4px 10px; font-size: 12px; }
.lib-actions .input-sm { padding: 4px 6px; font-size: 12px; }
.lib-actions form { gap: 6px; }

/* Library table view (the refine toolbar filters its rows too). */
.lib-table-wrap { overflow-x: auto; }
.lib-table td { vertical-align: top; }
.lib-table-desc { max-width: 340px; color: var(--text-muted); font-size: 13px; }
.lib-table-icon svg { width: 16px; height: 16px; vertical-align: -3px; }
.lib-table .lib-actions { border-top: 0; padding-top: 0; margin-top: 4px; }

/* Sortable column headers. */
.lib-table th[data-sort] { cursor: pointer; user-select: none; white-space: nowrap; }
.lib-table th[data-sort]:hover { color: var(--primary); }
.lib-table th.sort-asc::after { content: ' ▲'; font-size: 9px; }
.lib-table th.sort-desc::after { content: ' ▼'; font-size: 9px; }

/* Upload drop zone */
.upload-drop {
  position: relative;
  padding: 28px 18px 20px;
  margin-bottom: 14px;
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  cursor: pointer;
  text-align: center;
  transition: border-color .15s ease, background .15s ease;
}
.upload-drop:hover { border-color: var(--primary); }
.upload-drop.dragover {
  border-color: var(--primary);
  background: var(--primary-soft);
}
.upload-drop input[type="file"] {
  /* the native control stays for no-JS, but tucked out of the way */
  margin-bottom: 8px;
  font-size: 12.5px;
}
.upload-drop-hint {
  margin: 0;
  font-size: 13px;
  color: var(--text-muted);
  text-align: center;
}
.upload-files {
  list-style: none;
  margin: 10px 0 0;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 12.5px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.upload-warn { color: var(--warning); }

.upload-access {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin: 0 0 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.upload-access legend {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  padding: 0 6px;
}

.upload-results {
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.upload-result {
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  border: 1px solid var(--border);
}
.upload-result.ok   { background: var(--success-soft); border-color: color-mix(in srgb, var(--success) 30%, transparent); }
.upload-result.fail { background: var(--danger-soft);  border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
.upload-result.warn { background: var(--warning-soft); border-color: color-mix(in srgb, var(--warning) 35%, transparent); flex-wrap: wrap; }
.upload-confirm { display: inline-flex; gap: 8px; margin-left: auto; }

/* Code blocks (package format docs on the upload page) */
.code-block {
  margin: 8px 0 14px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.6;
  overflow-x: auto;
  white-space: pre;
}
.code-block em { color: var(--text-muted); font-style: normal; }

/* Installed-module list on the upload page */
.installed-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.installed-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

code {
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
}

/* ==========================================================================
   Wide module cards — handled by the per-card layout system above:
   wide-capable modules (kanban, calendar, stats) carry .module-card--wide2 /
   .module-card--wide3, and the layout editor assigns a clamped grid-column
   (inline) so spanning always works, from any column.
   ========================================================================== */

/* ==========================================================================
   Admin panel (Pass 5) — user table, module table, activity log, pager.
   ========================================================================== */

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.admin-table th,
.admin-table td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.admin-table th {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  font-weight: 700;
}
.admin-table tr:last-child td { border-bottom: 0; }
.admin-table tr.is-inactive td { opacity: 0.55; }
.admin-table .row-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}
.admin-table .row-actions form { display: inline; }
.admin-meta {
  font-size: 12.5px;
  color: var(--text-muted);
  word-break: break-word;
}
.admin-meta code { word-break: break-all; }

/* Pager for the activity log */
.pager {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: center;
  margin-top: 12px;
  font-size: 13.5px;
  color: var(--text-muted);
}

/* Tables scroll sideways on narrow screens instead of crushing the layout */
.table-scroll { overflow-x: auto; }

@media (max-width: 640px) {
  .admin-table th, .admin-table td { padding: 7px 8px; font-size: 13px; }
}

/* ==========================================================================
   My Tasks page (my-tasks.php + assets/js/my-tasks.js)
   ========================================================================== */

.mt-page { display: flex; flex-direction: column; gap: 14px; }

.mt-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.mt-pills { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.mt-pill {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.mt-pill.active {
  background: var(--primary-soft);
  border-color: transparent;
  color: var(--primary);
}
.mt-count { font-size: 11.5px; opacity: .8; }

.mt-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.mt-select { width: auto; padding: 7px 10px; font-size: 13px; }
.mt-search { width: 190px; padding: 7px 10px; font-size: 13px; }

.mt-form-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 8px;
  margin-bottom: 8px;
}
.mt-edit-grid { grid-template-columns: 1fr 1fr 1fr 1fr; margin: 8px 0; }
.mt-form-actions { display: flex; gap: 8px; margin-top: 8px; }

.mt-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.mt-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
}

.mt-check {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  margin-top: 2px;
  border: 2px solid var(--border);
  border-radius: 7px;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  color: transparent;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.mt-check:hover { border-color: var(--primary); }
.mt-done .mt-check {
  background: var(--success);
  border-color: var(--success);
  color: #fff;
}
.mt-check::after {
  content: '';
  width: 12px;
  height: 12px;
  background: currentColor;
  clip-path: polygon(14% 46%, 0 62%, 40% 100%, 100% 18%, 86% 4%, 38% 72%);
}

.mt-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.mt-title { font-weight: 700; font-size: 14.5px; word-break: break-word; }
.mt-done .mt-title { text-decoration: line-through; color: var(--text-muted); }
.mt-desc { font-size: 13px; color: var(--text-muted); white-space: pre-wrap; word-break: break-word; }
.mt-badges { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 3px; }

.mt-pri-high   { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
.mt-pri-medium { background: var(--warning-soft); color: var(--warning); border-color: transparent; }
.mt-pri-low    { background: var(--surface-2); color: var(--text-muted); }

.mt-due-overdue { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
.mt-due-today   { background: var(--warning-soft); color: var(--warning); border-color: transparent; }
.mt-due-soon    { background: var(--primary-soft); color: var(--primary); border-color: transparent; }

.mt-loc { background: var(--surface-2); color: var(--text-muted); }

.mt-status-open        { background: var(--surface-2); color: var(--text-muted); }
.mt-status-in_progress { background: var(--primary-soft); color: var(--primary); border-color: transparent; }
.mt-status-done        { background: var(--success-soft); color: var(--success); border-color: transparent; }

.mt-actions { display: flex; gap: 2px; flex-shrink: 0; }

.mt-edit { flex: 1; min-width: 0; }
.mt-edit .input { margin-bottom: 0; }

.mt-empty { color: var(--text-muted); font-size: 14px; padding: 12px 2px; }
.mt-error { margin: 0; font-size: 14px; color: var(--danger); }

@media (max-width: 900px) {
  .mt-form-grid { grid-template-columns: 1fr 1fr; }
  .mt-search { flex: 1; min-width: 140px; }
}

/* ==========================================================================
   Public share page (share.php) + shared-links list (modules.php) — Pass 6
   ========================================================================== */

.share-page {
  min-height: 100vh;
  background: var(--bg);
}
/* .share-wrap rides on .content's padding/max-width so the shared view
   matches the logged-in dashboard's gutters exactly */
.share-wrap {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.share-wrap:not(.share-wrap-wide) { max-width: 760px; margin: 0 auto; }
.share-top {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text-muted);
}
.share-brand { font-weight: 800; font-size: 17px; color: var(--text); }
.share-top .logo-mark { width: 32px; height: 32px; }
.share-by { margin-left: auto; }
.share-foot {
  margin: 0;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-muted);
}
/* Share pages use the SAME masonry as the logged-in dashboard
   (assets/js/share-layout.js) — .cards--masonry positions the cards. */

.share-url {
  width: 100%;
  margin-top: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  padding: 6px 8px;
  cursor: text;
}

.input-sm { padding: 6px 8px; font-size: 12.5px; width: 200px; }

/* ------------------ Searchable selects (select2-lite) -------------------
   app.js enhances every <select> element: the source element is visually
   hidden (its value still submits), a filterable dropdown takes its place. */
select.s2-source {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  opacity: 0;
  pointer-events: none;
}
.s2 { position: relative; display: inline-block; }
.s2-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-width: 140px;
  cursor: pointer;
  text-align: left;
}
.s2-toggle:disabled { opacity: 0.5; cursor: default; }
.s2-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s2-chevron { flex-shrink: 0; display: inline-flex; color: var(--text-muted); }
.s2-drop {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 1200;   /* dropdown tier: above cards, topbar, chatbot (200),
                      flash bar (900) and drag ghosts (1000); only toasts
                      (2000) and drag followers stay higher */
  min-width: 100%;
  width: max-content;
  max-width: 300px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
/* While open the drop lives on <body> (see app.js enhanceSelect): fixed
   positioning escapes the card body's overflow clipping entirely, and the
   inline top/left from place() anchor it to the toggle (flipped above it
   near the viewport bottom). */
.s2-drop--float {
  position: fixed;
  top: auto;
  left: auto;
  max-width: min(300px, calc(100vw - 16px));
  max-height: calc(100vh - 16px);
}
.s2-search { width: 100%; min-width: 160px; }
.s2-list {
  display: flex;
  flex-direction: column;
  max-height: 220px;
  overflow-y: auto;
}
.s2-option {
  padding: 6px 8px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}
.s2-option:hover,
.s2-option.active { background: var(--hover); }
.s2-option.selected { color: var(--primary); font-weight: 600; }
.s2-empty { padding: 6px 8px; color: var(--text-muted); font-size: 12px; }

@media (max-width: 640px) {
  .input-sm { width: 100%; }
}

/* ==========================================================================
   Dashboard tabs + dashboard share rows (Pass 7)
   ========================================================================== */

.dashbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
}

/* ==========================================================================
   Top band — unified dashboard/board toolbar. Full-bleed purple gradient:
   negative margins cancel .content's 24px gutter so the band runs corner
   to corner. Row 1: dashboard pills + action cluster. Row 2: board tabs.
   (The legacy .dashbar/.dash-tab styles above still serve pages that use
   them, e.g. modules/calendar/dashboard.php.)
   ========================================================================== */

.topband {
  background: var(--band-bg);
  border-bottom: 1px solid var(--band-edge);
  margin: -24px -24px 14px;
  padding: 14px 24px 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.band-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* Actions stay pinned top-right: the row itself never wraps — the dashboard
   pills wrap onto a second line inside .seg instead. */
.band-main {
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: nowrap;
}
.band-main .seg { flex-wrap: wrap; }
.band-main .actions { flex-shrink: 0; margin-left: auto; }

/* Segmented dashboard pills. Radius is 16px (not a full pill) so the
   container still looks clean when the pills wrap onto extra rows. */
.seg {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--band-surface);
  border: 1px solid var(--band-border);
  border-radius: 16px;
  padding: 4px;
  box-shadow: var(--shadow-sm);
}
.seg-pill {
  display: inline-flex;
  align-items: center;
  padding: 6px 16px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
}
.seg-pill:hover { color: var(--text); }
.seg-pill.active {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 40%, transparent);
}

/* Inline "add" pill: round + button + borderless input */
.seg-add,
.btab-add {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 12px 3px 4px;
  border: 1.5px dashed rgba(79, 70, 229, .45);
  border-radius: 999px;
  color: var(--primary);
}
.seg-add input,
.btab-add input {
  border: 0;
  background: transparent;
  outline: none;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  width: 134px;
}
.seg-add input::placeholder,
.btab-add input::placeholder { color: rgba(79, 70, 229, .65); }
.seg-add-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex: none;
  border: 0;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}
.seg-add-btn:hover { background: var(--primary); color: #fff; }

/* Action cluster — quiet ghost group of icon forms */
.actions {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: var(--band-surface);
  border: 1px solid var(--band-border);
  border-radius: 999px;
  padding: 4px;
  box-shadow: var(--shadow-sm);
}
.act {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}
.act:hover { background: var(--surface); color: var(--text); }
.act svg { width: 14px; height: 14px; flex: none; }
.act button {
  border: 0;
  background: transparent;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.act + .act { position: relative; }
.act + .act::before {
  content: "";
  position: absolute;
  left: -1px;
  top: 22%;
  bottom: 22%;
  width: 1px;
  background: var(--border);
}
.act-mini {
  border: 0;
  border-bottom: 1px dashed var(--text-muted);
  background: transparent;
  outline: none;
  font: inherit;
  color: var(--text);
  width: 96px;
  padding: 1px 0;
}
.act-mini[type="email"] { width: 132px; }
.act select {
  border: 0;
  background: transparent;
  font: inherit;
  color: inherit;
  outline: none;
  cursor: pointer;
  width: auto;
  padding: 0;
  margin: 0;
}
.act-danger { color: #b91c1c; }
.act-danger:hover { background: var(--danger-soft); color: var(--danger); }
[data-theme="dark"] .act-danger { color: var(--danger); }

/* The JS columns toggle blends into the action cluster. */
.actions .cols-toggle {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: inherit;
}
.actions .cols-toggle:hover { background: transparent; }

/* Board tabs — second, lighter row */
.btabs { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.btab {
  display: inline-flex;
  align-items: center;
  padding: 5px 14px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
}
.btab:hover { color: var(--text); background: var(--band-surface); }
.btab.active {
  background: var(--surface);
  border-color: var(--band-edge);
  color: var(--primary);
  box-shadow: var(--shadow-sm);
}
.btab-add { padding: 3px 12px 3px 4px; background: transparent; }
.btab-add input { width: 74px; }

/* Share-link bars: slim white pills under the band */
.sharebars {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: -4px 0 14px;
}
.sharebar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 8px 6px 14px;
  box-shadow: var(--shadow-sm);
  font-size: 12.5px;
}

/* Merged notifications (Pass 22): one bar for ALL public links, one bar for
   ALL user/group grants — rounded card shape instead of a pill. */
.sharebar-merged { border-radius: var(--radius); align-items: flex-start; }
.sharebar-merged .share-tag { padding-top: 5px; }
.share-merged-rows {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.share-merged-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Column alignment: every scope label gets the same fixed width, so the
   URLs (and the rows) all start at the same left edge. */
.share-merged-row .share-for { flex: 0 0 120px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.share-merged-row .share-url { flex: 1; min-width: 220px; width: auto; margin-top: 0; }
/* .share-for is nowrap AND follows this block in the file, so this needs
   the extra .share-for segment to win the cascade — the merged list must
   wrap instead of overflowing the page when many targets are shared. */
.sharebar .share-for.share-merged-targets {
  flex: 1;
  min-width: 0;
  padding-top: 4px;
  white-space: normal;
  overflow-wrap: anywhere;
}
.share-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--primary);
  background: var(--primary-soft);
  border-radius: 999px;
  padding: 4px 10px;
  font-weight: 700;
  white-space: nowrap;
}
.share-tag svg { width: 12px; height: 12px; }
.share-for { color: var(--text-muted); white-space: nowrap; }
.sharebar .share-url {
  flex: 1;
  min-width: 180px;
  border: 0;
  background: transparent;
  outline: none;
  color: var(--text-muted);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chip {
  border: 1px solid var(--border);
  background: var(--surface-2);
  border-radius: 999px;
  padding: 5px 14px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.chip:hover { background: var(--hover); }
.chip-danger { color: var(--danger); }
.chip-danger:hover { background: var(--danger-soft); }
.chip-form { display: inline-flex; }

.dash-tabs {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}
.dash-tab {
  display: inline-block;
  padding: 7px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-muted);
  text-decoration: none;
  background: var(--surface);
}
.dash-tab:hover { color: var(--text); border-color: var(--primary); }
.dash-tab.active {
  background: var(--accent, #4f7cff);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent, #4f7cff) 40%, transparent);
}

.dash-new,
.dash-inline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.dash-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.dash-name-input {
  width: 130px;
  padding: 6px 9px;
  font-size: 12.5px;
}

.dash-shares {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: -6px 0 14px;
}
.dash-share-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 10px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.dash-share-row .share-url { flex: 1; min-width: 220px; width: auto; margin-top: 0; }
.dash-share-row .badge { display: inline-flex; align-items: center; gap: 5px; }
.dash-share-row .badge svg { width: 13px; height: 13px; }

/* Whole-dashboard share pages: no max-width cap — .content's full-width,
   24px-gutter box matches the logged-in dashboard exactly, so the shared
   grid (same .cards, same 16px gap, same percentage-based card widths)
   renders pixel-identical proportions. */

.lib-hint { margin: 0 0 12px; font-size: 13px; }

@media (max-width: 768px) {
  .dashbar { flex-direction: column; align-items: stretch; }
  .dash-actions { justify-content: flex-start; }
  .dash-name-input { width: 110px; }
  /* Small screens: let the band stack — the actions drop below the pills. */
  .band-main { flex-wrap: wrap; }
}

/* ==========================================================================
   Boards — flat sub-dashboards (Pass 14). The board bar has an aggregate
   Dashboard tab plus one tab per board; visible boards stack in titled
   sections carrying their add/rename/delete controls.
   ========================================================================== */

.boardbar {
  margin: -6px 0 14px;
  padding-top: 10px;
  border-top: 1px dashed var(--border);
}
.boardbar .dash-tab {
  padding: 5px 12px;
  font-size: 12.5px;
  font-weight: 600;
}
.boardbar .dash-name-input { width: 110px; }

.board-section {
  margin-bottom: 22px;
  padding: 14px 16px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.board-section-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px dashed var(--border);
}
.board-title { margin: 0; font-size: 15px; font-weight: 700; }
/* Standalone heading above a tab board's grid. */
.board-title-tab { margin: -4px 0 12px; font-size: 17px; }

/* Open/close toggle for board sections (state persists in localStorage). */
.board-toggle svg { transition: transform .2s ease; }
.board-section.board-closed .cards { display: none; }
.board-section.board-closed .board-toggle svg { transform: rotate(-90deg); }
.board-section.board-closed .board-section-head {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: 0;
}
.board-head-form .dash-name-input { width: 110px; }

/* Compact per-board empty note when several boards are stacked. */
.empty-state-compact { padding: 20px 16px; }
.empty-state-compact p { margin: 0; max-width: none; font-size: 13px; }

/* Shared pages stack every board with its title above its grid. */
.share-board-title { margin: 18px 0 10px; font-size: 15px; font-weight: 700; }
.share-board-title:first-of-type { margin-top: 0; }

/* ==========================================================================
   Module Generator page (module-generator.php)
   ========================================================================== */

.mg-page .card-header .card-actions { margin-left: auto; }

/* ---------------- Module Architect, 4-step layout (Pass 68) ---------------- */

.ma2-head { margin: 4px 0 18px; }
.ma2-title { margin: 0; font-size: 26px; font-weight: 800; }
.ma2-sub { margin: 4px 0 0; color: var(--text-muted); font-size: 14px; }

.ma2-stepper {
  list-style: none; margin: 0 0 20px; padding: 0;
  display: grid; grid-template-columns: repeat(4, 1fr);
  position: relative;
}
.ma2-stepper::before {
  content: ''; position: absolute; left: 0; right: 0; top: 19px;
  border-top: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
}
.ma2-stepper > li {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px;
}
.ma2-stepnum {
  width: 38px; height: 38px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; font-weight: 800; font-size: 16px;
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 18%, transparent);
  flex-shrink: 0;
}
.ma2-stepname { font-size: 13px; font-weight: 700; text-align: center; }

.ma2-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px; align-items: stretch;
}
@media (max-width: 1200px) { .ma2-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .ma2-grid { grid-template-columns: 1fr; } }

.ma2-card { display: flex; flex-direction: column; }
.ma2-card-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px 10px;
}
.ma2-card-title { margin: 0; font-size: 16px; font-weight: 800; }
.ma2-card-sub { margin: 2px 0 0; font-size: 12.5px; color: var(--text-muted); }
.ma2-card-body { flex: 1; display: flex; flex-direction: column; }
.ma2-text { font-size: 13.5px; margin: 0 0 12px; }
.ma2-bigbtn {
  width: 100%; margin-top: auto; justify-content: center;
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 15px; padding: 10px 16px;
}
.ma2-copied { margin: 10px 0 0; text-align: center; color: var(--success); font-weight: 700; font-size: 13px; }

/* Blueprint preview box */
.ma2-bp-box {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2, rgba(127,127,127,.06));
  margin-bottom: 14px; overflow: hidden;
}
.ma2-bp-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 12px; font-size: 11px; font-weight: 800; letter-spacing: .06em;
  color: var(--accent);
  border-bottom: 1px solid var(--border);
}
.ma2-bp-mini {
  border: 0; background: none; cursor: pointer; font-size: 14px;
  color: var(--accent); padding: 2px 6px;
}
.ma2-bp-pre {
  margin: 0; padding: 10px 12px; max-height: 170px; overflow: hidden;
  font-size: 11.5px; white-space: pre-wrap; color: var(--text-muted);
  -webkit-mask-image: linear-gradient(#000 60%, transparent);
  mask-image: linear-gradient(#000 60%, transparent);
}

/* Build-with-AI hint rows */
.ma2-hint {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; margin-bottom: 8px;
  border: 1px solid var(--border); border-radius: var(--radius);
  font-size: 13px;
}
.ma2-hint em { color: var(--text-muted); font-size: 12px; }
.ma2-hint-ico { font-size: 17px; }
.ma2-hint-chev { margin-left: auto; color: var(--text-muted); font-weight: 800; }
.ma2-tip {
  margin: auto 0 0; padding: 10px 12px; font-size: 12.5px; color: var(--text-muted);
  border: 1px dashed var(--border); border-radius: var(--radius);
}

/* Download ZIP card */
.ma2-ready {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 22px 14px; margin-bottom: 14px; text-align: center;
  border: 2px dashed var(--border); border-radius: var(--radius);
}
.ma2-ready-check {
  width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2.5px solid var(--success); color: var(--success);
  font-size: 20px; font-weight: 800; margin-bottom: 4px;
}
.ma2-incl-title { margin: 0 0 6px; font-size: 13px; font-weight: 700; }
.ma2-incl { list-style: none; margin: 0 0 12px; padding: 0; font-size: 13px; }
.ma2-incl li { padding: 2px 0; }
.ma2-incl li::before { content: '✓ '; color: var(--success); font-weight: 800; }

/* Access radio cards: option text left, radio right */
.ma-access-card { justify-content: flex-start; }
.ma-access-card input[type="radio"] { margin-left: auto; }

.ma2-foot {
  margin: 18px 0 0; text-align: center;
  font-size: 13px; color: var(--text-muted);
}

/* --------------------- Module Architect (Pass 65) ------------------------ */

.ma-page.cards-align-start:not(.lib-grid) {
  display: grid; columns: unset; column-gap: 0;
  /* Two equal panels across the full screen width, stacking on narrow. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px; align-items: start;
}
@media (max-width: 900px) {
  .ma-page.cards-align-start:not(.lib-grid) { grid-template-columns: 1fr; }
}
.ma-page > .card { margin-top: 0 !important; }

/* Numbered steps with connecting line */
.ma-steps { list-style: none; margin: 0; padding: 0; }
.ma-steps > li { position: relative; display: flex; gap: 14px; padding-bottom: 26px; }
.ma-steps > li:last-child { padding-bottom: 6px; }
.ma-steps > li::before {
  content: ''; position: absolute; left: 17px; top: 38px; bottom: 0;
  border-left: 2px dashed color-mix(in srgb, var(--accent, #4f7cff) 35%, transparent);
}
.ma-steps > li:last-child::before { display: none; }
.ma-num {
  flex-shrink: 0; width: 36px; height: 36px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent, #4f7cff); color: #fff;
  font-size: 16px; font-weight: 800;
}
.ma-step-title { display: block; font-size: 15.5px; }
.ma-step-sub { margin: 3px 0 8px; font-size: 13px; color: var(--text-muted); }
.ma-prompt-cta { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ma-btn-ico { font-weight: 700; }
.ma-view-prompt { margin-top: 10px; }
.ma-view-prompt > summary {
  cursor: pointer; font-size: 13.5px; font-weight: 600;
  color: var(--accent, #4f7cff); list-style: none;
  display: inline-flex; align-items: center; gap: 6px;
}
.ma-view-prompt > summary::-webkit-details-marker { display: none; }
.ma-chev { flex-shrink: 0; transition: transform .15s ease; }
details[open] > summary .ma-chev { transform: rotate(180deg); }
.ma-included {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 12px; border-radius: 999px;
  background: var(--success-soft); color: var(--success);
  font-size: 12.5px; font-weight: 700;
}
.ma-example {
  margin: 4px 0 8px; padding: 12px 14px;
  background: var(--surface-2, rgba(127,127,127,.08));
  border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--text-muted); font-size: 13.5px;
}
.ma-example-label {
  display: block; margin-bottom: 4px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--accent, #4f7cff);
}
.ma-include { margin: 0 0 8px; font-size: 13px; }
.ma-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.ma-chip {
  padding: 6px 12px; border-radius: 999px; font-size: 12.5px;
  background: var(--surface-2, rgba(127,127,127,.10));
  border: 1px solid var(--border); color: var(--text-muted);
}
.ma-code-alt > summary {
  cursor: pointer; list-style: none;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface-2, rgba(127,127,127,.08));
  font-size: 13px; font-weight: 600;
}
.ma-code-alt > summary::-webkit-details-marker { display: none; }
.ma-code-alt > summary:hover { border-color: var(--accent, #4f7cff); }
.ma-tips {
  margin: 14px 0 0; padding-top: 12px; font-size: 13px; color: var(--text-muted);
  border-top: 1px solid var(--border);
}

/* Upload & Install */
.ma-zip-badge { display: block; margin: 0 auto 12px; text-align: center; filter: drop-shadow(0 4px 10px rgba(0,0,0,.35)); }
.ma-zip-badge svg { width: 64px; height: 64px; display: inline-block; }
/* The real file input covers the zone invisibly (click anywhere = browse);
   the native "Choose file / No file chosen" chrome never shows. */
.upload-drop input[type="file"] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; font-size: 0;
}
.upload-drop input[type="file"]::file-selector-button { display: none; }
.ma-drop-text { margin: 0 0 14px; font-size: 15px; }
.ma-drop-text strong { font-size: 16px; }
.ma-drop-text .text-muted { font-size: 13px; }
.ma-browse { pointer-events: none; }   /* the whole zone is the click target */
.ma-drop-cap { margin: 14px 0 0; font-size: 12px; color: var(--text-muted); }
.ma-access { border: 0; margin: 14px 0 0; padding: 0; }
.ma-access > legend { font-size: 13.5px; font-weight: 700; margin-bottom: 8px; }
.ma-access-card {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; margin-bottom: 8px; cursor: pointer;
  border: 1.5px solid var(--border); border-radius: var(--radius);
}
.ma-access-card:has(input:checked) {
  border-color: var(--accent, #4f7cff);
  background: color-mix(in srgb, var(--accent, #4f7cff) 7%, transparent);
}
.ma-access-card input { accent-color: var(--accent, #4f7cff); }
.ma-access-ico { font-size: 17px; }
.ma-access-text { display: flex; flex-direction: column; line-height: 1.3; }
.ma-access-text small { color: var(--text-muted); }
.ma-install { width: 100%; margin-top: 10px; justify-content: center; }
.ma-rate { margin: 8px 0 0; font-size: 12px; color: var(--text-muted); text-align: center; }
.ma-req { margin-top: 16px; }
.ma-req > summary {
  cursor: pointer; list-style: none; font-size: 13.5px; font-weight: 600;
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.ma-req > summary::-webkit-details-marker { display: none; }
.ma-req > summary .ma-chev { margin-left: auto; }
.ma-after {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 14px 0 0; padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 13px; color: var(--text-muted);
}
.ma-after a { color: var(--accent, #4f7cff); font-weight: 600; margin-left: auto; }

.mg-steps {
  margin: 0 0 10px;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 14px;
}

.mg-prompt,
.mg-after {
  max-height: 420px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12.5px;
  line-height: 1.55;
}

.mg-after { max-height: 260px; }

/* ==========================================================================
   AI chatbot widget — floating bubble + panel (api/chat.php, local LLM).
   ========================================================================== */
.chatbot { position: fixed; right: 20px; bottom: 20px; z-index: 200; }

.chat-bubble {
  width: 52px;
  height: 52px;
  border: 0;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--primary);
  color: #fff;
  cursor: pointer;
  box-shadow: var(--shadow-md);
}
.chat-bubble:hover { background: var(--primary-hover); }
.chat-bubble svg { width: 24px; height: 24px; }

.chat-panel {
  position: absolute;
  right: 0;
  bottom: 64px;
  width: 360px;
  max-width: calc(100vw - 40px);
  height: 480px;
  max-height: calc(100vh - 110px);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.chat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.chat-close {
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.chat-close:hover { color: var(--text); }

.chat-log {
  flex: 1;
  overflow-y: auto;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.chat-msg {
  max-width: 85%;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 13px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.chat-user {
  align-self: flex-end;
  background: var(--primary);
  color: #fff;
  border-bottom-right-radius: 3px;
}
.chat-assistant {
  align-self: flex-start;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-bottom-left-radius: 3px;
}
.chat-typing { color: var(--text-muted); font-style: italic; }

.chat-chip {
  align-self: flex-start;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--success-soft);
  color: var(--success);
  font-size: 11.5px;
  font-weight: 600;
}
.chat-chip.error { background: var(--danger-soft, rgba(220,38,38,.12)); color: var(--danger); }

.chat-form {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
}
.chat-form .input { flex: 1; }

@media (max-width: 640px) {
  .chatbot { right: 12px; bottom: 12px; }
  .chat-panel { width: calc(100vw - 24px); }
}

/* ------------------------- Confirm modal (app.js) -------------------------
   window.appConfirm() dialog — replaces window.confirm. The overlay is
   transparent until .modal-open triggers the fade/scale-in. */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  padding: 16px;
  overflow-y: auto;   /* modals taller than the viewport scroll instead of clipping */
  background: rgba(17, 24, 39, 0);
  backdrop-filter: blur(0);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease, background .18s ease, backdrop-filter .18s ease;
}

.modal-overlay.modal-open {
  background: rgba(17, 24, 39, .45);
  backdrop-filter: blur(3px);
  opacity: 1;
  pointer-events: auto;
}

.modal {
  width: 100%;
  max-width: 400px;
  margin: auto;   /* scroll-safe centering: centered when it fits, fully reachable via overlay scroll when it doesn't */
  padding: 22px 22px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  text-align: center;
  transform: scale(.94) translateY(8px);
  transition: transform .18s ease;
}

.modal-overlay.modal-open .modal { transform: scale(1) translateY(0); }

.modal-icon {
  width: 44px;
  height: 44px;
  margin: 0 auto 12px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary);
}

.modal-icon svg { width: 22px; height: 22px; }

.modal-icon.modal-icon-danger { background: var(--danger-soft); color: var(--danger); }

.modal-title {
  margin: 0 0 6px;
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
}

.modal-msg {
  margin: 0 0 18px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-muted);
  overflow-wrap: break-word;
}

.modal-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
}

.modal-actions .btn { flex: 1; max-width: 160px; }

/* --------------------- Sharing hierarchy (Pass 15) --------------------- */

.hier-layout {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  gap: 16px;
  margin-top: 16px;
  align-items: start;
}

.hier-hint { font-size: 12px; margin: 8px 0; }

.hier-root-form {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.hier-root-form .input { flex: 1; }

.hier-user-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 60vh;
  overflow-y: auto;
}

.hier-user {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: 13px;
  cursor: grab;
  user-select: none;
  touch-action: none;
}

.hier-user-self { cursor: default; color: var(--text-muted); }

.hier-grip { color: var(--text-muted); font-size: 12px; }

.hier-tree { min-height: 120px; border-radius: var(--radius-sm); padding: 4px; }

.hier-node {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  margin: 6px 0;
  transition: border-color .12s ease, box-shadow .12s ease;
}

.hier-node.hier-drop,
.hier-tree.hier-drop {
  border: 1px dashed var(--primary);
  box-shadow: var(--ring);
}

.hier-tree.hier-drop { outline: 2px dashed var(--primary); outline-offset: -2px; }

.hier-node-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  cursor: grab;
  user-select: none;
  touch-action: none;
}

.hier-name { font-weight: 600; font-size: 13px; flex: 1; overflow-wrap: break-word; }

.hier-btn {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  border-radius: 6px;
  width: 24px;
  height: 24px;
  line-height: 1;
  cursor: pointer;
  font-size: 13px;
  padding: 0;
}

.hier-btn:hover { color: var(--primary); border-color: var(--primary); }

.hier-btn-danger:hover { color: var(--danger); border-color: var(--danger); }

.hier-members {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 10px 8px 30px;
}

.hier-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 6px 3px 10px;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 12px;
  cursor: grab;
  user-select: none;
  touch-action: none;
}

.hier-chip-x {
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 0 2px;
  opacity: .7;
}

.hier-chip-x:hover { opacity: 1; }

.hier-children {
  margin: 0 10px 10px 22px;
  border-left: 2px solid var(--border);
  padding-left: 10px;
}

.hier-ghost {
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  background: var(--primary);
  color: #fff;
  font-size: 13px;
  box-shadow: var(--shadow-md);
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.hier-dragging { cursor: grabbing; }
body.hier-dragging * { user-select: none !important; }

@media (max-width: 900px) {
  .hier-layout { grid-template-columns: 1fr; }
}

/* Grant target select inside a sharebar pill */
.sharebar .share-target {
  flex: 1;
  min-width: 200px;
  border: 0;
  background: transparent;
  outline: none;
  color: var(--text);
  font-size: 13px;
  padding: 4px 0;
}

.sharebar a.chip { text-decoration: none; }
.sharebar a.share-for { color: var(--primary); font-weight: 600; }

/* Roster user rows: name over email, remove button on the right */
.hier-user-who {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.hier-user-name { font-weight: 600; }

.hier-user-email {
  font-size: 11px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hier-user .hier-chip-x { color: var(--text-muted); font-size: 15px; }
.hier-user .hier-chip-x:hover { color: var(--danger); }

.hier-users-card .hier-root-form { margin-bottom: 8px; }

/* Pending invitation badge on roster rows */
.hier-user-namerow {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.hier-badge-pending {
  flex: none;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--warning-soft);
  color: var(--warning);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* "Requested" badge on roster rows + inline request actions (Pass 21) */
.hier-badge-requested {
  flex: none;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.hier-request-actions { display: flex; gap: 6px; margin-top: 4px; }
/* Incoming-request rows: no drag cursor, let the badge + buttons wrap
   cleanly in narrow sidebars. */
.hier-user-request { cursor: default; flex-direction: column; align-items: stretch; }
.hier-user-request .hier-user-namerow { flex-wrap: wrap; }
.hier-user-request .hier-request-actions { margin-top: 6px; }

/* "shared" badge on dashboard tabs that come from a grant */
.seg-shared {
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  vertical-align: middle;
}

/* Active tab is solid primary — invert the badge so it stays readable */
.seg-pill.active .seg-shared {
  background: rgba(255, 255, 255, .22);
  color: #fff;
}

/* --------------------- Password viewer (Pass 21) ------------------------ */

/* Wrapper around the password input — the eye toggle sits on its right edge */
.pw-wrap { position: relative; }

/* Holds ONLY the input: the toggle centers on this, so showing the preview
   below never moves the icon. */
.pw-field { position: relative; }

.pw-wrap .input { padding-right: 40px; width: 100%; }

.pw-view-toggle {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 0;
  background: transparent;
  padding: 0;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 6px;
}

.pw-view-toggle:hover { color: var(--primary); }
.pw-view-toggle[aria-pressed="true"] { color: var(--primary); }

.pw-view-toggle svg { width: 18px; height: 18px; }

.pw-view-preview {
  margin-top: 6px;
  padding: 6px 10px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  overflow-wrap: break-word;
  user-select: all;
}

.pw-view-preview:empty { display: none; }

/* --------------------- Admin view-as banner (Pass 21) ------------------- */

/* Compact pill inside the top bar (next to the theme toggle) */
.viewas-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--warning-soft);
  border: 1px solid var(--warning);
  color: var(--text);
  font-size: 12px;
  white-space: nowrap;
}

.viewas-pill svg { width: 14px; height: 14px; color: var(--warning); }

.viewas-form { margin: 0; }

/* Pending share-request pill (topbar, next to the theme toggle) */
.share-req-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--warning-soft);
  border: 1px solid var(--warning);
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  animation: share-req-pulse 2s ease-in-out infinite;
}
.share-req-pill:hover { background: var(--warning); color: #fff; }
.share-req-pill svg { width: 14px; height: 14px; color: var(--warning); }
.share-req-pill:hover svg { color: #fff; }
@keyframes share-req-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--warning) 45%, transparent); }
  50%      { box-shadow: 0 0 0 5px transparent; }
}

/* ------------------- Pull-to-refresh indicator (mobile) ------------------ */

.ptr-indicator {
  position: fixed; top: 0; left: 0; right: 0; z-index: 1500;
  height: 0; overflow: hidden; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; color: var(--text-muted);
  background: var(--surface); border-bottom: 1px solid var(--border);
  transition: height .18s ease;
}

/* --------------------- Shared-task inbox (Pass 36) --------------------- */

.share-inbox { position: relative; display: inline-flex; }
.share-inbox-count {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  pointer-events: none;
}
.share-inbox-drop {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 1200;
  width: 320px;
  max-width: calc(100vw - 24px);
  padding: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.share-inbox-empty { margin: 4px 2px; font-size: 12.5px; color: var(--text-muted); }
.share-inbox-row { padding: 8px 4px; border-bottom: 1px solid var(--border); }
.share-inbox-row:last-child { border-bottom: 0; }
.share-inbox-row.share-inbox-busy { opacity: .5; pointer-events: none; }
.share-inbox-who { font-size: 12.5px; color: var(--text-muted); }
.share-inbox-task { font-size: 13.5px; font-weight: 600; margin: 2px 0 6px; }
.share-inbox-acts { display: flex; gap: 6px; }

/* --------------------- Notifications bell (Pass 46) ---------------------- */

.notif-row { cursor: pointer; border-left: 3px solid transparent; }
.notif-row.notif-unread { background: color-mix(in srgb, var(--accent, #4f7cff) 7%, transparent); }
.notif-row.notif-success { border-left-color: var(--success, #2f9e6e); }
.notif-row.notif-warning { border-left-color: var(--warning, #d9930d); }
.notif-row.notif-error   { border-left-color: var(--danger, #d64545); }
.notif-msg { font-size: 13.5px; margin: 2px 0 4px; white-space: pre-wrap; word-break: break-word; }
.notif-read-all { width: 100%; margin-top: 6px; }

/* --------------------- Storage usage pill (Pass 52) ---------------------- */

.storage-pill {
  font-size: 12px; font-weight: 600; color: var(--text-muted);
  padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px;
  white-space: nowrap;
}

/* ------------------- Unread-messages icon (Pass 47) ----------------------
   Uses the shared .share-inbox / .share-inbox-count badge styles. */
#msg-unread-btn { color: inherit; text-decoration: none; position: relative; }
#msg-unread-btn:hover { text-decoration: none; }

/* --------------------------- My Files (Pass 59) ---------------------------- */
/* Preview lightbox (Pass 60) — reuses the messages lightbox chrome. */
.files-lb {
  position: fixed; inset: 0; z-index: 1300;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0); opacity: 0; pointer-events: none;
  transition: opacity .18s ease, background .18s ease;
}
.files-lb.files-lb-open { background: rgba(0,0,0,.85); opacity: 1; pointer-events: auto; }
.files-lb-stage { max-width: 90vw; max-height: 82vh; display: flex; }
.files-lb-stage img, .files-lb-stage video { max-width: 90vw; max-height: 82vh; border-radius: 8px; }
.files-lb-other { text-align: center; color: #ddd; display: flex; flex-direction: column; gap: 14px; align-items: center; }
.files-lb-other .files-icon { font-size: 64px; }

.files-filter { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; margin-bottom: 4px; }
.files-filter-chip {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 999px; padding: 4px 12px; font-size: 12.5px; cursor: pointer;
  color: var(--text-muted);
}
.files-filter-chip.active {
  background: var(--accent, #4f7cff); border-color: var(--accent, #4f7cff); color: #fff;
}

.files-app { position: relative; }
.files-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.files-crumb { display: inline-flex; align-items: center; gap: 6px; font-weight: 800; font-size: 16px; }
.files-crumb-sep { width: 14px; height: 14px; color: var(--text-muted); }
.files-actions { display: flex; gap: 6px; }
.files-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px; margin-top: 12px;
}
.files-card {
  position: relative; padding: 14px 12px; text-align: center;
  min-height: 175px;   /* every tile is the same size, even the ".." back tile */
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); cursor: pointer;
  display: flex; flex-direction: column; gap: 6px; align-items: center;
  justify-content: center;   /* text sits vertically centered in the tile */
}
.files-card:hover {
  border-color: var(--accent, #4f7cff);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.files-card { transition: box-shadow .15s ease, transform .15s ease, border-color .15s ease; }
.files-icon { font-size: 34px; line-height: 1; }
.files-thumb { width: 100%; height: 90px; object-fit: cover; border-radius: 6px; }
.files-name {
  font-size: 13px; font-weight: 600; word-break: break-all; text-align: center;
  /* two lines max — long names truncate with an ellipsis so every tile
     stays the same size */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.files-meta { font-size: 11.5px; color: var(--text-muted); text-align: center; }
.files-meta-size { font-weight: 600; }
.files-card-actions { display: flex; gap: 6px; margin-top: 2px; }
.files-del {
  position: absolute; top: 4px; right: 6px;
  border: 0; background: none; color: var(--text-muted);
  font-size: 16px; cursor: pointer; line-height: 1;
}
.files-del:hover { color: var(--danger); }
.files-ren {
  position: absolute; top: 4px; right: 26px;
  border: 0; background: none; color: var(--text-muted);
  font-size: 14px; cursor: pointer; line-height: 1;
}
.files-ren:hover { color: var(--accent, #4f7cff); }
.files-goto {
  position: absolute; top: 4px; left: 6px;
  color: var(--text-muted); font-size: 13px; line-height: 1;
  text-decoration: none;
}
.files-goto:hover { color: var(--accent, #4f7cff); text-decoration: none; }

/* Deep-link flash: highlight the whole ROW behind the message. */
.msg-jump-flash {
  background: color-mix(in srgb, var(--accent, #4f7cff) 22%, transparent);
  border-radius: 10px;
  transition: background .5s ease;
}
.files-folder.files-drop-here {
  border-color: var(--accent, #4f7cff);
  background: color-mix(in srgb, var(--accent, #4f7cff) 8%, transparent);
}
.files-app.files-drag::after {
  content: '📎 Drop to upload';
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 800; color: var(--accent, #4f7cff);
  background: color-mix(in srgb, var(--accent, #4f7cff) 8%, transparent);
  border: 3px dashed var(--accent, #4f7cff);
  pointer-events: none;
}

.call-quality {
  margin: -10px 0 12px; font-size: 11.5px; letter-spacing: 2px;
  color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.call-q4, .call-q3 { color: var(--success); }
.call-q2 { color: var(--warning); }
.call-q1 { color: var(--danger); }

/* Call history modal (Pass 67) */
.call-history-modal { max-width: 460px; text-align: left; }
.call-history-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.call-history-head .modal-title { margin: 0; }
.call-history-list { max-height: 420px; overflow-y: auto; }
.call-history-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--border);
}
.call-history-row:last-child { border-bottom: 0; }
.call-history-dir { font-size: 16px; color: var(--accent); width: 20px; text-align: center; }
.call-history-main { flex: 1; display: flex; flex-direction: column; }
.call-history-meta { font-size: 12px; color: var(--text-muted); }
.call-history-when { font-size: 11px; color: var(--text-muted); }

/* --------------------------- Group calls (Pass 72) ------------------------ */

.gcall-overlay {
  position: fixed; inset: 0; z-index: 1400;
  display: flex; flex-direction: column;
  background: rgba(10,12,18,.96);
}
.gcall-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px; color: #fff;
}
.gcall-title { font-size: 16px; }
.gcall-state { flex: 1; font-size: 13px; color: rgba(255,255,255,.65); }
.gcall-actions { display: flex; gap: 10px; }
.gcall-grid {
  flex: 1; display: grid; gap: 10px; padding: 12px 18px 18px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  align-content: center; overflow-y: auto;
}
/* Balanced layouts chosen by JS (cols = ceil(sqrt(n))): 4 → 2×2,
   5–9 → 3 columns, 10+ → 4. Row count caps tile height via --rows so the
   grid fits the viewport instead of scrolling. */
.gcall-grid[data-cols="1"] { grid-template-columns: minmax(260px, 640px); justify-content: center; }
.gcall-grid[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.gcall-grid[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.gcall-grid[data-cols="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.gcall-tile {
  position: relative; border-radius: 12px; overflow: hidden;
  background: #000; aspect-ratio: 16/9;
  width: 100%; margin: 0 auto;
  max-height: calc((100vh - 150px) / var(--rows, 1));
  box-shadow: 0 0 0 0 transparent;
  transition: box-shadow .15s ease;
}
/* Speaking indicator: green ring around the whole tile AND the name pill
   while audio is heard. */
.gcall-tile.gcall-speaking {
  box-shadow: 0 0 0 3px var(--success), 0 0 14px rgba(34,197,94,.45);
}
.gcall-tile video { width: 100%; height: 100%; object-fit: cover; display: block; }
.gcall-local video { transform: scaleX(-1); }
.gcall-label {
  position: absolute; left: 8px; bottom: 8px;
  padding: 2px 10px; border-radius: 999px;
  background: rgba(0,0,0,.55); color: #fff; font-size: 12px;
  border: 2px solid transparent;
  transition: border-color .15s ease, box-shadow .15s ease;
}
/* Speaking indicator: green ring around the name while audio is heard. */
.gcall-tile.gcall-speaking .gcall-label {
  border-color: var(--success);
  box-shadow: 0 0 8px rgba(34,197,94,.55);
}

/* Muted badge (top-right corner of a tile). Indicator for everyone;
   clickable mic toggle for the starter. */
.gcall-mutepill {
  position: absolute; top: 8px; right: 8px;
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.55); color: #fff; border: 0; padding: 0;
}
.gcall-mutepill[hidden] { display: none; }
.gcall-mutepill.soft { background: #d97706; }      /* muted — they can unmute */
.gcall-mutepill.off { background: var(--danger); } /* locked — only the starter releases */
.call-btn.call-locked { background: var(--danger); color: #fff; cursor: not-allowed; opacity: .85; }
.gcall-mutepill.ind { cursor: default; pointer-events: none; }
button.gcall-mutepill:not(.ind) { cursor: pointer; }
button.gcall-mutepill:not(.ind):hover { background: rgba(0,0,0,.8); }
/* Phones: never more than 2 columns or the tiles get unreadable. */
@media (max-width: 560px) {
  .gcall-grid[data-cols="3"],
  .gcall-grid[data-cols="4"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Spotlight: stage (focus tile) + rail (small tiles) as two grid regions
   whose tops and heights always line up. Every tile size is computed in
   layout() (--stagew / --smallw / --rcols), so each tile is exactly 16:9. */
.gcall-grid.spot {
  display: grid; gap: 10px; overflow: hidden;
  align-content: start;   /* never vertically center the spotlight regions */
  --stagew: 320px; --smallw: 180px;
}
.gcall-grid.spot.spot-wide { grid-template-columns: minmax(0, 1fr) auto; }
.gcall-grid.spot.spot-tall { grid-template-columns: 1fr; overflow-y: auto; }

.gcall-stage {
  min-width: 0; min-height: 0;
  display: flex; justify-content: center; align-items: flex-start;
}
.gcall-stage .gcall-tile {
  width: var(--stagew); height: calc(var(--stagew) * 0.5625);
  margin: 0; max-height: none; flex: 0 0 auto;
}
.gcall-rail {
  min-height: 0; overflow-y: auto;
  /* Room for the speaking ring + glow so it isn't clipped by the scroll edge */
  padding: 6px;
  display: grid; grid-template-columns: repeat(var(--rcols, 1), auto);
  gap: 10px; align-content: start; justify-content: start;
}
.gcall-rail .gcall-tile {
  width: var(--smallw); height: calc(var(--smallw) * 0.5625);
  margin: 0; max-height: none; cursor: pointer;
}
/* Portrait: focus on top, small tiles wrap in centered rows below. */
.gcall-grid.spot.spot-tall .gcall-rail {
  display: flex; flex-wrap: wrap; justify-content: center; overflow-y: visible;
}

/* Call bar: in-flow at the top of the main column whenever a group call is
   live — the rest of the page drops down below it. Sticky so it survives
   scrolling; the topbar parks underneath it while it's on. */
.gcall-bar {
  position: sticky; top: 0; z-index: 35;
  display: flex; flex-direction: column; justify-content: center; gap: 4px;
  min-height: 44px; padding: 4px 16px;
  background: #101623; color: #fff;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.gcall-bar[hidden] { display: none; }
/* One row per live call (1:1, group, …). */
.gcall-bar-row { display: flex; align-items: center; gap: 10px; width: 100%; }
.gcall-bar-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--success); animation: call-pulse 1.6s infinite;
  flex-shrink: 0;
}
.gcall-bar-state { font-size: 13px; color: rgba(255,255,255,.65); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Timer sits between the "Group call" title and the state text. */
.gcall-bar-timer {
  font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: #fff;
}
.gcall-timer { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: #fff; }
.gcall-timer:empty { display: none; }
.gcall-bar-btn {
  padding: 5px 14px; border-radius: 999px; border: 0; cursor: pointer;
  font-size: 12px; font-weight: 700; white-space: nowrap;
  background: rgba(255,255,255,.12); color: #fff;
}
.gcall-bar-join  { background: var(--success); }
.gcall-bar-leave { background: var(--danger); }
body.gcall-bar-on .topbar { top: 44px; }
@media (max-width: 760px) {
  body.gcall-bar-on .msg-app { top: 98px; }   /* 44px bar + 54px topbar */
}

/* --------------------------- Voice calls (Pass 64) ------------------------ */

.call-overlay {
  position: fixed; inset: 0; z-index: 1400;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.45); backdrop-filter: blur(3px);
}
.call-card {
  width: min(920px, 94vw); padding: 26px 20px 20px; text-align: center;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-md);
}
.call-avatar {
  width: 72px; height: 72px; margin: 0 auto 12px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; font-size: 30px; font-weight: 800;
}
.call-card .call-avatar[style*="none"] { margin: 0; }
.call-name { font-size: 17px; font-weight: 800; }
.call-state { margin: 4px 0 16px; font-size: 13px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.call-actions { display: flex; justify-content: center; gap: 14px; }
.call-btn {
  width: 52px; height: 52px; border-radius: 50%; border: 0; cursor: pointer;
  font-size: 20px; display: inline-flex; align-items: center; justify-content: center;
}
/* Clicks on the icon land on the button itself (SVG hit-testing quirks in
   some browsers made centre clicks dead). */
.call-btn svg { pointer-events: none; }
.call-btn-accept { background: var(--success); color: #fff; animation: call-pulse 1.4s infinite; }
.call-btn-end    { background: var(--danger); color: #fff; }
.call-btn-mute   { background: var(--surface-2, rgba(127,127,127,.15)); color: var(--text); }
.call-btn-mute.call-muted { background: var(--warning); color: #fff; }
.call-video {
  position: relative; margin: -6px 0 12px; border-radius: 10px;
  overflow: hidden; background: #000;
}
.call-remote { width: 100%; max-height: 62vh; display: block; }
.call-local {
  position: absolute; right: 8px; bottom: 8px;
  width: 84px; border-radius: 8px; border: 1px solid rgba(255,255,255,.4);
}
.call-remote2 {
  position: absolute; left: 8px; bottom: 8px;
  width: 120px; border-radius: 8px; border: 1px solid rgba(255,255,255,.4);
}
.call-btn.call-on { background: var(--accent); color: #fff; }
.call-rec-badge {
  margin: 0 0 12px; font-size: 12px; font-weight: 800; color: var(--danger);
}
.call-consent {
  display: flex; flex-direction: column; gap: 8px; align-items: center;
  margin: 0 0 12px; padding: 10px; font-size: 12.5px;
  border: 1px dashed var(--border); border-radius: 8px;
}
.call-consent .btn { margin: 0 2px; }

@keyframes call-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 45%, transparent); }
  50%      { box-shadow: 0 0 0 8px transparent; }
}

/* ------------------------- Messages (Pass 47) ---------------------------- */

/* Fill the window: on the messages page the content area becomes a flex
   column so the chat app stretches to the bottom edge (minus the page
   padding), whatever the topbar height is. */
/* Cap the frame at the viewport on the messages page: without this, .app's
   min-height:100vh lets the whole page grow and the thread never needs to
   scroll. With it, only the thread (and chat list) scroll. */
body:has(.msg-app) { overflow: hidden; }
body:has(.msg-app) .app { height: 100vh; height: 100dvh; }   /* dvh tracks the Android toolbar + soft keys */
.content:has(> .msg-app) { display: flex; flex-direction: column; }
.msg-app {
  position: relative;
  flex: 1;
  min-height: 0;              /* flex child must be allowed to shrink */
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 14px;
}
.msg-side {
  display: flex; flex-direction: column;
  min-height: 0;   /* grid row must shrink so the list scrolls, not the page */
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
}
.msg-side-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px; border-bottom: 1px solid var(--border);
  min-height: 57px; box-sizing: border-box;   /* lines up with .msg-pane-head */
}
.msg-side-actions { display: flex; gap: 2px; }
.msg-add-btn { position: relative; }
.msg-add-plus {
  position: absolute; right: 1px; bottom: 1px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--accent, #4f7cff); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 13px; text-align: center;
  pointer-events: none;
}
.msg-list { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.msg-list-empty { padding: 14px; font-size: 13px; color: var(--text-muted); }
.msg-conv {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 10px 12px; background: none; border: 0; border-bottom: 1px solid var(--border);
  color: inherit; font: inherit;
}
.msg-conv:hover { background: var(--surface-2, rgba(127,127,127,.06)); }
.msg-conv.active { background: color-mix(in srgb, var(--accent, #4f7cff) 10%, transparent); }
.msg-conv-top { display: flex; justify-content: space-between; gap: 8px; }
.msg-conv-title { font-weight: 700; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-conv-time { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.msg-conv-bottom { display: flex; justify-content: space-between; gap: 8px; margin-top: 2px; }
.msg-conv-preview {
  font-size: 12.5px; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msg-conv-unread {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: var(--success); color: #fff; font-size: 11px; font-weight: 700;
  line-height: 18px; text-align: center;
}
.msg-pane {
  position: relative;
  display: flex; flex-direction: column;
  min-height: 0;   /* grid row must shrink so the thread scrolls, not the page */
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
}
.msg-pane-head {
  padding: 10px 14px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 6px;
  min-height: 57px; box-sizing: border-box;   /* lines up with .msg-side-head */
}
/* Title/subtitle take the slack so the action buttons sit tight on the right. */
.msg-pane-head > div { flex: 1; min-width: 0; }
.msg-pane-head > div strong,
.msg-pane-head > div .msg-pane-sub {
  display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
/* Group headers open the participants modal. */
#msg-pane-info { position: relative; }
#msg-pane-info.is-group { cursor: pointer; border-radius: 8px; padding: 2px 26px 2px 8px; margin: -2px -8px; }
#msg-pane-info.is-group:hover { background: var(--surface-2, rgba(127,127,127,.08)); }
.msg-pane-chev {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  opacity: .45; display: none; pointer-events: none;
}
#msg-pane-info.is-group .msg-pane-chev { display: block; }
#msg-pane-info.is-group:hover .msg-pane-chev { opacity: .8; }

/* Participants modal rows */
.msg-member-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 7px 8px; border-radius: 8px;
}
.msg-member-row:hover { background: var(--surface-2, rgba(127,127,127,.06)); }
.msg-member-name { font-size: 14px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.msg-members-add-title {
  margin: 14px 0 4px; font-size: 11px; font-weight: 700;
  color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em;
}
.msg-pane-sub { font-size: 12px; color: var(--text-muted); }
.msg-font-ctl { display: inline-flex; gap: 2px; }
.msg-font-ctl .icon-btn { width: 34px; height: 34px; font-size: 13px; font-weight: 700; }
.msg-font-ctl .icon-btn:disabled { opacity: .35; cursor: default; pointer-events: none; }
.msg-font-a { font-size: 16px; }
.msg-font-a-sm { font-size: 12px; }
.msg-thread {
  flex: 1;
  min-height: 0;            /* lets the thread shrink so IT scrolls, not the pane */
  overflow-y: auto;
  overflow-x: hidden;       /* bubbles wrap; never a horizontal scrollbar */
  /* Browser scroll-anchoring bumps scrollTop as images load above the
     reader; saved, that drift compounds on every refresh. */
  overflow-anchor: none;
  padding: 14px; display: flex; flex-direction: column; gap: 6px;
}
.msg-empty { margin: auto; text-align: center; max-width: 320px; }
.msg-date-sep { display: flex; justify-content: center; margin: 10px 0 4px; flex-shrink: 0; }
/* Floating scroll-position date pill (same look as the day separators). */
.msg-date-float {
  position: absolute; top: 65px; left: 50%; transform: translateX(-50%);
  z-index: 40; pointer-events: none;
}
.msg-date-float .msg-date-pill {
  background: var(--surface);   /* opaque — covers separators scrolling under it */
  box-shadow: var(--shadow-md);
}
.msg-date-pill {
  padding: 4px 12px; border-radius: 8px;
  background: var(--surface-2, rgba(127,127,127,.14));
  border: 1px solid var(--border);
  font-size: 11.5px; font-weight: 700; color: var(--text-muted);
}

.msg-row { display: flex; flex-wrap: wrap; justify-content: flex-start; }
.msg-row.mine { justify-content: flex-end; }
.msg-bubble {
  max-width: min(70%, 480px); padding: 8px 12px; border-radius: 14px;
  background: var(--surface-2, rgba(127,127,127,.10)); border: 1px solid var(--border);
}
.msg-row.mine .msg-bubble {
  background: color-mix(in srgb, var(--accent, #4f7cff) 16%, transparent);
}
.msg-sender { font-size: 11.5px; font-weight: 700; color: var(--accent, #4f7cff); margin-bottom: 2px; }
.msg-text { font-size: var(--msg-font, 15.5px); white-space: pre-wrap; word-break: break-word; }
.msg-emoji-big { font-size: 1.5em; line-height: 1; vertical-align: -0.12em; }
.msg-meta {
  display: flex; align-items: center; justify-content: flex-end; gap: 2px;
  font-size: 10.5px; color: var(--text-muted); margin-top: 3px;
}
.msg-tick { margin-left: 4px; font-size: 11px; letter-spacing: -2px; }
.msg-tick-read { color: #34b7f1; }   /* WhatsApp blue */
.msg-bubble audio { max-width: 240px; height: 36px; }
.msg-voice { display: flex; align-items: center; gap: 8px; }
.msg-voice-dur { font-size: 12px; font-weight: 600; color: var(--text-muted); white-space: nowrap; }

/* WhatsApp-style voice player. */
.msg-vp { display: flex; align-items: center; gap: 10px; min-width: 220px; }
.msg-vp-play {
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: 50%; border: 0; cursor: pointer;
  background: var(--accent, #4f7cff); color: #fff;
  font-size: 14px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.msg-vp-play:hover { filter: brightness(1.1); }
/* Chrome/Android force-recolors buttons in some modes — pin the accent
   background through every state. */
.msg-vp-play:active, .msg-vp-play:focus, .msg-vp-play:focus-visible {
  background: var(--accent, #4f7cff); color: #fff; outline: none;
}
.msg-vp-play { -webkit-tap-highlight-color: transparent; }
.msg-vp-bar {
  flex: 1; height: 5px; border-radius: 3px; cursor: pointer;
  background: color-mix(in srgb, var(--text-muted) 30%, transparent);
  overflow: hidden;
}
.msg-vp-fill {
  width: 0; height: 100%; border-radius: 3px;
  background: var(--accent, #4f7cff);
  transition: width .2s linear;
}
.msg-vp-time {
  flex-shrink: 0; font-size: 11.5px; color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.msg-nosound { font-size: 12.5px; font-style: italic; color: var(--text-muted); }
.msg-image { max-width: 240px; max-height: 240px; border-radius: 8px; display: block; }
.msg-video { max-width: 260px; max-height: 260px; border-radius: 8px; display: block; background: #000; }
.msg-file {
  display: flex; align-items: center; gap: 8px;
  color: inherit; text-decoration: none; font-size: 13.5px;
}
.msg-file:hover { text-decoration: underline; }
.msg-file-icon { font-size: 16px; }
.msg-file-label { word-break: break-all; }
.msg-file-name { font-size: 11px; color: var(--text-muted); margin-top: 3px; }
.msg-file-name2 { display: block; }
.msg-file-size { font-size: 11px; color: var(--text-muted); }
.msg-composer {
  position: relative; display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 10px; border-top: 1px solid var(--border);
}
/* Reply bar (Pass 54): full-width strip above the input row. */
.msg-replybar {
  flex: 0 0 100%; order: -1;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; margin-bottom: 4px;
  border-left: 3px solid var(--accent, #4f7cff);
  background: var(--surface-2, rgba(127,127,127,.08));
  border-radius: 6px;
}
.msg-replybar-text { flex: 1; min-width: 0; font-size: 12.5px; }
.msg-replybar-text strong { display: block; color: var(--accent, #4f7cff); }
.msg-replybar-text span {
  display: block; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msg-composer textarea { flex: 1; resize: none; min-height: 40px; max-height: 120px; }
/* Composer buttons match the 40px text input so the row lines up. */
.msg-composer .icon-btn {
  width: 40px; height: 40px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 20px;
}
.msg-composer .icon-btn svg { width: 20px; height: 20px; }
.msg-composer #msg-send { height: 40px; padding: 0 18px; font-size: 14px; }
.msg-recording { color: var(--danger) !important; animation: msg-rec-pulse 1s infinite; }
@keyframes msg-rec-pulse { 50% { opacity: .4; } }

/* WhatsApp-style recorder bar (replaces the composer row while recording). */
.msg-recbar {
  flex: 1; display: flex; align-items: center; gap: 12px;
  min-height: 40px; padding: 0 4px;
}
.msg-rec-dot {
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--danger); animation: msg-rec-pulse 1s infinite;
}
.msg-rec-time { flex: 1; font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.msg-recbar .icon-btn, .msg-recbar .btn { height: 40px; }
.msg-emoji {
  position: absolute; bottom: calc(100% + 6px); left: 8px; z-index: 50;
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px;
  width: 300px; max-width: calc(100vw - 32px); padding: 8px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-md);
}
.msg-emoji-item {
  border: 0; background: none; font-size: 30px; padding: 5px; cursor: pointer;
  border-radius: 6px; line-height: 1;
}
.msg-emoji-item:hover { background: var(--surface-2, rgba(127,127,127,.10)); }
.msg-contact-list { max-height: 300px; overflow-y: auto; margin: 8px 0; }
.msg-contact {
  display: block; width: 100%; text-align: left; padding: 8px 10px;
  border: 0; border-bottom: 1px solid var(--border); background: none;
  color: inherit; font: inherit; cursor: pointer;
}
.msg-contact:hover { background: var(--surface-2, rgba(127,127,127,.06)); }

/* "Who reacted" popover (Pass 63): small card under the reaction pill. */
.msg-reactinfo {
  position: absolute; z-index: 60;
  width: 300px; max-width: calc(100% - 16px); max-height: 320px;
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-md);
  padding: 10px 12px;
}
.msg-reactinfo-head { display: flex; align-items: center; justify-content: space-between; }
.msg-reactinfo-tabs { display: flex; gap: 6px; margin: 8px 0; flex-wrap: wrap; }
.msg-reactinfo-tab {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 999px; padding: 3px 12px; font-size: 13px; cursor: pointer;
}
.msg-reactinfo-tab.active {
  background: color-mix(in srgb, var(--success) 20%, transparent);
  border-color: var(--success);
}
.msg-reactinfo-list { overflow-y: auto; }
.msg-reactinfo-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--border);
}
.msg-reactinfo-row:last-child { border-bottom: 0; }
.msg-reactinfo-avatar {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent, #4f7cff); color: #fff; font-weight: 700;
}
.msg-reactinfo-who { flex: 1; display: flex; flex-direction: column; }
.msg-reactinfo-hint { font-size: 11.5px; color: var(--text-muted); }
.msg-reactinfo-mine { cursor: pointer; }
.msg-reactinfo-emoji { font-size: 20px; }

/* Emoji reactions (Pass 58). */
.msg-row { position: relative; }
.msg-bubble { position: relative; }
/* React button: inline, right after the time — fades in on hover. */
.msg-react-btn {
  border: 0; background: none; padding: 0 2px; margin-left: 4px;
  font-size: 12px; cursor: pointer; line-height: 1;
  opacity: 0; transition: opacity .15s ease;
}
.msg-row:hover .msg-react-btn, .msg-react-btn:focus-visible { opacity: 1; }
@media (hover: none) { .msg-react-btn { opacity: .6; } }
.msg-react-bar {
  position: absolute; z-index: 50;
  display: flex; gap: 2px; padding: 4px 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; box-shadow: var(--shadow-md);
}
.msg-react-bar-item {
  border: 0; background: none;
  /* Scales with the message text size (A−/A+ sets --msg-font on .msg-pane). */
  font-size: calc(var(--msg-font, 15.5px) + 4px);
  padding: calc(var(--msg-font, 15.5px) * 0.25);
  cursor: pointer; border-radius: 50%; line-height: 1;
  transition: transform .1s ease;
}
.msg-react-bar-item:hover { transform: scale(1.25); background: var(--surface-2, rgba(127,127,127,.12)); }
.msg-react-bar-item.selected {
  background: color-mix(in srgb, var(--accent, #4f7cff) 18%, transparent);
  box-shadow: inset 0 0 0 1.5px var(--accent, #4f7cff);
}
/* Reactions form ONE pill half-overlapping the bubble's bottom edge
   (WhatsApp style): emojis side by side, count alongside. The chips div
   is a full-width lane under the bubble; the pill floats inside it. */
.msg-react-chips {
  flex: 0 0 100%;
  position: relative; z-index: 2;
  display: flex; margin-top: -13px; padding: 0 10px;
}
.msg-row.mine .msg-react-chips { justify-content: flex-end; }
.msg-react-chip {
  border: 0; background: none; padding: 0 2px;
  font-size: 14px; cursor: pointer; line-height: 1.3;
  color: var(--text-muted);
}
.msg-react-chip.mine { color: var(--accent, #4f7cff); font-weight: 700; }
.msg-react-pill {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 2px 7px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: var(--shadow-sm, 0 1px 3px rgba(0,0,0,.18));
}

/* Drag & drop staging (Pass 56). */
.msg-dropzone {
  position: absolute; inset: 0; z-index: 45;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent, #4f7cff) 10%, transparent);
  border: 2px dashed var(--accent, #4f7cff); border-radius: var(--radius);
  pointer-events: none;
}
.msg-dropzone-inner {
  font-size: 16px; font-weight: 700; color: var(--accent, #4f7cff);
  background: var(--surface); padding: 12px 22px; border-radius: 999px;
  box-shadow: var(--shadow-md);
}
.msg-pending {
  flex: 0 0 100%; order: -1;
  display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px;
}
.msg-pending-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 8px; border-radius: 999px;
  background: var(--surface-2, rgba(127,127,127,.12));
  border: 1px solid var(--border); font-size: 12px;
}
.msg-pending-name { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-pending-size { color: var(--text-muted); }
.msg-pending-x {
  border: 0; background: none; cursor: pointer; color: var(--text-muted);
  font-size: 14px; line-height: 1; padding: 0 2px;
}
.msg-pending-x:hover { color: var(--danger); }

/* Quoted reply snippet inside a bubble (Pass 54). */
.msg-quote {
  border-left: 3px solid var(--accent, #4f7cff);
  background: var(--surface-2, rgba(127,127,127,.10));
  border-radius: 6px; padding: 4px 8px; margin-bottom: 5px;
  font-size: 12px; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msg-quote strong { display: block; color: var(--accent, #4f7cff); font-size: 11.5px; }

.msg-older {
  align-self: center; margin: 4px auto 10px;
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 999px; padding: 5px 14px; font-size: 12.5px;
  color: var(--text-muted); cursor: pointer;
}
.msg-older:hover { background: var(--hover); }
.msg-older:disabled { opacity: .5; cursor: default; }

.msg-scroll-down {
  position: absolute; right: 16px; bottom: 74px; z-index: 40;
  width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text); font-size: 18px; line-height: 1; cursor: pointer;
  box-shadow: var(--shadow-md);
}
.msg-scroll-down:hover { background: var(--hover); }

/* ----------------------- Media lightbox (Pass 55) ------------------------ */

.msg-image { cursor: zoom-in; }
.msg-video-wrap { position: relative; }
.msg-video-expand {
  position: absolute; top: 6px; right: 6px;
  width: 28px; height: 28px; border-radius: 6px; border: 0;
  background: rgba(0,0,0,.55); color: #fff; font-size: 15px; cursor: pointer;
}
.msg-video-expand:hover { background: rgba(0,0,0,.8); }
.msg-lightbox {
  position: fixed; inset: 0; z-index: 1300;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0); opacity: 0; pointer-events: none;
  transition: opacity .18s ease, background .18s ease;
}
.msg-lightbox.msg-lb-open { background: rgba(0,0,0,.85); opacity: 1; pointer-events: auto; }
.msg-lb-stage { max-width: 90vw; max-height: 82vh; display: flex; }
.msg-lb-stage img, .msg-lb-stage video {
  max-width: 90vw; max-height: 82vh; border-radius: 8px;
}
.msg-lb-cap {
  position: absolute; bottom: 18px; left: 0; right: 0;
  text-align: center; color: #ddd; font-size: 13px; pointer-events: none;
}
.msg-lb-close, .msg-lb-prev, .msg-lb-next {
  position: absolute; z-index: 1; border: 0; cursor: pointer;
  background: rgba(255,255,255,.12); color: #fff; border-radius: 50%;
  width: 42px; height: 42px; font-size: 22px; line-height: 1;
}
.msg-lb-close:hover, .msg-lb-prev:hover, .msg-lb-next:hover { background: rgba(255,255,255,.28); }
.msg-lb-close { top: 16px; right: 16px; }
.msg-lb-prev { left: 16px; top: 50%; transform: translateY(-50%); }
.msg-lb-next { right: 16px; top: 50%; transform: translateY(-50%); }

.msg-ptr {
  position: absolute; top: 0; left: 0; right: 0; z-index: 5;
  height: 0; overflow: hidden; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; color: var(--text-muted);
  background: var(--surface); border-bottom: 1px solid transparent;
  transition: height .18s ease;
}

/* Back button only exists in the mobile flow. */
.msg-back { display: none; margin-right: 2px; }

@media (max-width: 760px) {
  /* WhatsApp mobile flow: chat list is the first screen; opening a chat
     swaps to a full-height conversation with a back button. The app is a
     FIXED layer pinned below the topbar (54px) to the physical bottom of
     the visible viewport — vh-chains misreport on Android, fixed doesn't.
     safe-area padding keeps the composer above the soft-key bar. */
  .msg-app {
    position: fixed; left: 0; right: 0; bottom: 0; top: 54px; z-index: 20;   /* below topbar (30) and the nav drawer (40) */
    display: block;
    background: var(--bg);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .msg-side { max-height: none; height: 100%; border-radius: 0; border-left: 0; border-right: 0; }
  .msg-pane { display: none; height: 100%; border-radius: 0; border-left: 0; border-right: 0; }
  .msg-app.msg-open .msg-side { display: none; }
  .msg-app.msg-open .msg-pane { display: flex; }
  .msg-back { display: inline-grid; }
}

/* --------------------- Admin tables (Pass 21) --------------------------- */

.at-bar { margin-bottom: 10px; }
.at-filter { max-width: 260px; }

.admin-table th.at-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.admin-table th.at-sortable:hover { color: var(--primary); }

.admin-table th.at-sortable::after {
  content: "↕";
  margin-left: 5px;
  font-size: 10px;
  opacity: .45;
}

.admin-table th.at-asc::after  { content: "↑"; opacity: 1; color: var(--primary); }
.admin-table th.at-desc::after { content: "↓"; opacity: 1; color: var(--primary); }

.at-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-muted);
}

/* ==========================================================================
   Share sheet (Pass 22) — iPhone-style bottom sheet for picking share targets
   ========================================================================== */

/* Dashboard share button sits at the right end of the board tab row. */
.band-boards .btabs { flex: 1 1 auto; }
/* The right-corner pair is [Create Public Share Link] [Share …] — the auto
   margin belongs to whichever is present FIRST (the create form hides once
   a link exists, then Share itself pins right). */
.btabs .share-open-btn,
.board-section-head .share-open-btn { margin-left: auto; }
.btabs .share-link-form,
.board-section-head .share-link-form { margin-left: auto; }
.btabs .share-link-form + .share-open-btn,
.board-section-head .share-link-form + .share-open-btn { margin-left: 0; }
/* One line: icon left of the label (the global svg{display:block} reset
   would otherwise stack them). */
.share-open-btn { display: inline-flex; align-items: center; gap: 5px; }
.share-open-btn svg { width: 13px; height: 13px; flex: none; }

.ssheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 1300;   /* above the dropdown tier (1200), below toasts (2000) */
  /* transparent — it exists only to catch click-away (mousedown on itself) */
}

.ssheet {
  /* Pop-down panel anchored to the Share button — JS sets left/top inline
     from the button's viewport rect (flipped above when there's no room). */
  position: fixed;
  width: 360px;
  max-width: calc(100vw - 16px);
  /* Grows to fit the whole list — no inner scrolling for normal list sizes;
     the viewport cap only ever bites at the 30-row settings maximum. */
  max-height: calc(100vh - 16px);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.22);
  padding: 12px 14px 14px;
}

.ssheet-handle { display: none; }   /* bottom-sheet artifact — not used in pop-down mode */

.ssheet-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.ssheet-title {
  flex: 1;
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ssheet-filter { width: 100%; margin-bottom: 10px; }

.ssheet-list {
  flex: 1;
  overflow-y: auto;
  scrollbar-width: none;              /* no visible scrollbar… */
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
  min-height: 60px;
}
.ssheet-list::-webkit-scrollbar { display: none; }   /* …in WebKit too */

.ssheet-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  cursor: pointer;
  user-select: none;
  line-height: 1.2;
}
.ssheet-row:hover { border-color: var(--primary); }
.ssheet-row:has(.ssheet-box:checked) {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.ssheet-box {
  flex: none;
  width: 18px;
  height: 18px;
  accent-color: var(--primary);
  cursor: pointer;
}

.ssheet-kind {
  flex: none;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 700;
  background: var(--primary-soft);
  color: var(--primary);
}
.ssheet-kind-group { background: var(--warning-soft); color: var(--warning); }

.ssheet-who { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ssheet-name {
  font-size: 13.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ssheet-sub {
  font-size: 11px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ssheet-more {
  padding: 8px 10px;
  font-size: 12px;
  color: var(--text-muted);
  text-align: center;
}

.ssheet-foot { padding-top: 12px; }
.ssheet-foot .ssheet-apply { width: 100%; }

/* ==========================================================================
   Calendar page (my-calendar.php) — day / week / month / year over the
   shared task store. Adapted from the calendar module's card styles.
   ========================================================================== */

.myc-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.myc-search {
  width: 180px;
  padding: 6px 12px;
  font-size: 12.5px;
  border-radius: 999px;
}
@media (max-width: 720px) {
  .myc-search { width: 100%; order: 5; }
}
.myc-views {
  display: inline-flex;
  gap: 4px;
  padding: 3px;
  border-radius: 999px;
  background: var(--surface-2);
}
.myc-pill {
  padding: 5px 14px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  transition: background .12s ease, box-shadow .12s ease, color .12s ease;
}
.myc-pill:hover { color: var(--primary); }
.myc-pill.active {
  background: var(--surface);
  color: var(--text);
  font-weight: 700;
  box-shadow: 0 1px 4px rgba(28, 39, 76, .14);
}
.myc-nav { display: inline-flex; gap: 4px; }
.myc-title { flex: 1; margin: 0; font-size: 17px; font-weight: 800; }

.myc-error { color: var(--danger); font-size: 13px; }

/* ---------- month view ---------- */

.myc-weekdays {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));   /* minmax(0,…): chips must never force the track wider than the screen */
  gap: 4px;
  margin-bottom: 4px;
}
.myc-weekdays span {
  text-align: center;
  font-size: 11px;
  font-weight: 800;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .03em;
}
.myc-month {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 4px;
  /* Fill the viewport: weeks share the available height instead of fixed
     110px rows (topbar + toolbar + weekday head ≈ 240px). */
  grid-auto-rows: minmax(110px, 1fr);
  min-height: calc(100vh - 240px);
}
.myc-day {
  min-width: 0;
  min-height: 110px;
  padding: 5px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  cursor: context-menu;
  display: flex;
  flex-direction: column;
  gap: 3px;
  transition: border-color .15s ease, background .15s ease;
}
.myc-day:hover { border-color: var(--primary); background: var(--surface-2); }
.myc-day.myc-today { border-color: var(--primary); background: var(--primary-soft); }
.myc-day.myc-drop {
  border-color: var(--primary);
  border-style: dashed;
  background: var(--primary-soft);
}
.myc-day.myc-outside { opacity: .55; }
.myc-daynum { font-size: 11.5px; font-weight: 800; color: var(--text-muted); }
.myc-day.myc-today .myc-daynum { color: var(--primary); }

/* ---------- week view ---------- */

.myc-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.myc-weekday-col {
  min-width: 0;
  min-height: 300px;
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.myc-weekday-col.myc-today { border-color: var(--primary); background: var(--primary-soft); }
.myc-weekday-col.myc-drop {
  border-color: var(--primary);
  border-style: dashed;
  background: var(--primary-soft);
}
.myc-weekday-head {
  font-size: 11.5px;
  font-weight: 800;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .03em;
  margin-bottom: 2px;
}
.myc-weekday-col.myc-today .myc-weekday-head { color: var(--primary); }

/* ---------- task chips (month + week) ---------- */

.myc-chip {
  display: flex;
  align-items: baseline;
  gap: 5px;
  padding: 3px 7px;
  border-radius: 10px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 11.5px;
  font-weight: 600;
  overflow: hidden;
  cursor: grab;
  user-select: none;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .07);
  touch-action: none;      /* let pointer drag win over page scroll on touch */
}
.myc-chip:active { cursor: grabbing; }
.myc-chip.myc-dragging { opacity: .4; }
.myc-chip-ghost {
  position: fixed;
  z-index: 1200;
  pointer-events: none;    /* never blocks elementFromPoint drop targeting */
  max-width: 220px;
  box-shadow: var(--ring);
  opacity: .92;
}
.myc-chip.myc-done { opacity: .55; text-decoration: line-through; }
.myc-chip.myc-inprogress { background: var(--warning-soft); color: var(--warning); }
/* Chip anatomy: [dot] [time prefix] [body: title + description]. The time
   prefix never wraps; the body column holds the title and, under it, the
   description — both ellipsized. */
.myc-chip .myc-pri-dot {
  flex-shrink: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
}
.myc-chip-when { flex-shrink: 0; white-space: nowrap; }
.myc-chip-body { min-width: 0; overflow: hidden; }
.myc-chip-title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.myc-pri-high { background: var(--danger); }
.myc-pri-medium { background: var(--warning); }
.myc-pri-low { background: var(--text-muted); }

.myc-more { font-size: 10px; color: var(--text-muted); cursor: pointer; }
.myc-more:hover { color: var(--primary); }

/* ---------- day view ---------- */

.myc-dayview {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.myc-dayrow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  cursor: context-menu;
}
.myc-dayrow:last-child { border-bottom: 0; }
.myc-dayrow:hover { background: var(--surface-2); }
.myc-dayrow-title { font-weight: 600; }
.myc-dayrow.myc-done .myc-dayrow-title { text-decoration: line-through; opacity: .6; }
.myc-dayrow .badge { flex: none; }
.myc-day-empty { padding: 24px; text-align: center; color: var(--text-muted); }

/* ---------- year view ---------- */

.myc-year {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  /* 3 rows of 4 mini months share the viewport height. */
  grid-auto-rows: minmax(0, 1fr);
  min-height: calc(100vh - 240px);
}
.myc-ymin {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2);
  padding: 8px;
  display: flex; flex-direction: column;
}
.myc-ymin-title {
  font-size: 12.5px;
  font-weight: 800;
  margin: 0 0 6px;
  cursor: pointer;
  color: var(--text);
}
.myc-ymin-title:hover { color: var(--primary); }
.myc-ymin-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  flex: 1;
  grid-auto-rows: 1fr;   /* day rows stretch to fill the mini month */
}
.myc-ymin-wd { font-size: 8.5px; text-align: center; color: var(--text-muted); font-weight: 700; }
.myc-ymin-day {
  font-size: 9.5px;
  text-align: center;
  padding: 2px 0;
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted);
  cursor: pointer;
  position: relative;
}
.myc-ymin-day:hover { background: var(--primary-soft); color: var(--primary); }
.myc-ymin-day.myc-hastasks { color: var(--text); font-weight: 700; background: var(--primary-soft); }
.myc-ymin-day.myc-today { outline: 1px solid var(--primary); color: var(--primary); font-weight: 800; }
.myc-ymin-blank { cursor: default; }

/* ---------- task modal ---------- */

.myc-task-modal { text-align: left; max-width: 720px; }
.myc-modal-title { margin: 0 0 12px; font-size: 16px; }
.myc-form-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0 12px;
}
/* wide fields (location) take two tracks */
.myc-form-grid .field-span2 { grid-column: span 2; }
/* full-width rows (repeat hint) take all three */
.myc-form-grid .field-span3 { grid-column: span 3; }

@media (max-width: 640px) {
  .myc-task-modal { max-width: 480px; }
  .myc-form-grid { grid-template-columns: 1fr 1fr; }
  .myc-form-grid .field-span3 { grid-column: span 2; }
}
@media (max-width: 420px) {
  .myc-form-grid { grid-template-columns: 1fr; }
  .myc-form-grid .field-span2,
  .myc-form-grid .field-span3 { grid-column: auto; }
}
/* Task modal: the s2 select widgets match the plain inputs exactly —
   same height, padding, font and full grid-cell width (the default s2
   toggle is input-sm: smaller padding, 12.5px font, 200px cap). */
.myc-task-modal .s2 { display: block; width: 100%; }
.myc-task-modal .s2-toggle {
  width: 100%;
  min-width: 0;
  padding: 10px 12px;
  font: inherit;
}

.myc-form-actions { display: flex; gap: 8px; margin-top: 12px; justify-content: flex-end; }
/* Delete sits at the far left of the actions row (Save/Cancel stay right). */
.myc-form-actions .btn-danger { margin-right: auto; }

/* ---------- "move to date" popover ---------- */

.myc-move {
  position: fixed;
  z-index: 1300;
  width: 220px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.myc-move .input { width: 100%; }

/* ---------- context menu ---------- */

.myc-menu {
  position: fixed;
  z-index: 1300;
  min-width: 180px;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 6px 24px rgba(20, 20, 60, 0.16);
}
.myc-menu-item {
  display: block;
  width: 100%;
  border: none;
  background: transparent;
  color: inherit;
  padding: 7px 10px;
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
  border-radius: 6px;
}
.myc-menu-item:hover:not(:disabled) { background: var(--primary-soft); }
.myc-menu-item.myc-menu-danger { color: var(--danger); }
.myc-menu-item.myc-menu-danger:hover { background: var(--danger-soft); }


/* ---------- time grid (day / week views) ---------- */

.myc-tgrid {
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(28, 39, 76, .08);
}
.myc-tgrid-headrow,
.myc-tgrid-alldayrow { display: flex; }
.myc-tgrid-headrow { border-bottom: 1px solid var(--border); }
.myc-tgrid-gutter { flex: 0 0 64px; }
.myc-tgrid-gutter-label {
  padding: 6px 6px 0 0;
  text-align: right;
  font-size: 10px;
  color: var(--text-muted);
}
.myc-tgrid-dayhead {
  flex: 1;
  min-width: 0;
  padding: 8px 4px;
  text-align: center;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .05em;
  border-left: 1px solid var(--border);
}
.myc-tgrid-dnum {
  display: block;
  width: 26px;
  height: 26px;
  line-height: 26px;
  margin: 2px auto 0;
  border-radius: 50%;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  text-transform: none;
  letter-spacing: 0;
}
.myc-tgrid-dayhead.myc-today { color: var(--primary); }
.myc-tgrid-dayhead.myc-today .myc-tgrid-dnum {
  background: var(--primary);
  color: #fff;
  box-shadow: 0 2px 8px rgba(79, 70, 229, .4);
}

/* all-day strip */
.myc-tgrid-alldayrow { border-bottom: 1px solid var(--border); }
.myc-tgrid-allday {
  flex: 1;
  min-width: 0;
  min-height: 30px;
  max-height: 92px;
  overflow-y: auto;
  padding: 3px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  border-left: 1px solid var(--border);
  transition: background .15s ease;
}
.myc-tgrid-allday.myc-drop {
  background: var(--primary-soft);
  outline: 1px dashed var(--primary);
  outline-offset: -1px;
}

/* scrollable hour grid */
.myc-tgrid-scroll {
  max-height: calc(100vh - 260px);
  min-height: 320px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.myc-tgrid-body { display: flex; position: relative; }

.myc-tgrid-hours { flex: 0 0 64px; }   /* wide enough for "12:00 am" + the next-day date marker */
.myc-tgrid-hour { height: 48px; text-align: right; padding-right: 6px; }  /* keep in sync with HOUR_PX in my-calendar.js */
.myc-tgrid-hour span {
  position: relative;
  top: -6px;
  padding: 0 2px;
  background: var(--surface);
  font-size: 10px;
  color: var(--text-muted);
  white-space: normal;   /* the midnight-boundary date marker wraps under the time */
}
.myc-tgrid-hour-end { height: 0; overflow: visible; }

.myc-tgrid-col {
  flex: 1;
  min-width: 0;
  position: relative;
  border-left: 1px solid var(--border);
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 47px,
    var(--border) 47px,
    var(--border) 48px
  );
  touch-action: pan-y;    /* vertical swipe still scrolls the grid on touch */
}
.myc-tgrid-col.myc-today { background-color: var(--primary-soft); }
.myc-tgrid-col.myc-drop {
  outline: 1px dashed var(--primary);
  outline-offset: -1px;
  background-color: var(--primary-soft);
}

/* timed event blocks — Aurora: gradient pills with soft shadows */
.myc-tblock {
  position: absolute;
  z-index: 1;
  display: flex;
  flex-direction: column;
  padding: 3px 7px 9px;
  border-radius: 10px;
  background: linear-gradient(135deg, #4f46e5, #818cf8);
  color: #fff;
  font-size: 11px;
  overflow: hidden;
  cursor: grab;
  user-select: none;
  touch-action: none;     /* pointer drag wins over page scroll, like the chips */
  box-shadow: 0 3px 8px rgba(28, 39, 76, .18);
  transition: transform .12s ease, box-shadow .12s ease;
}
.myc-tblock:hover { transform: translateY(-1px); box-shadow: 0 5px 12px rgba(28, 39, 76, .22); }
.myc-tblock:active { cursor: grabbing; }
.myc-tblock.myc-dragging { opacity: .9; box-shadow: 0 6px 16px rgba(28, 39, 76, .3); z-index: 6; }
.myc-tblock.myc-inprogress { background: linear-gradient(135deg, #d97706, #fbbf24); }
.myc-tblock.myc-done {
  background: var(--surface-2);
  color: var(--text-muted);
  box-shadow: none;
}
.myc-tblock.myc-done .myc-tblock-title { text-decoration: line-through; }
.myc-tblock-time { font-size: 10px; font-weight: 700; white-space: nowrap; opacity: .85; }
.myc-tblock-title {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Description preview under the title (task chips + timed blocks) */
.myc-chip-desc {
  display: block;
  font-size: 10.5px;
  font-weight: 400;
  opacity: .75;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.myc-tblock-desc {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  font-size: 10.5px;
  font-weight: 400;
  opacity: .85;
  overflow: hidden;
  overflow-wrap: break-word;
}
.myc-tblock-resize {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 8px;
  cursor: ns-resize;
  touch-action: none;
}
.myc-tblock-resize::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 2px;
  width: 22px;
  height: 3px;
  margin-left: -11px;
  border-radius: 2px;
  background: #fff;
  opacity: .5;
}
.myc-tblock.myc-done .myc-tblock-resize::after { background: currentColor; }

/* current-time marker across the whole grid (appended to .myc-tgrid-body,
   so it starts after the 52px hour gutter) */
.myc-nowline {
  position: absolute;
  left: 52px;
  right: 0;
  height: 2px;
  background: #ff5a7a;
  z-index: 5;
  pointer-events: none;
}
.myc-nowline::before {
  content: '';
  position: absolute;
  left: -1px;
  top: -4px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ff5a7a;
}

/* drag-to-create selection */
.myc-tgrid-select {
  position: absolute;
  left: 2px;
  right: 2px;
  z-index: 4;
  padding: 2px 5px;
  border: 1px dashed var(--primary);
  border-radius: 6px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  pointer-events: none;
}

/* ---------- task detail popup ---------- */

.myc-detail {
  position: fixed;
  z-index: 1300;
  width: 520px;
  max-width: calc(100vw - 16px);   /* stay on-screen on narrow viewports */
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.myc-detail-title { margin: 0 0 4px; font-size: 14px; }
.myc-detail-title.myc-done { text-decoration: line-through; opacity: .6; }
.myc-detail-when { margin: 0 0 6px; font-size: 12px; color: var(--text-muted); }
.myc-detail-badges { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 8px; }
.myc-detail-desc {
  margin: 0 0 8px;
  font-size: 12px;
  color: var(--text-muted);
  max-height: 90px;
  overflow-y: auto;
  white-space: pre-wrap;
}
.myc-detail-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.myc-detail-delete { color: var(--danger); }

/* ---------- task comments / follow-ups (Pass 33) ---------- */

.myc-comments-title { margin: 10px 0 4px; font-size: 12px; color: var(--text-muted); }
.myc-comments {
  max-height: 160px;
  overflow-y: auto;
  border-top: 1px solid var(--border);
  padding-top: 6px;
  margin-bottom: 8px;
}
.myc-comments-empty { margin: 4px 0; font-size: 12px; color: var(--text-muted); }
.myc-comment { margin-bottom: 8px; }
.myc-comment-meta { font-size: 11px; color: var(--text-muted); }
.myc-comment-body { margin: 1px 0 0; font-size: 13px; white-space: pre-wrap; overflow-wrap: break-word; }
.myc-comment-form { display: flex; gap: 6px; align-items: flex-end; }
.myc-comment-form .input { flex: 1; }
.myc-comment-input {
  resize: none;              /* auto-grow handles sizing (JS scrollHeight) */
  min-height: 34px;
  max-height: 140px;         /* ~6 lines, then scrolls */
  overflow-y: auto;
  line-height: 1.4;
}

/* ---------- category manager modal ---------- */

.myc-catmgr { max-width: 440px; text-align: left; }
.myc-catmgr-list { max-height: 320px; overflow-y: auto; margin: 8px 0; }
.myc-catmgr-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.myc-catmgr-row:last-child { border-bottom: 0; }
.myc-catmgr-dot {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.35);
}
.myc-catmgr-name { flex: 1; min-width: 140px; }
.myc-catmgr-del { color: var(--text-muted); }
.myc-catmgr-del:hover { color: var(--danger); }
.myc-catmgr-palette-wrap { flex-basis: 100%; }
.myc-catmgr-palette { display: flex; gap: 6px; flex-wrap: wrap; padding: 6px 0; }
.myc-catmgr-sw {
  width: 22px;
  height: 22px;
  border: 2px solid transparent;
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
}
.myc-catmgr-sw.on { border-color: var(--text); }
/* The custom-colour swatch: rainbow + "+" so it's obviously "any colour". */
.myc-catmgr-custom {
  background: conic-gradient(#f44336, #ff9800, #ffeb3b, #4caf50, #2196f3, #9c27b0, #f44336);
  color: #fff; font-weight: 800; text-shadow: 0 1px 2px rgba(0,0,0,.5);
}
.myc-catmgr-custom.on { border-color: var(--text); }
.myc-catmgr-colorpick {
  position: absolute; width: 0; height: 0; opacity: 0; pointer-events: none;
}
.myc-catmgr-add { display: flex; gap: 8px; margin-top: 10px; }

/* ---------- "+N more" day popover ---------- */

.myc-daypop {
  position: fixed;
  z-index: 1300;
  width: 240px;
  max-height: 320px;
  overflow-y: auto;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.myc-daypop-title { margin: 0 0 8px; font-size: 13px; }
.myc-daypop-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 6px;
  border-radius: 6px;
  font-size: 12px;
  cursor: pointer;
}
.myc-daypop-row:hover { background: var(--primary-soft); }
.myc-daypop-row.myc-done .myc-daypop-name { text-decoration: line-through; opacity: .6; }
.myc-daypop-time {
  flex: 0 0 42px;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
}
.myc-daypop-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- external calendar events (Google / Outlook) ----------
   Read-only outlined pills — the TaskFlow gradient pills stay untouched.
   Provider glyph: a small circle with G / O via ::before. */
.myc-chip.myc-ext,
.myc-tblock.myc-ext {
  background: transparent;
  border: 1.5px solid;
  box-shadow: none;
  cursor: grab;   /* draggable — the drop writes back to the provider */
}
.myc-tblock.myc-ext { padding: 3px 7px; }   /* no resize handle to clear */
.myc-tblock.myc-ext:hover { transform: none; box-shadow: none; }
.myc-ext-google { border-color: #ea4335; color: #ea4335; }
.myc-ext-outlook { border-color: #0078d4; color: #0078d4; }
.myc-chip.myc-ext::before,
.myc-tblock.myc-ext .myc-tblock-time::before {
  content: 'G';
  display: inline-block;
  width: 12px;
  height: 12px;
  line-height: 12px;
  border-radius: 50%;
  margin-right: 5px;
  text-align: center;
  font-size: 8px;
  font-weight: 800;
  color: #fff;
  vertical-align: 1px;
}
.myc-chip.myc-ext-google::before,
.myc-tblock.myc-ext-google .myc-tblock-time::before { content: 'G'; background: #ea4335; }
.myc-chip.myc-ext-outlook::before,
.myc-tblock.myc-ext-outlook .myc-tblock-time::before { content: 'O'; background: #0078d4; }

/* continuation days of a multi-day event: dimmed, dashed edge reads as
   "carried over" rather than a separate event */
.myc-chip.myc-ext-cont {
  opacity: .65;
  border-style: dashed;
}

/* detail popup extras */
.myc-detail-loc { margin: 0 0 6px; font-size: 12px; color: var(--text-muted); }
.myc-detail-ext { margin: 0 0 8px; font-size: 11px; font-style: italic; color: var(--text-muted); }

/* ⇄ origin marker on task chips/blocks synced to Google/Outlook */
.myc-chip-sync {
  margin-left: 4px;
  font-size: 9px;
  opacity: .65;
}
/* Share direction icons (arrow-out = shared out / arrow-in = shared with
   you): pinned to the chip's right edge (flex auto-margin). */
.myc-chip .myc-chip-share {
  margin-left: auto;
  display: inline-flex;
  opacity: .9;
}
.myc-chip-share svg { width: 13px; height: 13px; display: block; }
/* Timed blocks are a vertical stack — the share icon sits top-right. */
.myc-tblock .myc-chip-share {
  position: absolute;
  top: 3px;
  right: 5px;
  margin-left: 0;
  opacity: .9;
}

/* provider label in the "+N more" day popover */
.myc-daypop-prov {
  flex: 0 0 auto;
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .03em;
}

/* ---------- 3-pane productivity layout (categories · calendar · agenda) -- */

.myc-layout {
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr) 280px;   /* categories panel: 50% wider (240→360) */
  gap: 16px;
  /* Panels stretch to the full viewport height (topbar + content padding
     ≈ 105px) and grow past it when their content is taller. */
  align-items: stretch;
  min-height: calc(100vh - 105px);
  max-width: 100%;            /* never push the page past the screen width */
}
.myc-main { min-width: 0; }   /* let the time grid shrink instead of overflowing */

/* The agenda and categories are always-on side columns only when the content
   area has room. The breakpoint depends on the sidebar width (248px expanded,
   68px collapsed rail), which media queries can't see — so JS tags <html>
   with .myc-narrow (matchMedia in my-calendar.js) and both panels become
   edge fly-outs toggled from the toolbar. */
.myc-cats-toggle,
.myc-agenda-toggle { display: none; }
.myc-agenda-toggle::before { content: "\00AB"; font-weight: 800; }    /* « */
body.myc-agenda-open .myc-agenda-toggle::before { content: "\00BB"; } /* » */
.myc-cats-toggle::before { content: "\00BB"; font-weight: 800; }      /* » */
body.myc-cats-open .myc-cats-toggle::before { content: "\00AB"; }     /* « */

html.myc-narrow .myc-layout { grid-template-columns: minmax(0, 1fr); }
html.myc-narrow .myc-cats-toggle,
html.myc-narrow .myc-agenda-toggle { display: inline-flex; }

/* Fly-outs: parked just past their screen edge, slide in over the calendar.
   visibility is toggled with the transform so a parked panel can never add
   scrollable overflow beyond the screen edge. */
html.myc-narrow .myc-cats,
html.myc-narrow .myc-agenda {
  position: fixed;
  top: 0;
  bottom: 0;
  width: min(320px, 88vw);
  border: 0;
  border-radius: 0;
  box-shadow: var(--shadow-md);
  overflow-y: auto;
  visibility: hidden;
  transition: transform .25s ease, visibility 0s linear .25s;
  z-index: 45;                /* above the sidebar drawer (40), below modals (1000) */
}
html.myc-narrow .myc-cats {
  left: 0;
  border-right: 1px solid var(--border);
  transform: translateX(-105%);
}
html.myc-narrow .myc-agenda {
  right: 0;
  border-left: 1px solid var(--border);
  transform: translateX(105%);
}
html.myc-narrow body.myc-cats-open .myc-cats,
html.myc-narrow body.myc-agenda-open .myc-agenda {
  transform: translateX(0);
  visibility: visible;
  transition-delay: 0s;
}

.myc-panel-title { margin: 0 0 4px; font-size: 14px; font-weight: 800; }

.myc-cats,
.myc-agenda {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 14px;
}

/* ---------- left panel: category pills ---------- */

.myc-cats-hint { margin: 0 0 10px; font-size: 11.5px; color: var(--text-muted); }
.myc-cat-list { display: flex; flex-direction: column; gap: 6px; }
.myc-cat-pill {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 9px;
  border: 1px solid transparent;
  border-radius: 10px;
  background: transparent;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  text-align: left;
  cursor: grab;
  user-select: none;
  touch-action: none;      /* pointer drag wins over page scroll on touch */
  transition: background .12s ease, box-shadow .12s ease, transform .12s ease, border-color .12s ease;
}
.myc-cat-pill:hover {
  background: var(--surface-2);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}
.myc-cat-pill:active { cursor: grabbing; }
.myc-cat-pill.dragging { opacity: .4; }
.myc-cat-pill.myc-cat-active {
  background: var(--primary-soft);
  border-color: var(--primary);
  box-shadow: var(--ring);
}
.myc-cat-ico {
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 8px;
}
.myc-cat-ico svg { width: 15px; height: 15px; }
.myc-cat-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.myc-cat-count {
  flex: 0 0 auto;
  min-width: 20px;
  padding: 1px 7px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-align: center;
}
.myc-cat-pill.myc-cat-active .myc-cat-count {
  background: var(--surface);
  border-color: transparent;
  color: var(--primary);
}
.myc-cats-empty { margin: 4px 0; font-size: 12px; color: var(--text-muted); }
.myc-cats-manage {
  display: inline-block;
  margin-top: 12px;
  font-size: 12.5px;
  font-weight: 600;
  /* it's a <button> now (opens the in-page manager) — strip button chrome */
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--primary);
  font-family: inherit;
}
.myc-cats-manage:hover { text-decoration: underline; }

/* ghost pill following the pointer while dragging a category */
.myc-cat-ghost {
  position: fixed;
  z-index: 1200;
  pointer-events: none;    /* never blocks elementFromPoint drop targeting */
  max-width: 220px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  box-shadow: var(--shadow-md);
  opacity: .92;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- drag-across-days highlight (drag-create) ---------- */

.myc-in-range {
  background-color: var(--primary-soft) !important;
  outline: 1px dashed var(--primary);
  outline-offset: -1px;
  animation: mycRangePulse 1.1s ease-in-out infinite;
}
@keyframes mycRangePulse {
  0%, 100% { outline-color: var(--primary); }
  50% { outline-color: transparent; }
}

/* continuation days of a multi-day task: dimmed, reads as "carried over" */
.myc-chip.myc-chip-cont { opacity: .6; box-shadow: none; }

/* ---------- right panel: today's agenda ---------- */

.myc-agenda-head {
  margin: 14px 0 4px;
  font-size: 11px;
  font-weight: 800;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.myc-agenda-day { margin: 8px 0 2px; font-size: 11px; font-weight: 700; }
.myc-agenda-empty { margin: 2px 0 6px; font-size: 12px; color: var(--text-muted); }

.myc-agenda-bar {
  height: 6px;
  margin: 8px 0 2px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}
.myc-agenda-bar-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--success);
  transition: width .3s ease;
}
.myc-agenda-pct { margin: 2px 0 0; font-size: 11px; color: var(--text-muted); }

.myc-agenda-item {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px;
  border-radius: 8px;
  font-size: 12.5px;
  cursor: pointer;
}
.myc-agenda-item:hover { background: var(--surface-2); }
.myc-agenda-check {
  flex: 0 0 auto;
  margin: 0;
  accent-color: var(--primary);
  cursor: pointer;
}
.myc-agenda-catdot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; }
.myc-agenda-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.myc-agenda-name {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.myc-agenda-name.myc-done { text-decoration: line-through; opacity: .6; }
.myc-agenda-desc {
  font-size: 11.5px; color: var(--text-muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; word-break: break-word;
}
.myc-agenda-time { font-size: 10.5px; color: var(--text-muted); }
.myc-agenda-time.myc-agenda-red { color: var(--danger); font-weight: 700; }

/* ====================== User Analytics (super-analytics.php, Pass 39) ==== */

.ana-filters {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.ana-filters .label { margin: 0; }
.ana-filters select { width: auto; }
.ana-custom { display: inline-flex; align-items: center; gap: 6px; }
.ana-range-note { font-size: 12px; margin-left: auto; }

/* KPI row: always exactly one line (12 across) on wide screens, two even
   lines of six below that — cards grow/shrink to fill every row. */
.ana-kpis {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 18px;
}
.ana-kpi { flex: 1 1 calc(100% / 6 - 10px); min-width: 0; }   /* two full rows of six */
@media (min-width: 1800px) {
  .ana-kpi { flex-basis: 0; }                                    /* one row of twelve */
}
.ana-kpi .card-body { padding: 14px 16px; }
.ana-kpi-label { margin: 0 0 4px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ana-kpi-value { margin: 0; font-size: 24px; font-weight: 800; }
.ana-kpi-sub { margin: 4px 0 0; font-size: 11.5px; color: var(--text-muted); }
@media (max-width: 900px) {
  .ana-kpi .card-body { padding: 10px 12px; }
  .ana-kpi-value { font-size: 18px; }
  .ana-kpi-sub { font-size: 10.5px; }
}

.ana-delta { font-weight: 800; }
.ana-delta.up { color: var(--success, #10b981); }
.ana-delta.down { color: var(--danger); }

.ana-session-stats,
.ana-paid-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
  margin-bottom: 12px;
  text-align: center;
}
.ana-paid-stats { margin: 12px 0 0; }
.ana-session-stats > div,
.ana-paid-stats > div { display: flex; flex-direction: column; gap: 2px; font-size: 11.5px; }
.ana-big { font-size: 18px; font-weight: 800; }

.ana-heat th, .ana-heat td { text-align: center; }
.ana-heat th:first-child, .ana-heat td:first-child { text-align: left; }
.ana-heat-cell { font-size: 12px; font-weight: 700; white-space: nowrap; }
.ana-heat-na { color: var(--text-muted); }

.ana-cohort-toggle { margin-left: auto; display: inline-flex; gap: 4px; }
.ana-cohort-toggle .myc-pill { text-decoration: none; }

@media (max-width: 640px) {
  .ana-range-note { margin-left: 0; width: 100%; }
}

/* Calendar connection sync errors (Pass 40) — settings page warning. */
.cal-sync-error {
  padding: 8px 10px;
  border: 1px solid var(--danger);
  border-radius: var(--radius-sm);
  background: var(--danger-soft);
  color: var(--danger);
  font-size: 12.5px;
}

/* ==================== Pricing page (plans.php, redesigned) ============== */

.pricing {
  position: relative;
  max-width: 1240px;
  margin: 8px auto 0;
  padding: 10px 8px 30px;
  text-align: center;
}
.pricing-eyebrow {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--primary);
}
.pricing-title {
  margin: 0;
  font-size: clamp(28px, 4vw, 44px);
  font-weight: 800;
  letter-spacing: -.02em;
}
.pricing-sub {
  margin: 10px auto 22px;
  max-width: 560px;
  color: var(--text-muted);
  font-size: 15px;
}

/* Faint handwritten-style captions on the sides, like the design mock. */
.pricing-side {
  position: absolute;
  top: 60px;
  font-family: "Segoe Script", "Comic Sans MS", cursive;
  font-size: 13px;
  line-height: 1.5;
  color: var(--primary);
  opacity: .45;
  pointer-events: none;
}
.pricing-side-left  { left: -6px; transform: rotate(-8deg); text-align: left; }
.pricing-side-right { right: -6px; transform: rotate(8deg); text-align: right; }
@media (max-width: 1300px) { .pricing-side { display: none; } }

/* Monthly/annual switch */
.pricing-toggle {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 26px;
}
.pricing-cycle { font-size: 14px; font-weight: 600; color: var(--text-muted); transition: color .15s ease; }
.pricing-cycle.is-on { color: var(--text); font-weight: 800; }
.pricing-switch {
  position: relative;
  width: 52px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--primary);
  cursor: pointer;
  transition: background .15s ease;
}
.pricing-knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
  transition: left .18s ease;
}
.pricing-switch.is-annual .pricing-knob { left: 27px; }

/* Card grid */
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  text-align: left;
  align-items: stretch;
}

.price-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: var(--shadow-sm);
  padding: 22px 22px 18px;
  transition: transform .15s ease, box-shadow .15s ease;
}
.price-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

.price-card.is-featured {
  background: linear-gradient(160deg, var(--primary), #6d5ef0);
  border-color: var(--primary);
  color: #fff;
  box-shadow: 0 14px 34px rgba(79, 70, 229, .35);
}
.price-card.is-featured .price-tag,
.price-card.is-featured .price-note { color: rgba(255,255,255,.75); }

.price-card-top {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}
.price-ico {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--primary-soft);
  color: var(--primary);
  flex: none;
}
.price-ico svg { width: 20px; height: 20px; }
.price-card.is-featured .price-ico { background: rgba(255,255,255,.18); color: #fff; }
.price-name { margin: 0; font-size: 19px; font-weight: 800; }
.price-badge {
  margin-left: auto;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.4);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.price-tag { margin: 0 0 12px; font-size: 13px; color: var(--text-muted); min-height: 2.6em; }

.price-amount {
  margin: 0 0 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -.02em;
}
.price-card.is-featured .price-amount { border-bottom-color: rgba(255,255,255,.25); }
.price-cur { font-size: 17px; }
.price-per { font-size: 14px; font-weight: 600; color: var(--text-muted); }
.price-card.is-featured .price-per { color: rgba(255,255,255,.75); }
.price-note { font-size: 15px; font-weight: 600; color: var(--text-muted); }

.price-feats {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
  flex: 1;
}
.price-feats li {
  position: relative;
  padding-left: 30px;
  font-size: 13.5px;
  font-weight: 600;
}
.price-feats li::before {
  content: "\2713";   /* ✓ */
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 19px;
  height: 19px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 800;
  background: var(--primary-soft);
  color: var(--primary);
}
.price-card.is-featured .price-feats li::before { background: rgba(255,255,255,.2); color: #fff; }

.price-cta { margin-top: auto; }

/* Widescreens: .pricing's 1240px cap leaves the four cards floating in a
   narrow centered strip (the rest of the app uses the full window width).
   Lift the cap in steps and let the cards and type grow with the viewport. */
@media (min-width: 1600px) {
  .pricing { max-width: 1520px; margin-top: 4vh; padding-left: 24px; padding-right: 24px; }
  .pricing-grid { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; }
  .price-card { padding: 28px 28px 24px; }
  .pricing-side-left  { left: 8px; }
  .pricing-side-right { right: 8px; }
}
@media (min-width: 2400px) {
  .pricing { max-width: 2000px; margin-top: 7vh; }
  .pricing-title { font-size: 56px; }
  .pricing-sub { max-width: 680px; font-size: 17px; }
  .pricing-grid { grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: 32px; }
  .price-card { padding: 36px 36px 30px; border-radius: 22px; }
  .price-ico { width: 48px; height: 48px; border-radius: 14px; }
  .price-ico svg { width: 24px; height: 24px; }
  .price-name { font-size: 22px; }
  .price-tag { font-size: 14.5px; }
  .price-amount { font-size: 38px; }
  .price-cur { font-size: 20px; }
  .price-per { font-size: 16px; }
  .price-feats { gap: 12px; }
  .price-feats li { font-size: 15.5px; padding-left: 34px; }
  .price-feats li::before { width: 22px; height: 22px; font-size: 12.5px; }
  .price-cta { font-size: 15px; padding: 12px 18px; }
}

/* ==================== Admin next-payment banner (admin.php) ============= */

.next-payment {
  display: flex;
  align-items: stretch;      /* all blocks share the banner's height … */
  gap: 30px;
  flex-wrap: wrap;
  margin-bottom: 18px;
  padding: 26px 30px;
  border-radius: 18px;
  background: linear-gradient(160deg, var(--primary), #6d5ef0);
  color: #fff;
  box-shadow: 0 14px 34px rgba(79, 70, 229, .35);
}
/* … and each block is a column: label on top, value in the middle, note or
   button pinned to the bottom — so all three rows line up across blocks. */
.next-payment .np-block { display: flex; flex-direction: column; }
.next-payment .np-block + .np-block {
  border-left: 1px solid rgba(255,255,255,.25);
  padding-left: 30px;
}
.next-payment .np-label {
  margin: 0 0 6px;
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .18em;
  text-transform: uppercase;
  opacity: .8;
}
/* The middle value — one size across amount, date and plan name. */
.next-payment .np-amount,
.next-payment .np-date,
.next-payment .np-plan-name {
  margin: 0;
  font-size: 40px;
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.1;
}
.next-payment .np-note { margin: auto 0 0; padding-top: 6px; font-size: 13px; font-weight: 600; opacity: .85; }
/* Pushes the plan + price blocks to the right edge of the banner. */
.next-payment .np-plan { margin-left: auto; min-width: 220px; }
.next-payment .np-plan-name { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.next-payment .np-plan form { margin: auto 0 0; padding-top: 10px; }
/* Badges and the ghost button sit on the purple gradient here. */
.next-payment .badge {
  background: rgba(255,255,255,.16);
  border-color: rgba(255,255,255,.4);
  color: #fff;
  font-size: 13px;
  padding: 4px 12px;
}
.next-payment .btn-ghost { border-color: rgba(255,255,255,.5); color: #fff; }
.next-payment .btn-ghost:hover { background: rgba(255,255,255,.12); }
@media (max-width: 640px) {
  .next-payment { gap: 16px; padding: 20px; }
  .next-payment .np-block + .np-block { border-left: 0; padding-left: 0; }
  .next-payment .np-amount,
  .next-payment .np-date,
  .next-payment .np-plan-name { font-size: 30px; }
}

/* ==================== Team invite panel (admin.php) ===================== */

.team-invite {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 420px));
  gap: 16px 32px;
  margin-top: 14px;
  padding: 18px 20px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.team-invite form { margin: 0; }
.team-invite .label { margin-bottom: 8px; color: var(--text-muted); font-size: 12.5px; text-transform: uppercase; letter-spacing: .06em; }
.team-invite-row { display: flex; gap: 8px; align-items: stretch; }
/* Native <select> sizes itself taller than a text input — pin both to one
   explicit height so the two invite rows match exactly. */
.team-invite-row .input { flex: 1; min-width: 0; height: 41px; }
.team-invite-row .btn { flex: none; white-space: nowrap; }

/* ------------------------- Settings overview (redesign) ------------------ */

.set-wrap { width: 100%; padding-bottom: 24px; }   /* full content width, like the dashboard */

.set-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; margin: 4px 0 18px;
}
.set-title { margin: 0; font-size: 26px; font-weight: 800; }
.set-sub { margin: 4px 0 0; font-size: 13.5px; color: var(--text-muted); }
.set-search {
  display: flex; align-items: center; gap: 8px;
  min-width: 260px; padding: 8px 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  color: var(--text-muted);
}
.set-search input {
  flex: 1; border: 0; outline: none; background: none;
  color: var(--text); font-size: 14px;
}

.set-notice {
  margin-bottom: 14px; padding: 10px 14px; font-size: 13px;
  background: color-mix(in srgb, var(--accent, #4f7cff) 10%, var(--surface));
  border: 1px solid var(--border); border-radius: 10px; color: var(--text-muted);
}

/* Banner */
.set-banner {
  display: flex; align-items: center; gap: 26px; flex-wrap: wrap;
  padding: 18px 22px; margin-bottom: 18px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
}
.set-banner-id { display: flex; align-items: center; gap: 14px; min-width: 0; }
.set-banner-id .set-avatar {
  display: flex; align-items: center; justify-content: center;   /* beats the bare span rule below */
  width: 56px; height: 56px; border-radius: 50%; flex-shrink: 0;
  background: var(--accent, #4f7cff); color: #fff; font-size: 24px; font-weight: 800;
  line-height: 1;
}
.set-banner-id strong { display: block; font-size: 17px; }
.set-banner-id div > span { display: block; font-size: 13px; color: var(--text-muted); }
.set-pill {
  padding: 8px 16px; border-radius: 10px; white-space: nowrap;
  background: var(--accent, #4f7cff); color: #fff; font-size: 13px; font-weight: 700;
}
.set-banner-status { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 220px; }
.set-banner-status strong { display: block; font-size: 14px; }
.set-banner-status span { display: block; font-size: 12.5px; color: var(--text-muted); }
.set-good-text { color: var(--success, #22c55e); }
.set-warn-text { color: #f59e0b; }
.set-dot {
  width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0;
  background: var(--success, #22c55e);
}
.set-dot-warn { background: #f59e0b; }
.set-dot-dim { background: var(--text-muted); opacity: .45; }
.set-banner-deco {
  margin-left: auto; font-size: 12px; line-height: 1.25; text-align: right;
  color: var(--text-muted); opacity: .55;
}

/* Card grid */
.set-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 1020px) { .set-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 680px)  { .set-grid { grid-template-columns: 1fr; } }

.set-card {
  display: flex; flex-direction: column; gap: 14px;
  padding: 18px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  transition: border-color .15s ease, box-shadow .15s ease, transform .12s ease;
}
.set-card:hover { border-color: var(--accent, #4f7cff); transform: translateY(-1px); box-shadow: var(--shadow-md); }
.set-card-hi { border-color: var(--accent, #4f7cff); box-shadow: 0 0 0 1px var(--accent, #4f7cff), 0 0 18px color-mix(in srgb, var(--accent, #4f7cff) 25%, transparent); }

.set-card-head { display: flex; align-items: flex-start; gap: 12px; }
.set-tile {
  width: 44px; height: 44px; border-radius: 12px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; color: #fff;
}
.set-tile svg { width: 22px; height: 22px; }
.tile-indigo { background: #6366f1; }
.tile-red    { background: #ef4459; }
.tile-purple { background: #8b5cf6; }
.tile-green  { background: #22a35e; }
.tile-amber  { background: #e8960c; }
.tile-teal   { background: #14a394; }
.tile-blue   { background: #3b82f6; }
.set-card-titles { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.set-card-titles strong { font-size: 15.5px; }
.set-card-titles span { font-size: 12.5px; color: var(--text-muted); }
.set-chev { font-size: 22px; line-height: 1; color: var(--text-muted); }

.set-rows { display: flex; flex-direction: column; gap: 9px; flex: 1; }
.set-row {
  display: flex; align-items: center; gap: 9px;
  font-size: 13px; color: var(--text-muted);
}
.set-row svg { flex-shrink: 0; opacity: .75; }
.set-row > span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

.set-btn {
  align-self: flex-start; margin-top: 2px;
  padding: 7px 16px; border-radius: 8px; font-size: 13px; font-weight: 700;
  background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text);
}
.set-card:hover .set-btn { background: color-mix(in srgb, var(--text) 14%, transparent); }

/* Category chips */
.set-cats { display: flex; flex-wrap: wrap; gap: 8px; flex: 1; align-content: flex-start; }
.set-cat {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 12px; border-radius: 999px; font-size: 12.5px;
  background: color-mix(in srgb, var(--text) 7%, transparent);
}
.set-cat-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }

/* Appearance mini preview */
.set-thumb {
  display: flex; gap: 4px; width: 150px; height: 74px;
  padding: 5px; border-radius: 8px;
  background: #0e1420; border: 1px solid var(--border);
  transition: background .2s ease;
}
.set-thumb .st-side { width: 22px; border-radius: 4px; background: #1b2740; transition: background .2s ease; }
.set-thumb .st-main { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.set-thumb .st-main b { display: block; height: 9px; border-radius: 3px; background: #26334f; transition: background .2s ease; }
.set-thumb .st-main b:first-child { width: 60%; background: var(--accent, #4f7cff); }
.set-thumb .st-main em { display: block; height: 16px; border-radius: 4px; background: #1b2740; transition: background .2s ease; }
/* The preview mirrors the live theme toggle. */
[data-theme="light"] .set-thumb { background: #eef1f7; }
[data-theme="light"] .set-thumb .st-side { background: #d7deec; }
[data-theme="light"] .set-thumb .st-main b { background: #c6d0e2; }
[data-theme="light"] .set-thumb .st-main b:first-child { background: var(--accent, #4f7cff); }
[data-theme="light"] .set-thumb .st-main em { background: #d7deec; }

/* Calendar provider rows */
.set-cal-row { gap: 10px; }
.set-cal-logo {
  width: 22px; height: 22px; border-radius: 6px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800; background: #fff;
}
.set-cal-logo.g { color: #4285f4; border: 1px solid #dadce0; }
.set-cal-logo.o { color: #0078d4; background: #e7f2fb; }
.set-cal-name { flex: 1; }
.set-cal-ok, .set-cal-no, .set-cal-warn {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; white-space: nowrap;
}
.set-cal-ok { color: var(--success, #22c55e); }
.set-cal-no { color: var(--text-muted); }
.set-cal-warn { color: #f59e0b; }

/* Wide session card */
.set-card-wide {
  grid-column: 1 / -1;
  flex-direction: row; align-items: center; gap: 26px; flex-wrap: wrap;
}
.set-wide-left { display: flex; align-items: center; gap: 12px; flex: 1.2; min-width: 230px; }
.set-wide-cell {
  display: flex; align-items: center; gap: 10px; flex: 1; min-width: 190px;
  color: var(--text-muted);
}
.set-wide-cell strong { display: block; font-size: 13px; color: var(--text); }
.set-wide-cell span { display: block; font-size: 12.5px; color: var(--text-muted); }

/* Modal close button */
.set-modal .modal { position: relative; }
.set-modal-x {
  position: absolute; top: 10px; right: 10px;
  width: 30px; height: 30px; font-size: 17px; line-height: 1;
}

/* Search filtering */
.set-card.set-hidden { display: none; }

/* ------------------------------ Meetings (Pass 71) ----------------------- */

.mtg-wrap { max-width: 860px; margin: 0 auto; padding-bottom: 24px; }
.mtg-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; margin: 4px 0 18px;
}
.mtg-title { margin: 0; font-size: 24px; font-weight: 800; }
.mtg-sub { margin: 4px 0 0; font-size: 13px; color: var(--text-muted); }
.mtg-sec {
  margin: 18px 0 8px; font-size: 12px; font-weight: 800;
  color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em;
}
.mtg-list { display: flex; flex-direction: column; gap: 8px; }
.mtg-row {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
}
.mtg-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mtg-row-title { font-size: 14.5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.mtg-row-meta { font-size: 12.5px; color: var(--text-muted); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* Meetings participant pager */
.mtg-pager {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 4px 2px; margin-top: 4px;
  border-top: 1px solid var(--border);
}
.mtg-pager-info { font-size: 12px; color: var(--text-muted); }

/* ------------------------- In-call polls (Pass 72) ------------------------ */

.gcall-poll-panel {
  position: absolute; z-index: 60;   /* top/right set by panelUnder() */
  width: min(300px, calc(100vw - 28px));
  max-height: calc(100vh - 140px); overflow-y: auto;
  display: flex; flex-direction: column; gap: 8px;
  padding: 14px; border-radius: 12px;
  background: rgba(16, 22, 35, .96);
  border: 1px solid rgba(255,255,255,.1);
  box-shadow: 0 10px 30px rgba(0,0,0,.5);
  color: #fff;
}
.gcall-poll-panel[hidden] { display: none; }
.gcall-poll-title { font-size: 14px; }
.gcall-poll-sub { font-size: 11.5px; color: rgba(255,255,255,.55); }
.gcall-poll-panel .input {
  padding: 7px 10px; font-size: 13px;
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.14);
  color: #fff;
}
.gcall-poll-actions { display: flex; gap: 8px; }
.gcall-poll-opt {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 8px 10px;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.12); border-radius: 9px;
  color: #fff; font-size: 13px; text-align: left; cursor: pointer;
}
.gcall-poll-opt:disabled { cursor: default; }
.gcall-poll-opt.is-muted { opacity: .55; cursor: default; }
.gcall-poll-opt .gcall-poll-fill {
  position: absolute; inset: 0 auto 0 0;
  background: color-mix(in srgb, var(--accent, #4f7cff) 28%, transparent);
  transition: width .3s ease;
}
.gcall-poll-opt.voted { border-color: var(--accent, #4f7cff); }
.gcall-poll-label { position: relative; flex: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.gcall-poll-count { position: relative; font-size: 11.5px; color: rgba(255,255,255,.65); white-space: nowrap; }

/* ------------------------- In-call reactions (Pass 73) -------------------- */

.gcall-reactbar {
  position: absolute; z-index: 60;   /* top/right set by panelUnder() */
  display: flex; flex-wrap: wrap; justify-content: flex-end;
  gap: 4px; padding: 6px 10px;
  max-width: min(620px, calc(100vw - 28px));
  background: rgba(16, 22, 35, .96);
  border: 1px solid rgba(255,255,255,.1); border-radius: 999px;
  box-shadow: 0 10px 30px rgba(0,0,0,.5);
  transform-origin: top right;
  animation: gcall-reactpop .18s cubic-bezier(.2, 1.4, .4, 1);
}
.gcall-reactbar[hidden] { display: none; }
@keyframes gcall-reactpop {
  from { transform: scale(.6); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
.gcall-reactbar-item {
  border: 0; background: none; font-size: 22px; padding: 4px 6px;
  cursor: pointer; border-radius: 50%; line-height: 1;
  transition: transform .12s cubic-bezier(.2, 1.6, .4, 1);
}
.gcall-reactbar-item:hover { transform: scale(1.35); }
.gcall-reactbar-item:active { transform: scale(.8); }
/* The pop-in runs on the GLYPH so the button's hit area never shrinks. */
.gcall-reactbar-emoji { display: inline-block; animation: gcall-reactitem .3s cubic-bezier(.2, 1.6, .4, 1) backwards; }
.gcall-reactbar-item:nth-child(1) .gcall-reactbar-emoji { animation-delay: 15ms; }
.gcall-reactbar-item:nth-child(2) .gcall-reactbar-emoji { animation-delay: 45ms; }
.gcall-reactbar-item:nth-child(3) .gcall-reactbar-emoji { animation-delay: 75ms; }
.gcall-reactbar-item:nth-child(4) .gcall-reactbar-emoji { animation-delay: 105ms; }
.gcall-reactbar-item:nth-child(5) .gcall-reactbar-emoji { animation-delay: 135ms; }
.gcall-reactbar-item:nth-child(6) .gcall-reactbar-emoji { animation-delay: 165ms; }
.gcall-reactbar-item:nth-child(7) .gcall-reactbar-emoji { animation-delay: 195ms; }
.gcall-reactbar-item:nth-child(8) .gcall-reactbar-emoji { animation-delay: 225ms; }
@keyframes gcall-reactitem {
  from { transform: scale(0) rotate(-25deg); }
  to   { transform: scale(1) rotate(0); }
}
.gcall-reactbar-item:hover { transform: scale(1.35); }
.gcall-reactbar-item:active { transform: scale(.8); }

.gcall-bursts {
  position: absolute; inset: 0; z-index: 70;
  pointer-events: none; overflow: hidden;
}
.gcall-burst {
  position: absolute; bottom: 76px; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  animation: gcall-rise 3.2s ease-out forwards;
}
.gcall-burst-emoji { filter: drop-shadow(0 3px 6px rgba(0,0,0,.45)); }
span.gcall-burst-emoji { font-size: 56px; }       /* text fallback */
img.gcall-burst-emoji { width: 72px; height: 72px; }  /* animated Noto GIF */
.gcall-burst-name {
  font-size: 11px; font-weight: 700; color: #fff;
  padding: 1px 8px; border-radius: 999px; background: rgba(0,0,0,.55);
}
@keyframes gcall-rise {
  0%   { transform: translate(-50%, 0); opacity: 0; }
  10%  { opacity: 1; }
  70%  { opacity: 1; }
  100% { transform: translate(-50%, -55vh); opacity: 0; }
}

/* Vote chips on call tiles (Pass 72 follow-up): who answered the live poll. */
.gcall-vote {
  position: absolute; top: 8px; left: 8px; z-index: 3;
  max-width: 70%; padding: 2px 10px; border-radius: 999px;
  background: rgba(21, 101, 52, .85); color: #fff;   /* green: responded */
  font-size: 11.5px; font-weight: 700;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.gcall-vote.waiting { background: rgba(0, 0, 0, .5); color: rgba(255,255,255,.75); }
.gcall-vote[hidden] { display: none; }

/* Add-people panel in group calls */
.gcall-add-panel {
  position: absolute; z-index: 60;   /* top/right set by panelUnder() */
  width: min(300px, calc(100vw - 28px));
  max-height: calc(100vh - 140px); overflow-y: auto;
  display: flex; flex-direction: column; gap: 8px;
  padding: 14px; border-radius: 12px;
  background: rgba(16, 22, 35, .96);
  border: 1px solid rgba(255,255,255,.1);
  box-shadow: 0 10px 30px rgba(0,0,0,.5);
  color: #fff;
}
.gcall-add-panel[hidden] { display: none; }
.gcall-add-panel .input {
  padding: 7px 10px; font-size: 13px;
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.14);
  color: #fff;
}
.gcall-add-list { display: flex; flex-direction: column; gap: 4px; }
.gcall-add-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 6px 8px; border-radius: 8px;
}
.gcall-add-row:hover { background: rgba(255,255,255,.06); }
.gcall-add-name { font-size: 13px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* Poll stack: multiple concurrent polls, bottom-left of the call. */
.gcall-polls {
  position: absolute; left: 14px; bottom: 14px; z-index: 60;
  display: flex; flex-direction: column; gap: 10px;
  max-height: calc(100vh - 140px); overflow-y: auto;
  width: min(300px, calc(100vw - 28px));
}
.gcall-polls[hidden] { display: none; }
/* Cards in the stack are plain block children (the panel style without the
   absolute positioning). */
.gcall-polls .gcall-poll-panel {
  position: static; width: auto; max-height: none; overflow: visible;
}

/* New-poll form: space the fields evenly. */
.gcall-poll-form { display: flex; flex-direction: column; gap: 8px; }
.gcall-poll-form .btn { align-self: flex-start; }

/* Poll picture (Pass 75): preview in the form, image on the card. */
.gcall-poll-imgprev { position: relative; align-self: flex-start; max-width: 100%; }
.gcall-poll-imgprev[hidden] { display: none; }
.gcall-poll-imgprev img {
  display: block; max-width: 100%; max-height: 120px; border-radius: 8px;
  border: 1px solid rgba(255,255,255,.14);
}
.gcall-poll-imgrm {
  position: absolute; top: -7px; right: -7px;
  width: 20px; height: 20px; border-radius: 50%; border: 0;
  background: rgba(220, 60, 60, .95); color: #fff;
  font-size: 13px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.gcall-poll-img {
  display: block; max-width: 100%; max-height: 180px; border-radius: 8px;
  border: 1px solid rgba(255,255,255,.14); cursor: zoom-in;
}

/* Poll options: clicks always land on the button, not inner spans. */
.gcall-poll-opt span { pointer-events: none; }

/* Poll responses list (caller sees who answered and what they picked). */
.gcall-voter-list {
  display: flex; flex-direction: column; gap: 2px;
  padding-top: 6px; margin-top: 2px;
  border-top: 1px solid rgba(255,255,255,.1);
}
.gcall-voter-list[hidden] { display: none; }
.gcall-voter-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 12.5px; padding: 3px 2px;
}
.gcall-voter-name { font-weight: 700; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.gcall-voter-answer { color: rgba(255,255,255,.7); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* Group call recording badge. */
.gcall-rec-badge {
  color: #ff5a5a; font-size: 13px; font-weight: 800;
  animation: call-pulse 1.4s infinite;
}
.gcall-rec-badge[hidden] { display: none; }

/* ==========================================================================
   Module theme enforcement (Pass 76/77)
   Modules render inline inside .module-card, so app tokens reach them — but
   some modules pin their own palette (dark-styled widgets stay dark on the
   light theme, light-styled ones stay light on dark). These overrides remap
   each pinned palette to the ACTIVE theme. Accent colours (gold, teal, …)
   are the module's identity and are kept; only surfaces, text and lines move.

   COLOURED-THEME READY: every value here is a --mt-* alias that tracks the
   active theme's tokens (see :root / [data-theme="dark"]) — a new coloured
   theme only redefines the app tokens and these overrides follow.

   Specificity note: module scoped CSS loads AFTER app.css, so every selector
   here carries [data-theme] + .module-<slug> + the module's own host class —
   one notch above the module's scoped rule — which is what makes the remap
   win. Custom properties that share a name with an app token (--text, --bg)
   read the alias instead (var(--mt-text)): --text: var(--text) would be a
   self-reference cycle.
   ========================================================================== */

/* --- Always-dark modules, forced onto the LIGHT theme -------------------- */

[data-theme="light"] .module-bullion-btc-tracker .mbt-root {
  --bg: var(--mt-surface);
  --panel: var(--mt-surface-2);
  --panel-2: var(--mt-surface);
  --line: var(--mt-border);
  --text: var(--mt-text);
  --muted: var(--mt-muted);
  --faint: var(--mt-faint);
  /* The shell paints a hardcoded dark gradient over the vars — replace it. */
  background: var(--mt-surface);
  border-color: var(--mt-border);
  box-shadow: 0 1px 2px var(--mt-shadow);
  scrollbar-color: var(--mt-faint) var(--mt-bg);
}
[data-theme="light"] .module-bullion-btc-tracker .mbt-root .mbt-asset,
[data-theme="light"] .module-bullion-btc-tracker .mbt-root .mbt-select-wrap select,
[data-theme="light"] .module-bullion-btc-tracker .mbt-root .mbt-refresh,
[data-theme="light"] .module-bullion-btc-tracker .mbt-root .mbt-weight {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="light"] .module-bullion-btc-tracker .mbt-root .mbt-switch,
[data-theme="light"] .module-bullion-btc-tracker .mbt-root .mbt-ranges {
  background: var(--mt-bg);
}
[data-theme="light"] .module-bullion-btc-tracker .mbt-root .mbt-chart-loading {
  background: rgba(249, 250, 251, .8);
}
[data-theme="light"] .module-bullion-btc-tracker .mbt-root::-webkit-scrollbar-track,
[data-theme="light"] .module-bullion-btc-tracker .mbt-root::-webkit-scrollbar-corner {
  background: var(--mt-bg);
}

[data-theme="light"] .module-prayer-times {
  --pt-bg: var(--mt-surface);
  --pt-bg2: var(--mt-surface-2);
  --pt-surface: var(--mt-overlay);
  --pt-surface2: var(--mt-overlay-2);
  --pt-border: var(--mt-border);
  --pt-text: var(--mt-text);
  --pt-muted: var(--mt-muted);
  --pt-shadow: 0 18px 44px var(--mt-shadow);
}
[data-theme="light"] .module-prayer-times .pt-card {
  background: var(--mt-surface);
  border-color: var(--mt-border);
}
[data-theme="light"] .module-prayer-times .pt-nextPanel,
[data-theme="light"] .module-prayer-times .pt-qiblaPanel,
[data-theme="light"] .module-prayer-times .pt-modal {
  background: var(--mt-surface-2);
}
[data-theme="light"] .module-prayer-times .pt-modal {
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="light"] .module-prayer-times .pt-modal input,
[data-theme="light"] .module-prayer-times .pt-modal select {
  background: var(--mt-surface);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="light"] .module-prayer-times .pt-settingsBtn,
[data-theme="light"] .module-prayer-times .pt-close,
[data-theme="light"] .module-prayer-times .pt-secondary,
[data-theme="light"] .module-prayer-times .pt-result,
[data-theme="light"] .module-prayer-times .pt-glowBar {
  background: var(--mt-overlay);
}
[data-theme="light"] .module-prayer-times .pt-prayer.active .pt-prayerName {
  color: #14532d;
}

[data-theme="light"] .module-sydney-prayer-times {
  --pt-bg: var(--mt-surface);
  --pt-bg2: var(--mt-surface-2);
  --pt-bg3: var(--mt-surface-3);
  --pt-panel: var(--mt-overlay);
  --pt-panel2: var(--mt-overlay-2);
  --pt-border: var(--mt-border);
  --pt-text: var(--mt-text);
  --pt-muted: var(--mt-muted);
  --pt-shadow: 0 18px 50px var(--mt-shadow);
}
[data-theme="light"] .module-sydney-prayer-times .pt-card {
  border-color: var(--mt-border);
}
[data-theme="light"] .module-sydney-prayer-times .pt-nextPanel,
[data-theme="light"] .module-sydney-prayer-times .pt-modal {
  background: var(--mt-surface-2);
}
[data-theme="light"] .module-sydney-prayer-times .pt-modal {
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="light"] .module-sydney-prayer-times .pt-locationPill,
[data-theme="light"] .module-sydney-prayer-times .pt-settingsBtn,
[data-theme="light"] .module-sydney-prayer-times .pt-close,
[data-theme="light"] .module-sydney-prayer-times .pt-secondary,
[data-theme="light"] .module-sydney-prayer-times .pt-result,
[data-theme="light"] .module-sydney-prayer-times .pt-progress,
[data-theme="light"] .module-sydney-prayer-times .pt-modal input,
[data-theme="light"] .module-sydney-prayer-times .pt-modal select {
  background: var(--mt-overlay);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="light"] .module-sydney-prayer-times .pt-modal select option {
  background: var(--mt-surface);
  color: var(--mt-text);
}
[data-theme="light"] .module-sydney-prayer-times .pt-countdown,
[data-theme="light"] .module-sydney-prayer-times .pt-field label {
  color: var(--mt-muted);
}
[data-theme="light"] .module-sydney-prayer-times .pt-prayer.active .pt-prayerTime {
  color: var(--mt-text);
}

[data-theme="light"] .module-private-jet-explorer .pje-shell {
  --pje-bg: var(--mt-surface);
  --pje-panel: var(--mt-surface-2);
  --pje-panel-2: var(--mt-surface-3);
  --pje-panel-3: var(--mt-surface-3);
  --pje-line: var(--mt-border);
  --pje-line-strong: var(--mt-border-strong);
  --pje-text: var(--mt-text);
  --pje-muted: var(--mt-muted);
  background: var(--mt-surface);
}
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-topbar {
  background: rgba(255, 255, 255, .6);
}
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-filter-panel,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-map-panel,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-selected-panel,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-aircraft-card,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-cabin-interior-card {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
}
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-aircraft-card h4,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-legend-title,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-selected-empty strong,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-field output,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-check {
  color: var(--mt-text);
}
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-legend-item,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-card-meta {
  color: var(--mt-muted);
}
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-departure-wrap select,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-sort-wrap select {
  background: var(--mt-surface-2);
  color: var(--mt-text);
}
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-spec-item,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-cost-card,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-selected-item,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-btn-ghost,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-icon-btn,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-tabs,
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-visual-legend-item {
  background: var(--mt-overlay);
}
[data-theme="light"] .module-private-jet-explorer .pje-shell .pje-modal-card {
  background: var(--mt-surface);
  border-color: var(--mt-border);
}

[data-theme="light"] .module-streamline-lead-tracker .slt-root {
  --line: var(--mt-border);
  background: var(--mt-surface);
  border-color: var(--mt-border);
  scrollbar-color: var(--mt-faint) var(--mt-bg);
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-kpis article,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-panel,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-empty {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-dialog {
  background: var(--mt-surface);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-search,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-filters select,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-stage-select,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-priority-select,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-money {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-search input,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-field input,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-field select,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-field textarea {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-table th {
  background: var(--mt-bg);
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-table td,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-contact strong,
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-product-cell strong {
  color: var(--mt-text-2);
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-lead-name strong {
  color: var(--mt-text);
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root .slt-value {
  color: var(--mt-text) !important;
}
[data-theme="light"] .module-streamline-lead-tracker .slt-root::-webkit-scrollbar-track,
[data-theme="light"] .module-streamline-lead-tracker .slt-root::-webkit-scrollbar-corner {
  background: var(--mt-bg);
}

[data-theme="light"] .module-streamline-product-showroom .ssr-root {
  --bg: var(--mt-surface);
  --panel: var(--mt-surface-2);
  --line: var(--mt-border);
  --text: var(--mt-text);
  --muted: var(--mt-muted);
  --faint: var(--mt-faint);
  background: var(--mt-surface);
  border-color: var(--mt-border);
}
[data-theme="light"] .module-streamline-product-showroom .ssr-root .ssr-feature,
[data-theme="light"] .module-streamline-product-showroom .ssr-root .ssr-side,
[data-theme="light"] .module-streamline-product-showroom .ssr-root .ssr-product {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
}
[data-theme="light"] .module-streamline-product-showroom .ssr-root .ssr-thumb,
[data-theme="light"] .module-streamline-product-showroom .ssr-root .ssr-feature-media {
  background: var(--mt-surface-3);
}
[data-theme="light"] .module-streamline-product-showroom .ssr-root .ssr-specs span,
[data-theme="light"] .module-streamline-product-showroom .ssr-root .ssr-footer-card {
  background: var(--mt-overlay);
  border-color: var(--mt-border);
  color: var(--mt-text-2);
}
[data-theme="light"] .module-streamline-product-showroom .ssr-root .ssr-feature-copy p {
  color: var(--mt-muted);
}
[data-theme="light"] .module-streamline-product-showroom .ssr-root::-webkit-scrollbar-track,
[data-theme="light"] .module-streamline-product-showroom .ssr-root::-webkit-scrollbar-corner {
  background: var(--mt-bg);
}

/* --- Always-light modules, forced onto the DARK theme -------------------- */

[data-theme="dark"] .module-provision .pv-shell {
  --pv-cream: var(--mt-surface);
  --pv-ink: var(--mt-text);
  --pv-ink-2: var(--mt-text-2);
  --pv-line: var(--mt-border);
  border-color: var(--mt-border);
  box-shadow: 0 18px 50px var(--mt-shadow);
}
[data-theme="dark"] .module-provision .pv-shell .pv-card,
[data-theme="dark"] .module-provision .pv-shell .pv-tabs,
[data-theme="dark"] .module-provision .pv-shell .pv-meal,
[data-theme="dark"] .module-provision .pv-shell .pv-filter,
[data-theme="dark"] .module-provision .pv-shell .pv-shop-row,
[data-theme="dark"] .module-provision .pv-shell .pv-crew-card,
[data-theme="dark"] .module-provision .pv-shell .pv-my-row,
[data-theme="dark"] .module-provision .pv-shell .pv-day-button,
[data-theme="dark"] .module-provision .pv-shell .pv-profile-choice,
[data-theme="dark"] .module-provision .pv-shell .pv-modal,
[data-theme="dark"] .module-provision .pv-shell .pv-modal-head,
[data-theme="dark"] .module-provision .pv-shell .pv-tiny-btn,
[data-theme="dark"] .module-provision .pv-shell .pv-inbox-row {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="dark"] .module-provision .pv-shell .pv-inbox {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
}
[data-theme="dark"] .module-provision .pv-shell .pv-field .input,
[data-theme="dark"] .module-provision .pv-shell .pv-field select,
[data-theme="dark"] .module-provision .pv-shell .pv-field textarea,
[data-theme="dark"] .module-provision .pv-shell .pv-name-row .input,
[data-theme="dark"] .module-provision .pv-shell .pv-inbox-input {
  background: var(--mt-surface);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="dark"] .module-provision .pv-shell .pv-modal .pv-field .input,
[data-theme="dark"] .module-provision .pv-shell .pv-modal .pv-field select,
[data-theme="dark"] .module-provision .pv-shell .pv-modal .pv-field textarea {
  color: var(--mt-text);
  background: var(--mt-surface);
}
[data-theme="dark"] .module-provision .pv-shell .pv-progress,
[data-theme="dark"] .module-provision .pv-shell .pv-mini-btn,
[data-theme="dark"] .module-provision .pv-shell .pv-modal-close,
[data-theme="dark"] .module-provision .pv-shell .pv-action.pv-soft,
[data-theme="dark"] .module-provision .pv-shell .pv-avatar {
  background: var(--mt-surface-3);
}
[data-theme="dark"] .module-provision .pv-shell .pv-empty {
  border-color: var(--mt-border);
}
[data-theme="dark"] .module-provision .pv-shell .pv-profile-choice b,
[data-theme="dark"] .module-provision .pv-shell .pv-my-icon {
  background: #26332c;
}

[data-theme="dark"] .module-qview-configurator {
  --qv-ink: var(--mt-text);
  --qv-pale: var(--mt-surface-2);
  --qv-line: var(--mt-border);
}
/* qview hardcodes its surfaces — remap the big ones directly. */
[data-theme="dark"] .module-qview-configurator .qv-shell {
  background: var(--mt-surface);
}
[data-theme="dark"] .module-qview-configurator .qv-header,
[data-theme="dark"] .module-qview-configurator .qv-palette,
[data-theme="dark"] .module-qview-configurator .qv-inspector,
[data-theme="dark"] .module-qview-configurator .qv-summary,
[data-theme="dark"] .module-qview-configurator .qv-drawer-card,
[data-theme="dark"] .module-qview-configurator .qv-saved-item,
[data-theme="dark"] .module-qview-configurator .qv-asset-card,
[data-theme="dark"] .module-qview-configurator .qv-action,
[data-theme="dark"] .module-qview-configurator .qv-icon-btn,
[data-theme="dark"] .module-qview-configurator .qv-product,
[data-theme="dark"] .module-qview-configurator .qv-statusbar,
[data-theme="dark"] .module-qview-configurator .qv-port-row {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="dark"] .module-qview-configurator .qv-toolbar,
[data-theme="dark"] .module-qview-configurator .qv-selected-head,
[data-theme="dark"] .module-qview-configurator .qv-position-readout {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
}
[data-theme="dark"] .module-qview-configurator .qv-product-tabs,
[data-theme="dark"] .module-qview-configurator .qv-library-tabs {
  background: var(--mt-surface);
}
[data-theme="dark"] .module-qview-configurator .qv-product-tabs button.active,
[data-theme="dark"] .module-qview-configurator .qv-library-tabs button.active {
  background: var(--mt-surface-2);
}
[data-theme="dark"] .module-qview-configurator .qv-stage-wrap,
[data-theme="dark"] .module-qview-configurator .qv-stage {
  background: var(--mt-bg);
}
[data-theme="dark"] .module-qview-configurator .qv-statusbar b {
  color: var(--mt-text);
}

/* --- taskflow-time: redefines the app's own token names on .tt-app with
       light values, so the whole module stays light. Remap the palette to
       the dark tokens, then catch the hardcoded white surfaces. ---------- */

[data-theme="dark"] .module-taskflow-time .tt-app {
  --text: var(--mt-text);
  --text-muted: var(--mt-muted);
  --surface: var(--mt-surface);
  --surface-2: var(--mt-surface-2);
  --border: var(--mt-border);
  /* keep the module's cyan brand — just darken its soft tint */
  --primary-soft: rgba(3, 169, 237, .16);
  background: var(--mt-surface);
  border-color: var(--mt-border);
}
[data-theme="dark"] .module-taskflow-time .tt-topbar,
[data-theme="dark"] .module-taskflow-time .tt-nav,
[data-theme="dark"] .module-taskflow-time .tt-layout,
[data-theme="dark"] .module-taskflow-time .tt-tracker-bar,
[data-theme="dark"] .module-taskflow-time .tt-tracker-welcome,
[data-theme="dark"] .module-taskflow-time .tt-feature-heading,
[data-theme="dark"] .module-taskflow-time .tt-feature-status,
[data-theme="dark"] .module-taskflow-time .tt-empty-notice,
[data-theme="dark"] .module-taskflow-time .tt-rates-section,
[data-theme="dark"] .module-taskflow-time .tt-rate-history,
[data-theme="dark"] .module-taskflow-time .tt-report-visual,
[data-theme="dark"] .module-taskflow-time .tt-report-grid,
[data-theme="dark"] .module-taskflow-time .tt-filter-strip,
[data-theme="dark"] .module-taskflow-time .tt-shared-list,
[data-theme="dark"] .module-taskflow-time .tt-shared-list th,
[data-theme="dark"] .module-taskflow-time .tt-calendar-grid .tt-day {
  background: var(--mt-surface);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="dark"] .module-taskflow-time .tt-popover {
  background: var(--mt-surface-2);
  border-color: var(--mt-border);
  color: var(--mt-text);
}
[data-theme="dark"] .module-taskflow-time .tt-popover .tt-menu-item {
  background: transparent;
  color: var(--mt-text-2);
}
[data-theme="dark"] .module-taskflow-time .tt-popover .tt-menu-item:hover:enabled {
  background: var(--mt-surface-3);
}
[data-theme="dark"] .module-taskflow-time .tt-popover .tt-menu-item.tt-selected,
[data-theme="dark"] .module-taskflow-time .tt-nav .tt-nav-link.tt-selected,
[data-theme="dark"] .module-taskflow-time .tt-report-tabs .tt-selected,
[data-theme="dark"] .module-taskflow-time .tt-group-controls,
[data-theme="dark"] .module-taskflow-time .tt-report-totals,
[data-theme="dark"] .module-taskflow-time .tt-shared-heading,
[data-theme="dark"] .module-taskflow-time .tt-feature-badge,
[data-theme="dark"] .module-taskflow-time .tt-rate-base {
  background: var(--mt-surface-3);
  color: var(--mt-text);
  border-color: var(--mt-border);
}
[data-theme="dark"] .module-taskflow-time .tt-nav .tt-nav-link {
  background: transparent;
  color: var(--mt-text-2);
}
[data-theme="dark"] .module-taskflow-time .tt-nav .tt-nav-link:hover:enabled {
  background: var(--mt-surface-3);
}
[data-theme="dark"] .module-taskflow-time .tt-logo {
  color: var(--mt-text);
}
[data-theme="dark"] .module-taskflow-time .tt-chart-select,
[data-theme="dark"] .module-taskflow-time .tt-shared-tools>input,
[data-theme="dark"] .module-taskflow-time .tt-switch input {
  background: var(--mt-surface-2);
  border-color: var(--mt-border) !important;
  color: var(--mt-text);
}
[data-theme="dark"] .module-taskflow-time .tt-report-grid details[open] {
  background: var(--mt-overlay);
}
[data-theme="dark"] .module-taskflow-time .tt-count {
  background: rgba(3, 169, 237, .15);
  color: #6ec6ee;
}
[data-theme="dark"] .module-taskflow-time .tt-donut-inner,
[data-theme="dark"] .module-taskflow-time .tt-tracker-clock,
[data-theme="dark"] .module-taskflow-time .tt-feature-heading h2 {
  color: var(--mt-text);
}
[data-theme="dark"] .module-taskflow-time .tt-finance-warning {
  background: rgba(251, 191, 36, .08);
  border-color: rgba(251, 191, 36, .3);
}
[data-theme="dark"] .module-taskflow-time .tt-nav .tt-collapse,
[data-theme="dark"] .module-taskflow-time .tt-close {
  background: transparent;
}
[data-theme="dark"] .module-taskflow-time .tt-calendar-grid .tt-in-range {
  background: rgba(3, 169, 237, .14);
}
[data-theme="dark"] .module-taskflow-time .tt-tracker-bar .tt-field input,
[data-theme="dark"] .module-taskflow-time .tt-tracker-bar .tt-field select,
[data-theme="dark"] .module-taskflow-time .tt-tracker-task input {
  color: var(--mt-text);
}
