/* ============================================================
   AceMakers course platform - UI system.
   Restyled to a Supabase/Resend dashboard aesthetic: neutral surfaces,
   1px borders define edges, flat (near-invisible shadows), tight spacing.
   The brand teal/green is kept but used ONLY as an accent - primary
   buttons, the active nav row, links, and focus rings. Everything else
   is neutral. Every component is written against the tokens, so a
   re-theme stays a token swap.
   Dark mode = dark NEUTRAL surfaces with the same teal accent.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

/* DARK - dark neutral surfaces, teal accent (brand mint). */
:root {
  --background: #131313;
  --card: #1b1b1b;
  --surface: #1f1f1f;        /* subtle panel fill (columns, metrics, rows) */
  --surface-hover: #242424;  /* hover / active neutral fill */
  --primary: #70ffe2;        /* brand accent - interactive/active/links only */
  --primary-fg: #0c1f1b;     /* text/icon on a solid primary button */
  --primary-30: rgba(112,255,226,.30);
  --primary-20: rgba(112,255,226,.20);
  --primary-12: rgba(112,255,226,.12);
  --primary-08: rgba(112,255,226,.08);
  --primary-04: rgba(112,255,226,.05);
  --foreground: #ededed;     /* near-white text */
  --muted-foreground: #a3a3a3;
  --muted-2: #6f6f6f;
  --line: #2b2b2b;           /* neutral 1px border */
  --line-strong: #363636;
  --ring: rgba(112,255,226,.35);
  --red: #ff8a8a;  --amber: #ffce5a;  --blue: #5ad7e8;  --gold: #f5b301;  --purple: #a78bfa;
  /* Low-opacity fills for the calendar category chips + all-day banners. */
  --red-bg: rgba(255,138,138,.14); --amber-bg: rgba(255,206,90,.14);
  --blue-bg: rgba(90,215,232,.14); --purple-bg: rgba(167,139,250,.14);
  --navy: #13282a; --dark-ink: #0c1f1b;
  --radius: 6px;  --card-radius: 8px;
  --shadow: none;
  --shadow-pop: 0 10px 30px rgba(0,0,0,.5);
  /* Shell geometry (theme-independent, so they live only here). --topbar-h is the
     full-width top bar; --sb-full / --sb-rail are the two sidebar widths. */
  --topbar-h: 56px;  --sb-full: 240px;  --sb-rail: 60px;
  --card-bg: var(--card);
  --input-bg: #1c1c1c;
  --th-bg: #1a1a1a;
  --td-border: #262626;
  --bar-track: #2b2b2b;
  --dnd-slot: #363636;       /* the flat gray drop slot (Asana placeholder) */
  --gold-bg: rgba(245,179,1,.08); --gold-border: rgba(245,179,1,.28); --gold-fg: #ffd98a;
  /* Swatches: a patch of the OTHER theme's surface, so one page can show both.
     Used by the logo uploader, where the whole question is whether a mark reads
     on light and on dark. Each theme block holds the values it is not currently
     painting, so a colour still only ever appears in a token declaration. */
  --swatch-dark-bg: var(--background);  --swatch-dark-line: var(--line-strong);
  --swatch-dark-fg: var(--muted-foreground);
  --swatch-light-bg: #f7f7f6;  --swatch-light-line: #d9d9d6;  --swatch-light-fg: #6b6b6b;
}

/* LIGHT - near-white background, white cards, neutral gray borders.
   Accent changes VALUE (deep teal), never hue. */
[data-theme="light"] {
  --background: #f7f7f6;
  --card: #ffffff;
  --surface: #fafafa;
  --surface-hover: #f2f2f1;
  --primary: #0a7d68;
  --primary-fg: #ffffff;
  --primary-30: rgba(10,125,104,.28);
  --primary-20: rgba(10,125,104,.18);
  --primary-12: rgba(10,125,104,.12);
  --primary-08: rgba(10,125,104,.08);
  --primary-04: rgba(10,125,104,.05);
  --foreground: #1a1a1a;
  --muted-foreground: #6b6b6b;
  --muted-2: #9a9a9a;
  --line: #e6e6e4;
  --line-strong: #d9d9d6;
  --ring: rgba(10,125,104,.22);
  --red: #d12f2f;  --amber: #a9760a;  --blue: #0d7f9e;  --gold: #9c7400;  --purple: #6d28d9;
  --red-bg: rgba(209,47,47,.10); --amber-bg: rgba(169,118,10,.12);
  --blue-bg: rgba(13,127,158,.12); --purple-bg: rgba(109,40,217,.10);
  --dark-ink: #ffffff;
  --shadow: none;
  --shadow-pop: 0 8px 28px rgba(16,24,24,.12);
  --card-bg: #ffffff;
  --input-bg: #ffffff;
  --th-bg: #fafafa;
  --td-border: #eeeeec;
  --bar-track: #ececea;
  --dnd-slot: #e8e8e8;       /* the flat gray drop slot (Asana placeholder) */
  --gold-bg: rgba(169,118,10,.10); --gold-border: rgba(169,118,10,.28); --gold-fg: #6b4e00;
  --swatch-dark-bg: #131313;  --swatch-dark-line: #363636;  --swatch-dark-fg: #a3a3a3;
  --swatch-light-bg: var(--background);  --swatch-light-line: var(--line-strong);
  --swatch-light-fg: var(--muted-foreground);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--background);
  color: var(--foreground);
  font-family: Inter, system-ui, -apple-system, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

/* Flat design: no ambient glow, no crosshatch. Borders define edges. */

/* ============================================================
   App shell (Asana / Supabase pattern)
   - A full-width TOP BAR: fixed brand far left, then the per-page toolbar, search
     far right. It never moves when the sidebar changes.
   - Below it, the SIDEBAR (fixed, icon rail <-> labelled column) and the CONTENT.

   Two custom properties drive the widths:
     --sb-cur     the sidebar's RENDERED (visual) width - what animates.
     --sb-reserve the width the content is offset by. It equals --sb-cur in the
                  expanded/collapsed modes, but in HOVER mode it stays pinned to
                  the rail, so a hover-expansion floats OVER the content as an
                  overlay instead of reflowing the page.
   data-sidebar (expanded|collapsed) is the rendered form; data-sb-mode
   (expanded|collapsed|hover) is the persisted choice.
   ============================================================ */
html { --sb-reserve: var(--sb-cur); }
[data-sidebar="expanded"]  { --sb-cur: var(--sb-full); }
[data-sidebar="collapsed"] { --sb-cur: var(--sb-rail); }
/* Hover mode: the page is always reserved a rail; the expansion overlays it. */
[data-sb-mode="hover"] { --sb-reserve: var(--sb-rail); }

.app-shell { min-height: 100vh; }

/* ---------- full-width top bar ----------
   LEFT = fixed brand slot, then the hamburger (phones) + page title / context.
   RIGHT = the page's view controls, then the static search button. */
.topbar {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  display: flex; align-items: center; gap: 12px;
  height: var(--topbar-h);
  padding-right: 20px;
  background: var(--background);
  border-bottom: 1px solid var(--line);
}
.topbar .sp { flex: 1 1 auto; min-width: 8px; }
.topbar .btn-sec, .topbar .product, .topbar .who { white-space: nowrap; }

/* The brand: a fixed slot the width of the expanded sidebar, so the wordmark
   sits far left and holds its place no matter what the sidebar does. */
.brand {
  display: flex; align-items: center; flex: none;
  width: var(--sb-full); height: 100%;
  padding-left: 20px; box-sizing: border-box;
  text-decoration: none;
}
.brand .logo-full { height: 18px; }
.brand-light, .brand-dark, .brand-custom { display: none; }
html[data-theme="light"] .logo-full.brand-light { display: block; }
html:not([data-theme="light"]) .logo-full.brand-dark { display: block; }

/* A user's own logo takes the slot outright, and switches on theme exactly like
   the AceMakers pair above. It is sized by a BOX rather than a fixed height:
   their mark may be a wide wordmark or a square icon, and either has to sit in
   the same slot without pushing the top bar around. */
.brand[data-brand="custom"] .logo-full.brand-light,
.brand[data-brand="custom"] .logo-full.brand-dark { display: none; }
html[data-theme="light"] .brand[data-brand="custom"] .logo-full.brand-custom-light,
html:not([data-theme="light"]) .brand[data-brand="custom"] .logo-full.brand-custom-dark {
  display: block; height: auto;
  max-height: 26px; max-width: calc(var(--sb-full) - 40px);
  width: auto; object-fit: contain;
}

/* The hamburger lives in the top bar; only the phone drawer regime shows it. */
.nav-burger {
  display: none; flex: none;
  width: 34px; height: 34px; padding: 0; border-radius: var(--radius);
  align-items: center; justify-content: center;
  border: 1px solid var(--line-strong); background: var(--card); color: var(--muted-foreground);
  cursor: pointer; transition: background .12s, color .12s;
}
.nav-burger:hover { background: var(--surface-hover); color: var(--foreground); }
.nav-burger .ico { width: 18px; height: 18px; }

/* ---------- app body: the sidebar + the content column, under the top bar ---------- */
.app-body { position: relative; }

.sidebar {
  position: fixed; top: var(--topbar-h); left: 0; bottom: 0; z-index: 40;
  width: var(--sb-cur);
  display: flex; flex-direction: column; gap: 4px;
  padding: 14px 12px;
  background: var(--card);
  border-right: 1px solid var(--line);
  transition: width .18s ease-out, box-shadow .18s ease;
}
/* Hover mode, currently expanded (mouse over the rail): float the full column
   over the content with a soft shadow - the page underneath never reflows. */
[data-sb-mode="hover"][data-sidebar="expanded"] .sidebar {
  z-index: 55; box-shadow: var(--shadow-pop);
}

/* the nav - a vertical list of icon+label rows */
.nav { display: flex; flex-direction: column; gap: 2px; overflow-y: auto; flex: 1; min-height: 0; }
.nav::-webkit-scrollbar { width: 0; }

/* ---------- sidebar foot: four fixed rows, identical in rail and expanded ----------
   The rule that stops hover-expand from misfiring (Supabase follows it): expanding
   may only ADD a label to the RIGHT of an already-visible icon. Every control keeps
   its exact row and vertical position in BOTH states - nothing reorders, nothing
   appears or disappears as a row, no height changes - so the element under a
   stationary cursor can never swap mid-hover. The rows mirror .nav-item geometry so
   the whole sidebar shares ONE icon column. */
.sidebar-foot {
  display: flex; flex-direction: column; gap: 2px;
  padding-top: 10px; margin-top: 6px; border-top: 1px solid var(--line);
}
/* ONE shared row - the single NavRow component behind BOTH sidebar groups: the
   nav items (Course, Tools, Calendar, ...) AND the foot rows (profile, theme,
   sidebar, sign out). Sharing one geometry is exactly what stops the two groups
   drifting: the same 40px height in the rail and expanded, one 16px icon column
   that never moves, and a label that only fades in to the RIGHT of that icon. */
.navrow {
  display: flex; align-items: center; gap: 10px; width: 100%;
  height: 40px; padding: 0 9px; border-radius: var(--radius);
  border: none; background: transparent; color: var(--muted-foreground);
  font: 500 13px/1.2 Inter; text-align: left; cursor: pointer;
  transition: background .12s, color .12s;
}
.navrow:hover { background: var(--surface-hover); color: var(--foreground); }
/* A fixed 16px icon slot sitting at the SAME x in every row, so the cursor stays
   on the same icon as the sidebar width animates. */
.navrow-ico {
  flex: none; width: 16px; height: 16px;
  display: grid; place-items: center;
}
.navrow-ico > svg, .navrow-ico > .ico { width: 16px; height: 16px; }
/* Labels fade in place to the right; clipped (not display:none) in the rail so
   they can animate and never mount/unmount a row. */
.navrow .lbl {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  opacity: 1; transition: opacity .12s ease .1s;
}
/* The foot group adds only the open-popover highlight; all geometry is .navrow. */
.foot-row[aria-expanded="true"] { background: var(--surface-hover); color: var(--foreground); }

/* content column: offset by the top bar and by the reserved sidebar width. */
.content {
  margin-top: var(--topbar-h);
  margin-left: var(--sb-reserve);
  min-width: 0; min-height: calc(100vh - var(--topbar-h));
  display: flex; flex-direction: column;
  transition: margin-left .18s ease-out;
}

/* The overlay scrim behind the phone drawer. Painted only in that regime. */
.nav-scrim { display: none; }

/* ---------- sidebar-control popover (the three-mode picker) ---------- */
.sb-menu {
  position: fixed; z-index: 400; width: 236px; padding: 6px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--card-radius);
  box-shadow: var(--shadow-pop);
}
.sb-menu .sb-menu-title {
  padding: 6px 10px 8px; font: 600 11px/1 Inter; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted-foreground);
}
.sb-menu .sb-opt {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; text-align: left;
  padding: 8px 10px; border-radius: var(--radius);
  background: transparent; border: none; color: var(--foreground);
  font: 500 13px/1.3 Inter; cursor: pointer;
}
.sb-menu .sb-opt:hover { background: var(--surface-hover); }
.sb-menu .sb-opt .sb-opt-check { width: 16px; height: 16px; flex: none; margin-top: 1px; color: var(--primary); opacity: 0; }
.sb-menu .sb-opt.on .sb-opt-check { opacity: 1; }
.sb-menu .sb-opt .sb-opt-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sb-menu .sb-opt .sb-opt-sub { font: 500 11.5px/1.35 Inter; color: var(--muted-foreground); }

/* ---------- top-bar toolbar slots (filled per page via setTopbar) ----------
   LEFT (#tb-left)  = page title (15px semibold) + an optional context control.
   RIGHT (#tb-right) = that page's view controls, then the static search button. */
/* Nudged 2px below the bar's true centre: the brand image carries the mountain
   mark ABOVE the wordmark, so the wordmark sits low-of-centre. Dropping the whole
   left cluster (title + any context control, kept in sync with each other) onto
   the wordmark's line stops the title reading as too high next to the logo. */
.tb-left  { display: flex; align-items: center; gap: 12px; min-width: 0; position: relative; top: 2px; }
.tb-right { display: flex; align-items: center; gap: 14px; min-width: 0; }
.tb-title {
  margin: 0; font: 600 15px/1.35 Inter; letter-spacing: 0; color: var(--foreground);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-meta { font: 500 12px/1.4 Inter; color: var(--muted-foreground); white-space: nowrap; }

/* A compact page-context control that lives beside the title (board client
   picker, cohort switcher). Smaller than a form select - it is chrome. */
.tb-select {
  width: auto; max-width: 220px; height: 30px;
  padding: 0 26px 0 10px; font: 500 12.5px/1 Inter;
}
/* The quiet "?" that folds a page's explainer into a hover tooltip next to the title. */
.tb-info {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: none; padding: 0; border-radius: 50%;
  border: none; background: transparent; color: var(--muted-2);
  transition: color .12s, background .12s;
}
.tb-info:hover { color: var(--foreground); background: var(--surface-hover); }
.tb-info .ico { width: 16px; height: 16px; }

/* Month stepper (‹ September 2026 ›) - used by the calendar toolbar. */
.tb-monthnav { display: inline-flex; align-items: center; gap: 6px; }
.tb-monthnav .cal-month { font-size: 14px; white-space: nowrap; min-width: 118px; text-align: center; }
.tb-monthnav .cal-nav {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: none; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--card); color: var(--foreground);
}
.tb-monthnav .cal-nav:hover { background: var(--surface-hover); }
.tb-monthnav .cal-nav .ico { width: 15px; height: 15px; }

/* Calendar toolbar RIGHT: the cohort countdown + the category legend. The
   legend ALWAYS folds into a "Legend" popover so the bar stays on one line and
   the grid never has to scroll. Below 1200px the countdown hides too. */
.tb-range { font: 500 12px/1.4 Inter; color: var(--muted-foreground); white-space: nowrap; }
.cal-legend-btn { display: inline-flex; }
.cal-legend-pop { display: grid; gap: 8px; }
.cal-legend-pop .cal-key { font-size: 12px; }
@media (max-width: 1200px) {
  .tb-range { display: none; }
}

/* PMO board's track legend, in the toolbar RIGHT: keep it on one row, and shed
   it before it can crowd the search button on a narrow window (the cards still
   carry their track colour, so the legend is a nicety, not load-bearing). */
.tb-right .track-legend { margin-left: 0; flex-wrap: nowrap; gap: 4px 12px; }
@media (max-width: 1100px) { .tb-right .track-legend { display: none; } }

/* profile row - a plain NavRow like every other. Its icon is the same 16px person
   line glyph the Admin item uses, sitting in the shared .navrow-ico slot, so it
   lines up with the rest instead of a larger circle that read as offset. */
.who-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The popover the collapsed avatar opens: name/email header, then Sign out. */
.who-menu {
  position: fixed; z-index: 400; width: 214px; padding: 6px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--card-radius);
  box-shadow: var(--shadow-pop);
}
.who-menu .wm-head {
  display: block; width: 100%; text-align: left; padding: 8px 10px; border-radius: var(--radius);
  background: transparent; border: none; cursor: pointer;
}
.who-menu .wm-head:hover { background: var(--surface-hover); }
.who-menu .wm-name { font: 600 13px/1.35 Inter; color: var(--foreground);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who-menu .wm-email { font: 500 11.5px/1.35 Inter; color: var(--muted-foreground);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who-menu .wm-sep { height: 1px; background: var(--line); margin: 6px 4px; }
.who-menu .wm-item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 8px 10px; border-radius: var(--radius);
  background: transparent; border: none; color: var(--foreground);
  font: 500 13px/1 Inter; cursor: pointer;
}
.who-menu .wm-item:hover { background: var(--surface-hover); }
.who-menu .wm-item .ico { width: 15px; height: 15px; flex: none; color: var(--muted-foreground); }

/* ============================================================
   Collapsed rail - the 60px icon-only state. Scoped to >=768px so the phone
   drawer (which reuses the full labelled layout) is never affected.
   ============================================================ */
@media (min-width: 768px) {
  [data-sidebar="collapsed"] .sidebar { padding-left: 8px; padding-right: 8px; }

  /* Every NavRow (nav items AND foot rows) collapses the same way: keep the icon
     in place, fold the label to a clipped zero-width so it can fade back in on
     expand. Let the tooltip escape the rail (the column is short enough to not
     need a scrollbar). ONE rule for both groups - they cannot diverge.
     Left-align with a computed left pad (rail 8 + 13 = full 12 + 9) instead of
     justify-content:center, so the icon's centre stays at x=29 - the SAME column
     as the expanded rows, with no sideways slide on expand. */
  [data-sidebar="collapsed"] .nav { overflow: visible; }
  [data-sidebar="collapsed"] .navrow { padding: 0 0 0 13px; }
  [data-sidebar="collapsed"] .navrow .lbl { flex: 0 0 0; width: 0; opacity: 0; transition-delay: 0s; }
  [data-sidebar="collapsed"] .nav-item { position: relative; }   /* anchors the hover tooltip */
  [data-sidebar="collapsed"] .nav-item .dot { display: none; }
  /* In the rail there's no room for the "Admin" word, but the heading must keep
     its FULL box so the rows below it don't jump up when collapsed: visibility
     hidden reserves the same height (margin + padding + text line) as expanded,
     it just hides the glyph. Same reason the divider keeps its 10px vertical
     margin here - any mismatch shifts every admin icon and the foot group. */
  [data-sidebar="collapsed"] .nav-section { visibility: hidden; }
  [data-sidebar="collapsed"] .nav-divider { margin: 10px 10px; }

  /* Right-side dark tooltip, ~300ms in on hover. Dark in BOTH themes on purpose. */
  [data-sidebar="collapsed"] .nav-item::after {
    content: attr(data-label);
    position: absolute; left: calc(100% + 12px); top: 50%; transform: translateY(-50%);
    padding: 5px 9px; border-radius: 6px; white-space: nowrap;
    background: #1c1c1c; color: #f4f4f4; font: 500 12px/1 Inter;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .22);
    opacity: 0; visibility: hidden; pointer-events: none; z-index: 400;
    transition: opacity .12s ease, visibility .12s ease;
  }
  [data-sidebar="collapsed"] .nav-item:hover::after,
  [data-sidebar="collapsed"] .nav-item:focus-visible::after {
    opacity: 1; visibility: visible; transition-delay: .3s;
  }

}

/* nav rows - geometry (row height, icon slot, label fade) all comes from .navrow;
   this block only carries what is unique to a nav item: the icon colour, the
   active state, and the count dot. */
.nav-item .ico { width: 16px; height: 16px; flex: none; }
.nav-item.on { background: var(--surface-hover); color: var(--primary); }
.nav-item.on .ico { color: var(--primary); }
.nav-item .dot {
  min-width: 18px; padding: 0 5px; border-radius: 4px;
  background: var(--surface-hover); color: var(--muted-foreground);
  font: 600 11px/18px Inter; text-align: center;
}
.nav-item.on .dot { background: var(--primary-12); color: var(--primary); }

/* Product group heading in the sidebar - only shown when a member has more than
   one product to tell apart. 11px, muted, NOT uppercase (per the design guide's
   quiet-labels rule). The first heading sits flush; later ones get breathing
   room above so the groups read as distinct clusters. */
.nav-section {
  padding: 4px 9px 2px; margin-top: 12px;
  color: var(--muted-foreground);
  font: 600 11px/1.4 Inter; letter-spacing: .01em;
}
.nav-section:first-child { margin-top: 0; }
/* The divider above the Admin group. A hairline, plus matching space. */
.nav-divider {
  height: 1px; margin: 10px 4px; background: var(--line);
}

/* The admin's inline edit pencil. Quiet until you hover its card. */
.edit-pin {
  margin-left: auto; background: transparent; border: none; border-radius: var(--radius);
  padding: 3px 5px; opacity: 0; color: var(--muted-foreground);
  display: inline-flex; align-items: center;
  transition: opacity .12s, background .12s, color .12s;
}
.edit-pin .ico { width: 13px; height: 13px; vertical-align: 0; }
.kcard:hover .edit-pin, .lrow:hover .edit-pin, .edit-pin:focus-visible { opacity: .7; }
.edit-pin:hover { opacity: 1; background: var(--surface-hover); color: var(--primary); }

/* ---------- profile ---------- */
.avatar-lg {
  width: 64px; height: 64px; border-radius: 50%; flex: none;
  display: grid; place-items: center; overflow: hidden;
  background: var(--surface-hover); color: var(--primary);
  border: 1px solid var(--line); font: 600 24px/1 Inter;
}
.avatar-lg img { width: 100%; height: 100%; object-fit: cover; }

/* The avatar doubles as the photo drop target, so the thing you replace is the
   thing you are looking at. Quiet until you reach for it - a permanent dashed
   ring on a face would read as an error state. */
.avatar-drop { cursor: pointer; transition: border-color .12s, box-shadow .12s; }
.avatar-drop:hover, .avatar-drop:focus-visible, .avatar-drop.dragover {
  border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-08); outline: none;
}

/* ---------- Profile > Your logo ----------
   Two drop targets, each painted in the surface of the theme it is FOR, so the
   card answers the only question that matters about a logo: does it read there.
   Each doubles as its own preview - what you see is the mark that will land in
   the top bar, on that background. */
.logo-slots { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 780px) { .logo-slots { grid-template-columns: 1fr; } }

.logo-slot .fl { display: block; margin-bottom: 7px; }
.logo-slot .help { margin: 7px 0 0; }

.logo-drop {
  display: grid; place-items: center;
  min-height: 96px; padding: 16px 20px;
  border: 1px dashed var(--swatch-light-line); border-radius: var(--card-radius);
  background: var(--swatch-light-bg); color: var(--swatch-light-fg);
  cursor: pointer; text-align: center;
  transition: border-color .12s, box-shadow .12s;
}
.logo-drop.on-dark {
  border-color: var(--swatch-dark-line);
  background: var(--swatch-dark-bg); color: var(--swatch-dark-fg);
}
.logo-drop:hover, .logo-drop.dragover { border-color: var(--primary); box-shadow: 0 0 0 3px var(--ring); }
.logo-drop img { max-height: 44px; max-width: 100%; width: auto; object-fit: contain; }
.logo-drop .ico { width: 20px; height: 20px; }
.logo-drop .t { font-size: 12.5px; margin-top: 6px; }

/* The slot itself, at the size the top bar renders it. */
.logo-preview {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 9px 16px; border: 1px solid var(--line); border-radius: 9999px;
  background: var(--background);
}
.logo-preview .lbl {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted-2); white-space: nowrap;
}
.logo-preview img { max-height: 18px; max-width: 150px; width: auto; object-fit: contain; }

.kv {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 8px 0; border-bottom: 1px solid var(--td-border); font-size: 13px;
}
.kv:last-child { border-bottom: none; }
.kv span { color: var(--muted-foreground); }

/* Page container: content spans the full content area (viewport minus sidebar)
   with the standard page padding - never a centred, capped island. A page that
   needs a narrow READABLE column caps its own CONTENT (.page-desc at 78ch, the
   wizard body at 620px), not the page itself. .wide / .full are kept as no-op
   aliases so the renderers that still set them (admin, boards) keep working. */
.main { margin: 0; width: 100%; padding: 24px 24px 72px; }
.main.wide, .main.full { max-width: none; }

/* ---------- card ---------- */
.card {
  background: var(--card-bg);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  padding: 18px 18px;
  margin-bottom: 14px;
  box-shadow: var(--shadow);
}
.card-title {
  font-size: 15px; font-weight: 600; letter-spacing: 0;
  color: var(--foreground); margin: 0 0 14px; display: flex; align-items: center; gap: 8px;
}
/* ============================================================
   Global page pattern - ONE layout for every route.

   Content sits DIRECTLY on the page background. A `.card` is reserved for
   ATOMIC items (a kanban card, a chapter tile, a tool tile) - it never wraps
   a whole page or a whole section. A page is:

     .page-head   -> .page-title (+ right-aligned .meta) and an optional
                     one-line .page-desc, then content directly below.
     .page-section -> whitespace + a semibold heading to separate sections,
                     OR a .page-divider hairline. Never a nested box.

   Every route shares this, so page padding, title size and section rhythm
   match app-wide (Admin and the Operations Board already looked like this). */
.page-head { margin: 0 0 22px; }
.page-title {
  display: flex; align-items: center; gap: 10px; margin: 0;
  font: 600 16px/1.35 Inter; letter-spacing: 0; color: var(--foreground);
}
.page-title .meta {
  margin-left: auto; display: inline-flex; align-items: center; gap: 10px;
  font: 500 13px/1.4 Inter; color: var(--muted-foreground);
}
.page-desc {
  margin: 7px 0 0; max-width: 78ch;
  font-size: 13px; line-height: 1.6; color: var(--muted-foreground);
}
/* A slim progress row that hangs under a page title (course header). */
.page-progress { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.page-progress .progress-bar-wrap { flex: 1; height: 5px; }

/* Separate sections on one page: 32px of air, then a quiet heading. */
.page-section { margin-top: 32px; }
.page-section:first-child { margin-top: 0; }
.page-section-title {
  display: flex; align-items: center; gap: 8px; margin: 0 0 14px;
  font: 600 14px/1.3 Inter; letter-spacing: 0; color: var(--foreground);
}
.page-section-title .meta {
  margin-left: auto; font: 500 12.5px/1.4 Inter; color: var(--muted-foreground);
}
.page-section-title .sec-kick { margin: 0; }
/* Full-width hairline, an alternative to a heading between sections. */
.page-divider { height: 1px; background: var(--line); border: 0; margin: 24px 0; }

/* A card-less disclosure (details) that reads as a link, not a box - used for
   "how it works" explainers that shouldn't sit in a giant empty card. */
.page-accordion { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.page-accordion > summary {
  display: flex; align-items: center; gap: 8px; cursor: pointer; list-style: none;
  padding: 13px 2px; font: 600 13px/1.4 Inter; color: var(--foreground);
}
.page-accordion > summary::-webkit-details-marker { display: none; }
.page-accordion > summary::before {
  content: '▸'; color: var(--muted-foreground); font-size: 11px; transition: transform .12s;
}
.page-accordion[open] > summary::before { transform: rotate(90deg); color: var(--primary); }
.page-accordion > summary:hover { color: var(--primary); }
.page-accordion .page-accordion-body { padding: 2px 2px 16px; }

.card-title .meta {
  margin-left: auto; font-weight: 500;
  font-size: 13px; color: var(--muted-foreground);
}

/* ---------- buttons ---------- */
button { font-family: Inter, system-ui, sans-serif; cursor: pointer; }

.btn-primary {
  width: 100%; height: 32px; padding: 0 14px; font: 600 13px/1 Inter; letter-spacing: 0;
  border: 1px solid transparent; border-radius: var(--radius);
  background: var(--primary); color: var(--primary-fg);
  box-shadow: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  transition: filter .12s, background .12s;
}
.btn-primary:hover { filter: brightness(1.06); }
.btn-primary:active { filter: brightness(.96); }
.btn-primary:disabled { opacity: .45; cursor: not-allowed; filter: none; }

.btn-sec {
  height: 32px; padding: 0 14px; font: 500 13px/1 Inter; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--card); color: var(--foreground);
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  transition: background .12s, border-color .12s;
}
.btn-sec:hover { background: var(--surface-hover); border-color: var(--line-strong); }
.btn-sec:disabled { opacity: .5; cursor: not-allowed; }

.btn-green {
  height: 32px; padding: 0 14px; font: 600 13px/1 Inter; border: 1px solid transparent; border-radius: var(--radius);
  background: var(--primary); color: var(--primary-fg);
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
}
.btn-green:hover { filter: brightness(1.06); }

.btn-danger {
  height: 30px; padding: 0 12px; font: 500 13px/1 Inter; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--card); color: var(--red);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.btn-danger:hover { background: rgba(209,47,47,.08); border-color: var(--red); }
.btn-sm { height: 28px; padding: 0 10px; font-size: 12.5px; }
.btn-auto { width: auto; }

/* ---------- inputs ---------- */
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], select, textarea {
  width: 100%; font-family: Inter, sans-serif; font-size: 13px;
  padding: 8px 11px; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--input-bg); color: var(--foreground);
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--ring);
}
::placeholder { color: var(--muted-2); }
textarea { resize: vertical; min-height: 76px; line-height: 1.6; }
label.fl { display: block; font-size: 13px; font-weight: 500; color: var(--foreground); margin-bottom: 6px; }
.field { margin-bottom: 13px; }
.help { font-size: 12.5px; color: var(--muted-foreground); line-height: 1.5; margin-top: 5px; }

/* ---------- segmented control (was tab pills) - used inside pages ---------- */
.tabs {
  display: flex; gap: 2px; padding: 3px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--line); width: fit-content;
  flex-wrap: nowrap; overflow-x: auto; max-width: 100%;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  padding: 6px 12px; font: 500 13px/1 Inter; border-radius: 4px;
  border: none; background: transparent; color: var(--muted-foreground);
  display: flex; align-items: center; gap: 6px; white-space: nowrap; flex: none;
  transition: background .12s, color .12s;
}
.tab:hover { color: var(--foreground); }
.tab.on { background: var(--card); color: var(--foreground); box-shadow: var(--shadow); }
.tab .dot {
  min-width: 16px; padding: 0 5px; border-radius: 4px;
  background: var(--primary-12); color: var(--primary);
  font: 600 10px/16px Inter; text-align: center;
}

/* ---------- chips ---------- */
.chip {
  padding: 4px 11px; font: 500 12.5px/1 Inter; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--card);
  color: var(--muted-foreground);
}
.chip.on { background: var(--primary-12); color: var(--primary); border-color: var(--primary-30); }
.chip .n { opacity: .7; }

/* ---------- status badges ---------- */
.badge {
  display: inline-block; padding: 2px 8px; border-radius: 5px;
  font: 500 12px/1.5 Inter; text-transform: none; letter-spacing: 0;
}
.b-success { background: var(--primary-12); color: var(--primary); }
.b-danger  { background: rgba(209,47,47,.12); color: var(--red); }
.b-warning { background: rgba(169,118,10,.15); color: var(--amber); }
.b-neutral { background: var(--surface-hover); color: var(--muted-foreground); }
.b-info    { background: rgba(13,127,158,.12); color: var(--blue); }

/* ---------- metric row ---------- */
.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.metric {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--card-radius);
  padding: 14px; text-align: left;
}
.metric .n { font: 600 24px/1.2 Inter; }
.metric .l {
  font: 500 12px/1.4 Inter; text-transform: none; letter-spacing: 0;
  color: var(--muted-foreground); margin-top: 3px;
}
.n-success { color: var(--primary); } .n-danger { color: var(--red); }
.n-warning { color: var(--amber); }   .n-info { color: var(--blue); }

/* ---------- table ---------- */
.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 700px; }
table.data th {
  position: sticky; top: 0; padding: 8px 10px; text-align: left;
  font: 500 12px/1.4 Inter; text-transform: none; letter-spacing: 0;
  color: var(--muted-foreground); background: var(--th-bg);
  border-bottom: 1px solid var(--line);
}
table.data td {
  padding: 9px 10px; vertical-align: top; border-bottom: 1px solid var(--td-border);
  overflow-wrap: anywhere;
}
table.data tr:hover td { background: var(--surface); }

/* ---------- progress ---------- */
.progress-bar-wrap { height: 6px; border-radius: 4px; background: var(--bar-track); overflow: hidden; }
.progress-bar {
  height: 100%; border-radius: 4px;
  background: var(--primary);
  box-shadow: none;
  transition: width .4s;
}

/* ---------- modal ---------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 100; padding: 20px;
  background: rgba(0,0,0,.5); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
}
.modal {
  max-width: 560px; width: 100%; max-height: 88vh; overflow-y: auto;
  padding: 20px 20px; border-radius: var(--card-radius);
  border: 1px solid var(--line); background: var(--card);
  box-shadow: var(--shadow-pop);
}
.modal.lg { max-width: 900px; }
.modal-head { display: flex; align-items: center; margin-bottom: 14px; }
.modal-head h3 { font: 600 16px/1.3 Inter; margin: 0; flex: 1; }
.modal-head .x {
  background: none; border: none; color: var(--muted-foreground);
  display: inline-flex; align-items: center; padding: 4px; border-radius: var(--radius);
}
.modal-head .x .ico { width: 17px; height: 17px; vertical-align: 0; }
.modal-head .x:hover { background: var(--surface-hover); color: var(--foreground); }

/* ============================================================
   Admin - dense data tables (Supabase / Resend style).

   Rows are one line, 46px, 13px. Secondary info (email, VAT, IP, timestamps)
   lives INLINE next to the name or in the right-side detail panel, never on a
   second row. All controls that used to sit in the row moved to the "..." menu
   and the panel, so the grid stays scannable.
   ============================================================ */
.adm { display: block; }

/* --- inline metrics header: "label value" pairs, <=32px tall --- */
.adm-stats {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  min-height: 32px; margin-bottom: 14px; font-size: 13px; color: var(--muted-foreground);
}
.adm-stat { display: inline-flex; align-items: baseline; gap: 6px; }
.adm-stat b { color: var(--foreground); font-weight: 600; }
.adm-stats .sep { color: var(--line-strong); }

/* --- toolbar: search on the left, actions on the right --- */
.adm-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.adm-toolbar .spacer { flex: 1; }

.adm-search {
  display: inline-flex; align-items: center; gap: 7px;
  height: 32px; padding: 0 10px; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--input-bg);
  color: var(--muted-2); min-width: 230px;
}
.adm-search:focus-within { border-color: var(--primary); }
.adm-search .ico { width: 14px; height: 14px; }
.adm-search input {
  border: none; background: transparent; padding: 0; height: 100%;
  font: 400 13px/1 Inter; color: var(--foreground); flex: 1; outline: none;
}

/* --- section title + hint tooltip (replaces the beige banners) --- */
.adm-title {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  font: 600 15px/1.3 Inter; color: var(--foreground);
}
.adm-sub { font-size: 12px; color: var(--muted-foreground); margin: 0 0 14px; line-height: 1.5; }
.hint {
  width: 15px; height: 15px; border-radius: 50%; flex: none;
  border: 1px solid var(--line-strong); background: transparent; color: var(--muted-2);
  font: 600 10px/13px Inter; text-align: center; cursor: help; position: relative; padding: 0;
}
.hint:hover, .hint:focus-visible { color: var(--foreground); border-color: var(--line-strong); }
.hint:hover::after, .hint:focus-visible::after {
  content: attr(data-tip); position: absolute; left: 0; top: calc(100% + 7px);
  width: max-content; max-width: 340px;
  background: var(--foreground); color: var(--background);
  padding: 8px 11px; border-radius: 6px; font: 400 12px/1.55 Inter; text-align: left;
  z-index: 60; box-shadow: var(--shadow-pop); white-space: normal;
}

/* --- the dense table itself --- */
.dtable { width: 100%; border-collapse: collapse; font-size: 13px; }
.dtable th {
  text-align: left; padding: 7px 12px; font: 500 12px/1.4 Inter;
  color: var(--muted-foreground); border-bottom: 1px solid var(--line); white-space: nowrap;
}
.dtable th.right, .dtable td.right { text-align: right; }
.dtable td {
  padding: 0 12px; height: 46px; vertical-align: middle;
  border-bottom: 1px solid var(--td-border); color: var(--foreground);
}
.dtable tbody tr { transition: background .1s; }
.dtable tbody tr.clickable { cursor: pointer; }
.dtable tbody tr:hover { background: var(--surface); }
.dtable td.num { font-variant-numeric: tabular-nums; }
.dtable td.actions { width: 44px; padding-left: 0; padding-right: 8px; }
.dtable .empty-cell { color: var(--muted-foreground); height: 60px; }

/* --- row selection (checkbox column + bulk-action bar) --- */
.dtable th.checkcell, .dtable td.checkcell { width: 34px; padding-right: 0; text-align: center; }
.dtable .checkcell input { width: 15px; height: 15px; margin: 0; cursor: pointer; accent-color: var(--primary); vertical-align: middle; }
.bulk-bar { display: inline-flex; align-items: center; gap: 10px; }
.bulk-bar .bulk-count { font: 500 13px/1 Inter; color: var(--muted-foreground); white-space: nowrap; }

.dt-name { font-weight: 600; color: var(--foreground); }
.dt-email { color: var(--muted-foreground); font-weight: 400; margin-left: 6px; }
.dt-muted { color: var(--muted-foreground); }

/* --- small tags: subtle tinted, max 2 then a "+N" chip --- */
.tags { display: inline-flex; gap: 5px; align-items: center; white-space: nowrap; }
.tag {
  display: inline-block; padding: 2px 7px; border-radius: 4px;
  font: 500 11px/1.5 Inter; background: var(--surface-hover); color: var(--muted-foreground);
  white-space: nowrap;
}
.tag.green { background: var(--primary-12); color: var(--primary); }
.tag.blue  { background: rgba(13,127,158,.12); color: var(--blue); }
.tag.gold  { background: var(--gold-bg); color: var(--gold-fg); }
.tag.more  { background: transparent; color: var(--muted-2); border: 1px solid var(--line); }

/* --- Admin -> Emails: the template catalogue + editor --- */
.adm-subtitle { font: 600 12px/1.3 Inter; color: var(--muted-foreground);
  text-transform: uppercase; letter-spacing: .5px; }
.mail-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; }
.mail-card { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  background: var(--card); display: flex; flex-direction: column; }
.mail-card-head { display: flex; justify-content: space-between; align-items: flex-start;
  gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); }
.mail-subj { font: 600 13px/1.35 Inter; color: var(--foreground); }
.mail-card-head .actions { display: flex; gap: 6px; flex: none; }
.mail-frame { width: 100%; height: 260px; border: 0; background: var(--background);
  display: block; }
.mail-frame.tall { height: 100%; min-height: 420px; border: 1px solid var(--line);
  border-radius: var(--radius); }
.mail-editor { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: stretch; }
.mail-editor-preview { display: flex; flex-direction: column; gap: 6px; }
@media (max-width: 720px) { .mail-editor { grid-template-columns: 1fr; }
  .mail-frame.tall { min-height: 300px; } }

/* --- status: a coloured dot + the word, not a pill --- */
.stat-dot { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; color: var(--foreground); }
.stat-dot .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.dot.green { background: var(--primary); }
.dot.amber { background: var(--amber); }
.dot.red { background: var(--red); }
.dot.blue { background: var(--blue); }
.dot.neutral { background: var(--muted-2); }

/* --- icon button (the "..." trigger and toolbar overflow) --- */
.icon-btn {
  width: 28px; height: 28px; border-radius: var(--radius); padding: 0;
  border: 1px solid transparent; background: transparent; color: var(--muted-2);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.icon-btn:hover { background: var(--surface-hover); color: var(--foreground); border-color: var(--line); }
.icon-btn .ico { width: 16px; height: 16px; vertical-align: 0; }
.icon-btn.box { width: 32px; height: 32px; border-color: var(--line-strong); background: var(--card); color: var(--muted-foreground); }
.icon-btn.box:hover { background: var(--surface-hover); color: var(--foreground); }

/* --- floating row-action menu --- */
.row-menu {
  position: fixed; z-index: 120; min-width: 178px; padding: 5px;
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--card-radius); box-shadow: var(--shadow-pop);
  display: flex; flex-direction: column; gap: 1px;
}
.row-menu-item {
  text-align: left; padding: 7px 10px; border-radius: var(--radius);
  font: 500 13px/1.3 Inter; color: var(--foreground); background: transparent; border: none; cursor: pointer;
}
.row-menu-item:hover { background: var(--surface-hover); }
.row-menu-item.danger { color: var(--red); }
.row-menu-item.danger:hover { background: rgba(209,47,47,.08); }

/* --- right-side detail panel --- */
.adm-panel-scrim {
  position: fixed; inset: 0; z-index: 110; background: rgba(0,0,0,.28);
  opacity: 0; transition: opacity .24s;
}
.adm-panel-scrim.show { opacity: 1; }
.adm-panel {
  position: fixed; top: 0; right: 0; z-index: 111; height: 100vh;
  width: min(460px, 96vw); background: var(--card); border-left: 1px solid var(--line);
  box-shadow: -12px 0 40px rgba(0,0,0,.18);
  transform: translateX(100%); transition: transform .28s cubic-bezier(.32,.72,0,1);
  display: flex; flex-direction: column;
}
[data-theme="light"] .adm-panel { box-shadow: -12px 0 40px rgba(16,24,24,.12); }
.adm-panel.show { transform: translateX(0); }
.adm-panel-head {
  display: flex; align-items: center; gap: 10px; padding: 15px 18px;
  border-bottom: 1px solid var(--line); flex: none;
}
.adm-panel-head h3 { font: 600 15px/1.3 Inter; margin: 0; flex: 1; overflow-wrap: anywhere; }
.adm-panel-head .sub { font: 400 12px/1.4 Inter; color: var(--muted-foreground); margin-top: 2px; }
.adm-panel-head .x {
  background: none; border: none; color: var(--muted-foreground); flex: none;
  display: inline-flex; padding: 5px; border-radius: var(--radius); cursor: pointer; align-self: flex-start;
}
.adm-panel-head .x:hover { background: var(--surface-hover); color: var(--foreground); }
.adm-panel-body { flex: 1; overflow-y: auto; padding: 18px; }

.pnl-kv {
  display: flex; justify-content: space-between; gap: 14px; padding: 9px 0;
  border-bottom: 1px solid var(--td-border); font-size: 13px;
}
.pnl-kv .k { color: var(--muted-foreground); flex: none; }
.pnl-kv .v { color: var(--foreground); text-align: right; overflow-wrap: anywhere; }
.pnl-kv .v.mono { font-family: ui-monospace, monospace; font-size: 12px; }
.pnl-sec { margin-top: 20px; }
.pnl-sec:first-child { margin-top: 0; }
.pnl-sec > h4 {
  font: 600 12px/1.4 Inter; color: var(--muted-foreground); margin: 0 0 10px; text-transform: none; letter-spacing: 0;
}

@media (max-width: 560px) {
  .adm-panel { width: 100vw; }
}

/* ============================================================
   Keyboard-key chip - the ONE shared component behind every keyboard hint
   (⌘K in the search pill, esc on a detail panel, ↵ / Esc in the palette).
   A kbd-style key: 11px text, muted gray, 1px border with a slightly thicker
   BOTTOM edge for the physical-key look, 4px corners.
   ============================================================ */
.kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; padding: 2px 6px; border-radius: 4px;
  font: 500 11px/1.35 Inter; color: var(--muted-foreground);
  background: var(--surface); border: 1px solid var(--line); border-bottom-width: 2px;
}
.kbd .ico { width: 12px; height: 12px; }

/* A detail-panel close control: a quiet ✕ icon button with the shared "esc" key
   chip beside it. Used on the chapter drawer and the slide-in admin/calendar
   panels, so every panel closes the same way and advertises the same shortcut. */
.close-ctl { display: inline-flex; align-items: center; gap: 6px; flex: none; }
.close-ctl .close-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: none; padding: 0; border-radius: var(--radius);
  border: none; background: transparent; color: var(--muted-foreground); cursor: pointer;
  transition: background .12s, color .12s;
}
.close-ctl .close-x:hover { background: var(--surface-hover); color: var(--foreground); }
.close-ctl .close-x .ico { width: 17px; height: 17px; }

/* ============================================================
   Command palette (Cmd/Ctrl-K) - public/search.js.
   ============================================================ */
.cmd-open {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  padding: 6px 10px; border-radius: var(--radius);
  background: var(--card); border: 1px solid var(--line-strong);
  color: var(--muted-foreground); font-size: 13px; font-weight: 500;
  transition: background .12s, border-color .12s;
}
.cmd-open:hover { border-color: var(--line-strong); background: var(--surface-hover); }
.cmd-open .ico { width: 15px; height: 15px; }
/* ⌘K hint - the shared .kbd look; no bespoke styling of its own. */
@media (max-width: 720px) { .cmd-open-label, .cmd-open-kbd { display: none; } .cmd-open { padding: 7px; } }

.cmd-overlay {
  position: fixed; inset: 0; z-index: 200; padding: 12vh 20px 20px;
  background: rgba(0,0,0,.5); backdrop-filter: blur(2px);
  display: flex; align-items: flex-start; justify-content: center;
  animation: cmd-fade .12s ease-out;
}
@keyframes cmd-fade { from { opacity: 0; } to { opacity: 1; } }

.cmd-panel {
  width: 100%; max-width: 620px; max-height: 74vh; display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--card-radius);
  box-shadow: var(--shadow-pop); overflow: hidden;
  animation: cmd-rise .14s ease-out;
}
@keyframes cmd-rise { from { transform: translateY(-8px); opacity: .6; } to { transform: none; opacity: 1; } }

.cmd-search { display: flex; align-items: center; gap: 11px; padding: 13px 16px; border-bottom: 1px solid var(--line); }
.cmd-search-ic { display: inline-flex; color: var(--muted-foreground); }
.cmd-search-ic .ico { width: 18px; height: 18px; }
.cmd-search input {
  flex: 1; border: none; background: transparent; color: var(--foreground);
  font: 400 15px/1.4 Inter; padding: 0; outline: none; box-shadow: none;
}
.cmd-search input:focus { box-shadow: none; }
/* .cmd-esc is just a .kbd chip - shared styling, no bespoke rules. */

.cmd-list { overflow-y: auto; padding: 6px 6px 8px; }
.cmd-note { padding: 24px 18px; text-align: center; font-size: 13px; color: var(--muted-foreground); }

/* Group header - Raycast-style small muted label above each type's rows. */
.cmd-group {
  font: 500 11px/1 Inter; letter-spacing: .01em; color: var(--muted-2);
  padding: 12px 12px 5px;
}
.cmd-list > .cmd-group:first-child { padding-top: 4px; }

.cmd-row {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  min-height: 44px; padding: 4px 10px; border-radius: 6px; border: none;
  background: transparent; color: var(--foreground); cursor: pointer;
}
/* Selected row: clear full-row neutral fill, no border blob (Alfred-style). */
.cmd-row.on { background: var(--surface-hover); }
/* Fixed 32px slot so every title starts at the same x. Line icon, muted, no box. */
.cmd-ic {
  flex: none; width: 32px; height: 32px; display: grid; place-items: center;
  color: var(--muted-foreground);
}
.cmd-ic .ico { width: 16px; height: 16px; }
.cmd-main {
  flex: 1; min-width: 0; display: flex; flex-direction: column;
  justify-content: center; gap: 1px;
}
.cmd-title {
  font: 400 14px/1.35 Inter; color: var(--foreground);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cmd-sub {
  font: 400 12px/1.3 Inter; color: var(--muted-foreground);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Matched characters: bold, same colour - no background highlight. */
.cmd-hl { font-weight: 600; color: inherit; }
/* The only affordance on the selected row: a quiet enter hint at the right. */
.cmd-enter {
  flex: none; opacity: 0; color: var(--muted-foreground);
  display: inline-flex; align-items: center; padding-right: 4px;
}
.cmd-enter .ico { width: 14px; height: 14px; }
.cmd-row.on .cmd-enter { opacity: 1; }
/* Marks the mode an Actions row already has in force - same accent tick as the
   sidebar's own mode popover (.sb-opt-check), so the two read as one control. */
.cmd-check { flex: none; display: inline-flex; align-items: center; color: var(--primary); }
.cmd-check .ico { width: 14px; height: 14px; }
.cmd-more .cmd-title { color: var(--muted-foreground); font-weight: 500; }

.cmd-foot {
  display: flex; gap: 16px; padding: 9px 16px; border-top: 1px solid var(--line);
  font-size: 11px; color: var(--muted-2);
}
/* Footer hints are .kbd chips, one notch smaller and with a little trailing gap. */
.cmd-foot .kbd { font-size: 10px; min-width: 15px; padding: 2px 5px; margin-right: 3px; }
.cmd-foot .cmd-kbd-ic { padding: 2px 4px; }
@media (max-width: 560px) { .cmd-foot { display: none; } }

/* ---------- misc ---------- */
.empty { text-align: center; padding: 36px; }
.empty .ic { font-size: 30px; opacity: .7; }
.empty .t { font: 600 14px/1.5 Inter; margin-top: 8px; }
.empty .d { font-size: 12.5px; color: var(--muted-foreground); margin-top: 4px; }

.spinner {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid var(--line); border-top-color: var(--primary);
  animation: spin .8s linear infinite; margin: 0 auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

.callout {
  background: var(--gold-bg); border: 1px solid var(--gold-border); color: var(--gold-fg);
  border-radius: var(--radius); padding: 12px; font-size: 12.5px; line-height: 1.6;
}
/* Status variant: something needs attention (e.g. calls with no join link). Gold
   is for insight, so a warning gets the amber status tokens instead. */
.callout.warn {
  background: var(--amber-bg); border-color: rgba(169,118,10,.34); color: var(--amber);
}
/* Section intro on the first screen of a wizard section - the doc's per-section
   framing. Gold = insight, so it reads as knowledge, not a status. */
.wiz-intro { margin: 0 0 16px; display: flex; gap: 8px; align-items: flex-start; }
.wiz-intro svg { flex: none; margin-top: 2px; }

/* Calendar Subscribe: the little popover, and the same links on the profile page. */
.sub-pop { min-width: 240px; max-width: 300px; }
/* Full-width stacked buttons - a flex-wrap row let two long labels (Apple
   Calendar + Outlook) share a line and spill past the popover edge. */
.sub-links { display: grid; grid-template-columns: 1fr; gap: 6px; }
.sub-links > * { width: 100%; box-sizing: border-box; text-align: center; }
.error-banner {
  background: rgba(209,47,47,.08); border: 1px solid rgba(209,47,47,.28); color: var(--red);
  border-radius: var(--radius); padding: 10px 13px; font-size: 13px; font-weight: 500; margin-bottom: 14px;
}

/* ---------- icons ---------- */
.ico { width: 15px; height: 15px; display: inline-block; vertical-align: -2px; flex: none; }
.ico-sm { width: 13px; height: 13px; }
.ico-lg { width: 20px; height: 20px; }
.empty .ico { width: 28px; height: 28px; opacity: .5; vertical-align: 0; }

/* The theme toggle is a .foot-row (layout comes from there); only the sun/moon
   swap is its own - show the icon for the mode you'd switch TO. */
.theme-toggle .ico-sun  { display: block; }
.theme-toggle .ico-moon { display: none; }
[data-theme="light"] .theme-toggle .ico-sun  { display: none; }
[data-theme="light"] .theme-toggle .ico-moon { display: block; }

.row { display: flex; gap: 10px; align-items: center; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
/* Tool tiles flow to fill the full page width - as many per row as fit, each at
   least 340px, so more tools wrap naturally instead of a fixed two-up column. */
.tools-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 14px; }
.muted { color: var(--muted-foreground); }
.hidden { display: none !important; }

/* ============================================================
   Course views
   ============================================================ */

/* --- GTM Framework diagram --- */
.gtm {
  display: grid; gap: 12px;
  grid-template-areas: "pos pos pos" "lead sales cs" "revops revops revops";
  grid-template-columns: 1fr 1fr 1fr;
}
.gtm-box {
  position: relative; border: 1px solid var(--line); border-radius: var(--card-radius);
  padding: 18px 16px 16px; background: var(--surface); cursor: pointer; text-align: center;
  transition: border-color .12s, background .12s;
  overflow: hidden;
}
.gtm-box:hover { border-color: var(--line-strong); background: var(--surface-hover); }
.gtm-box[data-pillar="positioning"] { grid-area: pos; }
.gtm-box[data-pillar="leadgen"] { grid-area: lead; }
.gtm-box[data-pillar="sales"] { grid-area: sales; }
.gtm-box[data-pillar="cs"] { grid-area: cs; }
.gtm-box[data-pillar="revops"] { grid-area: revops; }
.gtm-box .num {
  position: absolute; top: 12px; left: 12px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface-hover); color: var(--muted-foreground);
  font: 600 12px/22px Inter; text-align: center;
}
.gtm-box.done .num { background: var(--primary); color: var(--primary-fg); }
.gtm-box .t { font: 600 15px/1.35 Inter; margin: 6px 0 8px; }
.gtm-box .c { font-size: 12.5px; color: var(--muted-foreground); margin-bottom: 10px; }
.gtm-box .fill {
  position: absolute; left: 0; bottom: 0; height: 3px;
  background: var(--primary); box-shadow: none; transition: width .4s;
}
.gtm-box.done { background: var(--primary-08); border-color: var(--primary-30); }

/* --- Kanban --- */
.kanban { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 12px; align-items: flex-start; }
.kcol {
  flex: 0 0 280px; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--card-radius); padding: 12px;
}
.kanban.fit .kcol { flex: 1 1 0; min-width: 168px; padding: 10px; }
.kcol.dragover { border-color: var(--primary); background: var(--primary-08); }
/* Pointer-DnD: the column under the cursor gets a barely-there wash (a faint
   grey overlay that darkens light columns / lightens dark ones), so the drop
   zone is obvious at column level without shouting. */
.kcol.drop-active, .ops-board .kcol.drop-active {
  box-shadow: inset 0 0 0 999px rgba(128, 128, 128, .045);
}
.kcol h4 {
  font: 600 13px/1.4 Inter; text-transform: none; letter-spacing: 0;
  color: var(--muted-foreground); margin: 0 0 10px; display: flex; gap: 8px; align-items: center;
}
.kcol h4 .n {
  margin-left: auto; font-weight: 500; font-size: 12px;
  color: var(--muted-2); letter-spacing: 0;
}
.kcard {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 11px 12px; margin-bottom: 8px; cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
}
.kcard[data-drag] { cursor: grab; touch-action: none; }
.kcard:not(.dragging):hover { border-color: var(--line-strong); }

/* --- pointer drag/drop (see makeSortable in board.js) --- */
/* The card's own slot while it's in flight: a plain flat GRAY BLOCK, Asana-style,
   marking where the card will land. It IS the card (so it keeps the card's exact
   size), but its content is hidden and it carries no border, no shadow, and no
   track-colour tint - just a neutral slot. Its position is FLIP-animated in
   board.js, so it slides between valid positions. */
.kcard.dragging,
.ops-board .kcard.dragging {
  background: var(--dnd-slot);
  border-color: transparent;
  box-shadow: none; cursor: grabbing;
}
.kcard.dragging > * { visibility: hidden; }   /* no text */
.kcard.dragging::before { display: none; }     /* no track-colour stripe */
/* The floating clone that follows the cursor - tilt + shadow, click-through.
   `.kcard.dnd-ghost` (not bare `.dnd-ghost`) so it outweighs `.pmo-card`, which
   is `position: relative` and defined later - otherwise the clone would drop out
   of fixed positioning and no longer track the pointer. */
.kcard.dnd-ghost,
.dnd-ghost {
  position: fixed; left: 0; top: 0; margin: 0; z-index: 1000;
  pointer-events: none; cursor: grabbing;
  box-shadow: var(--shadow-pop); opacity: .97; will-change: transform;
}
body.dnd-dragging { cursor: grabbing; user-select: none; }
.kcard .head { display: flex; align-items: flex-start; gap: 9px; margin-bottom: 8px; }
.kcard .t { font: 500 13px/1.45 Inter; }
.kcard.done .t { color: var(--muted-foreground); }
.kcard .kcheck {
  width: 18px; height: 18px; border-radius: 50%; flex: none; margin-top: 1px;
  border: 1.5px solid var(--line-strong); display: grid; place-items: center;
  font-size: 10px; color: var(--primary); background: transparent; cursor: pointer;
}
.kcard .kcheck:hover { border-color: var(--primary); }
.kcard .kcheck.on { background: var(--primary); border-color: var(--primary); color: var(--primary-fg); }
.kcard .foot { display: flex; align-items: center; gap: 8px; }
.kcard .tasks { font-size: 11.5px; color: var(--muted-foreground); margin-left: auto; }

/* pillar tag - identity, kept neutral */
.pill-tag {
  display: inline-block; padding: 2px 8px; border-radius: 5px;
  font: 500 11px/1.6 Inter; background: var(--surface-hover);
  color: var(--muted-foreground); border: 1px solid var(--line);
}

/* Track tag - the coloured category chip. Colours come from `.track-<key>`,
   which is GENERATED from src track-colors.js so it can't drift. Asana-style:
   soft tint, no border, 11px, 4px radius. */
.ctag {
  display: inline-flex; align-items: center; padding: 2px 7px; border-radius: 4px;
  font: 600 11px/1.5 Inter; white-space: nowrap; border: none;
  background: var(--surface-hover); color: var(--muted-foreground);   /* fallback before a track class lands */
}

/* The 3px left accent stripe, shared by every card/section that carries a track
   class. An INSET box-shadow, not a border, so the card's own border-color
   hover can't recolour it. `--track-accent` is set by the generated rule. */
/* The PMO board (.kanban.fit) no longer wears the stripe - its track lives in
   the dot+label above the title - so this is scoped to the course kanban and
   the List sections, which still carry it. */
.kanban:not(.fit) .kcard[class*="track-"], .sec-box[class*="track-"] {
  box-shadow: inset 3px 0 0 var(--track-accent, transparent);
}
.kanban:not(.fit) .kcard[class*="track-"] { padding-left: 13px; }

/* Track dot - a bare colour disc that stands in for the tag text. Colour rides
   on `--track-accent` (set by the generated `.track-<key>` class on the same
   element), so it can never drift from the borders and tags. Used in the PMO
   legend and the List section header. */
.tdot {
  display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 50%;
  background: var(--track-accent, var(--muted-foreground));
}

/* The PMO board legend - the one place the board names its tracks in text.
   Right-aligned on the card-title line, quiet, wraps if the row runs out. */
.track-legend {
  margin-left: auto; display: flex; flex-wrap: wrap; align-items: center;
  gap: 4px 13px; justify-content: flex-end;
}
.track-legend-item {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  font: 500 11.5px/1 Inter; color: var(--muted-foreground);
}

/* --- List view --- */
.lsec { margin-bottom: 22px; }
.lsec h3 {
  font: 600 13px/1.4 Inter; text-transform: none; letter-spacing: 0;
  color: var(--muted-foreground); margin: 0 0 10px;
}
.lrow {
  display: flex; align-items: center; gap: 12px; padding: 11px 13px;
  border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 7px;
  background: var(--card); cursor: pointer;
  transition: border-color .12s, background .12s;
}
.lrow:hover { border-color: var(--line-strong); background: var(--surface); }
.lrow .tick {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  border: 1.5px solid var(--line-strong); display: grid; place-items: center;
  color: var(--primary); background: transparent; padding: 0;
}
.lrow .tick .ico { width: 12px; height: 12px; vertical-align: 0; }
.lrow.done .tick { background: var(--primary); color: var(--primary-fg); border-color: var(--primary); }
.lrow .t { font-weight: 500; flex: 1; }
.lrow.done .t { color: var(--muted-foreground); }

/* --- module reader --- */
.mod-body { font-size: 14px; line-height: 1.75; }
.mod-body h3 { font: 600 15px/1.4 Inter; text-transform: none; letter-spacing: 0;
  color: var(--foreground); margin: 22px 0 8px; }
.mod-body p { margin: 0 0 12px; }
.mod-body a { color: var(--primary); }
.mod-body img { max-width: 100%; border-radius: var(--card-radius); }
.mod-body .import-todo {
  background: var(--gold-bg); border: 1px solid var(--gold-border); color: var(--gold-fg);
  border-radius: var(--radius); padding: 10px 12px; font-size: 12.5px;
}
.mod-body .import-todo a { color: var(--gold-fg); text-decoration: underline; }
.video-wrap {
  position: relative; padding-bottom: 56.25%; height: 0; border-radius: var(--card-radius); overflow: hidden;
  border: 1px solid var(--line); margin-bottom: 16px; background: #000;
}
.video-wrap iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.checklist { list-style: none; padding: 0; margin: 0; }
.checklist li {
  display: flex; gap: 11px; align-items: flex-start; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 7px;
  background: var(--card); cursor: pointer; font-size: 13px; line-height: 1.55;
}
.checklist li:hover { border-color: var(--line-strong); }
.checklist li .box {
  width: 18px; height: 18px; border-radius: 5px; flex: none; margin-top: 1px;
  border: 1.5px solid var(--line-strong); display: grid; place-items: center;
  color: var(--primary-fg);
}
.checklist li .box .ico { width: 12px; height: 12px; vertical-align: 0; }
.checklist li.done .box { background: var(--primary); border-color: var(--primary); }
.checklist li.done span { color: var(--muted-foreground); text-decoration: line-through; }

/* --- achievements --- */
.badges { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
.badge-card {
  border: 1px solid var(--line); border-radius: var(--card-radius); padding: 16px; text-align: center;
  background: var(--surface); opacity: .5; filter: grayscale(1);
}
.badge-card.earned {
  opacity: 1; filter: none; border-color: var(--primary-30); background: var(--primary-08);
}
.badge-card .ic { font-size: 28px; }
.badge-card .t { font: 600 13px/1.4 Inter; margin: 7px 0 4px; }
.badge-card .d { font-size: 11.5px; color: var(--muted-foreground); line-height: 1.5; }
.badge-card .when { font-size: 10.5px; color: var(--primary); font-weight: 600; margin-top: 7px; }

/* toast */
.toast {
  position: fixed; right: 22px; bottom: 22px; z-index: 200;
  display: flex; gap: 12px; align-items: center;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--card-radius);
  padding: 13px 16px; box-shadow: var(--shadow-pop); animation: pop .3s ease-out;
}
.toast .ic { font-size: 24px; }
.toast .t { font: 600 13px/1.3 Inter; }
.toast .d { font-size: 11.5px; color: var(--muted-foreground); }
@keyframes pop { from { transform: translateY(14px); opacity: 0; } to { transform: none; opacity: 1; } }

/* --- tools --- */
.tool-sec { border-top: 1px solid var(--line); padding-top: 18px; margin-top: 18px; }
.tool-sec:first-child { border-top: none; padding-top: 0; margin-top: 0; }
.tool-sec > h3 { font: 600 15px/1.4 Inter; margin: 0 0 5px; }
.tool-sec > .blurb { font-size: 12.5px; color: var(--muted-foreground); line-height: 1.6; margin-bottom: 14px; }
.banned { background: rgba(209,47,47,.12); border-bottom: 1.5px solid var(--red); }
.saved-note { font-size: 12px; color: var(--primary); font-weight: 600; }
.trow { display: grid; gap: 8px; margin-bottom: 8px; align-items: start; }
.trow .del {
  background: none; border: none; color: var(--muted-foreground); font-size: 16px; padding: 8px 4px;
}
.trow .del:hover { color: var(--red); }

/* --- tools: wizard --- */
/* De-boxed: the wizard sits directly on the page background (no outer card).
   The gap stands in for the padding the removed card used to give the content
   column, so the body keeps a gutter from the rail rather than hugging it. */
/* The wizard is a LEFT-anchored two-column layout: the rail sits flush against
   the sidebar (the page's own 24px padding is the only gutter), never a centred
   island. So the tools page opts out of the centred 1080px column. */
/* FIT layout, same pattern as the calendar page: the wizard owns the viewport,
   the page itself never scrolls, and the Back/Continue bar is pinned under a
   single scroll region (.wiz-stage) instead of riding the content. Released
   again under 900px, where an on-screen keyboard needs normal page scroll. */
.content:has(.main.wiz-page) { height: calc(100dvh - var(--topbar-h)); overflow: hidden; }
.main.wiz-page {
  flex: 1 1 auto; min-height: 0; max-width: none; margin: 0;
  padding: 20px 24px 0; overflow: hidden;
  display: flex; flex-direction: column;
}
.wiz { display: flex; gap: 44px; align-items: flex-start; flex: 1 1 auto; min-height: 0; }

/* left step rail - flush to the content column's left edge, its own scroller
   (the page no longer scrolls, so there is nothing left to stick to) */
.wiz-rail {
  width: 230px; flex: none; align-self: stretch; min-height: 0; overflow-y: auto;
}
.wiz-steplist { display: flex; flex-direction: column; gap: 2px; }
.wiz-node {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 8px 10px; border: none; background: none; border-radius: var(--radius);
  color: var(--muted-foreground); font: 500 13px/1.35 Inter; cursor: pointer;
  transition: background .12s, color .12s;
}
.wiz-node:hover { background: var(--surface-hover); color: var(--foreground); }
.wiz-node-t { min-width: 0; }
.wiz-step .wiz-node-t { flex: 1; }
.wiz-mark {
  width: 22px; height: 22px; flex: none; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font: 600 11px/1 Inter; border: 1px solid var(--line-strong);
  background: var(--card); color: var(--muted-foreground);
}
.wiz-mark .ico { width: 13px; height: 13px; }
.wiz-mark.done { background: var(--primary-12); border-color: var(--primary-30); color: var(--primary); }
.wiz-mark.current { background: var(--primary); border-color: var(--primary); color: var(--primary-fg); }
.wiz-node.is-current { color: var(--primary); font-weight: 700; background: var(--primary-08); }
.wiz-node.is-done .wiz-node-t { color: var(--foreground); }
/* "n/total" position pill on the active step */
.wiz-pos {
  flex: none; font: 600 11px/1 Inter; color: var(--muted-foreground);
  background: var(--surface); border-radius: 9999px; padding: 3px 8px;
}
.wiz-node.is-current .wiz-pos { background: var(--primary-12); color: var(--primary); }
/* sub-items: the fields of the current step */
.wiz-sub { padding: 6px 10px; font-size: 12.5px; }
.wiz-subdot {
  width: 7px; height: 7px; flex: none; border-radius: 50%;
  background: var(--line-strong); margin-left: 7px;
}
.wiz-sub.is-current { color: var(--primary); font-weight: 600; }
.wiz-sub.is-current .wiz-subdot { background: var(--primary); box-shadow: 0 0 0 3px var(--primary-12); }
.wiz-sub.is-done .wiz-subdot { background: var(--primary); }
.wiz-sub.is-done .wiz-node-t { color: var(--foreground); }
.wiz-subs {
  display: flex; flex-direction: column; gap: 1px;
  margin: 2px 0 4px 21px; padding-left: 10px; border-left: 1px solid var(--line);
}
/* compact rail (dropdown + slim bar) - only shown under 900px */
.wiz-rail-compact { display: none; flex-direction: column; gap: 10px; }
.wiz-rail-compact .progress-bar-wrap { height: 4px; }

/* right content column - LEFT-aligned to the rail. Three stacked parts: the
   progress row (fixed), the stage (the only scroller) and the pinned nav. */
.wiz-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; }
.wiz-progress {
  flex: none; margin: 0 0 20px; display: flex; align-items: center; gap: 12px;
}
.wiz-progress .progress-bar-wrap { flex: 1; height: 4px; }
.wiz-count { font: 500 11.5px/1 Inter; color: var(--muted-foreground); white-space: nowrap; }

/* The stage: field column + context aside. The field column keeps a READABLE
   measure; the width left over goes to the aside rather than to a dead gutter. */
.wiz-stage {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-bottom: 8px;
  display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 0 34px;
  align-items: start;
}
.wiz-body { max-width: 760px; margin: 0; }
.wiz-aside { position: sticky; top: 0; display: flex; flex-direction: column; gap: 14px; }

/* A wide screen (map, persona grid, tiles, tables, Review) takes the whole
   stage; the aside drops to a row underneath and keeps only the summary bar. */
.wiz-stage.is-wide { grid-template-columns: minmax(0, 1fr); }
.wiz-stage.is-wide .wiz-body { max-width: none; }
.wiz-stage.is-wide .wiz-aside { position: static; }
.wiz-stage.is-wide .wiz-aside-step, .wiz-stage.is-wide .wiz-aside-tips { display: none; }
/* Two presentations, one source: when the aside shows the tips, the heading's
   "?" chip would be a duplicate, so it stands down. */
.wiz-stage:not(.is-wide) .wiz-tipsq { display: none; }

/* aside blocks - tokens only, no new colour: a hairline frame on the surface */
.wiz-aside-where {
  font: 600 11px/1 Inter; letter-spacing: .04em; text-transform: uppercase;
  color: var(--primary); margin-bottom: 6px;
}
.wiz-aside-title { font: 600 14px/1.4 Inter; color: var(--foreground); }
.wiz-aside-tips {
  border: 1px solid var(--line); border-radius: var(--card-radius);
  background: var(--surface); padding: 13px 15px;
}
.wiz-aside-h {
  display: flex; align-items: center; gap: 7px; font: 600 12px/1.3 Inter;
  color: var(--primary); margin-bottom: 8px;
}
.wiz-aside-tips ul {
  margin: 0; padding-left: 18px; line-height: 1.7; font-size: 12.5px; color: var(--muted-foreground);
}
.wiz-aside-tips li { margin-bottom: 5px; }
.wiz-aside-tips li:last-child { margin-bottom: 0; }
/* In the aside column the summary reads as a stacked card; in wide mode it
   stays the one-line bar it has always been, under the fields. */
.wiz-stage:not(.is-wide) .wiz-summary {
  margin-top: 0; flex-direction: column; align-items: flex-start; gap: 8px;
}

.wiz-head { margin-bottom: 18px; }
.wiz-stepno { font: 600 11px/1 Inter; letter-spacing: .04em; text-transform: uppercase; color: var(--primary); margin-bottom: 7px; }
.wiz-title-row { display: flex; align-items: center; gap: 9px; margin-bottom: 6px; }
.wiz-title { font: 600 20px/1.3 Inter; margin: 0; }
.wiz-purpose { font-size: 13px; color: var(--muted-foreground); line-height: 1.6; margin: 0; }

.wiz-human { margin-bottom: 16px; font-size: 12px; padding: 10px 12px; }

/* tips as a small "?" next to the heading, revealing a popover */
.wiz-tipsq { position: relative; flex: none; }
.wiz-tipsq > summary {
  cursor: pointer; list-style: none; width: 20px; height: 20px; border-radius: 50%;
  border: 1px solid var(--line-strong); background: var(--card); color: var(--muted-foreground);
  font: 700 12px/1 Inter; display: inline-flex; align-items: center; justify-content: center;
  transition: background .12s, color .12s, border-color .12s;
}
.wiz-tipsq > summary::-webkit-details-marker { display: none; }
.wiz-tipsq > summary:hover { color: var(--primary); border-color: var(--primary-30); }
.wiz-tipsq[open] > summary { background: var(--primary); color: var(--primary-fg); border-color: var(--primary); }
.wiz-tipsq-pop {
  position: absolute; z-index: 60; top: 28px; left: 0; width: 330px; max-width: 78vw;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--card-radius);
  box-shadow: var(--shadow-pop); padding: 12px 14px;
}
.wiz-tipsq-h { display: flex; align-items: center; gap: 7px; font: 600 12px/1.3 Inter; color: var(--primary); margin-bottom: 8px; }
.wiz-tipsq-pop ul { margin: 0; padding-left: 18px; line-height: 1.7; font-size: 12.5px; color: var(--muted-foreground); }
.wiz-tipsq-pop li { margin-bottom: 5px; }

/* one field per screen */
.wiz-body .field { margin-bottom: 18px; }
.wiz-body label.fl { font-size: 14px; font-weight: 500; }
.wiz-body .field .help { font-size: 12px; }
/* Bare screen: hide the single field's own label + help (the heading carries
   them). Direct children only, so a widget's nested subfield labels survive.
   The live banned-buzzword warning is NOT help text, so it stays visible. */
.wiz-fields.is-bare > .field > label.fl { display: none; }
.wiz-fields.is-bare > .field > .help:not(.banned-note) { display: none; }
.wiz-fields.is-bare > .field { margin-bottom: 0; }
/* A multi-field screen on a wide stage (the matched competitor / USP tables)
   sits side by side rather than stacking two half-empty builders. */
.wiz-stage.is-wide .wiz-fields:not(.is-bare) {
  display: grid; gap: 24px; align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
}

/* continue / back - pinned below the stage, so it never scrolls away */
.wiz-nav {
  flex: none; display: flex; align-items: center; margin-top: 0;
  padding: 16px 0; border-top: 1px solid var(--line); background: var(--background);
}

/* personas as a 2-col card grid */
.persona-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: start; }
.persona {
  border: 1px solid var(--line); border-radius: var(--card-radius); padding: 13px 14px;
  background: var(--surface); transition: border-color .12s;
}
.persona[open] { border-color: var(--line-strong); background: var(--card); grid-column: 1 / -1; }
.persona.is-filled { border-color: var(--primary-30); }
.persona > summary { cursor: pointer; }
.persona > summary::-webkit-details-marker { display: none; }
.persona-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.persona h4 { font: 600 13.5px/1.4 Inter; margin: 0; color: var(--foreground); }
.persona .role { font-size: 11.5px; color: var(--muted-foreground); margin-top: 5px; line-height: 1.5; }
.persona-empty {
  font: 500 11px/1 Inter; color: var(--muted-2); padding: 2px 7px;
  border: 1px solid var(--line); border-radius: 9999px;
}
.persona-body { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }

/* review "document" - columns of sections, so the whole positioning is readable
   without scrolling a single narrow ribbon. Every section keeps its hairline
   rule (no first-child exception: in a grid the "first" one is per column). */
.rv-doc {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
  gap: 0 34px; align-items: start;
}
.rv-sec { border-top: 1px solid var(--line); padding: 18px 0; }
.rv-open { grid-column: 1 / -1; }
.rv-sec-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.rv-sec-head h3 { font: 600 15px/1.4 Inter; margin: 0; }
.rv-none { font-size: 12.5px; color: var(--muted-2); font-style: italic; }
.rv-f { margin-bottom: 13px; }
.rv-l { font: 500 12px/1.4 Inter; color: var(--muted-foreground); margin-bottom: 3px; }
.rv-v { font-size: 13.5px; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
.rv-list { margin: 2px 0 0; padding-left: 18px; font-size: 13.5px; line-height: 1.7; }
.rv-rows { display: flex; flex-direction: column; gap: 8px; }
.rv-row {
  border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px;
  background: var(--surface); display: flex; flex-direction: column; gap: 7px;
}
.rv-cell { font-size: 13px; line-height: 1.55; overflow-wrap: anywhere; }
.rv-ck { display: block; font: 500 11px/1.4 Inter; color: var(--muted-foreground); margin-bottom: 1px; }
.rv-persona {
  border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px;
  background: var(--surface); margin-top: 8px; display: flex; flex-direction: column; gap: 7px;
}
.rv-persona h4 { font: 600 13px/1.4 Inter; margin: 0 0 2px; }
.rv-open { border-top: 1px solid var(--line); padding-top: 18px; margin-top: 8px; }
.rv-open h3 { font: 600 14px/1.4 Inter; margin: 0 0 10px; display: flex; align-items: center; gap: 6px; }
.rv-open h3 .muted { font-weight: 500; }
.rv-open ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.rv-open li { font-size: 12.5px; }
.rv-jump {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--primary); font: 600 12.5px/1.4 Inter; text-decoration: underline;
}
.rv-alldone h3 { color: var(--primary); }
.rv-alldone h3 .ico { width: 15px; height: 15px; }

/* ---------- responsive ----------
   Below 768px the sidebar leaves the flow and becomes an overlay drawer: it
   slides in from the left over a scrim, toggled by the top-bar hamburger. It
   keeps its FULL labelled layout here (it is not a rail), so the collapsed-rail
   rules above - all gated to >=768px - never touch it. */
@media (max-width: 767px) {
  .nav-burger { display: inline-flex; }

  /* The brand slot shrinks to its content so the hamburger + page title fit. */
  .brand { width: auto; padding-left: 16px; }

  /* The sidebar becomes an overlay drawer: full labelled layout (the rail rules
     are all gated to >=768px), slid off-screen until the hamburger opens it. Hover
     mode never fires here - the drawer is all-or-nothing. Content takes the full
     width; the drawer floats over it. */
  .content { margin-left: 0; }
  .sidebar {
    top: var(--topbar-h); width: 264px; z-index: 120;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: none;
  }
  body.nav-open .sidebar { transform: translateX(0); box-shadow: 6px 0 30px rgba(16, 24, 24, .22); }

  /* Scrim only exists while the drawer is open - this override beats both the
     element's [hidden] attribute and the base .nav-scrim rule. */
  body.nav-open .nav-scrim {
    display: block; position: fixed; inset: var(--topbar-h) 0 0 0; z-index: 110;
    background: rgba(16, 24, 24, .38);
  }
}
@media (max-width: 760px) {
  .topbar { padding: 8px 14px; }
  .main { padding: 20px 14px 56px; }
  .card { padding: 15px 15px; }
  .grid2, .grid3 { grid-template-columns: 1fr; }
  .metrics { grid-template-columns: repeat(2, 1fr); }
  .gtm { grid-template-areas: "pos" "lead" "sales" "cs" "revops"; grid-template-columns: 1fr; }
  .tabs { width: 100%; }
  table.data { min-width: 700px; }
  .persona-grid { grid-template-columns: 1fr; }
}
/* Under 1280px there is no room for a second column: the aside drops below the
   fields and keeps only the summary, and the tips go back into the "?" chip. */
@media (max-width: 1279px) {
  .wiz-stage { grid-template-columns: minmax(0, 1fr); }
  .wiz-stage .wiz-body { max-width: none; }
  .wiz-stage .wiz-aside { position: static; }
  .wiz-stage .wiz-aside-step, .wiz-stage .wiz-aside-tips { display: none; }
  /* both selectors match the :not(.is-wide) rules above, so they win on order */
  .wiz-stage:not(.is-wide) .wiz-tipsq { display: block; }
  .wiz-stage:not(.is-wide) .wiz-summary {
    margin-top: 22px; flex-direction: row; align-items: center; gap: 8px 10px;
  }
}

/* Under 900px the rail collapses to a top progress bar + a step dropdown, and
   the viewport lock is released - a phone with an on-screen keyboard needs the
   page to scroll normally (the calendar page does exactly the same). */
@media (max-width: 900px) {
  .content:has(.main.wiz-page) { height: auto; overflow: visible; }
  .main.wiz-page { overflow: visible; padding: 20px 24px 56px; }
  .wiz { flex-direction: column; gap: 14px; }
  .wiz-rail {
    width: 100%; align-self: auto; overflow: visible;
    padding-bottom: 14px; margin-bottom: 2px; border-bottom: 1px solid var(--line);
  }
  .wiz-steplist { display: none; }
  .wiz-rail-compact { display: flex; }
  .wiz-rail-select {
    width: 100%; padding: 9px 12px; border: 1px solid var(--line-strong);
    border-radius: var(--radius); background: var(--card); color: var(--foreground);
    font: 500 13px/1.3 Inter; cursor: pointer;
  }
  .wiz-stage { overflow: visible; }
  .wiz-nav { padding-bottom: 0; }
}

/* ============================================================
   Hackathon - calendar + scorecard
   ============================================================ */
.cal-head { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.cal-key { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--muted-foreground); }
.cal-key i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-dow {
  font: 500 11px/1 Inter; text-transform: none; letter-spacing: 0;
  color: var(--muted-foreground); text-align: center; padding: 6px 0;
}
.cal-cell {
  position: relative; min-height: 90px; padding: 6px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.cal-cell.out { background: transparent; border-color: transparent; }
.cal-cell.today { border-color: var(--primary); background: var(--primary-08); }
.cal-cell .d { font: 500 11px/1 Inter; color: var(--muted-foreground); margin-bottom: 5px; }
.cal-cell.today .d { color: var(--primary); }
.cal-cell:hover .cal-add { opacity: 1; }
.cal-add {
  position: absolute; top: 4px; right: 4px; opacity: 0;
  width: 20px; height: 20px; border-radius: 5px; line-height: 1;
  border: 1px solid var(--line-strong); background: var(--card); color: var(--primary);
  transition: opacity .12s;
}

.cal-ev {
  display: flex; align-items: center; gap: 4px; width: 100%; text-align: left;
  border: none; border-radius: 5px; padding: 3px 5px; margin-bottom: 3px;
  font: 500 10.5px/1.35 Inter; color: var(--foreground);
  background: var(--surface-hover); cursor: pointer;
}
.cal-ev .cdot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.cal-ev .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.cal-ev .tm { font-weight: 600; opacity: .7; font-size: 9.5px; white-space: nowrap; }
.cal-ev .rec { flex: none; width: 11px; height: 11px; opacity: .55; }
.cal-ev:hover { filter: brightness(1.06); }

/* ============================================================
   Calendar - FIT layout (the participant #calendar page).
   The whole page is the grid: week rows that divide ALL remaining viewport
   height equally. The month nav, date range and legend live in the top bar
   (see .tb-monthnav / .tb-range / .cal-legend-btn), so there is no in-page
   header row here - no card, no page scroll.
   ============================================================ */
/* The page owns the viewport exactly, so the SHELL must stop adding its own.
   .content's top margin (the top bar's height) COLLAPSES out through .app-body,
   .app-shell and body - none of them has padding, a border or a BFC - so the
   shell box already starts one bar-height down the page. Leaving their
   min-height: 100vh in place would then stack a full viewport UNDER that
   collapsed margin and the page would scroll by exactly the bar's height. Every
   other page is taller than the viewport anyway, which is why it only ever shows
   up here. min-height: 0 on .content also stops the base vh minimum from beating
   the dvh height where browser chrome makes 100vh > 100dvh. */
html:has(.main.cal-view), body:has(.main.cal-view) { overflow: hidden; }
body:has(.main.cal-view), .app-shell:has(.main.cal-view) { min-height: 0; }
.content:has(.main.cal-view) {
  height: calc(100dvh - var(--topbar-h)); min-height: 0; overflow: hidden;
}
.main.cal-view {
  flex: 1 1 auto; min-height: 0; max-width: none; margin: 0;
  padding: 16px 20px; overflow: hidden;
  display: flex; flex-direction: column;
}
.cal-fit { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }

/* collapsed grid: 1px lines shown through the gaps, one outer border, no radius per cell.
   First row auto (weekday labels), then one 1fr row per week so they share the height. */
.cal-grid.fit {
  flex: 1 1 auto; min-height: 0; gap: 1px;
  grid-template-rows: auto repeat(var(--weeks, 5), minmax(0, 1fr));
  background: var(--line); border: 1px solid var(--line);
  border-radius: var(--card-radius); overflow: hidden;
}
.cal-grid.fit .cal-dow { background: var(--card-bg); padding: 6px 0 5px; }
.cal-grid.fit .cal-cell {
  min-height: 0; border: none; border-radius: 0; padding: 3px 4px;
  background: var(--card-bg); display: flex; flex-direction: column; overflow: hidden;
}
.cal-grid.fit .cal-cell.out { background: var(--surface); }   /* days outside the month: muted */
.cal-grid.fit .cal-cell.today { background: var(--primary-08); }
.cal-grid.fit .cal-cell .d {
  font: 500 12px/1 Inter; color: var(--muted-foreground); margin: 1px 0 3px 1px; flex: none;
}
.cal-grid.fit .cal-cell.today .d {
  align-self: flex-start; display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 4px; border-radius: 999px;
  background: var(--primary); color: var(--primary-fg); font-weight: 600; margin-bottom: 3px;
}
/* the event bars stack in the remaining cell height; fitCalCells() trims the overflow */
.cal-grid.fit .cal-evs { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.cal-grid.fit .cal-ev {
  gap: 5px; height: 18px; padding: 0 5px; margin-bottom: 2px; border-radius: 4px;
  background: var(--surface-hover); font-size: 11px; line-height: 18px;
}
.cal-grid.fit .cal-ev .cdot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.cal-grid.fit .cal-more {
  font: 500 10.5px/1 Inter; color: var(--muted-foreground);
  padding: 2px 5px; cursor: default;
}

/* The five categories - identity colour, drawn from the app palette.
   topic = teal, coach = blue, implementation = purple, judge = amber, deadline = red. */
i.k-topic          { background: var(--primary); }
i.k-coach          { background: var(--blue); }
i.k-implementation { background: var(--purple); }
i.k-judge          { background: var(--amber); }
i.k-deadline       { background: var(--red); }

/* All-day banners (self-paced categories): a muted tinted bar, no time - kept
   visually lighter than a timed call bar so the month doesn't read as meetings. */
.cal-band {
  display: flex; align-items: center; gap: 5px; width: 100%; text-align: left;
  border: none; border-radius: 4px; padding: 1px 6px; margin-bottom: 2px;
  font: 500 10.5px/1.6 Inter; color: var(--muted-foreground); cursor: pointer; overflow: hidden;
}
.cal-band .cdot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.cal-band .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.cal-band:hover { filter: brightness(1.04); }
.cal-band.k-topic          { background: var(--primary-08); }
.cal-band.k-implementation { background: var(--purple-bg); }
.cal-band.k-deadline       { background: var(--red-bg); color: var(--red); }
.cal-grid.fit .cal-band { height: 16px; line-height: 16px; padding: 0 6px; }

/* "Hackathon starts Sep 1 ->" - the jump hint next to the month nav, shown when
   the current month is empty and the cohort is still ahead. */
.cal-hint {
  display: inline-flex; align-items: center; gap: 3px; white-space: nowrap;
  font: 500 12px/1 Inter; color: var(--primary);
  background: var(--primary-08); border: 1px solid var(--primary-30);
  padding: 5px 10px; border-radius: 999px; cursor: pointer;
}
.cal-hint:hover { background: var(--primary-12); }
.cal-hint .ico { width: 13px; height: 13px; }

/* Event details popover - opens anchored to the clicked event (uses .pop). */
.cal-pop { outline: none; display: flex; flex-direction: column; gap: 7px; }
.cal-pop-cat {
  display: inline-flex; align-items: center; gap: 6px;
  font: 600 11px/1 Inter; text-transform: uppercase; letter-spacing: .03em;
  color: var(--muted-foreground);
}
.cal-pop-cat i { width: 8px; height: 8px; border-radius: 50%; }
.cal-pop-title { font: 600 14px/1.3 Inter; color: var(--foreground); }
.cal-pop-when { font: 500 12px/1.4 Inter; color: var(--muted-foreground); }
.cal-pop-desc { font: 400 12.5px/1.5 Inter; color: var(--foreground); white-space: pre-wrap; }
.cal-pop-actions { display: flex; gap: 6px; margin-top: 3px; }
.cal-pop-actions:empty { display: none; }
/* Admin-only inline recording editor - paste a Fathom link straight on the call. */
.cal-pop-rec { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
.cal-pop-rec .fl { display: inline-flex; align-items: center; gap: 4px; margin-bottom: 4px; }
.cal-pop-rec .fl .ico { width: 12px; height: 12px; }

/* Admin event editor - a right-hand side panel (not a modal), so the calendar
   stays visible while you edit a day. */
.cal-panel-overlay { position: fixed; inset: 0; z-index: 120; background: rgba(0, 0, 0, .28); }
[data-theme="light"] .cal-panel-overlay { background: rgba(16, 24, 24, .18); }
.cal-panel {
  position: fixed; top: 0; right: 0; height: 100vh; width: min(420px, 94vw);
  background: var(--background); border-left: 1px solid var(--line);
  box-shadow: -12px 0 40px rgba(0, 0, 0, .22);
  transform: translateX(100%); transition: transform .28s cubic-bezier(.32, .72, 0, 1);
  display: flex; flex-direction: column;
}
[data-theme="light"] .cal-panel { box-shadow: -12px 0 40px rgba(16, 24, 24, .10); }
.cal-panel.show { transform: translateX(0); }
.cal-panel-head { display: flex; align-items: center; gap: 10px; padding: 18px 20px; border-bottom: 1px solid var(--line); }
.cal-panel-head h3 { margin: 0; font: 600 16px/1.2 Inter; flex: 1; }
.cal-panel-body { flex: 1 1 auto; overflow-y: auto; padding: 18px 20px; }
.cal-panel-foot { display: flex; align-items: center; gap: 8px; padding: 14px 20px; border-top: 1px solid var(--line); }
/* The "Pacific Time" tag on the time-field labels - times are always entered in PT. */
.fl-tz { font: 500 10.5px/1 Inter; text-transform: none; letter-spacing: 0; color: var(--primary); margin-left: 6px; }

/* --- leaderboard --- */
.lb { display: grid; gap: 6px; }
.lb-row {
  display: flex; align-items: center; gap: 12px; padding: 9px 12px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--card);
}
.lb-row.me { border-color: var(--primary-30); background: var(--primary-08); }
.lb-row .rank {
  width: 26px; text-align: center; font: 600 13px/1 Inter; color: var(--muted-foreground);
}
.lb-row .rank.gold { font-size: 16px; }
.lb-row .who { font-weight: 500; min-width: 120px; }
.lb-row .bar { flex: 1; height: 6px; border-radius: 4px; background: var(--bar-track); overflow: hidden; }
.lb-row .bar i { display: block; height: 100%; background: var(--primary-30); border-radius: 4px; }
.lb-row.me .bar i { background: var(--primary); }
.lb-row .pts { font: 600 13px/1 Inter; min-width: 62px; text-align: right; }

/* --- scorecard table --- */
table.data.score td.crit { padding-left: 22px; font-size: 12.5px; }
table.data.score tr.cat td {
  background: var(--surface); font-size: 12px; vertical-align: middle;
  text-transform: none; letter-spacing: 0; color: var(--foreground); font-weight: 600;
}
/* Collapsible category header - the chevron + name + always-on subtotals. */
table.data.score tr.cat { cursor: pointer; }
table.data.score tr.cat:hover td { background: var(--surface-hover); }
table.data.score tr.cat:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
table.data.score .cat-head { display: inline-flex; align-items: center; gap: 6px; }
table.data.score .cat-head b { font-size: 14px; }
table.data.score .cat-chev { color: var(--muted-foreground); transition: transform 150ms ease; }
table.data.score tr.cat.open .cat-chev { transform: rotate(90deg); }
table.data.score tr.cat .sub { font-size: 13px; }
table.data.score tr.cat .sub .muted { font-weight: 500; margin-left: 1px; }
/* Optional per-category progress - the viewer's own earned/max, in brand teal. */
table.data.score .cat-prog {
  display: block; height: 3px; max-width: 160px; margin-top: 5px;
  border-radius: 2px; background: var(--bar-track); overflow: hidden;
}
table.data.score .cat-prog i { display: block; height: 100%; background: var(--primary); border-radius: 2px; }
table.data.score tr.grand td {
  border-top: 2px solid var(--primary); background: var(--primary-08);
  font-size: 14px; color: var(--primary);
}
table.data.score th.me-col, table.data.score td.me-col { background: var(--primary-08); }
table.data.score th.me-col { color: var(--primary); }
table.data.score th.me-col .you { font-weight: 500; text-transform: none; letter-spacing: 0; }
.sc-in {
  width: 62px; text-align: center; padding: 5px; font-weight: 600;
  -moz-appearance: textfield;
}
.sc-in::-webkit-outer-spin-button, .sc-in::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.sc-in.bad { border-color: var(--red); }

@media (max-width: 760px) {
  .cal-cell { min-height: 64px; }
  .cal-ev .t { display: none; }
  .secs { overflow-x: auto; grid-auto-columns: minmax(150px, 1fr); padding-bottom: 6px; }

  /* Fit layout can't fit a whole month into a phone viewport - fall back to a
     natural-height grid the page scrolls, and keep the event titles visible.
     Restore the shell minimums the desktop fit rules dropped so the page can
     grow past the viewport and scroll again. */
  html:has(.main.cal-view), body:has(.main.cal-view) { overflow: visible; }
  body:has(.main.cal-view) { min-height: 100vh; }
  .app-shell:has(.main.cal-view) { min-height: 100vh; }
  .content:has(.main.cal-view) { height: auto; min-height: calc(100vh - var(--topbar-h)); overflow: visible; }
  .main.cal-view { overflow: visible; padding: 16px 14px; }
  .cal-fit { min-height: auto; }
  .cal-grid.fit { grid-template-rows: none; flex: 0 0 auto; }
  .cal-grid.fit .cal-cell { min-height: 60px; }
  .cal-grid.fit .cal-ev .t { display: block; }
}

/* ============================================================
   Rich-text editor
   ============================================================ */
.rte {
  position: relative;
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--input-bg); overflow: hidden;
}
.rte:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--ring); }

.rte-bar {
  display: flex; align-items: center; gap: 3px; flex-wrap: wrap;
  padding: 6px 8px; border-bottom: 1px solid var(--line);
  background: var(--surface); position: sticky; top: 0; z-index: 2;
}
.rte-sep { width: 1px; height: 18px; background: var(--line); margin: 0 4px; }
.rte-btn {
  border: 1px solid transparent; background: transparent; color: var(--foreground);
  border-radius: var(--radius); padding: 5px 9px; font: 500 12px/1.3 Inter;
  transition: background .1s, border-color .1s;
}
.rte-btn:hover { background: var(--surface-hover); border-color: var(--line); }
.rte-btn.on { background: var(--primary); color: var(--primary-fg); }
.rte-html { font-family: ui-monospace, monospace; font-size: 11px; }

.rte-body {
  min-height: 240px; max-height: 60vh; overflow-y: auto;
  padding: 15px 16px; font-size: 14px; line-height: 1.7; outline: none;
}
.rte-body:empty::before {
  content: 'Write the lesson. Paste a Loom link to embed it, or drag in an image.';
  color: var(--muted-2);
}
.rte-body h3 { font: 600 15px/1.4 Inter; text-transform: none; letter-spacing: 0;
  color: var(--foreground); margin: 20px 0 8px; }
.rte-body p { margin: 0 0 10px; }
.rte-body a { color: var(--primary); }
.rte-body img { max-width: 100%; border-radius: var(--radius); display: block; margin: 10px auto; }
.rte-body ul, .rte-body ol { padding-left: 22px; margin: 0 0 10px; }
.rte-uploading { color: var(--muted-foreground); font-style: italic; }

.rte-drop {
  position: absolute; inset: 40px 0 0; display: none; place-items: center;
  background: var(--primary-08); border: 2px dashed var(--primary);
  font: 600 13px Inter; color: var(--primary); pointer-events: none;
}
.rte.dragging .rte-drop { display: grid; }

/* ---------- video embeds - editor AND reader ---------- */
.embed, .mod-body .embed, .rte-body .embed {
  position: relative; padding-bottom: 56.25%; height: 0;
  border-radius: var(--card-radius); overflow: hidden; margin: 12px 0;
  border: 1px solid var(--line); background: #000;
}
.embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.rte-body .embed::after { content: ''; position: absolute; inset: 0; }
.rte-body .embed { pointer-events: none; }

/* ============================================================
   1-on-1 Consulting - calls documentation.
   ============================================================ */
/* The call log reuses the Admin `.dtable` (muted 12px header, 46px rows, 1px
   separators, --surface hover). Fixed layout so the two write-up columns can
   ellipsis-truncate; a date column and a chevron column are pinned to width. */
.calls-table { table-layout: fixed; }
.calls-table col.c-date { width: 200px; }
.calls-table col.c-chev { width: 44px; }

.call-row { cursor: pointer; }
.call-date-cell { font-weight: 600; white-space: nowrap; }
.call-trunc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.call-chev {
  display: inline-flex; color: var(--muted-foreground);
  transition: transform .15s ease, color .15s ease;
}
.call-chev .ico { width: 16px; height: 16px; }
.call-row.open .call-chev { transform: rotate(90deg); color: var(--primary); }
/* An open row and its detail panel share one subtle fill and drop the hairline
   between them, so the pair reads as a single expanded unit. */
.call-row.open td { background: var(--surface); border-bottom-color: transparent; }

/* The inline detail row: the cell carries no padding - the panel owns the
   indent and the #fafafa (light) / --surface fill. */
.call-detail > td { padding: 0; height: auto; }
.call-detail-panel { padding: 14px 16px 18px 34px; background: var(--surface); }

.call-sec { margin-bottom: 14px; }
.call-sec:last-child { margin-bottom: 0; }
.call-sec h4 {
  font: 600 12px/1.4 Inter; text-transform: none; letter-spacing: 0;
  color: var(--muted-foreground); margin: 0 0 6px;
}

/* The empty recording slot (admin only). A call is usually written up before
   the recording has finished processing, so the slot is a waiting drop target,
   not a real action - dashed and muted until the consultant has the link. */
.rec-slot {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border: 1px dashed var(--line); border-radius: 9999px;
  background: transparent; color: var(--muted-foreground);
  font: 500 12.5px/1 Inter;
  transition: border-color .12s, color .12s;
}
.rec-slot:hover { border-color: var(--primary); color: var(--primary); }
.rec-slot .ico { width: 14px; height: 14px; }

/* What the slot becomes once clicked: paste, save, done - no modal for one URL. */
.rec-paste { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rec-paste input { max-width: 380px; }

/* Edit / Delete for the call, at the foot of an open row. */
.call-admin-row {
  display: flex; gap: 8px; margin-top: 16px;
  padding-top: 14px; border-top: 1px solid var(--line);
}

.terms-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0 20px; }

/* ---------- List: the section boxes ---------- */
.secs {
  display: grid; gap: 10px;
  grid-auto-flow: column;
  /* Never let a tile collapse below a legible width: at ~40px the title wraps to
     one character per line. Tiles hold >=130px and the strip scrolls instead. */
  grid-auto-columns: minmax(130px, 1fr);
  overflow-x: auto;
}
.sec-box {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  text-align: left; padding: 12px 12px 12px 14px;
  border: 1px solid var(--line); border-radius: var(--card-radius);
  background: var(--card); color: var(--foreground);
  transition: border-color .12s, background .12s;
  min-width: 120px;
}
.sec-box:hover { border-color: var(--line-strong); background: var(--surface); }
.sec-box.on { border-color: var(--primary-30); background: var(--primary-08); }
.sec-box.done { border-color: var(--line-strong); }
.sec-box .t { font: 600 12.5px/1.3 Inter; overflow-wrap: anywhere; }
.sec-box .n { font: 500 11.5px/1 Inter; color: var(--muted-foreground); }
.sec-box.on .n { color: var(--primary); }
.sec-box .progress-bar-wrap { width: 100%; height: 5px; margin-top: 2px; }
.sec-box.done .t::after { content: ' ✓'; color: var(--primary); }

/* ---------- Chapter page ---------- */
.chapter-title { font: 600 20px/1.3 Inter; letter-spacing: 0; margin: 0 0 14px; }

.mod-body h1, .mod-body h2 {
  font: 600 16px/1.4 Inter; margin: 22px 0 8px; color: var(--foreground);
}
.mod-body h1:first-child, .mod-body h2:first-child { margin-top: 0; }

/* impersonation "way back" - quiet */
.unmask {
  width: 26px; height: 26px; border-radius: var(--radius); padding: 0; flex: none;
  border: 1px dashed var(--line-strong); background: transparent;
  color: var(--muted-2); opacity: .5;
  display: inline-flex; align-items: center; justify-content: center;
  transition: opacity .12s, color .12s, border-color .12s;
}
.unmask:hover { opacity: 1; color: var(--primary); border-color: var(--primary); }
.unmask .ico { width: 13px; height: 13px; }

/* ---------- lessons vs action items ---------- */
.lrow.lesson { cursor: pointer; }
.lrow.lesson .go { margin-left: 4px; display: inline-flex; color: var(--muted-foreground); opacity: .6; }
.lrow.lesson:hover .go { opacity: 1; color: var(--primary); }
.lrow.lesson:hover { border-color: var(--line-strong); }

.checklist li .txt { flex: 1; }
.checklist li .box { border-radius: 5px; }
.checklist li {
  padding: 9px 12px;
  font-size: 12.5px;
  background: transparent;
  border-color: var(--td-border);
}
.checklist li:hover { background: var(--surface); border-color: var(--line-strong); }

/* ============================================================
   Section naming - kicker + heading.
   ============================================================ */
.sec-box .k, .sec-kick, .kcol h4 .kk {
  display: block;
  font: 600 9.5px/1.4 Inter; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted-2);
}
.sec-box.on .k, .sec-box.on .t { color: var(--primary); }

.sec-box.lead {
  background: transparent;
  border-style: dashed;
}
.sec-box.lead .k { color: var(--primary); }

.sec-kick {
  margin-right: 8px; display: inline-block;
  text-transform: uppercase; letter-spacing: .04em;
  font: 600 9.5px/1 Inter; color: var(--muted-2);
}

.kcol h4 { display: block; }
.kcol h4 .kt { display: inline; }
.kcol h4 .n { float: right; }

/* ============================================================
   Goals - gold (knowledge/insight) rather than the course accent.
   ============================================================ */
.goals-card .page-section-title { color: var(--gold-fg); }
[data-theme="light"] .goals-card .page-section-title { color: var(--gold); }

.goals { display: grid; gap: 8px; }
.goal {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 15px; border-radius: var(--radius);
  border: 1px solid var(--gold-border); background: var(--gold-bg);
  font-size: 13px; font-weight: 500;
}
.goal.done { border-color: var(--primary-30); background: var(--primary-08); }
.goal.done .t { color: var(--muted-foreground); }
.goal-tick {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  border: 1.5px solid var(--gold-border); background: transparent;
  color: var(--primary-fg); cursor: pointer;
}
.goal.done .goal-tick { background: var(--primary); border-color: var(--primary); }

/* ---------- Operations board ----------
   A Linear/Trello board: the columns ARE the visual units, sitting directly on
   the page background (no outer card). All columns fit the viewport at once -
   no fixed widths, no horizontal scroll - and cards truncate rather than push a
   column wider. Inverse of the plan board: light-gray columns, white cards. */
.ops-board {
  display: flex; gap: 12px; width: 100%; align-items: stretch;
  min-height: calc(100vh - 190px);   /* fill the viewport so it isn't empty below */
}
.ops-board .kcol {
  flex: 1 1 0; min-width: 0;                       /* 7 columns share the width evenly */
  display: flex; flex-direction: column; gap: 8px;
  /* A touch darker than the page (light) / lighter (dark), so white cards pop. */
  background: var(--surface-hover); border: none; border-radius: var(--card-radius); padding: 8px;
}
.ops-board .kcol.dragover { background: var(--primary-08); }
.ops-board .kcol.dragover .ops-add { background: transparent; }

/* Column header - no card, one line, dark title + muted count. */
.ops-colhead { display: flex; align-items: baseline; gap: 8px; padding: 2px 4px; }
.ops-coltitle {
  font: 600 13px/1.4 Inter; color: var(--foreground);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.ops-colcount { margin-left: auto; flex: none; font: 500 12px/1.4 Inter; color: var(--muted-2); }

/* Cards stack; the list grows so "+ Add" pins to the column bottom. */
.ops-cards { display: flex; flex-direction: column; gap: 8px; flex: 1; min-height: 4px; }

.ops-board .kcard {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 9px 10px; margin: 0; box-shadow: none;
  transition: box-shadow .12s, border-color .12s;
}
/* `:not(.dragging)` is load-bearing: the ghost is pointer-events:none, so the
   element under the cursor mid-drag is the placeholder itself. This rule sits
   AFTER `.kcard.dragging` and ties it on specificity, so without the guard the
   ops slot would re-gain a border and shadow - and the ops board's drag would
   look different from the plan board's, where the ordering happens to be the
   other way round. */
.ops-board .kcard:not(.dragging):hover { border-color: var(--line-strong); box-shadow: 0 1px 4px rgba(0,0,0,.08); }
.ops-board .kcard .t {                              /* truncate - never force the column wider */
  font: 500 13px/1.4 Inter;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ops-notes {
  font: 400 11.5px/1.4 Inter; color: var(--muted-foreground); margin: 3px 0 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Checkbox sits left of the title, mirroring the PMO board's .pmo-main. */
.ops-board .ops-main { display: flex; align-items: flex-start; gap: 8px; }
.ops-board .ops-main .t { flex: 1 1 auto; min-width: 0; }   /* let the existing ellipsis work in flex */
.ops-board .ops-main .bcheck { margin-top: 0; }
.ops-board .kcard .foot { margin-top: 7px; flex-wrap: wrap; }
/* Icon-only chapter chip - square, just the book glyph. */
.ops-board .pill-tag.pill-icon { display: inline-flex; align-items: center; padding: 2px 5px; }
/* Tags become compact 11px chips. */
.ops-board .pill-tag,
.ops-board .badge { font: 500 11px/1.5 Inter; padding: 1px 7px; }

/* Chapter cards wear the same track treatment as the PMO board - tint body,
   tinted border, top accent bar, and the coloured label - so a track reads the
   same everywhere. Element-level selectors (no `.ops-board` ancestor) so the
   detached drag ghost, which lives on <body>, keeps the styling too. They sit
   after `.ops-board .kcard` to win the tie on background/border. */
.kcard.is-chapter {
  position: relative;
  background: var(--track-tint, var(--card));
  border-color: var(--track-border, var(--line));
}
.ops-track {
  margin-bottom: 4px;
  font: 500 11px/1.3 Inter; color: var(--track-label, var(--muted-foreground));
}

/* The 4px accent bar across the top edge, shared by PMO cards and Ops chapter
   cards. `border-radius: inherit` picks up each card's own corner radius, then
   the bottom corners are squared off. */
.pmo-card::before, .kcard.is-chapter::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: var(--track-accent);
  border-radius: inherit; border-bottom-left-radius: 0; border-bottom-right-radius: 0;
  pointer-events: none;
}

/* "+ Add" - a subtle full-width text button at the column bottom. No dashed box. */
.ops-add {
  width: 100%; margin-top: auto; padding: 6px 8px; border-radius: var(--radius);
  font: 500 13px/1 Inter; text-align: left;
  border: none; background: transparent; color: var(--muted-foreground);
  transition: background .12s, color .12s;
}
.ops-add:hover { color: var(--foreground); background: var(--surface-hover); }

.kcard .edit-pin[disabled] { opacity: .5; cursor: default; }
.edit-pin.is-on { opacity: .6; color: var(--primary); }
.kcard .edit-pin { font: 500 10.5px/1.4 Inter; opacity: 0; }
.kcard:hover .edit-pin { opacity: .75; }
.kcard .edit-pin:hover { opacity: 1; }

/* ============================================================
   Locked weeks (Hackathon pacing).
   ============================================================ */
.sec-box.locked, .lrow.locked {
  opacity: .55; cursor: not-allowed;
  background: transparent; border-style: dashed;
}
.sec-box.locked:hover, .lrow.locked:hover {
  border-color: var(--line);
}
.sec-box .n.lock, .lrow .tick.lock {
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--muted-foreground); font-weight: 600;
}
.lrow .tick.lock { border: none; background: transparent; }
.lrow.locked .t { color: var(--muted-foreground); }

.mod-body .video-wrap { margin: 16px 0 20px; }

/* ============================================================
   PMO board - Asana-style cards.
   Month columns are bare (no card) on a light-gray fill, like the Ops board.
   ============================================================ */
.kanban.fit .kcol {
  background: var(--surface-hover); border: none; border-radius: var(--card-radius);
  padding: 8px;
}
.kanban.fit .kcol h4 {
  font: 600 13px/1.4 Inter; color: var(--foreground);
  margin: 0 0 8px; padding: 2px 4px;
}
.kanban.fit .kcol h4 .n { color: var(--muted-2); font-weight: 500; }

/* The card wears its track as colour: a light TINT body, a stronger tinted
   border, and a 4px accent bar across the top edge (see the shared ::before
   rule near the Ops board). Neutral-dark title for readability; NO min-height,
   so a title-only card is ~64px and nothing reserves empty space. The tint vars
   come from the track class (track-colors.js); plain cards fall back to --card. */
.pmo-card {
  position: relative;
  background: var(--track-tint, var(--card));
  border: 1px solid var(--track-border, var(--line)); border-radius: var(--card-radius);
  padding: 11px 12px 10px; margin-bottom: 8px; cursor: pointer;
  transition: border-color .12s, box-shadow .12s, filter .12s;
}
/* Lift on hover; keep the tinted border (don't neutralise the hue). */
.pmo-card:hover { box-shadow: 0 2px 8px rgba(16,24,24,.10); }
/* Completed: keep the tint, but desaturate so done cards read quieter. */
.pmo-card.done { filter: saturate(.45); }
/* A locked (paced) course chapter: dimmed, not clickable, its check a dashed disc. */
.pmo-card.locked { cursor: not-allowed; opacity: .6; }
.pmo-card.locked:hover { box-shadow: none; }
.pmo-card.locked .bcheck { border-style: dashed; background: transparent; cursor: not-allowed; }
.pmo-card.locked .bcheck .ico { color: var(--muted-2); }

/* Track label - the track NAME only (no dot), directly under the accent bar,
   in the hue's dark shade. */
.pmo-track {
  margin-bottom: 4px;
  font: 500 11px/1.3 Inter; color: var(--track-label, var(--muted-foreground));
}

/* Title line: inline check, then the title (max 3 lines, then ellipsis). */
.pmo-main { display: flex; align-items: flex-start; gap: 8px; }
.pmo-card .t {
  font: 500 13px/1.35 Inter; color: var(--foreground);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.pmo-card.done .t { color: var(--muted-foreground); text-decoration: line-through; }
.pmo-card .bcheck { margin-top: 0; }

/* Metadata row: ONLY set fields (owner / due) + the mirrored Ops badge, all on ONE
   line - owner, then due, then "✓ Ops" to their right (Matt · Jul 28 · ✓ Ops).
   Empty = collapsed, so an untouched card stays compact.

   nowrap, NOT wrap: with wrap, the browser breaks a line on each chip's content
   width without considering shrink, so the Ops badge dropped to a second row even
   when there was clearly room. nowrap keeps the three together; the ONLY chip that
   may give ground is the owner (its name truncates with an ellipsis). The due date
   and the Ops status never shrink and never wrap, so toggling Ops on/off can't
   change the card's height. */
.pmo-meta { display: flex; align-items: center; flex-wrap: nowrap; gap: 6px; margin-top: 6px; min-width: 0; }
.pmo-meta:empty { display: none; }
.pmo-meta > .owner { flex: 0 1 auto; min-width: 0; }
.pmo-meta > .owner > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pmo-meta > .due, .pmo-meta > .ops-badge { flex: 0 0 auto; }
/* Course-board cards carry only informational badges (Video / Tool / checklist),
   with no owner chip to give ground - so let those wrap naturally in a narrow
   column instead of overflowing. The nowrap rule is for the PMO owner/due/Ops row. */
.course-board .pmo-meta { flex-wrap: wrap; }

/* The hover actions: what you'd SET (unset owner / due) plus the mirror button.
   ABSOLUTELY positioned, so revealing them on hover never changes the card's
   height - that height change was what made the row flicker as the pointer
   crossed the edge. Top-right, over a card-coloured chip so text stays legible. */
.pmo-actions {
  position: absolute; top: 8px; right: 7px;
  display: flex; align-items: center; gap: 3px;
  padding: 2px; border-radius: 7px; background: var(--track-tint, var(--card));
  opacity: 0; pointer-events: none; transition: opacity .12s;
}
.pmo-card:hover .pmo-actions,
.pmo-card:focus-within .pmo-actions { opacity: 1; pointer-events: auto; }
.pmo-actions .metachip { opacity: .6; }
.pmo-actions .metachip:hover { opacity: 1; }
.pmo-actions .edit-pin { opacity: 1; }

/* The "mirrored to Ops" badge - a stable, always-on status chip (no hover
   toggle, no re-mount), so it can't flicker. */
.ops-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px; border-radius: 4px;
  font: 500 11px/1.6 Inter; color: var(--primary); background: var(--primary-08);
}
.ops-badge svg { width: 12px; height: 12px; }

/* A metadata chip (owner / due). Set = a quiet gray chip; a ghost (in the hover
   actions) is a bare, faint icon you click to set the field. */
.metachip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px; border-radius: 4px; border: none;
  font: 500 11px/1.6 Inter; background: transparent; color: var(--muted-2);
}
.metachip svg { width: 12px; height: 12px; }
.metachip.set { background: var(--surface-hover); color: var(--muted-foreground); }
button.metachip { cursor: pointer; }
button.metachip:hover { background: var(--surface-hover); color: var(--foreground); }
.metachip.ghost { padding: 2px 5px; }
.metachip.due.set.late { background: rgba(209,47,47,.08); color: var(--red); }

/* Who a card belongs to, as a face rather than a name (see personDisc in
   board.js). The disc carries its own background, so the chip around it drops
   the usual .set fill and padding - otherwise it reads as a pill with a hole. */
.metachip.disc, .metachip.owner.disc { padding: 0; background: transparent; }
button.metachip.disc:hover { background: transparent; }
button.metachip.disc:hover .pdisc { box-shadow: 0 0 0 2px var(--primary-08); }

.pdisc {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  display: inline-grid; place-items: center; overflow: hidden;
  background: var(--surface-hover); color: var(--muted-foreground);
  border: 1px solid var(--line); font: 600 9px/1 Inter; letter-spacing: .2px;
  transition: box-shadow .12s;
}
.pdisc img { width: 100%; height: 100%; object-fit: cover; }

/* The little popover the chips open. */
.pop {
  position: absolute; z-index: 300; width: 230px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--card-radius);
  padding: 12px; box-shadow: var(--shadow-pop);
}

/* Complete a chapter straight from a board. */
.bcheck {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  display: grid; place-items: center; padding: 0; line-height: 0;
  border: 1.5px solid var(--line-strong); background: transparent;
  color: var(--primary-fg); cursor: pointer; transition: background .12s, border-color .12s;
}
.bcheck .ico { width: 11px; height: 11px; vertical-align: 0; color: var(--muted-2); }
.bcheck:hover { border-color: var(--primary); background: var(--surface-hover); }
.bcheck:hover .ico { color: var(--primary); }
.bcheck.on { background: var(--primary); border-color: var(--primary); }
.bcheck.on .ico { color: var(--primary-fg); }
.bcheck[disabled] { cursor: default; opacity: 1; }
.bcheck[disabled]:hover { border-color: var(--line-strong); background: transparent; }
.bcheck[disabled]:hover .ico { color: var(--muted-2); }

/* ============================================================
   Detail drawer - chapter slides in over the list, Asana-style.
   ============================================================ */
.detail-drawer {
  position: fixed; top: 0; right: 0; z-index: 92;
  height: 100vh; width: min(760px, 94vw);
  background: var(--background);
  border-left: 1px solid var(--line);
  box-shadow: -12px 0 40px rgba(0, 0, 0, .18);
  transform: translateX(100%);
  /* `width` animates too, so maximising (grow to the full content width) and
     restoring the side panel slide rather than jump. The right edge is pinned
     (`right:0`), so widening pushes the LEFT edge out over the board. */
  transition: transform .3s cubic-bezier(.32, .72, 0, 1),
              width .3s cubic-bezier(.32, .72, 0, 1);
  display: flex; flex-direction: column;
}
[data-theme="light"] .detail-drawer { box-shadow: -12px 0 40px rgba(16, 24, 24, .10); }
.detail-drawer.show { transform: translateX(0); }
/* Maximised over a board: no left border - it spans the whole content area, so
   there is no list peeking beside it for the seam to separate from. */
.detail-drawer.maximized { border-left: 0; }

/* Overlay push - the PMO / Operations board drawer. The list-split view opts out
   (`:not(.list-split)`): it shrinks the list to a real column instead of nudging
   the centred content sideways under an overlay. */
@media (min-width: 1200px) {
  body.drawer-open:not(.list-split) .main {
    margin-right: calc(min(760px, 94vw) + 32px);
    transition: margin .3s cubic-bezier(.32, .72, 0, 1);
  }
}

.drawer-body {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  padding: 24px 28px 56px;
}

.lrow.selected, .kcard.selected {
  border-color: var(--primary);
  background: var(--primary-08);
}

/* ---------- List split view ----------
   A chapter opened from the LIST turns the drawer into the right pane of a split:
   the list shrinks to a fixed column (SPLIT_LIST_W in app.js sets the drawer's
   left edge to match) and the detail fills the rest. Only on wide screens; below
   900px the drawer falls back to the overlay above.
   The drawer's left / width are set inline by updateSplitMode(); these rules
   handle the list side. */
@media (min-width: 900px) {
  /* Fixed column - not a flexing max-width. The drawer's left edge is pinned to
     380px (SPLIT_LIST_W in app.js), so the list must hold exactly that width. */
  #main[data-panel-open].main {
    width: 380px; max-width: 380px; flex: none;
    margin: 0;
    padding-left: 20px; padding-right: 16px;
  }
  /* Keep only the compact context row and the open section's module list; drop the
     progress header, the Chapters strip and the goals card while the pane is open.
     Keyed off data-panel-open on #main (not a `.card` wrapper the de-boxed markup
     no longer emits), so it hides whatever the list renders. */
  #main[data-panel-open] > *:not(#sec-list):not(.list-context-row) { display: none; }
  #main[data-panel-open] #sec-list { margin: 0; }
  /* The section's own title line is redundant with the context row's switcher. */
  #main[data-panel-open] #sec-list > .page-section-title { display: none; }

  /* Rows collapse to circle + title, one line, ellipsis on overflow. */
  #main[data-panel-open] #sec-list .lrow .pill-tag,
  #main[data-panel-open] #sec-list .lrow .badge,
  #main[data-panel-open] #sec-list .lrow .muted,
  #main[data-panel-open] #sec-list .lrow .edit-pin { display: none; }
  #main[data-panel-open] #sec-list .lrow .t {
    min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* The module open in the pane gets a teal left border on top of the tint. */
  #main[data-panel-open] #sec-list .lrow.selected {
    border-left: 2px solid var(--primary);
  }
}

/* The compact context row: a single ~40px line - section switcher + completion
   count - that replaces the Chapters strip in the shrunk split column. Hidden
   in the full list view; only data-panel-open reveals it. */
.list-context-row { display: none; }
#main[data-panel-open] .list-context-row {
  display: flex; align-items: center; gap: 10px;
  height: 40px; margin: 0 0 12px; min-width: 0;
}
.list-sec-select {
  flex: 1; min-width: 0; height: 34px; padding: 0 30px 0 11px;
  font: 600 12.5px/1 Inter; color: var(--foreground);
  border: 1px solid var(--line-strong); border-radius: 9999px;
  background: var(--input-bg);
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat; background-position: right 10px center;
  cursor: pointer; text-overflow: ellipsis;
}
.list-sec-select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--ring); }
.list-sec-count { flex: none; font: 500 11.5px/1 Inter; color: var(--muted-foreground); white-space: nowrap; }

@media (max-width: 640px) {
  .detail-drawer { width: 100vw; }
  .drawer-body { padding: 18px 15px 50px; }
}
@media (prefers-reduced-motion: reduce) {
  .detail-drawer { transition: none; }
  .main { transition: none; }
  .sidebar { transition: none; }
  .content { transition: none; }
  .navrow .lbl { transition: none; }
  .nav-item::after { transition: none; }
}

/* ============================================================
   Positioning wizard - rich widgets. Tokens only, one accent at low
   opacity, 1px borders, pills. No new colour, no themed decoration - the
   life comes from the widgets and motion, not styling.
   ============================================================ */

/* ---- step transition: content slides + fades in (200ms) ---- */
@keyframes panelInFwd  { from { transform: translateX(14px);  opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes panelInBack { from { transform: translateX(-14px); opacity: 0; } to { transform: none; opacity: 1; } }
.panel-in-fwd  { animation: panelInFwd  .2s ease both; }
.panel-in-back { animation: panelInBack .2s ease both; }

/* ---- live mini-summary line under a step ---- */
.wiz-summary {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px;
  margin-top: 22px; padding: 11px 14px;
  border: 1px solid var(--line); border-radius: var(--card-radius);
  background: var(--surface); animation: panelInFwd .25s ease both;
}
.wiz-summary-l { display: inline-flex; align-items: center; gap: 6px; font: 600 11px/1 Inter;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted-foreground); }
.wiz-summary-v { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.wiz-summary-chip { font: 600 12.5px/1.4 Inter; color: var(--foreground); }
.wiz-summary-dot { color: var(--muted-2); }

/* ---- rail: draw the check in only when a node has just completed ---- */
@keyframes railDraw { from { stroke-dashoffset: 22; } to { stroke-dashoffset: 0; } }
@keyframes markPop  { 0% { transform: scale(.5); } 60% { transform: scale(1.12); } 100% { transform: scale(1); } }
.wiz-mark.done.is-fresh { animation: markPop .3s ease both; }
.wiz-mark.done.is-fresh svg path { stroke-dasharray: 22; animation: railDraw .32s ease .04s both; }

/* ============================================================ region map + combo */
.pos-regions { display: flex; flex-direction: column; gap: 10px; }
/* The map is the screen, so it takes the height the viewport can spare. */
.pos-map {
  height: clamp(280px, 46vh, 560px);
  border: 1px solid var(--line-strong); border-radius: var(--card-radius);
  overflow: hidden; position: relative; background: var(--surface);
}
.pos-map.is-error { display: flex; align-items: center; justify-content: center; }
.pos-map-fail, .pos-map::after { color: var(--muted-foreground); font-size: 12.5px; }
.pos-map:empty::after { content: 'Loading map...'; position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center; }
.pos-map-fail { padding: 16px; text-align: center; }
/* city pin - a teal teardrop */
.pos-map-pin {
  width: 16px; height: 16px; border-radius: 50% 50% 50% 0; transform: rotate(-45deg);
  background: var(--primary); border: 2px solid #fff; box-shadow: 0 2px 6px rgba(16,24,24,.35);
}

/* combo type-ahead (shared by region + tool chip inputs) */
.pos-combo { position: relative; }
.pos-combo-in { display: flex; align-items: center; gap: 8px; padding: 0 11px;
  border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--input-bg);
  transition: border-color .12s, box-shadow .12s; }
.pos-combo-in:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--ring); }
.pos-combo-in .ico { color: var(--muted-2); flex: none; }
.pos-combo-in input { border: none; background: none; padding: 9px 0; }
.pos-combo-in input:focus { outline: none; box-shadow: none; }
.pos-suggest {
  position: absolute; z-index: 20; left: 0; right: 0; top: calc(100% + 4px);
  background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-pop); overflow: hidden; max-height: 280px; overflow-y: auto;
}
.pos-suggest-row {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 8px 11px; background: none; border: none; cursor: pointer; color: var(--foreground);
  font: 500 13px/1.3 Inter; border-bottom: 1px solid var(--line);
}
.pos-suggest-row:last-child { border-bottom: none; }
.pos-suggest-row:hover, .pos-suggest-row.is-active { background: var(--primary-08); }
.pos-suggest-row .ico { color: var(--muted-2); flex: none; }
.pos-suggest-l { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pos-suggest-s { font-size: 11.5px; color: var(--muted-2); flex: none; }
.pos-suggest-custom .pos-suggest-l { color: var(--primary); font-weight: 600; }

/* chips */
.pos-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.pos-chips-empty { font-size: 12.5px; color: var(--muted-2); padding: 2px 0; }
.pos-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 6px 5px 10px;
  border: 1px solid var(--primary-30); border-radius: 9999px;
  background: var(--primary-08); color: var(--foreground); font: 600 12.5px/1 Inter;
  animation: markPop .18s ease both;
}
.pos-chip .ico { color: var(--primary); flex: none; }
.pos-chip-custom { border-color: var(--line-strong); background: var(--surface); }
.pos-chip-custom .ico { color: var(--muted-2); }
/* Exclusion ("except Russia") - a carve-out, so read it as muted/subtractive,
   not selected. Dashed edge + struck label; neutral, never a decorative red. */
.pos-chip-exclude { border-style: dashed; border-color: var(--line-strong); background: var(--surface); color: var(--muted-foreground); }
.pos-chip-exclude .ico { color: var(--muted-2); }
.pos-chip-exclude > span { text-decoration: line-through; text-decoration-thickness: 1px; }
.pos-chip-x {
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
  width: 18px; height: 18px; border: none; border-radius: 50%; cursor: pointer;
  background: none; color: var(--muted-2);
}
.pos-chip-x:hover { background: var(--surface-hover); color: var(--red); }

/* ============================================================ segmented control */
.pos-seg {
  display: flex; gap: 3px; padding: 3px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--line); width: fit-content; max-width: 100%;
  flex-wrap: wrap;
}
.pos-seg-btn {
  padding: 7px 14px; border: none; border-radius: 4px; background: none; cursor: pointer;
  font: 600 12.5px/1 Inter; color: var(--muted-foreground);
  transition: background .15s, color .15s, transform .15s;
}
.pos-seg-btn:hover { color: var(--foreground); }
.pos-seg-btn.is-on { background: var(--primary); color: var(--primary-fg); }
.pos-seg-btn.pop { animation: markPop .15s ease; }
.pos-note { margin-top: 10px; }

/* ============================================================ revenue slider */
.pos-slider { margin: 6px 0 14px; }
.pos-slider-val {
  font: 700 15px/1 Inter; color: var(--primary); margin-bottom: 10px;
}
.pos-slider.is-unset .pos-slider-val { color: var(--muted-2); font-weight: 500; font-size: 13px; }
.pos-slider input[type=range] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 6px; padding: 0;
  border: none; border-radius: 4px; cursor: pointer;
  background: linear-gradient(to right, var(--primary) 0%, var(--primary) var(--fill, 40%),
    var(--bar-track) var(--fill, 40%), var(--bar-track) 100%);
}
.pos-slider.is-unset input[type=range] { background: var(--bar-track); }
.pos-slider input[type=range]:focus { outline: none; box-shadow: none; }
.pos-slider input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 18px; height: 18px; border-radius: 50%;
  background: var(--card); border: 2px solid var(--primary); box-shadow: var(--shadow-pop); cursor: grab;
  transition: transform .12s;
}
.pos-slider input[type=range]:active::-webkit-slider-thumb { transform: scale(1.15); cursor: grabbing; }
.pos-slider input[type=range]::-moz-range-thumb {
  width: 18px; height: 18px; border-radius: 50%; background: var(--card);
  border: 2px solid var(--primary); cursor: grab;
}
.pos-slider-ticks { display: flex; justify-content: space-between; margin-top: 8px;
  font: 500 10.5px/1 Inter; color: var(--muted-2); }
.pos-slider-ticks span { flex: 1; text-align: center; }
.pos-slider-ticks span:first-child { text-align: left; }
.pos-slider-ticks span:last-child { text-align: right; }
.pos-rev-reason { min-height: 68px; }

/* ============================================================ tool chip inputs */
.pos-toolchips { display: flex; flex-direction: column; gap: 10px; }
.pos-chip-tool { border-color: var(--line-strong); background: var(--card); }
.pos-tool-ava {
  display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  border-radius: 4px; background: var(--surface-hover); border: 1px solid var(--line);
  font: 700 10px/1 Inter; color: var(--muted-foreground); flex: none;
}

/* ============================================================ persona roster */
/* Fills whatever width the stage gives it - 2 cards on a laptop, 4 on a wide
   screen - instead of two stretched columns with the rest of the row empty. */
.pos-persona-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: 10px; align-items: start;
}
.pos-persona {
  border: 1px solid var(--line); border-radius: var(--card-radius); background: var(--surface);
  padding: 12px; transition: border-color .2s, background .2s, box-shadow .2s;
}
.pos-persona[open] { grid-column: 1 / -1; background: var(--card); border-color: var(--line-strong); }
.pos-persona.is-active { border-color: var(--primary-30); background: var(--primary-04); }
.pos-persona > summary { cursor: pointer; display: flex; align-items: flex-start; gap: 12px; }
.pos-persona > summary::-webkit-details-marker { display: none; }
.pos-persona-ava {
  flex: none; width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--line-strong); background: var(--card);
  display: flex; align-items: center; justify-content: center; color: var(--muted-2);
  transition: color .2s, border-color .2s, background .2s;
}
.pos-persona-ava svg { width: 30px; height: 30px; }
.pos-persona.is-active .pos-persona-ava {
  color: var(--primary); border-color: var(--primary-30); background: var(--primary-12);
}
.pos-persona-meta { flex: 1; min-width: 0; }
.pos-persona-meta h4 { font: 600 13.5px/1.35 Inter; margin: 0; }
.pos-persona-role { font-size: 11px; color: var(--muted-foreground); margin-top: 3px; line-height: 1.45; }
.pos-persona-state { display: inline-block; margin-top: 6px; font-size: 11px; color: var(--muted-2); }
.pos-persona.is-active .pos-persona-state { color: var(--primary); }
.pos-persona-jt { margin-top: 6px; }
.pos-persona-chev { color: var(--muted-2); flex: none; margin-top: 2px; transition: transform .2s; width: 16px; height: 16px; }
.pos-persona[open] .pos-persona-chev { transform: rotate(180deg); }
.pos-persona-body { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.pos-persona-body .field { margin-bottom: 12px; }
.pos-pop { animation: markPop .2s ease; }

/* ranking lineup */
.pos-ranking { display: flex; flex-direction: column; gap: 7px; }
.pos-ranking-empty { font-size: 12.5px; color: var(--muted-2); padding: 4px 0; line-height: 1.5; }
.pos-ranking-note {
  display: flex; align-items: baseline; gap: 6px; font-size: 12px; color: var(--muted-foreground);
  padding: 9px 11px; margin-bottom: 4px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); line-height: 1.5;
}
.pos-ranking-note .ico { flex: none; color: var(--muted-2); align-self: center; }
.pos-ranking-note span { color: var(--foreground); font-weight: 500; }
.pos-rank-row {
  display: flex; align-items: center; gap: 11px; padding: 9px 12px;
  border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--card);
  cursor: grab; transition: box-shadow .15s, border-color .15s, opacity .15s;
}
.pos-rank-row:hover { border-color: var(--primary-30); }
.pos-rank-row.is-dragging { opacity: .5; box-shadow: var(--shadow-pop); cursor: grabbing; }
.pos-rank-num {
  flex: none; width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; background: var(--primary-12); color: var(--primary); font: 700 12px/1 Inter;
}
.pos-rank-grip { color: var(--muted-2); display: inline-flex; }
.pos-rank-ava { flex: none; width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center; color: var(--primary); }
.pos-rank-ava svg { width: 20px; height: 20px; }
.pos-rank-title { font: 600 13px/1.3 Inter; }

/* ============================================================ touchpoint tiles */
.pos-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 10px; }
.pos-tile {
  border: 1px solid var(--line-strong); border-radius: var(--card-radius); background: var(--card);
  overflow: hidden; transition: border-color .18s, background .18s, box-shadow .18s;
}
.pos-tile.is-on { border-color: var(--primary); background: var(--primary-04); }
.pos-tile-head {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 13px 14px; background: none; border: none; cursor: pointer; color: var(--foreground);
}
.pos-tile-ico { display: inline-flex; color: var(--muted-foreground); flex: none; }
.pos-tile-ico .ico { width: 20px; height: 20px; }
.pos-tile.is-on .pos-tile-ico { color: var(--primary); }
.pos-tile-name { flex: 1; font: 600 13.5px/1.3 Inter; }
.pos-tile-check {
  flex: none; width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; background: var(--primary); color: var(--primary-fg);
  opacity: 0; transform: scale(.5); transition: opacity .18s, transform .18s;
}
.pos-tile-check .ico { width: 12px; height: 12px; }
.pos-tile.is-on .pos-tile-check { opacity: 1; transform: scale(1); }
.pos-tile-why { padding: 0 14px 13px; }
.pos-tile-why textarea { min-height: 54px; }
.pos-tile-add {
  display: flex; align-items: center; justify-content: center; gap: 7px; padding: 13px;
  border-style: dashed; color: var(--muted-foreground); cursor: pointer; font: 600 13px/1 Inter;
}
.pos-tile-add:hover { border-color: var(--primary-30); color: var(--primary); }
.pos-tile-add .ico { width: 16px; height: 16px; }

/* ============================================================ review page */
.rv-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.rv-count { flex: none; font: 700 26px/1 Inter; color: var(--muted-foreground); letter-spacing: -.01em; }
.rv-count.is-complete { color: var(--primary); }
.rv-count-sep { opacity: .4; margin: 0 1px; }
.rv-map {
  height: clamp(200px, 30vh, 380px);
  border: 1px solid var(--line-strong); border-radius: var(--card-radius);
  overflow: hidden; position: relative; margin-bottom: 20px; background: var(--surface);
}
@keyframes rvIn { from { transform: translateY(10px); opacity: 0; } to { transform: none; opacity: 1; } }
.rv-doc.rv-stagger > * { animation: rvIn .4s ease both; }

@media (max-width: 640px) {
  .pos-persona-grid, .pos-tiles { grid-template-columns: 1fr; }
  .pos-map { height: 260px; }
}
@media (prefers-reduced-motion: reduce) {
  .panel-in-fwd, .panel-in-back, .wiz-summary, .pos-chip, .pos-pop, .pos-seg-btn.pop,
  .wiz-mark.done.is-fresh, .wiz-mark.done.is-fresh svg path, .rv-doc.rv-stagger > * { animation: none; }
}

/* ============================================================
   COMMUNITY - the cohort chat.
   Written against the tokens only, so a re-theme stays a token swap. Own-message
   bubbles use the accent at low opacity (--primary-12); everyone else is neutral
   surface. Pills on every control. Red stays status-only - a mention badge uses
   the accent, a plain unread uses neutral ink.
   ============================================================ */

/* --- the sidebar unread badge on the Community nav row --- */
.navrow-badge {
  flex: none; min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  font: 700 11px/1 Inter; border-radius: 9999px;
  background: var(--surface-hover); color: var(--muted-foreground);
  border: 1px solid var(--line-strong);
}
.navrow-badge.mention {
  background: var(--primary-12); color: var(--primary);
  border-color: var(--primary-30);
}
/* In the collapsed rail there's no room for a number - show a small dot on the
   icon instead, reusing the same accent/neutral distinction. */
[data-sidebar="collapsed"] .navrow-badge { display: none; }
[data-sidebar="collapsed"] .nav-item[data-unread] .navrow-ico::after {
  content: ""; position: absolute; top: -2px; right: -2px;
  width: 7px; height: 7px; border-radius: 9999px;
  background: var(--muted-foreground); box-shadow: 0 0 0 2px var(--card);
}
[data-sidebar="collapsed"] .nav-item[data-mention] .navrow-ico::after { background: var(--primary); }
[data-sidebar="collapsed"] .navrow-ico { position: relative; }

/* --- two-pane layout --- */
.cm-wrap {
  display: grid; grid-template-columns: 240px 1fr; gap: 16px;
  height: calc(100vh - var(--topbar-h) - 48px); min-height: 420px;
}

/* --- channel list: de-boxed, mirrors the main sidebar .navrow rows --- */
.cm-channels {
  overflow-y: auto; padding: 0 4px;
  display: flex; flex-direction: column; gap: 2px;
}
.cm-ch-head {
  font: 700 11px/1 Inter; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted-2); padding: 4px 6px 6px;
}
.cm-ch {
  display: flex; align-items: center; gap: 10px; width: 100%;
  height: 40px; padding: 0 9px; border: 0; background: transparent; cursor: pointer;
  border-radius: var(--radius); color: var(--muted-foreground); text-align: left;
  font: 500 13px/1.2 Inter;
}
.cm-ch:hover { background: var(--surface-hover); color: var(--foreground); }
.cm-ch.on { background: var(--surface-hover); color: var(--primary); }
.cm-ch-ico { flex: none; width: 16px; height: 16px; display: grid; place-items: center; color: var(--muted-foreground); }
.cm-ch.on .cm-ch-ico { color: var(--primary); }
.cm-ch-ico svg { width: 16px; height: 16px; }
.cm-ch-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-ch[data-unread] .cm-ch-name { font-weight: 700; color: var(--foreground); }
.cm-ch-badge {
  flex: none; min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  font: 700 11px/1 Inter; border-radius: 9999px;
  background: var(--surface-hover); color: var(--muted-foreground);
}
.cm-ch-badge.mention { background: var(--primary-20); color: var(--primary); }

/* --- the channel pane --- */
.cm-main {
  position: relative;
  display: flex; flex-direction: column; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--card-radius);
  background: var(--card); overflow: hidden;
}
.cm-head {
  flex: none; display: flex; align-items: center; gap: 10px;
  height: 48px; padding: 0 16px; border-bottom: 1px solid var(--line);
}
.cm-head-ico { flex: none; display: grid; place-items: center; color: var(--muted-foreground); }
.cm-head-ico svg { width: 17px; height: 17px; }
.cm-head-name { flex: none; font: 700 14px/1 Inter; letter-spacing: -.01em; }
.cm-head-count { flex: none; font: 400 12px/1 Inter; color: var(--muted-2); }
.cm-head-desc {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font: 400 12px/1 Inter; color: var(--muted-foreground);
  padding-left: 6px; border-left: 1px solid var(--line);
}

/* --- pinned strip --- */
.cm-pins {
  flex: none; border-bottom: 1px solid var(--line);
  background: var(--gold-bg); padding: 6px 12px;
  display: flex; flex-direction: column; gap: 4px; max-height: 128px; overflow-y: auto;
}
.cm-pin {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: none; border: 0; cursor: pointer; text-align: left;
  font: 500 12.5px/1.3 Inter; color: var(--foreground); padding: 3px 2px;
}
.cm-pin-ico { flex: none; color: var(--gold-fg); display: grid; place-items: center; }
.cm-pin-ico svg { width: 14px; height: 14px; }
.cm-pin-who { flex: none; font-weight: 700; }
.cm-pin-body { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--muted-foreground); }
.cm-pin-body a { pointer-events: none; }

/* --- the message stream ---
   The scroll container is .cm-stream; .cm-stream-inner is a flex column pinned
   to the bottom (justify-content:flex-end) so a short channel hugs the composer
   with no whitespace above it, yet overflows and scrolls normally once full. */
.cm-stream { flex: 1; min-height: 0; overflow-y: auto; }
.cm-stream-inner {
  min-height: 100%; max-width: 760px; margin: 0 auto;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 2px;
  padding: 12px 12px 16px;
}
.cm-empty, .cm-loading {
  margin: auto; color: var(--muted-foreground); font: 400 13px/1.4 Inter;
}
.cm-older {
  align-self: center; margin: 4px 0 10px; padding: 6px 14px;
  border: 1px solid var(--line); background: var(--surface); color: var(--muted-foreground);
  border-radius: 9999px; font: 600 12px/1 Inter; cursor: pointer;
}
.cm-older:hover { background: var(--surface-hover); }

/* --- day + unread dividers: a centered label on a 1px line --- */
.cm-day, .cm-unread {
  display: flex; align-items: center; margin: 12px 0 6px; font: 600 11px/1 Inter;
}
.cm-day::before, .cm-day::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.cm-day span { padding: 0 10px; color: var(--muted-2); }
.cm-unread::before, .cm-unread::after { content: ""; flex: 1; height: 1px; background: var(--primary-30); }
.cm-unread span {
  padding: 0 10px; color: var(--primary); text-transform: uppercase; letter-spacing: .04em;
}

/* --- "New messages" jump pill, floating over the stream when scrolled up --- */
.cm-jump {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: 78px; z-index: 5;
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px;
  border: none; border-radius: 9999px; cursor: pointer;
  background: var(--primary); color: var(--primary-fg);
  box-shadow: var(--shadow-pop); font: 600 12px/1 Inter;
}
.cm-jump svg { width: 15px; height: 15px; }
.cm-jump:hover { filter: brightness(1.05); }

/* --- a message: a flat left-aligned row, avatar gutter + content column --- */
.cm-msg {
  position: relative; display: flex; flex-direction: row; gap: 10px;
  padding: 3px 8px; border-radius: var(--radius);
}
.cm-msg:hover { background: var(--surface-hover); }
.cm-msg.grouped { padding-top: 1px; padding-bottom: 1px; }
/* Mention wash as an inset left bar, so it coexists with the hover background. */
.cm-msg.mention { box-shadow: inset 2px 0 0 var(--primary), inset 0 0 0 999px var(--primary-08); }
.cm-gutter { flex: none; width: 28px; display: flex; justify-content: center; }
.cm-avatar {
  flex: none; width: 28px; height: 28px; border-radius: 9999px; overflow: hidden;
  display: grid; place-items: center; background: var(--surface-hover);
  font: 700 12px/1 Inter; color: var(--muted-foreground);
}
.cm-avatar img { width: 100%; height: 100%; object-fit: cover; }
.cm-gtime { font: 400 10px/28px Inter; color: var(--muted-2); opacity: 0; transition: opacity .12s; }
.cm-msg:hover .cm-gtime { opacity: 1; }
.cm-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.cm-msg-head { display: flex; align-items: baseline; gap: 8px; }
.cm-author { font: 700 13px/1.2 Inter; }
.cm-tag {
  font: 700 9.5px/1 Inter; letter-spacing: .05em; text-transform: uppercase;
  color: var(--primary); background: var(--primary-12); border-radius: 9999px; padding: 3px 6px;
  align-self: center;
}
.cm-time { font: 400 11px/1 Inter; color: var(--muted-2); }
.cm-deleted { color: var(--muted-2); font-style: italic; font-size: 13px; }
.cm-body { font: 400 14px/1.5 Inter; color: var(--foreground);
  white-space: pre-wrap; word-wrap: break-word; overflow-wrap: anywhere; }
.cm-body a { color: var(--primary); text-decoration: underline; }
.cm-at { color: var(--primary); background: var(--primary-12); border-radius: 4px; padding: 0 3px; font-weight: 600; }
.cm-edited { font: 400 10.5px/1 Inter; color: var(--muted-2); margin-left: 6px; }
.cm-img { display: block; padding: 0; margin: 2px 0; border: 0; background: none; cursor: zoom-in; }
.cm-img img { max-width: 360px; max-height: 240px; width: auto; height: auto;
  border-radius: 8px; display: block; object-fit: cover; }

/* --- full-size image lightbox --- */
.cm-lightbox {
  position: fixed; inset: 0; z-index: 100; background: rgba(0, 0, 0, .8);
  display: grid; place-items: center; padding: 32px;
}
.cm-lightbox img { max-width: 92vw; max-height: 92vh; border-radius: var(--card-radius); box-shadow: var(--shadow-pop); }
.cm-lightbox-x {
  position: fixed; top: 16px; right: 16px; width: 40px; height: 40px;
  display: grid; place-items: center; cursor: pointer;
  border-radius: 9999px; border: 1px solid var(--line); background: var(--card); color: var(--foreground);
}
.cm-lightbox-x:hover { background: var(--surface-hover); }
.cm-lightbox-x svg { width: 18px; height: 18px; }

/* quoted reply */
.cm-quote {
  display: flex; flex-direction: column; gap: 1px; margin-bottom: 6px;
  padding: 4px 8px; border-left: 3px solid var(--primary-30);
  background: var(--surface-hover); border-radius: 0 6px 6px 0;
  font-size: 12px; max-width: 100%;
}
.cm-quote.deleted { border-left-color: var(--line-strong); }
.cm-quote-who { font-weight: 700; color: var(--primary); }
.cm-quote-body { color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.cm-quote-body a { pointer-events: none; color: inherit; text-decoration: none; }

/* reactions */
.cm-reacts { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; align-items: center; }
.cm-react {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px;
  border: 1px solid var(--line); background: var(--surface); border-radius: 9999px;
  font: 600 11.5px/1 Inter; color: var(--muted-foreground); cursor: pointer;
}
.cm-react.mine { background: var(--primary-12); border-color: var(--primary-30); color: var(--primary); }
.cm-react-emo { font-size: 13px; }
.cm-react-add {
  display: inline-flex; padding: 3px; border: 1px solid transparent; background: none;
  color: var(--muted-2); border-radius: 9999px; cursor: pointer; opacity: 0; transition: opacity .12s;
}
.cm-react-add svg { width: 15px; height: 15px; }
.cm-msg:hover .cm-react-add { opacity: 1; }
.cm-msg:hover .cm-react-add:hover { color: var(--foreground); background: var(--surface-hover); }

/* hover actions */
.cm-actions {
  position: absolute; top: -12px; right: 8px; display: flex; gap: 2px;
  background: var(--card); border: 1px solid var(--line); border-radius: 9999px;
  padding: 2px; opacity: 0; transition: opacity .12s; box-shadow: var(--shadow-pop);
}
.cm-msg:hover .cm-actions { opacity: 1; }
.cm-actions button {
  display: inline-flex; padding: 5px; border: 0; background: none; cursor: pointer;
  color: var(--muted-foreground); border-radius: 9999px;
}
.cm-actions button:hover { background: var(--surface-hover); color: var(--foreground); }
.cm-actions button.danger:hover { color: var(--red); background: var(--surface-hover); }
.cm-actions svg { width: 15px; height: 15px; }

/* reaction picker popover */
.cm-picker {
  position: fixed; z-index: 60; display: flex; gap: 2px; padding: 5px;
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: 9999px; box-shadow: var(--shadow-pop);
}
.cm-picker-e {
  border: 0; background: none; cursor: pointer; font-size: 18px; line-height: 1;
  padding: 4px 6px; border-radius: 9999px;
}
.cm-picker-e:hover { background: var(--surface-hover); }

/* --- composer: a pill field holding the input + attach/emoji, send beside it --- */
.cm-composer {
  flex: none; border-top: 1px solid var(--line); padding: 10px 12px 14px;
  background: var(--card);
}
.cm-composer.drag { background: var(--primary-08); }
.cm-composer-row { display: flex; align-items: flex-end; gap: 8px; max-width: 760px; margin: 0 auto; }
.cm-field {
  position: relative; flex: 1; min-width: 0; display: flex; align-items: flex-end;
  border: 1px solid var(--line-strong); background: var(--input-bg);
  border-radius: 20px; padding: 6px 8px 6px 14px;
}
.cm-field:focus-within { border-color: var(--primary-30); box-shadow: 0 0 0 3px var(--ring); }
.cm-input {
  flex: 1; min-width: 0; resize: none; max-height: calc(1.4em * 6);
  border: 0; background: none; color: var(--foreground);
  padding: 4px 0; font: 400 14px/1.4 Inter;
}
.cm-input:focus { outline: none; }
.cm-field-tools { flex: none; display: flex; align-items: center; gap: 2px; padding-bottom: 2px; }
.cm-attach, .cm-emoji {
  width: 30px; height: 30px; display: grid; place-items: center; cursor: pointer;
  border: 0; background: none; color: var(--muted-2); border-radius: 9999px;
}
.cm-attach:hover, .cm-emoji:hover { background: var(--surface-hover); color: var(--foreground); }
.cm-attach svg, .cm-emoji svg { width: 18px; height: 18px; }
.cm-send {
  flex: none; width: 38px; height: 38px; display: grid; place-items: center;
  border-radius: 9999px; cursor: pointer; border: 1px solid var(--primary);
  background: var(--primary); color: var(--primary-fg);
}
.cm-send:hover { filter: brightness(1.05); }
.cm-send svg { width: 17px; height: 17px; }

.cm-reply-strip, .cm-img-strip {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
  padding: 6px 10px; background: var(--surface); border: 1px solid var(--line);
  border-radius: 8px; font: 500 12px/1.3 Inter;
}
.cm-reply-ico { color: var(--primary); display: grid; place-items: center; }
.cm-reply-ico svg { width: 14px; height: 14px; }
.cm-reply-who { font-weight: 700; color: var(--primary); flex: none; }
.cm-reply-body { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--muted-foreground); }
.cm-reply-body a { pointer-events: none; color: inherit; text-decoration: none; }
.cm-reply-x, .cm-img-x {
  flex: none; display: inline-flex; padding: 4px; border: 0; background: none;
  color: var(--muted-2); border-radius: 9999px; cursor: pointer;
}
.cm-reply-x:hover, .cm-img-x:hover { background: var(--surface-hover); color: var(--foreground); }
.cm-reply-x svg, .cm-img-x svg { width: 13px; height: 13px; }
.cm-img-thumb { width: 40px; height: 40px; object-fit: cover; border-radius: 6px; }
.cm-img-loading { color: var(--muted-foreground); }

/* --- phone: collapse to one pane at a time --- */
@media (max-width: 720px) {
  .cm-wrap { grid-template-columns: 1fr; height: calc(100vh - var(--topbar-h) - 32px); }
  .cm-channels { max-height: 168px; }
  .cm-stream-inner, .cm-composer-row { max-width: 100%; }
}

/* --- admin: community moderation --- */
.dtable td.dt-num { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted-foreground); }
.dtable tr.is-dim { opacity: .55; }
.dtable td.dt-actions { text-align: right; white-space: nowrap; }
.dtable td.dt-actions .btn-sec { margin-left: 6px; }
.cm-pnl-add { display: flex; gap: 8px; margin-bottom: 16px; }
.cm-pnl-add select {
  flex: 1; min-width: 0; border: 1px solid var(--line-strong); background: var(--input-bg);
  color: var(--foreground); border-radius: var(--radius); padding: 8px 10px; font: 400 13px/1 Inter;
}
.cm-pnl-list { display: flex; flex-direction: column; gap: 2px; }
.cm-pnl-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 4px; border-bottom: 1px solid var(--line);
}
.cm-pnl-row:last-child { border-bottom: 0; }
.cm-pnl-name { font: 500 13px/1.3 Inter; display: flex; align-items: center; gap: 8px; }

/* ============================================================
   CRM - the deal board. Reuses .kcol / .ops-* board geometry; only the
   card internals, the column value sum, the segmented view toggle and the
   Call-Tracking grid are CRM-specific.
   ============================================================ */
.crm-board { }
.crm-colsum { font: 700 12px/1 Inter; color: var(--muted-foreground); padding: 0 4px 8px; }
.crm-cards { display: flex; flex-direction: column; gap: 8px; min-height: 8px; }
.crm-card { padding: 10px 12px; }
.crm-title { font: 600 13.5px/1.35 Inter; color: var(--foreground); }
.crm-contact { font: 400 12px/1.3 Inter; color: var(--muted-foreground); margin-top: 2px; }
.crm-foot { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.crm-val { font: 700 12.5px/1 Inter; color: var(--foreground); }

/* Segmented view toggle (Board / List / Grid) in the top bar. */
.seg { display: inline-flex; background: var(--surface); border: 1px solid var(--line);
  border-radius: 9999px; padding: 2px; }
.seg-btn { border: 0; background: transparent; color: var(--muted-foreground);
  font: 600 12.5px/1 Inter; padding: 6px 13px; border-radius: 9999px; cursor: pointer; }
.seg-btn:hover { color: var(--foreground); }
.seg-btn.on { background: var(--primary); color: var(--primary-fg); }

/* The Call-Tracking grid - dense, every cell an input, like the sheet. */
.crm-grid-wrap { overflow-x: auto; }
.crm-grid td { padding: 3px 4px; }
.crm-grid .grid-sel, .crm-grid .grid-date, .crm-grid .grid-text {
  width: 100%; min-width: 116px; border: 1px solid transparent; background: transparent;
  color: var(--foreground); font: 400 13px/1.3 Inter; padding: 6px 7px; border-radius: var(--radius); }
.crm-grid .grid-sel:hover, .crm-grid .grid-date:hover, .crm-grid .grid-text:hover { background: var(--surface-hover); }
.crm-grid .grid-sel:focus, .crm-grid .grid-date:focus, .crm-grid .grid-text:focus {
  outline: none; border-color: var(--primary); background: var(--card); }
.crm-grid .grid-new { background: var(--surface); }

/* ============================================================
   KPI dashboard - the Sales KPI sheet, computed. A dense read-only grid:
   periods across the top, sections down the side, breakdown rows indented
   under each total, conversion-rate cells tinted against their benchmark.
   ============================================================ */
.kpi-wrap { overflow-x: auto; padding-bottom: 20px; }
.kpi-table { border-collapse: collapse; font: 400 12.5px/1.3 Inter; min-width: 100%; }
.kpi-table th, .kpi-table td { padding: 5px 10px; text-align: right; white-space: nowrap;
  border-bottom: 1px solid var(--line); }
.kpi-table thead th { position: sticky; top: 0; background: var(--background); z-index: 1;
  color: var(--muted-foreground); font-weight: 600; }
.kpi-rowhead { text-align: left; position: sticky; left: 0; background: var(--background);
  color: var(--foreground); }
.kpi-rowhead.sub { padding-left: 22px; color: var(--muted-foreground); font-weight: 400; }
.kpi-section td { font-weight: 800; font-size: 13px; padding-top: 16px; color: var(--foreground);
  border-bottom: 2px solid var(--line); }
.kpi-subhead td { font-weight: 700; color: var(--muted-foreground); padding-top: 12px; font-size: 11.5px;
  text-transform: uppercase; letter-spacing: .04em; }
.kpi-total td { font-weight: 700; color: var(--foreground); }
.kpi-total .kpi-rowhead { font-weight: 700; }
.kpi-zero { color: var(--muted-foreground); opacity: .45; }
.kpi-bench { color: var(--muted-foreground); font-size: 10.5px; margin-left: 4px; }
.kpi-rate .kpi-good { background: var(--primary-12); color: var(--primary); font-weight: 700; border-radius: 4px; }
.kpi-rate .kpi-warn { background: var(--amber-bg); color: var(--amber); font-weight: 700; border-radius: 4px; }
.kpi-rate .kpi-bad  { background: var(--red-bg); color: var(--red); font-weight: 700; border-radius: 4px; }

/* Booking admin - the weekly availability grid. Each row is a clear on/off day
   pill plus its hours; an off day dims its times and shows "Unavailable". */
.bk-avail-grid { display: flex; flex-direction: column; gap: 6px; }
.bk-avail-row { display: flex; align-items: center; gap: 12px; }
.bk-day-toggle { width: 74px; text-align: center; padding: 7px 0; border-radius: 9999px; cursor: pointer;
  font: 700 12.5px Inter; border: 1px solid var(--line); background: var(--surface);
  color: var(--muted-foreground); flex: none; }
.bk-day-toggle:hover { border-color: var(--primary); }
.bk-avail-row.on .bk-day-toggle { background: var(--primary); border-color: var(--primary); color: var(--primary-fg); }
.bk-avail-times { display: flex; align-items: center; gap: 8px; }
.bk-avail-row:not(.on) .bk-avail-times { display: none; }
.bk-avail-off { display: none; font-size: 12.5px; }
.bk-avail-row:not(.on) .bk-avail-off { display: inline; }
.bk-avail-row input[type="time"] { border: 1px solid var(--line); background: var(--surface);
  border-radius: var(--radius); padding: 5px 8px; font: 400 13px Inter; color: var(--foreground); }
