/* ============================================================
   Nexus — SP Desk spec: purple dark, warm-neutral light (Warm)
   ============================================================ */

/* The `hidden` attribute must actually hide things.
   The browser's own rule is `[hidden]{display:none}` at the lowest possible
   priority, so ANY author rule that sets `display` on a class defeats it —
   `.grid{display:grid}` and `.bulk-bar{display:flex}` both did. The symptom is
   nasty because it is silent: JS sets el.hidden = true, the element stays on
   screen, and the bug looks like broken toggle logic rather than CSS. It had
   already been patched once for .bulk-bar; this fixes the whole class of it,
   including the Reports tab panels (.grid) that rendered on every tab and the
   filter dropdowns that could all be open at once. */
[hidden]{display:none!important}

:root{
  /* SP Desk spec, dark. Sampled: sidebar, page, card, border, ink, muted,
     active fill/text, primary button. Estimated: --surface-2, --text-dim,
     the states. Every text token clears 4.5:1 on every surface (tested). */
  --bg:        #1d182d;
  --bg-2:      #120f1d;
  --surface:   #17142a;
  --surface-2: #231e38;
  --border:    #2b2646;
  --border-2:  #3d3660;
  --text:      #f3f5f8;
  --text-dim:  #d3cde3;
  --text-mute: #b1a9c9;
  /* --gold is the ACCENT: active text and icons, toggle on, checkbox, slider. */
  --gold:      #e0b068;
  --gold-2:    #e8be80;
  --gold-dim:  #8a6a3a;
  --on-gold:   #1f1404;
  --code-bg:   #120f1d;
  --code-text: #d8d3e8;
  --code-str:  #a8c98a;
  --ok:        #4fb886;
  --warn:      #e89e46;
  --bad:       #e07a6c;
  /* Brand, restated by the light block. --tan is the active fill (nav row,
     palette row), --brand the green of focus rings and success marks,
     --track the segmented-control groove, --menu every popover surface. */
  --tan:       #3b2d1b;
  --brand:     #35966a;
  --progress:  #e89e46;
  --track:     #120f1d;
  --divider:   #241f3b;
  --menu:      #1f1a33;
  --backdrop:  #0a0812;
  --cta-border: #c96a2c;
  --radius:    12px;
  --radius-sm: 8px;
  /* 1px borders everywhere: the one structural line is the border colour. */
  --rule:      #2b2646;
  /* Neutral overlays, as tokens rather than literals: a white wash is
     invisible on a white surface, so every one of these has to flip with the
     theme. --hover is a row/target highlight, --wash a barely-there fill,
     --sunk an inset track. */
  --hover:     #ffffff0a;
  --wash:      #ffffff05;
  --sunk:      #ffffff17;
  /* Translucent chrome for the sticky bars — content scrolls under it. */
  --chrome:    #1d182dcc;
  --chrome-solid: #1d182d;
  --shadow:    0 1px 2px #00000040;
  --shadow-lift: 0 4px 16px #00000055;
  --glow:      0 0 0 1px #e0b0682e;

  /* Easing tokens. The built-in CSS keywords are too weak to read as
     deliberate — these are the stronger variants. ease-out for anything
     entering or exiting (instant first movement = responsive), ease-in-out for
     something moving across the screen, and the Ionic drawer curve for
     sheet-like surfaces. Never ease-in on UI: it delays the first frame, which
     is the frame the user is watching. */
  /* ── chart series palette ─────────────────────────────────────
     Categorical hues in FIXED order, never cycled: colour follows the entity,
     so a filter that removes a series must not repaint the survivors. Stepped
     for a dark surface and validated as a set against #1a1a1a — lightness band,
     chroma floor, protan/deutan separation, normal-vision floor and 3:1
     contrast all pass. Do not hand-pick a "nicer" hue here without re-running
     that validation; the ordering IS the colourblind-safety mechanism.
     The brand gold is deliberately NOT a series colour — it means "primary
     action" everywhere else, and a chart series wearing it would read as one. */
  /* ── tone palette ─────────────────────────────────────────────
     Five hues for things that are CATEGORIES, not states: which lead type,
     which agent, which section of the nav. Each clears 4.5:1 as text on every
     surface and on its own 14% tint, in both themes. They are separate from
     the chart series (which are validated as a set for charts) and from
     ok / warn / bad (which mean a state and must keep meaning only that). */
  --c-blue:   #6fb0f5;
  --c-teal:   #4cc7a0;
  --c-violet: #b0a2f5;
  --c-pink:   #ec8fb2;
  --c-orange: #f09468;
  --series-1: #3987e5;   /* blue    */
  --series-2: #d95926;   /* orange  */
  --series-3: #199e70;   /* aqua    */
  --series-4: #c98500;   /* yellow  */
  --series-5: #d55181;   /* magenta */
  --series-6: #008300;   /* green   */

  --ease-out:      cubic-bezier(.23, 1, .32, 1);
  --ease-in-out:   cubic-bezier(.77, 0, .175, 1);
  --ease-drawer:   cubic-bezier(.32, .72, 0, 1);

  /* Global type scale. EVERY font-size in this file and in the templates is
     written as calc(<base>px * var(--fs,1)), so this one number resizes all
     text app-wide without touching padding, borders or column widths. 1 = the
     original sizing; raise it to make the whole UI more readable.
     Only font sizes scale, so a bigger value never reflows the layout the way
     browser zoom does. live.html is standalone (it does not load this file)
     and carries its own copy of this variable — keep the two in step. */
  --fs: 1.15;

  /* Type tokens. Every font-family in this file and the templates reads one of
     these, so a type change is one line here (the Warm theme restates them). */
  --font-sans:    'Inter',system-ui,sans-serif;
  --font-display: 'Inter Tight','Inter',system-ui,sans-serif;
  --font-mono:    'Geist Mono',ui-monospace,monospace;
}
/* ── light theme ────────────────────────────────────────────────────
   Opt-in, not the default. Dark stays on bare :root because that is what
   every existing board and wall display is running; flipping the default
   would change the product for everyone to serve a preference.

   Set by the toggle in the top bar, which stamps data-theme on <html> and
   remembers it. `prefers-color-scheme: light` is honoured only when the
   viewer has not chosen explicitly, so an explicit choice always wins.

   Every text token below was computed to clear WCAG AA (4.5:1) against
   --surface-2, the DARKEST of the light surfaces and therefore the worst
   case — not against white, which would have flattered all of them.
   test_every_text_colour_meets_wcag_aa_on_every_surface checks both themes. */
:root[data-theme="light"]{
  /* Cool, clean neutrals. The first light palette was warm beige, and under
     the gold and blue page washes it read as dingy paper rather than as a
     light UI: white cards had nothing crisp to sit on. --surface-2 is still
     the darkest light surface and is no darker than before, so every text
     token keeps its contrast. */
  --bg:        #f4f5f7;
  --bg-2:      #fafbfc;
  --surface:   #ffffff;
  --surface-2: #f1f3f5;
  --border:    #e3e6ea;
  --border-2:  #c9ced6;
  --rule:      #0000001f;
  --text:      #1a1a17;
  --text-dim:  #555145;
  --text-mute: #706c5b;
  --gold:      #78541c;
  --gold-2:    #6f4d17;
  --gold-dim:  #c9a66b;
  --on-gold:   #ffffff;
  --tan:       #f3e7cb;
  --brand:     #35966a;
  --progress:  #e89e46;
  --track:     #edeff3;
  --divider:   #e9ebe5;
  --menu:      #fcfbf8;
  --backdrop:  #323130;
  --cta-border: #835c21;
  --code-bg:   #f1f3f5;
  --code-text: #33302a;
  --code-str:  #3f6331;
  --ok:        #50763e;
  --warn:      #96601c;
  --bad:       #bc4334;
  /* Neutral overlays invert: a white wash is invisible on white. */
  --hover:     #0000000a;
  --chrome:    #ffffffcc;
  --chrome-solid: #ffffff;
  --wash:      #00000005;
  --sunk:      #00000012;
  --shadow:    0 1px 2px #0000000f;
  --shadow-lift: 0 2px 10px #00000014;
  --glow:      0 0 0 1px #816a2733;
  /* Chart series, light steps — the same eight hues re-stepped for a light
     surface and validated as a set against #faf9f6, not an automatic flip of
     the dark values. Slots 3, 4 and 5 sit below 3:1 here (the documented
     relief case): if a chart ever uses them, it must carry visible direct
     labels or a table view. The two the app currently plots (1 and 2) clear it. */
  --c-blue:   #1f5fb5;
  --c-teal:   #0c6a4c;
  --c-violet: #5a45c0;
  --c-pink:   #a83264;
  --c-orange: #9a4012;
  --series-1: #2a78d6;
  --series-2: #eb6834;
  --series-3: #1baf7a;
  --series-4: #eda100;
  --series-5: #e87ba4;
  --series-6: #008300;
}
/* ── warm theme ─────────────────────────────────────────────────────
   Light with cream paper and brown-gold ink. It rides on data-theme="light"
   (plus data-warm) so every chart and page that already knows "light" works
   unchanged; only the surfaces and ink are restated. Same AA rule as above,
   checked by the same test. */
:root[data-theme="light"][data-warm]{
  /* SP Desk spec, light. Sampled: page, sidebar, inner panel, card, border,
     ink, muted. --ok is a darker step of the spec green: #35966a is 3.7:1 on
     white, fine for a ring, too faint for text. */
  --bg:        #f3f4f0;
  --bg-2:      #f9f7f1;
  --surface:   #ffffff;
  --surface-2: #eeefeb;
  --border:    #d4d7ce;
  --border-2:  #bfc3b8;
  --rule:      #d4d7ce;
  --text:      #0e1722;
  --text-dim:  #3b3f4a;
  --text-mute: #5a5863;
  --code-bg:   #eeefeb;
  --ok:        #267050;
  --warn:      #8a5413;
  --bad:       #ae3d2e;
  --chrome:    #f3f4f0cc;
  --chrome-solid: #f3f4f0;
  --shadow:    0 1px 2px #0e17220d;
  --shadow-lift: 0 4px 14px #0e172214;
}

*{box-sizing:border-box}
html,body{margin:0;padding:0;background:var(--bg);color:var(--text);
  font-family:var(--font-sans);font-size:calc(14px*var(--fs,1));line-height:1.5;
  -webkit-font-smoothing:antialiased}
/* -0.03em (spec) on titles; section headings ease to -0.02em so word gaps don't close up. */
h1,h2,h3,h4{font-family:var(--font-display);font-weight:600;letter-spacing:-0.02em;margin:0}
/* Leading tracks size inversely: tight on headings, the body's 1.5 for prose.
   Tracking is already size-specific — negative as text grows, positive on the
   small uppercase labels below — so no single value is applied across sizes. */
h1{font-size:calc(30px*var(--fs,1));letter-spacing:-0.03em;line-height:1.15}
h2{font-size:calc(18px*var(--fs,1));line-height:1.3}
h3{font-size:calc(14px*var(--fs,1));color:var(--text-dim);text-transform:none;letter-spacing:0;font-weight:500}
a{color:inherit;text-decoration:none}
code{font-family:var(--font-mono);font-size:calc(12.5px*var(--fs,1))}
.mono{font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(12.5px*var(--fs,1))}

/* layout shell ============================================== */
.app{display:grid;grid-template-columns:240px 1fr;min-height:100vh}
.sidebar{background:var(--bg-2);border-right:1px solid var(--border);
  padding:20px 14px;position:sticky;top:0;height:100vh;display:flex;flex-direction:column;gap:18px}
.brand{display:flex;align-items:center;gap:10px;padding:6px 8px;color:inherit;text-decoration:none}
.brand .brand-mark{display:none}
.brand-full{display:block;width:100%}
.brand-mark{width:34px;height:34px;flex:none;
  display:grid;place-items:center;font-family:var(--font-display);font-weight:700;color:var(--on-gold);box-shadow:var(--glow)}
.brand-name{font-family:var(--font-display);font-weight:700;font-size:calc(22px*var(--fs,1));letter-spacing:-0.045em;line-height:1}
/* Nexus mark (_nx_mark.html): on .play the bars rise, the diagonal draws, the dot pops. */
.nx{display:block;width:100%;height:100%}
.nx-bar,.nx-dot{transform-box:fill-box}
.nx-bar{transform-origin:50% 100%}.nx-dot{transform-origin:50% 50%}.nx-diag{stroke-dasharray:100}
.nx.play .nx-bar{animation:nxbar .9s cubic-bezier(.2,.8,.2,1) both}
.nx.play .nx-diag{animation:nxdiag .8s ease-out .3s both}
.nx.play .nx-dot{animation:nxdot .5s ease-out .9s both}
@keyframes nxbar{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes nxdiag{from{stroke-dashoffset:100}to{stroke-dashoffset:0}}
@keyframes nxdot{0%{transform:scale(0)}70%{transform:scale(1.3)}100%{transform:scale(1)}}
@media(prefers-reduced-motion:reduce){.nx.play *{animation:none}}
.nav{display:flex;flex-direction:column;gap:2px;margin-top:4px}
.nav a{display:flex;align-items:center;gap:10px;
  min-height:36px;padding:0 10px;border-radius:10px;color:var(--text-dim);font-size:calc(13.5px*var(--fs,1));
  transition:background-color .12s,color .12s}
.nav a .nav-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav a > .ti{font-size:1.2em;color:var(--text-mute);transition:color .15s}
.nav a:hover > .ti{color:var(--text-dim)}
.nav a.active > .ti{color:var(--gold)}
.nav a:hover{background:var(--hover);color:var(--text)}
.nav a.active{background:var(--tan);color:var(--gold);font-weight:500}
.nav a kbd{font-family:var(--font-mono);font-size:calc(10px*var(--fs,1));padding:1px 5px;border:1px solid var(--border);
  border-radius:4px;color:var(--text-dim);background:var(--sunk)}
.sidebar-foot{margin-top:auto;padding:10px;border-top:1px solid var(--border);color:var(--text-mute);font-size:calc(11.5px*var(--fs,1))}
.sidebar-foot .foot-mini{display:none;gap:6px;justify-content:center}
.sidebar-foot .foot-mini a{display:grid;place-items:center;width:32px;height:32px;
  border-radius:var(--radius-sm);color:var(--text-mute);transition:background .15s,color .15s}
.sidebar-foot .foot-mini a:hover{background:var(--surface);color:var(--text)}

/* ── collapsible sidebar ──────────────────────────────────────
   `nav-collapsed` lives on <html> (set pre-paint by the inline snippet in
   base.html) so the rail is already correct on first frame. Collapsing hides
   the labels only — the icons and the whole nav structure stay put, and the
   label comes back as a tooltip on the right. */
.nav-collapse{display:none;background:none;border:0;color:var(--text-mute);
  cursor:pointer;padding:6px;border-radius:var(--radius-sm);line-height:1;
  transition:background .15s,color .15s}
.nav-collapse:hover{background:var(--surface);color:var(--text)}
.nav-collapse:focus-visible{outline:none;box-shadow:var(--ring)}
.nav-collapse .ti{font-size:calc(19px*var(--fs,1))}
.nav-collapse .when-shut{display:none}
html.nav-collapsed .nav-collapse .when-open{display:none}
html.nav-collapsed .nav-collapse .when-shut{display:inline-flex}
@media(min-width:761px){.nav-collapse{display:inline-flex}}

@media(min-width:761px){
  .app{transition:grid-template-columns .22s var(--ease-out)}
  html.nav-collapsed .app{grid-template-columns:64px 1fr}
  html.nav-collapsed .sidebar{padding:20px 8px;align-items:stretch}
  html.nav-collapsed .brand{justify-content:center;padding:6px 0}
  html.nav-collapsed .brand .brand-full{display:none}
  html.nav-collapsed .brand .brand-mark{display:block}
  html.nav-collapsed .nav a{justify-content:center;padding:10px 0;gap:0}
  html.nav-collapsed .nav a .nav-label,
  html.nav-collapsed .nav a kbd{display:none}
  html.nav-collapsed .nav a.active{box-shadow:inset 2px 0 0 var(--gold)}
  html.nav-collapsed .sidebar-foot{padding:10px 0 0}
  html.nav-collapsed .sidebar-foot .foot-full{display:none}
  html.nav-collapsed .sidebar-foot .foot-mini{display:flex}
}
/* The nav tooltip is the label's replacement — only useful once it's hidden,
   and it sits to the RIGHT of the rail rather than above it. */
html:not(.nav-collapsed) .nav a[data-tip]::after,
.sidebar-foot .foot-mini a[data-tip]::after{display:none}
html.nav-collapsed .nav a[data-tip]::after,
html.nav-collapsed .sidebar-foot .foot-mini a[data-tip]::after{
  bottom:auto;top:50%;left:calc(100% + 10px);transform:translateY(-50%)}
html.nav-collapsed .nav a[data-tip]:hover::after,
html.nav-collapsed .sidebar-foot .foot-mini a[data-tip]:hover::after{display:block}

.main{display:flex;flex-direction:column;min-width:0}
.topbar{position:sticky;top:0;z-index:5;background:var(--chrome);backdrop-filter:blur(10px);
  border-bottom:1px solid var(--border);padding:12px 28px;display:flex;align-items:center;gap:16px}
.search{flex:1;max-width:480px;position:relative}
.search input{width:100%;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-sm);padding:8px 12px 8px 34px;color:var(--text);font-size:calc(13px*var(--fs,1));outline:none}
.search input:focus{border-color:var(--brand)}
.search::before{content:"⌕";position:absolute;left:11px;top:50%;transform:translateY(-50%);color:var(--text-mute)}
.topbar-right{margin-left:auto;display:flex;align-items:center;gap:14px;color:var(--text-dim);font-size:calc(12.5px*var(--fs,1))}
.live{display:flex;align-items:center;gap:6px}
.live .dot{width:7px;height:7px;border-radius:50%;background:var(--ok);box-shadow:0 0 8px var(--ok)}
.avatar{width:30px;height:30px;border-radius:50%;background:linear-gradient(135deg,var(--gold-2),var(--gold));
  color:var(--on-gold);display:grid;place-items:center;font-weight:600;font-family:var(--font-display);font-size:calc(12px*var(--fs,1))}

.content{padding:28px;max-width:1500px;width:100%}
.page-head{display:flex;align-items:flex-end;justify-content:space-between;margin-bottom:24px;gap:24px}
.page-head .sub{color:var(--text-dim);margin-top:6px;font-size:calc(13.5px*var(--fs,1));
  /* Prose caps at ~75ch. On a 1500px content column this ran to well over
     200 characters a line, which the eye cannot track back from. */
  max-width:78ch;line-height:1.6}

/* primitives ================================================ */
.card{background:var(--surface);border:1px solid var(--rule);border-radius:var(--radius);
  padding:22px;box-shadow:none}
.card.tight{padding:15px}
.card h2{margin-bottom:14px}
.row{display:flex;align-items:center;gap:12px}
.grid{display:grid;gap:16px}
.grid.k6{grid-template-columns:repeat(6,1fr)}
.grid.k5{grid-template-columns:repeat(5,1fr)}
.grid.k4{grid-template-columns:repeat(4,1fr)}
.grid.k3{grid-template-columns:repeat(3,1fr)}
.grid.k2{grid-template-columns:1fr 1fr}
.grid.split{grid-template-columns:2fr 1fr}
@media(max-width:1100px){.grid.k6,.grid.k5{grid-template-columns:repeat(3,1fr)}.grid.k4{grid-template-columns:repeat(2,1fr)}}
@media(max-width:760px){.app{grid-template-columns:1fr}.sidebar{position:fixed;transform:translateX(-100%);z-index:20;width:240px}
  .grid.k6,.grid.k5,.grid.k4,.grid.k3,.grid.k2,.grid.split{grid-template-columns:1fr}}

.btn{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;border-radius:var(--radius-sm);
  border:1px solid var(--border);background:var(--surface);color:var(--text);font:inherit;font-size:calc(13px*var(--fs,1));
  cursor:pointer;transition:background .15s,border-color .15s,transform .15s var(--ease-out)}
.btn:hover{background:var(--surface-2);border-color:var(--border-2)}
.btn.primary{background:var(--gold-2);color:var(--on-gold);
  border-color:var(--gold-2);font-weight:600;box-shadow:none}
.btn.primary:hover{background:var(--gold);border-color:var(--gold)}
.btn.ghost{background:transparent}

/* Report section tabs. The Reports page carries 8 charts and 5 tables; shown
   all at once it reads as a wall. Each block declares the tab it belongs to
   and only the active tab's blocks are in flow. */
/* Floating chrome, so it reads as a translucent layer with content passing
   underneath rather than an opaque strip that eats a band of the page. The
   bright top edge is light catching the material. */
.rtabs{position:sticky;top:56px;z-index:5;display:flex;gap:4px;flex-wrap:wrap;
  margin:0 0 18px;padding:6px;border-radius:var(--radius);
  border:1px solid var(--border);border-top-color:var(--sunk);
  background:var(--bg-2);
  background:color-mix(in srgb, var(--bg-2) 72%, transparent);backdrop-filter:blur(16px) saturate(140%)}
.rtabs button,.rtabs a[role="tab"]{padding:7px 14px;border-radius:999px;border:0;background:none;cursor:pointer;
  font:inherit;font-size:calc(12.5px*var(--fs,1));color:var(--text-dim);
  display:inline-flex;align-items:center;gap:7px;transition:background .12s,color .12s}
.rtabs button:hover,.rtabs a[role="tab"]:hover{background:var(--surface-2);color:var(--text)}
.rtabs button:active,.rtabs a[role="tab"]:active{transform:scale(.96);transition-duration:.06s}
.rtabs button[aria-selected="true"],.rtabs a[role="tab"][aria-selected="true"]{background:color-mix(in srgb, var(--gold) 8%, transparent);color:var(--gold-2);
  box-shadow:inset 0 0 0 1px var(--gold-dim)}
[data-tab][hidden]{display:none}
@media(max-width:760px){.rtabs{position:static}}

/* Numbered pager (see templates/_pager.html) — first/last always reachable,
   with a window around the current page, so deep pages don't need N clicks. */
.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;margin-top:14px}
.pager-meta{color:var(--text-dim);font-size:calc(12.5px*var(--fs,1))}
.pager-links{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.pager-step{font-size:calc(12.5px*var(--fs,1))}
.pager-step.is-off{opacity:.35;pointer-events:none}
.pager-num{display:inline-grid;place-items:center;min-width:32px;height:32px;padding:0 8px;
  border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--surface);
  color:var(--text-dim);font-family:var(--font-sans);font-variant-numeric:tabular-nums;
  font-size:calc(12px*var(--fs,1));transition:background .12s,border-color .12s,color .12s,transform .15s var(--ease-out)}
a.pager-num:hover{background:var(--surface-2);border-color:var(--border-2);color:var(--text)}
/* Feedback belongs on the press, not on release: the element acknowledges the
   finger the instant it lands. Fast in, slower back out. */
a.pager-num:active{transform:scale(.94);transition-duration:.06s}
.pager-num.is-current{background:var(--gold-2);
  border-color:var(--gold);color:var(--on-gold);font-weight:600}
.pager-gap{color:var(--text-mute);padding:0 2px;font-size:calc(12px*var(--fs,1))}

/* Docked bulk-action bar (History). Floats above the page while a selection is
   live, so acting on a selection never requires scrolling to the table's end.

   It arrives as a material rather than appearing: blur, scale and offset move
   together so it reads as a real surface coming forward. Enter and exit travel
   the SAME path (up from below, back down), because a panel that leaves by a
   different route than it arrived reads as a different object. */
.bulk-bar{position:sticky;bottom:14px;z-index:15;display:flex;align-items:center;gap:10px;
  flex-wrap:wrap;margin-top:14px;padding:10px 14px;border-radius:var(--radius);
  border:1px solid var(--gold-dim);border-top-color:color-mix(in srgb, var(--gold-2) 20%, transparent);
  background:var(--surface-2);
  background:color-mix(in srgb, var(--surface-2) 82%, transparent);backdrop-filter:blur(18px) saturate(160%);
  box-shadow:var(--glow);
  opacity:0;transform:translateY(12px) scale(.98);
  transition:opacity .22s var(--ease-out),transform .28s var(--ease-out),
             backdrop-filter .28s var(--ease-out)}
.bulk-bar.is-in{opacity:1;transform:none}
.bulk-bar[hidden]{display:none}
.bulk-bar .bulk-count{color:var(--text-dim);font-size:calc(12.5px*var(--fs,1))}
.bulk-bar .bulk-count strong{color:var(--gold-2);font-family:var(--font-display);font-size:calc(14px*var(--fs,1))}
.bulk-bar .bulk-clear{font-size:calc(11.5px*var(--fs,1));padding:4px 9px}
.bulk-bar .bulk-sep{width:1px;align-self:stretch;background:var(--border-2);margin:0 2px}

.badge{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:999px;
  font-size:calc(10px*var(--fs,1));letter-spacing:0;text-transform:none;
  border:1px solid var(--rule);color:var(--text-dim);background:var(--wash);font-weight:500}
.badge.ok{color:var(--ok);border-color:color-mix(in srgb, var(--ok) 25%, transparent);background:color-mix(in srgb, var(--ok) 7%, transparent)}
.badge.warn{color:var(--warn);border-color:color-mix(in srgb, var(--warn) 25%, transparent);background:color-mix(in srgb, var(--warn) 7%, transparent)}
.badge.bad{color:var(--bad);border-color:color-mix(in srgb, var(--bad) 25%, transparent);background:color-mix(in srgb, var(--bad) 7%, transparent)}
.badge.admin{color:var(--gold-2);border-color:var(--gold-dim);background:color-mix(in srgb, var(--gold) 8%, transparent)}

.kpi{display:flex;flex-direction:column;gap:8px;min-width:0}
.kpi .label{color:var(--text-dim);font-size:calc(12px*var(--fs,1));letter-spacing:0;text-transform:none;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* clamp + wrap so a six-digit total can't blow out of a 1/6-width card */
.kpi .value{font-family:var(--font-display);font-size:calc(clamp(20px,1.6vw + 10px,30px)*var(--fs,1));
  font-weight:600;letter-spacing:-0.02em;line-height:1.15;overflow-wrap:anywhere}
.kpi .delta{font-size:calc(12px*var(--fs,1));color:var(--text-mute)}
.kpi .delta.ok{color:var(--ok)} .kpi .delta.warn{color:var(--warn)}
/* grid children must be allowed to shrink, or long content forces overflow */
.grid > *{min-width:0}

/* tables ==================================================== */
table{width:100%;border-collapse:collapse;font-size:calc(13px*var(--fs,1))}
th{text-align:left;color:var(--text-mute);font-weight:600;font-size:calc(12px*var(--fs,1));
  padding:0 12px 10px;
  border-bottom:1px solid var(--rule);white-space:nowrap}
td{padding:12px;border-bottom:1px solid var(--rule);color:var(--text)}
/* Figures must line up down a column; proportional digits make a table of
   numbers look ragged even when the values are right. */
td.num,th.num,td.mono,.mono,code{font-variant-numeric:tabular-nums}
/* Dates, phones and ids: wrapping one across three lines tripled every row
   height on History and made the table unreadable. */
td.mono{white-space:nowrap}
tr:hover td{background:var(--wash)}
tbody tr:last-child td{border-bottom:none}

/* Numeric columns read as numbers: right-aligned so the digits stack. */
th.num,td.num{text-align:right}

/* figure row ================================================
   A flat readout of headline numbers: rules, not cards, because these are
   values to READ. `.triage` is the tile that FILTERS the page (Coverage,
   UG Tools) — the two look different because they do different things, and
   using the clickable one for a static readout is what made Weekly Review and
   UG Efficiency look like two different products. */
.figures{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
  margin-bottom:26px}
.figure{padding:18px 22px 18px 0;border-right:1px solid var(--rule);min-width:0}
.figure:last-child{border-right:0}
.figure .k{font-size:calc(10px*var(--fs,1));letter-spacing:0;
  text-transform:none;color:var(--text-mute);font-weight:500}
.figure .v{font-family:var(--font-display);
  font-size:calc(30px*var(--fs,1));font-weight:500;letter-spacing:-0.03em;
  line-height:1.05;margin:9px 0 5px}
.figure .v small{font-size:.42em;letter-spacing:0;color:var(--text-mute);
  font-family:var(--font-sans);font-variant-numeric:tabular-nums;margin-left:3px}
.figure .n{color:var(--text-mute);font-size:calc(11.5px*var(--fs,1));line-height:1.5}
@media(max-width:760px){.figure{border-right:0;border-bottom:1px solid var(--rule)}}

/* A page section: rules and rhythm, no box. Cards are for things you can act
   on as a unit; a table of figures is not one. */
.sec{margin:0 0 34px}

/* Section header: a title with its caption pushed to the far rule. */
.sechead{display:flex;align-items:baseline;gap:12px;margin-bottom:12px}
.sechead h2{margin:0;font-size:calc(15px*var(--fs,1));letter-spacing:-0.01em}
.sechead .note{margin-left:auto;color:var(--text-mute);
  font-size:calc(11.5px*var(--fs,1))}

/* A percentage with its own bar. Colour is the signal, so it is the only
   place on these pages colour appears. */
.pctbar{display:inline-flex;align-items:center;gap:7px;
  font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-variant-numeric:tabular-nums}
.pctbar .track{width:44px;height:3px;background:var(--sunk);border-radius:2px;overflow:hidden}
.pctbar .track > span{display:block;height:100%;background:currentColor}
.pctbar.hi{color:var(--ok)}
.pctbar.mid{color:var(--warn)}
.pctbar.lo{color:var(--bad)}
.pctbar.na{color:var(--text-mute)}

/* Tiny inline bar series. NOT `.spark`, which is the 140px SVG sparkline. */
.microbar{display:inline-flex;align-items:flex-end;gap:2px;height:16px}
.microbar i{width:3px;background:var(--text-mute);border-radius:1px;display:block}
.microbar i.on{background:var(--ok)}

/* Staggered row entry for a freshly-rendered table. */
.stagger tbody tr{opacity:0;transform:translateY(10px);
  animation:rowin .5s var(--ease-out) forwards;
  animation-delay:calc(var(--i,0)*40ms)}
@keyframes rowin{to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){
  .stagger tbody tr{opacity:1;transform:none;animation:none}
}

/* progress + bars =========================================== */
.bar{height:6px;background:var(--surface-2);border-radius:999px;overflow:hidden}
.bar > span{display:block;height:100%;width:100%;background:var(--gold);border-radius:999px}

.heat{display:flex;flex-direction:column;gap:8px}
.heat .cell{display:flex;align-items:center;gap:10px}
.heat .st{width:32px;font-family:var(--font-sans);font-variant-numeric:tabular-nums;color:var(--text-dim);font-size:calc(12px*var(--fs,1))}
.heat .b{flex:1;height:8px;border-radius:4px;background:var(--surface-2);overflow:hidden}
.heat .b > span{display:block;height:100%;background:var(--gold)}
.heat .v{width:44px;text-align:right;font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(12px*var(--fs,1));color:var(--text)}

/* sparkline ================================================= */
.spark{width:100%;height:140px}
.spark .line{stroke:var(--gold-2);stroke-width:2;fill:none}
.spark .dot{fill:var(--gold-2)}

/* form bits ================================================= */
input,select,textarea{font:inherit;background:var(--surface);border:1px solid var(--rule);
  color:var(--text);border-radius:var(--radius-sm);padding:8px 10px;outline:none;width:100%}
input:focus,select:focus,textarea:focus{border-color:var(--brand)}
/* Placeholders are text and need the same 4.5:1. The browser default derives
   them from `color` at a reduced opacity, which lands under 3:1 on these
   surfaces; opacity:1 is required or Firefox re-applies its own. */
::placeholder{color:var(--text-mute);opacity:1}
/* One control height across the app. Inputs, selects and date pickers used to
   size themselves independently, so a filter row was a ragged line of
   different heights — the single loudest thing wrong with the dense pages. */
input:not([type=checkbox]):not([type=radio]):not([type=file]),select,.btn,
.search input,.ms-btn{height:34px;line-height:1}
/* A native select centres its own text; forcing line-height:1 on it pushes the
   label off the vertical centre of the control. */
select{line-height:normal;padding-top:0;padding-bottom:0}
/* A fixed height means a two-word label must not wrap, or it overflows the
   button it is sitting in. */
.btn{white-space:nowrap}
/* Buttons that genuinely need two lines opt out. */
.btn.tall{height:auto;min-height:34px;white-space:normal;line-height:1.25}
select{padding-right:26px}
/* Date inputs ship with a wide intrinsic width and were stretching the row. */
input[type=date]{width:auto;min-width:0;flex:0 0 auto}
/* Sentence case, Ethos-style: uppercase micro-labels made every form shout. */
label{display:block;font-size:calc(13px*var(--fs,1));font-weight:500;color:var(--text-dim);margin-bottom:6px}
.field{margin-bottom:14px}

/* drag-drop ================================================= */
.dropzone{border:1.5px dashed var(--border-2);border-radius:var(--radius);padding:48px 24px;
  text-align:center;color:var(--text-dim);background:var(--wash);transition:border-color .2s,background .2s}
.dropzone.hover{border-color:var(--gold);background:color-mix(in srgb, var(--gold) 3%, transparent)}
.dropzone .big{font-family:var(--font-display);font-size:calc(18px*var(--fs,1));color:var(--text);margin-bottom:6px}

/* slack preview ============================================= */
.slack{background:#1d1d1d;border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;
  font-family:'Lato',-apple-system,sans-serif;font-size:calc(13.5px*var(--fs,1));color:#d1d2d3;display:flex;gap:10px}
.slack .av{width:34px;height:34px;border-radius:6px;background:#4a154b;display:grid;place-items:center;color:#fff;font-weight:700}
.slack .body{flex:1}
.slack .name{font-weight:700;color:#fff;margin-bottom:2px}
.slack .name .time{color:#9a9a9a;font-weight:400;font-size:calc(11.5px*var(--fs,1));margin-left:6px}

/* matrix ==================================================== */
.matrix{width:100%;border-collapse:separate;border-spacing:0;font-size:calc(12.5px*var(--fs,1))}
.matrix th,.matrix td{padding:9px 10px;text-align:center}
.matrix th:first-child,.matrix td:first-child{text-align:left;color:var(--text-dim)}
.matrix .yes{color:var(--gold-2)} .matrix .no{color:var(--text-mute)}

/* status dot ================================================ */
.sdot{width:7px;height:7px;border-radius:50%;display:inline-block;margin-right:6px}
.sdot.online{background:var(--ok);box-shadow:0 0 6px var(--ok)}
.sdot.away{background:var(--warn)}
.sdot.offline{background:var(--text-mute)}

/* misc ====================================================== */
/* Filter strip. One bordered surface holding every control at one height, so
   filters read as a single instrument rather than a scatter of boxes. */
.toolbar{display:flex;gap:8px;align-items:center;margin-bottom:16px;flex-wrap:wrap;
  padding:12px;border:1px solid var(--rule);border-radius:var(--radius);
  background:var(--bg-2)}
.toolbar input,.toolbar select,.toolbar .ms-btn{background:var(--surface)}
/* Selects inherit the global width:100% and would stack the strip vertically. */
.toolbar select{width:auto;min-width:0;flex:0 0 auto}
/* The micro-label that names a control inside a strip. */
.lab{font-size:calc(10px*var(--fs,1));letter-spacing:0;text-transform:none;
  color:var(--text-mute);font-weight:500;flex:0 0 auto}
/* The search wrapper carries a max-width but no basis, so flex shrank it to a
   couple of characters once the row filled up. */
.toolbar .search{flex:1 1 180px;min-width:150px}
.toolbar > input[name]{flex:0 1 auto;min-width:110px}
.toolbar .sp{flex:1}
.divider{height:1px;background:var(--border);margin:18px 0}
.kbd{font-family:var(--font-mono);font-size:calc(10.5px*var(--fs,1));padding:1px 5px;border:1px solid var(--border);
  border-radius:4px;color:var(--text-dim);background:var(--sunk)}
.snippet{background:var(--code-bg);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:14px;font-family:var(--font-mono);font-size:calc(12.5px*var(--fs,1));color:var(--code-text);overflow-x:auto;white-space:pre}
.snippet .c{color:var(--text-mute)} .snippet .k{color:var(--gold-2)} .snippet .s{color:var(--code-str)}
.scroll{overflow-x:auto}
.menu-toggle{display:none;background:none;border:0;color:var(--text);font-size:calc(22px*var(--fs,1));cursor:pointer}
@media(max-width:760px){.menu-toggle{display:block}.sidebar.open{transform:translateX(0)}}

/* ── tablet breakpoint ─────────────────────────────────────── */
@media(max-width:1024px) and (min-width:761px){
  .app{grid-template-columns:200px 1fr}
  .sidebar{padding:16px 10px}
  .content{padding:20px}
  .grid.k6,.grid.k5{grid-template-columns:repeat(3,1fr)}
}

/* ── page load bar ─────────────────────────────────────────── */
#nprogress{pointer-events:none;position:fixed;top:0;left:0;right:0;z-index:9999}
#nprogress .bar{background:var(--gold-2);height:2px;position:relative;transition:width .2s}
#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;
  box-shadow:0 0 10px var(--gold-2),0 0 5px var(--gold-2);opacity:1;transform:rotate(3deg) translate(0,-4px)}

/* ── toast notifications ───────────────────────────────────── */
#toast-shelf{position:fixed;bottom:24px;right:24px;z-index:9000;
  display:flex;flex-direction:column-reverse;gap:10px;pointer-events:none}
.toast{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:var(--radius);
  border:1px solid var(--border);background:var(--surface-2);box-shadow:0 8px 32px #00000080;
  font-size:calc(13px*var(--fs,1));pointer-events:all;min-width:280px;max-width:400px;
  /* Transitions, not keyframes: toasts stack and are fired in bursts, and a
     keyframe restarts from zero when a new one interrupts it. A transition
     retargets from wherever the element currently is.
     Exit is faster than enter (.18s vs .24s) — the system responding should
     always be quicker than the system announcing. */
  opacity:0;transform:translateY(12px) scale(.97);
  transition:opacity .18s var(--ease-out),transform .18s var(--ease-out)}
.toast.is-in{opacity:1;transform:none;
  transition:opacity .24s var(--ease-out),transform .24s var(--ease-out)}
.toast .t-icon{font-size:calc(16px*var(--fs,1));flex-shrink:0}
.toast .t-msg{flex:1;line-height:1.4}
.toast .t-close{background:none;border:0;color:var(--text-mute);cursor:pointer;font-size:calc(16px*var(--fs,1));
  padding:0;line-height:1;flex-shrink:0}
.toast.ok{border-color:color-mix(in srgb, var(--ok) 25%, transparent);background:color-mix(in srgb, var(--ok) 12%, var(--bg))}
.toast.warn{border-color:color-mix(in srgb, var(--warn) 25%, transparent);background:color-mix(in srgb, var(--warn) 12%, var(--bg))}
.toast.bad{border-color:color-mix(in srgb, var(--bad) 25%, transparent);background:color-mix(in srgb, var(--bad) 12%, var(--bg))}
.toast.info{border-color:var(--gold-dim);background:var(--on-gold)}

/* ── skeleton shimmer ──────────────────────────────────────── */
@keyframes shimmer{0%{background-position:-400px 0}100%{background-position:400px 0}}
.skeleton{border-radius:4px;background:linear-gradient(90deg,var(--surface) 25%,var(--surface-2) 50%,var(--surface) 75%);
  background-size:800px 100%;animation:shimmer 1.4s infinite linear}
.sk-chart{height:140px;border-radius:var(--radius)}

/* ── modal ─────────────────────────────────────────────────── */
.modal-backdrop{position:fixed;inset:0;background:#00000088;backdrop-filter:blur(4px);
  z-index:8000;display:flex;align-items:center;justify-content:center;
  animation:fade-in .15s ease both}
.modal-backdrop.closing{animation:fade-out .15s ease forwards}
.modal{background:var(--surface);border:1px solid var(--border-2);border-radius:var(--radius);
  padding:24px;min-width:400px;max-width:600px;width:100%;box-shadow:0 24px 80px #000000cc;
  animation:modal-in .2s var(--ease-out) both;
  /* never taller than the viewport — the body scrolls as ONE region instead
     of nested scrollboxes per section */
  max-height:min(86vh,860px);display:flex;flex-direction:column}
.modal h2,.modal .modal-sub,.modal .modal-footer{flex-shrink:0}
.modal .modal-body{overflow-y:auto;min-height:0;overscroll-behavior:contain}
@media(max-width:640px){.modal{min-width:0;margin:0 12px}}
.modal-backdrop.closing .modal{animation:modal-out .15s ease forwards}
.modal h2{margin-bottom:4px}
.modal .modal-sub{color:var(--text-dim);font-size:calc(13px*var(--fs,1));margin-bottom:20px}
.modal-footer{display:flex;gap:8px;justify-content:flex-end;margin-top:20px;padding-top:16px;border-top:1px solid var(--border)}
.modal-close{position:absolute;top:16px;right:16px;background:none;border:0;
  color:var(--text-mute);font-size:calc(20px*var(--fs,1));cursor:pointer;line-height:1}
@keyframes fade-in{from{opacity:0}to{opacity:1}}
@keyframes fade-out{to{opacity:0}}
@keyframes modal-in{from{opacity:0;transform:scale(.96) translateY(8px)}to{opacity:1;transform:none}}
@keyframes modal-out{to{opacity:0;transform:scale(.97) translateY(4px)}}

/* ── tooltip ────────────────────────────────────────────────── */
[data-tip]{position:relative;cursor:default}
[data-tip]::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:50%;
  transform:translateX(-50%);white-space:pre-line;width:max-content;max-width:300px;
  text-align:left;line-height:1.45;background:var(--surface);color:var(--text);
  font-size:calc(12px*var(--fs,1));padding:5px 9px;border-radius:var(--radius-sm);border:1px solid var(--border);
  pointer-events:none;z-index:7000;box-shadow:0 4px 12px #00000060;
  /* Not laid out until hovered. An invisible (opacity 0) tooltip still takes
     up space, and one near the right edge made the Dashboard, Reports and UG
     analytics pages scroll sideways. It fades in on hover instead. */
  display:none}
[data-tip]:hover::after{display:block;animation:tip-in .15s var(--ease-out)}
@keyframes tip-in{from{opacity:0}to{opacity:1}}
@media(prefers-reduced-motion:reduce){[data-tip]:hover::after{animation:none}}

/* ── btn enhancements ───────────────────────────────────────── */
/* Press feedback is instant (.06s in), release eases back over the .15s above —
   the acknowledgement has to land under the finger, not after it. */
.btn:active{transform:scale(.97);transition-duration:.06s}
.btn.loading{opacity:.7;pointer-events:none;position:relative}
.btn.loading::after{content:'';width:12px;height:12px;border:2px solid currentColor;
  border-top-color:transparent;border-radius:50%;animation:spin .5s linear infinite;display:inline-block}
@keyframes spin{to{transform:rotate(360deg)}}

/* ── empty state ────────────────────────────────────────────── */
.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:56px 24px;text-align:center;gap:12px}
.empty-state .es-icon{font-size:calc(40px*var(--fs,1));opacity:.4}
.empty-state .es-title{font-family:var(--font-display);font-size:calc(16px*var(--fs,1));font-weight:600;color:var(--text)}
.empty-state .es-sub{color:var(--text-mute);font-size:calc(13px*var(--fs,1));max-width:320px;line-height:1.5}

/* ── inline edit ────────────────────────────────────────────── */

/* ── agent drill-down links ─────────────────────────────────── */
.agent-drill{cursor:pointer;border-bottom:1px dotted var(--gold-dim);transition:color .12s}
.agent-drill:hover{color:var(--gold-2)}

/* ── agent pivot modal ──────────────────────────────────────── */
.pivot-modal{max-width:640px}
.pchips{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.pchip{background:var(--surface-2);border:1px solid var(--border);border-radius:8px;padding:9px 11px;min-width:0}
.pchip .pl{font-size:calc(10px*var(--fs,1));color:var(--text-mute);text-transform:none;letter-spacing:0;margin-bottom:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pchip .pv{font-size:calc(17px*var(--fs,1));font-weight:500}
.pmix{color:var(--text-mute);font-size:calc(12px*var(--fs,1));margin:10px 2px 2px}
.pmix b{color:var(--text-dim);font-weight:500}
.psec{margin:16px 0 6px;font-size:calc(11px*var(--fs,1))}
table.pivot-mini{width:100%;border-collapse:collapse;font-size:calc(12.5px*var(--fs,1))}
.pivot-mini th{padding:7px 10px;font-size:calc(10.5px*var(--fs,1))}
.pivot-mini td{padding:8px 10px}
.pivot-mini th.num,.pivot-mini td.num{text-align:right;white-space:nowrap;width:1%}
.pivot-mini td:first-child{max-width:250px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pivot-mini .more{text-align:center;color:var(--text-mute);font-size:calc(11.5px*var(--fs,1));padding:8px}

/* ── thin, theme-matched scrollbars for inner scroll regions ── */
.scroll,.modal-body{scrollbar-width:thin;scrollbar-color:var(--border-2) transparent}
.scroll::-webkit-scrollbar,.modal-body::-webkit-scrollbar{width:8px;height:8px}
.scroll::-webkit-scrollbar-thumb{background:var(--border-2);border-radius:4px}
.scroll::-webkit-scrollbar-thumb:hover{background:var(--text-mute)}
.scroll::-webkit-scrollbar-track,.modal-body::-webkit-scrollbar-track{background:transparent}
.modal-body::-webkit-scrollbar-thumb{background:var(--border-2);border-radius:4px}

/* ── card hover ─────────────────────────────────────────────── */
.card.hoverable{transition:border-color .2s,box-shadow .2s}
.card.hoverable:hover{border-color:var(--border-2);box-shadow:var(--shadow-lift)}

/* ── table sort indicators ──────────────────────────────────── */
th.sortable{cursor:pointer;user-select:none}
th.sortable:hover{color:var(--text-dim)}
th.sort-asc::after,th.sorted-asc::after{content:' ↑';color:var(--gold-2)}
th.sort-desc::after,th.sorted-desc::after{content:' ↓';color:var(--gold-2)}

/* ── page transition ─────────────────────────────────────────────
   (History: there was deliberately none. The old rule faded the whole body in
   from opacity:0, which left pages blank wherever animations did not run. The
   "Motion layer" at the end of this file brings navigation motion back through
   the View Transitions API instead, which has no such failure mode: a browser
   without it simply navigates, and nothing is ever hidden waiting on it.)
   Originally: deliberately none. This is a multi-page app whose sidebar advertises
   single-key navigation shortcuts (D/U/R/H/G/S/W), so a page entrance plays
   dozens of times a day — at that frequency motion stops reading as polish and
   starts reading as latency. It also removes a total failure mode: the old rule
   was `animation:page-in .18s ease both` over `from{opacity:0}`, which leaves
   the whole page body invisible anywhere animations don't run (print, some
   headless renderers). If a settle is ever wanted back, it belongs on the
   content that changed, not on every navigation. */

/* ── team-scope dropdown (Users page) ───────────────────────── */
.scope-dd{position:relative;min-width:150px}
.scope-dd summary{list-style:none;display:block;background:var(--surface);border:1px solid var(--border-2);
  border-radius:var(--radius-sm);padding:7px 28px 7px 11px;font-size:calc(12.5px*var(--fs,1));color:var(--text);cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px;position:relative}
.scope-dd summary::-webkit-details-marker{display:none}
.scope-dd summary::after{content:"▾";position:absolute;right:10px;top:50%;transform:translateY(-50%);
  color:var(--text-mute);font-size:calc(10px*var(--fs,1))}
.scope-dd[open] summary{border-color:var(--gold-dim)}
.scope-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:120;background:var(--surface);
  border:1px solid var(--border-2);border-radius:10px;box-shadow:0 12px 32px #000000a0;
  padding:6px;min-width:240px;max-height:250px;overflow-y:auto}
.scope-opt{display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:7px;font-size:calc(13px*var(--fs,1));
  color:var(--text);cursor:pointer;text-transform:none;letter-spacing:0;font-weight:400;margin:0}
.scope-opt:hover{background:var(--surface-2)}
.scope-hint{color:var(--text-mute);font-size:calc(11px*var(--fs,1));padding:8px 9px 3px;border-top:1px solid var(--border);
  margin-top:5px;line-height:1.5;text-transform:none;letter-spacing:0;font-weight:400}

/* ── hint text ──────────────────────────────────────────────── */
/* The small explanatory paragraph under a card/section heading — was hand
   repeated as inline style="..." across settings.html, coverage.html, etc. */
.hint{color:var(--text-dim);font-size:calc(12.5px*var(--fs,1));line-height:1.6;margin:0 0 14px}
.hint.tight{margin-bottom:8px}
.hint-sm{color:var(--text-mute);font-size:calc(11.5px*var(--fs,1));line-height:1.5}

/* ── full-width alert banners ──────────────────────────────────
   Same tint convention as .badge (ok/warn/bad), but for a full-width
   page-level banner instead of an inline pill — was hand-hardcoded per
   template (background:color-mix(in srgb, var(--ok) 8%, transparent);border:1px solid color-mix(in srgb, var(--ok) 25%, transparent);...). */
.alert{border-radius:var(--radius);padding:12px 16px;margin-bottom:18px;
  border:1px solid var(--border);color:var(--text);background:var(--surface-2);
  display:flex;align-items:center;gap:8px}
.alert.ok{color:var(--ok);border-color:color-mix(in srgb, var(--ok) 25%, transparent);background:color-mix(in srgb, var(--ok) 8%, transparent)}
.alert.warn{color:var(--warn);border-color:color-mix(in srgb, var(--warn) 25%, transparent);background:color-mix(in srgb, var(--warn) 8%, transparent)}
.alert.bad{color:var(--bad);border-color:color-mix(in srgb, var(--bad) 25%, transparent);background:color-mix(in srgb, var(--bad) 8%, transparent)}

/* ── settings-style accordion group ────────────────────────────
   Card-styled <details> — builds on the bare <details> already used for
   deep-dive tables (reports.html) and the Users scope dropdown, so Settings
   groups look/behave like the rest of the app instead of a new pattern. */
details.settings-group{background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);box-shadow:var(--shadow);margin-bottom:14px}
details.settings-group > summary{list-style:none;cursor:pointer;padding:16px 18px;
  display:flex;align-items:center;gap:10px;font-family:var(--font-display);
  font-weight:600;font-size:calc(15px*var(--fs,1));color:var(--text)}
details.settings-group > summary::-webkit-details-marker{display:none}
details.settings-group > summary::after{content:"▾";margin-left:auto;color:var(--text-mute);
  font-size:calc(12px*var(--fs,1));transition:transform .15s}
details.settings-group[open] > summary::after{transform:rotate(180deg)}
details.settings-group > summary:hover{color:var(--gold-2)}
details.settings-group .settings-group-body{padding:0 18px 18px}

/* ── triage strip ─────────────────────────────────────────────
   Counts that mean "someone has to do something" are separated from counts
   that are just context, and the actionable ones ARE the filter — clicking a
   tile scopes the table below it. A zero deliberately goes quiet: nothing to
   act on should not look the same as fifty things to act on. */
.triage{display:flex;align-items:stretch;gap:10px;flex-wrap:wrap;margin-bottom:18px}
.triage .tri{display:flex;align-items:center;gap:11px;min-width:158px;
  padding:12px 15px;border-radius:var(--radius);border:1px solid var(--border);
  background:var(--surface);box-shadow:var(--shadow);color:var(--text);
  transition:border-color .15s,background .15s,transform .15s}
/* Lift only where there's a real pointer. On touch, a tap fires :hover and the
   card stays lifted until you tap something else. */
@media (hover:hover) and (pointer:fine){
  .triage .tri:hover{border-color:var(--border-2);transform:translateY(-1px)}
}
.triage .tri:active{transform:scale(.985);transition-duration:.06s}
.triage .tri .ic{display:grid;place-items:center;width:34px;height:34px;flex:none;
  border-radius:9px;background:var(--surface-2);color:var(--text-mute);font-size:calc(17px*var(--fs,1))}
.triage .tri .lbl{font-size:calc(10.5px*var(--fs,1));letter-spacing:0;text-transform:none;
  color:var(--text-mute);white-space:nowrap}
.triage .tri .val{font-family:var(--font-display);font-size:calc(23px*var(--fs,1));font-weight:600;
  line-height:1.15;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
/* live severity — only when the count is non-zero */
.triage .tri.hot .ic{background:color-mix(in srgb, var(--bad) 9%, transparent);color:var(--bad)}
.triage .tri.hot .val{color:var(--bad)}
.triage .tri.warm .ic{background:color-mix(in srgb, var(--warn) 9%, transparent);color:var(--warn)}
.triage .tri.warm .val{color:var(--warn)}
.triage .tri.lit .ic{background:color-mix(in srgb, var(--gold) 9%, transparent);color:var(--gold-2)}
.triage .tri.lit .val{color:var(--gold-2)}
.triage .tri.calm .val{color:var(--text-mute)}
.triage .tri.is-on{border-color:var(--gold);box-shadow:var(--glow)}
.triage .tri.is-on .lbl{color:var(--gold-2)}
/* passive context, visibly quieter than the actionable tiles */
.triage .tri-sep{width:1px;background:var(--border);margin:2px 4px}
.triage .stat{display:flex;flex-direction:column;justify-content:center;gap:3px;
  padding:12px 13px;min-width:0;white-space:nowrap}
.triage .stat .lbl{font-size:calc(10.5px*var(--fs,1));letter-spacing:0;text-transform:none;color:var(--text-mute)}
.triage .stat .val{font-family:var(--font-display);font-size:calc(19px*var(--fs,1));font-weight:600;
  color:var(--text-dim);font-variant-numeric:tabular-nums}
@media(max-width:760px){.triage .tri{flex:1 1 45%;min-width:0}.triage .tri-sep{display:none}}

/* ── icons (Tabler webfont, loaded in base.html) ──────────────
   Replaces the emoji that used to prefix headings, buttons, chips and
   alerts. Sized in `em` so an icon always tracks the font-size of the label
   it sits next to, and optically nudged off the baseline. Colour is
   inherited by default so an icon never fights its own label. */
.ti{display:inline-flex;align-items:center;justify-content:center;
  width:1.15em;height:1.15em;flex:0 0 auto;font-size:1.05em;line-height:1;
  vertical-align:-.17em}
h1 > .ti,h2 > .ti,h3 > .ti{color:var(--text-dim)}
.btn > .ti{opacity:.85}
.btn.primary > .ti{opacity:1}
.alert > .ti{font-size:1.15em;align-self:flex-start;margin-top:.12em}
.badge .ti,.tag .ti,.chip .ti{font-size:.95em;width:1em;height:1em}

/* ── motion utilities (opt-in, driven by app.js) ──────────────
   Three data attributes, one IntersectionObserver: an element animates the
   first time it scrolls into view, then stays put. Everything degrades to the
   final state instantly under prefers-reduced-motion (see the media query at
   the bottom of this block), so nothing here is load-bearing for layout. */
[data-reveal]{opacity:0;transform:translateY(10px);
  transition:opacity .26s var(--ease-out),transform .26s var(--ease-out)}
[data-reveal].revealed{opacity:1;transform:none}
/* A bar/segment that fills to its final width on reveal. Driven by scaleX, not
   width: width is a layout property and would relayout the row every frame, and
   this utility is the pattern every future bar in the app will copy. The span is
   laid out at full width and scaled DOWN, so the fraction is meaningful. */
[data-grow]{transform:scaleX(0);transform-origin:left center;
  transition:transform .25s var(--ease-out)}
/* an SVG donut/arc that sweeps to its final value on reveal */
[data-dash]{stroke-dasharray:0,100;transition:stroke-dasharray .55s var(--ease-out)}
/* counting numbers must not reflow the layout as digits change */
[data-count-to]{font-variant-numeric:tabular-nums}

/* ── tall scroll region with a pinned header row ─────────────
   `.scroll` alone is horizontal-only (overflow-x), which makes a sticky
   thead a no-op; capping the height is what gives it something to stick to. */
.scroll.tall{max-height:var(--tall,420px);overflow-y:auto}
/* Scroll edge effect rather than a hard rule: rows fade out under the pinned
   header instead of being sliced by a 1px line. The separation appears only
   where content actually passes beneath the header. */
.scroll.tall thead th{position:sticky;top:0;z-index:2;background:var(--surface);
  box-shadow:0 1px 0 var(--hover),0 6px 10px -6px #000000b0}

/* ── inline table filter box ────────────────────────────────── */
.tfilter{display:flex;align-items:center;gap:8px;flex:0 1 260px}
.tfilter input{padding:6px 10px;font-size:calc(12.5px*var(--fs,1))}
.tfilter .tcount{color:var(--text-mute);font-size:calc(11.5px*var(--fs,1));white-space:nowrap;font-family:var(--font-sans);font-variant-numeric:tabular-nums}

/* ── accessibility preferences ─────────────────────────────────
   Three independent signals, each with its own answer. Reduced motion is not
   "no feedback" — it's a non-vestibular equivalent, so opacity and colour
   changes (which carry meaning) stay while travel, scale and overshoot go. */
@media(prefers-reduced-motion:reduce){
  [data-reveal]{opacity:1;transform:none;transition:none}
  [data-grow],[data-dash]{transition:none}
  /* Keep the fade (it explains that something arrived); drop the travel. */
  .toast{transform:none;transition:opacity .15s var(--ease-out)}
  .toast.is-in{transform:none;transition:opacity .15s var(--ease-out)}
  .modal{animation:fade-in .12s ease both}
  .modal-backdrop.closing .modal{animation:fade-out .12s ease forwards}
  .bulk-bar{transition:opacity .15s var(--ease-out);transform:none}
  .bulk-bar.is-in{transform:none}
  /* Press feedback becomes non-positional. */
  .btn:active,a.pager-num:active,.rtabs button:active,
  .rtabs a[role="tab"]:active,.triage .tri:active{transform:none}
  .triage .tri:hover{transform:none}
  /* An indefinite loop is exactly the kind of motion this setting is for. */
  .skeleton{animation:none}
}

/* Frostier, not see-through: raise the background and drop the blur so the
   layer still reads as a distinct surface without content showing through. */
@media(prefers-reduced-transparency:reduce){
  .topbar{background:var(--chrome-solid);backdrop-filter:none}
  .rtabs{background:var(--bg-2);backdrop-filter:none}
  .bulk-bar{background:var(--surface-2);backdrop-filter:none}
  .modal-backdrop{background:#000000d9;backdrop-filter:none}
}

/* ── page hero ───────────────────────────────────────────────────
   One answer per page, stated before the evidence. The type scale has to
   actually JUMP here — the whole page previously sat between 13px and 15px,
   which is why it read as flat no matter how the colours were tuned. */
.hero{padding:4px 0 26px;margin-bottom:26px;border-bottom:1px solid var(--rule)}
.hero-eyebrow{margin:0 0 10px;font-size:calc(10px*var(--fs,1));letter-spacing:0;
  text-transform:none;color:var(--text-mute);font-weight:500}
.hero-lede{margin:0 0 16px;font-size:calc(clamp(15px,1.4vw,18px)*var(--fs,1));
  line-height:1.5;color:var(--text-dim);max-width:70ch}
.hero-lede strong{color:var(--text);font-weight:600}
.hero-figure{display:flex;align-items:baseline;gap:16px;flex-wrap:wrap}
.hero-num{font-family:var(--font-display);font-weight:500;
  font-size:calc(clamp(46px,5.5vw,68px)*var(--fs,1));line-height:1;
  letter-spacing:-.035em}
.hero-num small{font-size:.34em;letter-spacing:0;margin-left:2px;color:var(--text-mute)}
/* The accent marks the most important thing on the PAGE, not the chrome. */
.hero-num.is-high{color:var(--ok)}
.hero-num.is-mid{color:var(--warn)}
.hero-num.is-low{color:var(--bad)}
.hero-read{font-size:calc(13.5px*var(--fs,1));color:var(--text-dim);line-height:1.5}
.hero-delta{color:var(--text-mute)}
.hero-basis{margin:16px 0 0;max-width:78ch;font-size:calc(11.5px*var(--fs,1));
  line-height:1.6;color:var(--text-mute)}
.hero-basis strong{color:var(--text-dim)}
.hero-basis > summary{cursor:pointer;width:max-content;color:var(--text-mute);list-style:none}
.hero-basis > summary::-webkit-details-marker{display:none}
.hero-basis > summary::before{content:"\24D8  ";color:var(--text-mute)}
.hero-basis > summary:hover{color:var(--text-dim)}
.hero-basis p{margin:8px 0 0}
/* Performance: the everyday filters in a row, the rest one click away */
.rep-more{display:contents}
.rep-more > summary{list-style:none;cursor:pointer}
.rep-more > summary::-webkit-details-marker{display:none}
.rep-more[open] > summary{order:99}
.rep-more-body{display:flex;flex-wrap:wrap;gap:8px;flex-basis:100%}
/* Upload: lead type as a row of chips, recent uploads under the form */
.type-chips{display:flex;flex-wrap:wrap;gap:6px}
.type-chips label{position:relative;margin:0;text-transform:none;letter-spacing:0}
.type-chips input{position:absolute;inset:0;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
.type-chips span{display:inline-block;padding:6px 14px;border-radius:999px;border:1px solid var(--border-2);cursor:pointer;
  font-size:calc(13px*var(--fs,1));color:var(--text-dim)}
.type-chips input:checked + span{border-color:var(--gold);color:var(--text);background:color-mix(in srgb,var(--gold) 12%,transparent)}
.type-chips input:focus-visible + span{outline:none;box-shadow:var(--ring)}
.up-recent{margin-top:22px}
.hero-basis a{color:var(--text-dim);text-decoration:underline;text-underline-offset:2px}

/* ── trend chart ─────────────────────────────────────────────────
   A rate and a volume never share a y-axis. These are two plots on one
   x-axis: conversion as a line, volume as bars beneath it. */
.tgrid-wrap{display:flex;flex-direction:column;gap:6px}
.trow{display:flex;align-items:stretch;gap:10px}
/* Axis labels: top and bottom of their OWN row. Absolute positioning inside
   rows of different heights put the zero of one plot in the middle of another. */
.tax{width:48px;flex:none;display:flex;flex-direction:column;justify-content:space-between;
  font-family:var(--font-sans);font-variant-numeric:tabular-nums;
  font-size:calc(10px*var(--fs,1));color:var(--text-mute);text-align:right;
  font-variant-numeric:tabular-nums;line-height:1}
.tplot{position:relative;flex:1;height:140px}
.tsvg{width:100%;height:100%;display:block;overflow:visible}
/* Grid and axes recede; the data is the only thing with weight. */
.tgridline{stroke:var(--rule);stroke-width:1}
.tline{fill:none;stroke:var(--series-1);stroke-width:2;
  stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke}
.tdot{fill:var(--series-1);stroke:var(--surface);stroke-width:2;
  vector-effect:non-scaling-stroke}
/* A still-running cycle is a floor, not a result — hollow it out. */
.tdot.partial{fill:var(--surface);stroke:var(--series-1)}
.tcells{position:absolute;inset:0;display:flex}
.tcell{flex:1;position:relative;cursor:default;border-radius:6px;
  transition:background .15s var(--ease-out)}
.tcell:hover,.tcell:focus-visible{background:var(--hover);outline:none}
.tcell .tval{position:absolute;left:0;right:0;top:-2px;text-align:center;opacity:0;
  font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(10.5px*var(--fs,1));
  color:var(--text);transition:opacity .15s var(--ease-out);pointer-events:none}
.tcell:hover .tval,.tcell:focus-visible .tval{opacity:1}
.tbars{flex:1;display:flex;align-items:flex-end;gap:2px;height:46px}
.tbar{flex:1;height:100%;display:flex;align-items:flex-end;cursor:default;
  border-radius:4px 4px 0 0;transition:background .15s var(--ease-out)}
.tbar:hover,.tbar:focus-visible{background:var(--hover);outline:none}
/* 4px rounded data-end, anchored to the baseline. */
.tfill{display:block;width:100%;background:var(--series-2);
  border-radius:4px 4px 0 0;min-height:2px;
  transition:height .35s var(--ease-out)}
.tfill.partial{background:repeating-linear-gradient(135deg,
  var(--series-2) 0 4px,transparent 4px 8px)}
.tlabels{flex:1;display:flex;font-family:var(--font-sans);font-variant-numeric:tabular-nums;
  font-size:calc(10px*var(--fs,1));color:var(--text-mute)}
.tlabels span{flex:1;text-align:center}
/* Section wrapper for the trend block; the volume axis needs a touch more
   room than the percentage one. */
.sec.trend .sechead .note{display:flex;align-items:center;gap:6px}
.tax.tax-vol{justify-content:space-between}
.tdir{font-weight:600}
.tdir.down{color:var(--bad)}
.tdir.up{color:var(--ok)}
@media(prefers-reduced-motion:reduce){
  .tfill{transition:none}
  .tcell,.tbar{transition:none}
}

/* ── command palette ─────────────────────────────────────────────
   Anchored near the top rather than centred: the list grows downward, and a
   vertically-centred panel would move the input as results change. */
.cmdk{position:fixed;inset:0;z-index:9000;display:flex;align-items:flex-start;
  justify-content:center;padding:12vh 20px 20px}
.cmdk-backdrop{position:absolute;inset:0;background:#00000099;backdrop-filter:blur(3px)}
.cmdk-panel{position:relative;width:min(620px,100%);background:var(--surface);
  border:1px solid var(--border-2);border-radius:14px;overflow:hidden;
  box-shadow:0 24px 70px #00000080;
  animation:cmdk-in .16s var(--ease-out) both}
@keyframes cmdk-in{from{opacity:0;transform:translateY(-8px) scale(.985)}to{opacity:1;transform:none}}
.cmdk-field{display:flex;align-items:center;gap:10px;padding:0 14px;
  border-bottom:1px solid var(--rule)}
.cmdk-field > .ti{color:var(--text-mute);font-size:17px;flex:none}
.cmdk-field input{flex:1;height:52px;border:0;background:transparent;padding:0;
  font-size:calc(15px*var(--fs,1));color:var(--text)}
.cmdk-field input:focus{outline:none}
.cmdk-list{max-height:min(52vh,420px);overflow-y:auto;padding:6px;
  overscroll-behavior:contain}
.cmdk-item{display:flex;align-items:center;gap:11px;padding:9px 11px;
  border-radius:9px;cursor:pointer;font-size:calc(13.5px*var(--fs,1))}
.cmdk-item > .ti{color:var(--text-mute);font-size:16px;flex:none}
.cmdk-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cmdk-hint{flex:none;font-size:calc(10.5px*var(--fs,1));letter-spacing:0;
  text-transform:none;color:var(--text-mute)}
/* Selection follows the keyboard, so it must not depend on :hover. */
.cmdk-item.is-active{background:var(--surface-2)}
.cmdk-item.is-active > .ti,.cmdk-item.is-active .cmdk-label{color:var(--gold-2)}
.cmdk-item:hover{background:var(--hover)}
.cmdk-empty{padding:22px 14px;text-align:center;color:var(--text-mute);
  font-size:calc(13px*var(--fs,1));line-height:1.6}
.cmdk-foot{display:flex;gap:16px;padding:9px 14px;border-top:1px solid var(--rule);
  color:var(--text-mute);font-size:calc(11px*var(--fs,1))}
.cmdk kbd,.cmdk-foot kbd{display:inline-block;min-width:18px;padding:1px 5px;
  border:1px solid var(--rule);border-radius:4px;background:var(--surface-2);
  font-family:var(--font-mono);font-size:10px;
  text-align:center;color:var(--text-dim)}
@media(prefers-reduced-motion:reduce){
  .cmdk-panel{animation:none}
}
@media(prefers-reduced-transparency:reduce){
  .cmdk-backdrop{background:#000000d9;backdrop-filter:none}
}

/* The Dashboard's one call to action. A link, not a banner: the point is to
   go and deal with the thing, so the whole row is the target. */
.dash-attention{display:inline-flex;align-items:center;gap:10px;margin-top:10px;
  padding:9px 14px;border-radius:10px;border:1px solid var(--rule);
  background:var(--surface-2);color:var(--text-dim);
  font-size:calc(13px*var(--fs,1));line-height:1.45;max-width:72ch;
  transition:border-color .15s,background .15s}
.dash-attention strong{color:var(--text)}
.dash-attention:hover{border-color:var(--border-2);background:var(--surface)}
.dash-attention > .ti:first-child{flex:none;font-size:1.1em}
.dash-attention.is-low > .ti:first-child{color:var(--bad)}
.dash-attention.is-mid > .ti:first-child{color:var(--warn)}
.dash-attention-go{margin-left:auto;flex:none;opacity:.5;transition:transform .15s var(--ease-out)}
.dash-attention:hover .dash-attention-go{transform:translateX(2px);opacity:.9}
@media(prefers-reduced-motion:reduce){
  .dash-attention:hover .dash-attention-go{transform:none}
}

/* Segmented choice — a labelled pair, for a preference that deserves words
   rather than an icon the user has to discover. */
.seg-choice{display:inline-flex;border:1px solid var(--rule);border-radius:8px;
  overflow:hidden;background:var(--surface-2)}
.seg-opt{display:inline-flex;align-items:center;gap:7px;padding:0 14px;height:34px;
  border:0;background:transparent;color:var(--text-mute);font:inherit;
  font-size:calc(12.5px*var(--fs,1));cursor:pointer;white-space:nowrap;
  transition:background .15s,color .15s}
.seg-opt + .seg-opt{border-left:1px solid var(--rule)}
.seg-opt:hover{color:var(--text);background:var(--hover)}
.seg-opt.is-on{background:var(--surface);color:var(--gold-2);font-weight:600}
.seg-opt:focus-visible{outline:none;box-shadow:var(--ring)}

/* Theme toggle: one button, the icon shows what you will GET, not what you
   are on — a sun on a dark board reads as "go light". */
/* The Performance tab strip. Two levels of tabs now stack on this surface —
   which VIEW you are in (this) and which SECTION of it (#rtabs) — so they must
   not look alike. Identically-styled strips two rows apart, both with a tab
   called "Overview", made it impossible to tell which level you were operating
   at. Destination tabs are quiet underlined text; section tabs stay pills.
   Also non-sticky: two sticky strips fight for the same offset. */
.perftabs{position:static;gap:2px;padding:0;margin:0 0 20px;border:0;
  border-bottom:1px solid var(--rule);border-radius:0;background:none;
  backdrop-filter:none}
.perftabs a[role="tab"]{border-radius:0;padding:9px 14px 10px;margin-bottom:-1px;
  border-bottom:2px solid transparent;color:var(--text-mute);
  font-size:calc(13px*var(--fs,1))}
.perftabs a[role="tab"]:hover{background:none;color:var(--text)}
.perftabs a[role="tab"][aria-selected="true"]{background:none;box-shadow:none;
  color:var(--text);font-weight:600;border-bottom-color:var(--gold-2)}
.perftabs a[role="tab"]:active{transform:none}

.theme-toggle{display:inline-grid;place-items:center;width:30px;height:30px;
  padding:0;border:1px solid var(--rule);border-radius:8px;background:transparent;
  color:var(--text-mute);cursor:pointer;font-size:15px;line-height:1;
  transition:color .15s,border-color .15s,background .15s}
.theme-toggle:hover{color:var(--text);border-color:var(--border-2);background:var(--hover)}
.theme-toggle:focus-visible{outline:none;box-shadow:var(--ring)}
.theme-toggle .ti-moon{display:none}
:root[data-theme="light"] .theme-toggle .ti-sun{display:none}
:root[data-theme="light"] .theme-toggle .ti-moon{display:block}

/* ── choice lists: upload match mode (preview + settings) ──────────
   A radio per option with its explanation beside it. These are decisions
   about data, so each option says what it does, not just its name. */
.match-opts,.dup-plan{display:flex;flex-direction:column;gap:8px;margin:12px 0 16px}
.match-opt,.dup-plan-opt{display:flex;align-items:flex-start;gap:12px;padding:12px 14px;
  border:1px solid var(--rule);border-radius:var(--radius-sm);background:var(--surface);
  cursor:pointer;text-transform:none;letter-spacing:0;font-size:calc(13.5px*var(--fs,1));
  color:var(--text);margin:0;transition:border-color .15s,background .15s}
.match-opt:hover,.dup-plan-opt:hover{border-color:var(--border-2);background:var(--hover)}
.match-opt:has(input:checked),.dup-plan-opt:has(input:checked){
  border-color:var(--gold-dim);background:var(--surface-2)}
.match-opt input,.dup-plan-opt input{width:auto;margin:3px 0 0;flex:none;accent-color:var(--gold)}
.match-opt-body,.dup-plan-body{display:flex;flex-direction:column;gap:3px;min-width:0}
.match-opt-body .hint-sm,.dup-plan-body .hint-sm{max-width:78ch;line-height:1.5}
.dup-plan-card{margin-bottom:18px}
.dup-plan-nums{display:flex;flex-wrap:wrap;gap:6px 14px;margin-top:6px;
  font-size:calc(12.5px*var(--fs,1));color:var(--text-dim)}
.dup-num b{color:var(--text);font-variant-numeric:tabular-nums}
.dup-changes{margin-top:4px}
.dup-changes-title{margin:6px 0 8px;font-size:calc(11px*var(--fs,1));letter-spacing:0;
  text-transform:none;color:var(--text-mute)}
.dup-old{color:var(--text-mute)}

/* ── shared page furniture ───────────────────────────────────────
   Everything in this block was referenced by templates and never defined: the
   stacked page header on 8 pages, the muted note on 6, the table scroller on 5,
   and the entire column-mapping step of the upload flow. They rendered as
   unstyled markup. */

/* Stacked page header. Deliberately NOT an alias of `.page-head`, which is a
   flex ROW pairing a title block with actions — routing these through it would
   set the heading and its paragraph side by side. */
.content-head{margin-bottom:24px}
.content-head h1{margin-bottom:6px}
.content-head p{margin:0;max-width:75ch;color:var(--text-dim);
  font-size:calc(13.5px*var(--fs,1));line-height:1.6}
.muted{color:var(--text-mute)}

/* A wide table scrolls inside its own container instead of pushing the page
   sideways. */
.table-wrap{overflow-x:auto;scrollbar-width:thin;
  scrollbar-color:var(--border-2) transparent}
.table-wrap::-webkit-scrollbar{height:8px}
.table-wrap::-webkit-scrollbar-track{background:transparent}
.table-wrap::-webkit-scrollbar-thumb{background:var(--border-2);border-radius:4px}

/* A row of small metadata pills — file name, row count, columns detected. */
.chips{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:4px}
.chip{display:inline-flex;align-items:center;gap:6px;padding:5px 11px;
  border-radius:999px;border:1px solid var(--rule);background:var(--surface-2);
  font-size:calc(12px*var(--fs,1));color:var(--text-dim)}
.chip b{color:var(--text);font-weight:600}

/* Upload → map columns. Two columns on desktop: the field we need, and the
   sheet column that supplies it. */
.map-grid{display:grid;gap:14px}
.map-row{display:grid;grid-template-columns:minmax(170px,240px) 1fr;gap:14px;
  align-items:center}
.map-row[hidden]{display:none}
@media(max-width:700px){.map-row{grid-template-columns:1fr;gap:6px}}
.map-label{font-size:calc(13px*var(--fs,1));font-weight:500;display:flex;
  align-items:center;gap:7px;flex-wrap:wrap}
/* "required" / "optional" are status, so they read as the badge vocabulary
   rather than as a fourth kind of pill. */
.req,.opt{font-size:calc(10px*var(--fs,1));letter-spacing:0;
  text-transform:none;font-weight:500;padding:2px 7px;border-radius:999px;
  border:1px solid var(--rule)}
.req{color:var(--warn);border-color:color-mix(in srgb, var(--warn) 25%, transparent);background:color-mix(in srgb, var(--warn) 7%, transparent)}
.opt{color:var(--text-mute)}

/* ── sign-in ─────────────────────────────────────────────────────
   The auth screen renders through base.html's {% block auth %}, OUTSIDE the app
   shell, so it inherits none of the layout above. It had no styles at all:
   .login-wrap, .login-card and the brand lockup were referenced by login.html
   and never written, so the form rendered as full-bleed rows against the left
   edge. This is the first screen anyone sees. */
.login-wrap{min-height:100dvh;display:grid;place-items:center;padding:24px}
.login-card{width:min(384px,100%);background:var(--surface);
  border:1px solid var(--rule);border-radius:var(--radius);padding:32px}

/* The lockup rendered as "VeloOperational velocity platform" — one run-on
   string, because the <small> had no display of its own. Small text also wants
   POSITIVE tracking to stay legible, the inverse of the heading below it. */
.login-card .brand{padding:0;margin-bottom:26px;gap:11px;align-items:center}
.login-card .brand > span:last-child{line-height:1.2;font-weight:600}
.login-card .brand small{display:block;margin-top:3px;font-weight:500;
  font-size:calc(10px*var(--fs,1));letter-spacing:0;text-transform:none;
  color:var(--text-mute)}

/* Display type: tight leading and negative tracking as it grows. */
.login-card h1{font-size:calc(26px*var(--fs,1));line-height:1.05;
  letter-spacing:-.02em;margin-bottom:6px}
.login-card .sub{color:var(--text-dim);font-size:calc(13.5px*var(--fs,1));
  line-height:1.5;margin:0 0 24px}

.login-card .field{display:block;margin-bottom:16px}
.login-card .field input{margin-top:7px}

/* The one action on the screen. The app-wide 34px control height is right for a
   toolbar; a primary target wants 44px, and this button is the only thing the
   page asks anyone to hit. */
.login-card .btn.full{width:100%;height:44px;justify-content:center;
  background:linear-gradient(180deg, var(--cta-a), var(--cta-b));color:var(--on-cta);
  border-color:var(--cta-border);font-weight:500;box-shadow:inset 0 1px 0 #ffffff40}
.login-card .btn.full:hover{filter:brightness(1.04)}
/* Keyboard users must be able to see where they are. */
.login-card input:focus-visible,.login-card .btn:focus-visible{
  outline:none;box-shadow:var(--ring)}

/* Near-solid surfaces with a defined border, so every edge is unambiguous. */
@media(prefers-contrast:more){
  :root:not([data-theme="light"]){--text-dim:#d5d1c4;--text-mute:#a8a394;
    --border:#5a5a5a;--border-2:#7a7a7a}
  :root[data-theme="light"]{--text-dim:#3d3a30;--text-mute:#4f4b3e;
    --border:#8b8880;--border-2:#6f6c62}
  .topbar,.rtabs,.bulk-bar{background:var(--chrome-solid);backdrop-filter:none}
  .card,.rtabs,.bulk-bar,.btn,.login-card{border-color:var(--border-2)}
  .pager-num{border-color:var(--border-2)}
}

/* ── dashboard / Executive Control Room ===================== */
.dashboard-shell{
  --dashboard-bg:#070707;
  --dashboard-panel:#111111;
  --dashboard-panel-strong:#151515;
  --dashboard-line:#292929;
  --dashboard-line-soft:#1d1d1d;
  --dashboard-panel-soft:#0c0c0c;
  --dashboard-panel-deep:#090909;
  --dashboard-text:#f3f0e8;
  --dashboard-muted:#aaa397;
  --dashboard-dim:#8e8974;   /* 4.5:1 on every dashboard panel */
  --dashboard-gold:#d4af37;
  --dashboard-gold-soft:#edcc68;
  --dashboard-green:#8fbd76;
  --dashboard-red:#b95140;
  background:var(--dashboard-bg);
}
/* The Dashboard paints itself from this private palette, so without a light
   counterpart the landing page stayed dark while everything around it turned
   light — which is exactly how "light theme is not working" looked. */
:root[data-theme="light"] .dashboard-shell{
  --dashboard-bg:#f7f6f3;
  --dashboard-panel:#ffffff;
  --dashboard-panel-strong:#f2f1ed;
  --dashboard-line:#e4e2db;
  --dashboard-line-soft:#efeee9;
  --dashboard-panel-soft:#f2f1ed;
  --dashboard-panel-deep:#ffffff;
  --dashboard-text:#1a1a17;
  --dashboard-muted:#555145;
  --dashboard-dim:#706c5b;
  --dashboard-gold:#816a27;
  --dashboard-gold-soft:#6d5719;
  --dashboard-green:#50763e;
  --dashboard-red:#bc4334;
}
.dashboard-view{position:relative;isolation:isolate;color:var(--dashboard-text)}
.dashboard-view h1,.dashboard-view h2{font-family:var(--font-display)}
.dashboard-view h1{font-size:calc(clamp(28px,2.4vw,38px)*var(--fs,1));line-height:1;letter-spacing:-.04em}
.dashboard-view h2{font-size:calc(17px*var(--fs,1));line-height:1.15;letter-spacing:-.025em}
.dashboard-view .mono{font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-variant-numeric:tabular-nums}
.dashboard-heading{position:relative;z-index:1;display:flex;align-items:flex-end;justify-content:space-between;gap:24px;padding-bottom:22px;border-bottom:1px solid var(--dashboard-line)}
.dashboard-subtitle{margin-top:8px;color:var(--dashboard-muted);font-size:calc(14px*var(--fs,1))}
.dashboard-upload-btn{min-height:38px;border-radius:3px}
.dashboard-health{position:relative;z-index:1;display:flex;flex-direction:column;gap:8px;margin-top:16px}
.dashboard-health-item{display:flex;align-items:flex-start;gap:10px;padding:11px 14px;border-left:2px solid var(--dashboard-gold);background:color-mix(in srgb, var(--dashboard-gold) 7%, transparent);color:var(--dashboard-muted);font-size:calc(13px*var(--fs,1))}
.dashboard-health-item .ti{color:var(--dashboard-gold);margin-top:2px}
.dashboard-section-heading{position:relative;z-index:1;display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin:27px 0 11px}
.dashboard-section-meta{color:var(--dashboard-dim);font:12px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(12px*var(--fs,1))}
.dashboard-command-grid,.dashboard-pulse-grid,.dashboard-lower-grid{position:relative;z-index:1;display:grid;align-items:start;gap:14px}
.dashboard-command-grid{grid-template-columns:minmax(0,1.28fr) minmax(390px,.72fr)}
.dashboard-pulse-grid{grid-template-columns:minmax(0,1.5fr) minmax(330px,.7fr)}
.dashboard-lower-grid{grid-template-columns:minmax(0,1.28fr) minmax(330px,.72fr)}
.dashboard-spotlight,.dashboard-metric-cell,.dashboard-panel{background:var(--dashboard-panel);border:1px solid var(--dashboard-line);border-radius:3px}
.dashboard-spotlight{min-height:246px;padding:22px}
.dashboard-panel-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding-bottom:15px;border-bottom:1px solid var(--dashboard-line)}
.dashboard-panel-head h2{margin:0}
.dashboard-panel-head p{margin:5px 0 0;color:var(--dashboard-dim);font-size:calc(12px*var(--fs,1))}
.dashboard-panel-head>span:first-child{color:var(--dashboard-muted);font-size:calc(12px*var(--fs,1));letter-spacing:0;text-transform:none}
.dashboard-signal{color:var(--dashboard-green)!important;font:11px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(11px*var(--fs,1));letter-spacing:0!important;text-transform:none!important}
.dashboard-signal .ti{margin-right:5px}
.dashboard-spotlight-metrics{display:grid;grid-template-columns:1fr 1px 1fr;gap:20px;align-items:end;height:171px;padding-top:7px}
.dashboard-spotlight-divider{height:98px;background:var(--dashboard-line)}
.dashboard-hero-metric{display:flex;flex-direction:column;align-items:flex-start;gap:0}
.dashboard-metric-label{color:var(--dashboard-dim);font-size:calc(12px*var(--fs,1));letter-spacing:0;text-transform:none}
.dashboard-hero-metric strong{margin-top:7px;color:var(--dashboard-text);font:500 clamp(38px,4.2vw,66px)/.98 var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(clamp(38px,4.2vw,66px)*var(--fs,1));letter-spacing:-.07em}
.dashboard-hero-metric>span:last-child{margin-top:11px;color:var(--dashboard-muted);font-size:calc(12px*var(--fs,1))}
.dashboard-hero-metric.is-registered strong{color:var(--dashboard-green)}
.dashboard-metric-matrix{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;overflow:hidden;background:var(--dashboard-line);border:1px solid var(--dashboard-line);border-radius:3px}
.dashboard-metric-cell{min-height:122px;padding:17px;border:0;border-radius:0}
.dashboard-metric-cell.is-featured{background:color-mix(in srgb, var(--dashboard-gold) 6%, transparent)}
.dashboard-metric-name{display:block;margin-top:13px;color:var(--dashboard-gold-soft);font:600 22px/1.1 var(--font-display);font-size:calc(22px*var(--fs,1));letter-spacing:-.03em;
  /* Two lines before it truncates: a full name is the point of the tile, and a
     single nowrap line cut "Laura Hernandez" to "Laura Hernand…". */
  overflow:hidden;overflow-wrap:anywhere;display:-webkit-box;-webkit-box-orient:vertical;
  -webkit-line-clamp:2;line-clamp:2}
.dashboard-metric-value{display:block;margin-top:13px;color:var(--dashboard-text);font:500 28px/1 var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(28px*var(--fs,1));letter-spacing:-.06em}
.dashboard-metric-value.is-green{color:var(--dashboard-green)}
.dashboard-metric-value.is-gold{color:var(--dashboard-gold-soft)}
.dashboard-metric-value.is-red{color:var(--dashboard-red)}
.dashboard-metric-value.is-muted{color:var(--dashboard-dim)}
.dashboard-metric-detail{display:block;margin-top:10px;color:var(--dashboard-dim);font-size:calc(12px*var(--fs,1))}
.dashboard-panel{padding:20px}
.dashboard-trend-panel{min-height:0;border-top:2px solid var(--dashboard-gold);border-right:0;border-bottom:0;border-left:0;border-radius:0;padding-right:0;padding-left:0;background:transparent}
.dashboard-performers-panel{border-top:2px solid var(--dashboard-green);border-right:0;border-bottom:0;border-radius:0}
.dashboard-panel-icon{color:var(--dashboard-green);font-size:calc(18px*var(--fs,1))}
.dashboard-legend{display:flex;align-items:center;gap:12px;color:var(--dashboard-muted);font-size:calc(11px*var(--fs,1))}
.dashboard-legend>span{display:inline-flex;align-items:center;gap:6px}
.dashboard-legend-line{display:inline-block;width:9px;height:2px;background:var(--dashboard-gold)}
.dashboard-legend-line.is-green{background:var(--dashboard-green)}
.dashboard-chart-wrap{position:relative;min-height:250px}
.dashboard-chart{display:block;width:100%;height:250px;margin-top:18px;overflow:visible}
.dashboard-chart-grid{stroke:var(--dashboard-line-soft);stroke-width:1}
.dashboard-chart-axis{stroke:var(--dashboard-line);stroke-width:1}
.dashboard-chart-path{fill:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:round;vector-effect:non-scaling-stroke}
.dashboard-chart-path.is-assigned{stroke:var(--dashboard-gold)}
.dashboard-chart-path.is-registered{stroke:var(--dashboard-green)}
.dashboard-chart-point{cursor:help;vector-effect:non-scaling-stroke}
.dashboard-chart-point.is-assigned{fill:var(--dashboard-gold)}
.dashboard-chart-point.is-registered{fill:var(--dashboard-green)}
.dashboard-chart-label{fill:var(--dashboard-dim);font:11px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(11px*var(--fs,1))}
.dashboard-chart-label.is-today{fill:var(--dashboard-gold-soft)}
.dashboard-chart-empty,.dashboard-empty{padding:38px 12px;color:var(--dashboard-dim);text-align:center;font-size:calc(13px*var(--fs,1))}
.dashboard-performers{display:flex;flex-direction:column;margin-top:3px}
.dashboard-performer{display:grid;grid-template-columns:30px minmax(0,1fr) auto;gap:11px;align-items:center;padding:14px 0;border-bottom:1px solid var(--dashboard-line-soft)}
.dashboard-performer:last-child{border-bottom:0}
.dashboard-rank{color:var(--dashboard-dim);font:12px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(12px*var(--fs,1))}
.dashboard-performer:first-child .dashboard-rank{color:var(--dashboard-gold)}
.dashboard-performer-body>a{display:block;color:var(--dashboard-text);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dashboard-performer-body>span{display:block;margin-top:3px;color:var(--dashboard-dim);font:11px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(11px*var(--fs,1))}
.dashboard-score-line{height:2px;margin-top:7px;background:var(--dashboard-line)}
.dashboard-score-line span{display:block;width:var(--score);height:100%;background:var(--dashboard-gold)}
.dashboard-performer-delta{color:var(--dashboard-green);font:11px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(11px*var(--fs,1));white-space:nowrap}
.dashboard-secondary-btn{min-height:36px;border-radius:3px;background:transparent}
.dashboard-coverage-meter{margin:16px 0 4px;padding:13px 14px;border-left:2px solid var(--dashboard-gold);background:color-mix(in srgb, var(--dashboard-gold) 6%, transparent)}
.dashboard-coverage-meter>div{display:flex;justify-content:space-between;gap:12px;color:var(--dashboard-muted);font-size:calc(12px*var(--fs,1))}
.dashboard-coverage-meter strong{color:var(--dashboard-gold-soft);font:500 12px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(12px*var(--fs,1))}
.dashboard-meter{display:block;height:3px;margin-top:12px;background:var(--dashboard-line)}
.dashboard-meter i{display:block;width:var(--coverage);height:100%;background:var(--dashboard-gold)}
.dashboard-coverage-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:18px;align-items:center;padding:16px 0;border-bottom:1px solid var(--dashboard-line-soft);color:var(--dashboard-muted)}
.dashboard-coverage-row:last-child{border-bottom:0}
.dashboard-coverage-row>span{display:flex;align-items:center;gap:9px}
.dashboard-coverage-row strong{color:var(--dashboard-text);font:16px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(16px*var(--fs,1))}
.dashboard-coverage-row strong.is-red{color:var(--dashboard-red)}
.dashboard-status-dot{width:7px;height:7px;border-radius:50%;background:var(--dashboard-dim)}
.dashboard-status-dot.is-green{background:var(--dashboard-green)}
.dashboard-status-dot.is-gold{background:var(--dashboard-gold)}
.dashboard-quick-links{display:grid;grid-template-columns:1fr 1fr;gap:1px;margin-top:14px;background:var(--dashboard-line);border:1px solid var(--dashboard-line)}
.dashboard-quick-links a{display:flex;align-items:center;gap:9px;min-height:55px;padding:0 13px;background:var(--dashboard-panel);color:var(--dashboard-muted);font-size:calc(12px*var(--fs,1))}
.dashboard-quick-links a:hover{background:var(--dashboard-panel-strong);color:var(--dashboard-text)}
.dashboard-quick-links .ti{color:var(--dashboard-muted);font-size:calc(16px*var(--fs,1))}
.dashboard-quick-links a:hover .ti{color:var(--dashboard-gold)}
.dashboard-quick-note{display:flex;align-items:center;gap:8px;margin-top:17px;padding-top:14px;border-top:1px solid var(--dashboard-line);color:var(--dashboard-muted);font-size:calc(12px*var(--fs,1))}
.dashboard-quick-note .ti{color:var(--dashboard-gold)}
.dashboard-log-panel{position:relative;z-index:1;padding:18px 20px;border-top:1px solid var(--dashboard-line);border-right:0;border-bottom:0;border-left:2px solid var(--dashboard-red);background:transparent}
.dashboard-open-count{color:var(--dashboard-red);font:11px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(11px*var(--fs,1))}
.dashboard-log-list{margin-top:14px}
.dashboard-log-row{display:grid;grid-template-columns:70px minmax(0,1fr);gap:14px;align-items:center;min-height:45px;border-top:1px solid var(--dashboard-line-soft);font-size:calc(12px*var(--fs,1))}
.dashboard-log-row:first-child{border-top:0}
.dashboard-log-level{font:11px var(--font-sans);font-variant-numeric:tabular-nums;font-size:calc(11px*var(--fs,1))}
.dashboard-log-row.is-warning .dashboard-log-level{color:var(--dashboard-red)}
.dashboard-log-row.is-info .dashboard-log-level{color:var(--dashboard-green)}
.dashboard-log-message{color:var(--dashboard-text)}
.dashboard-uploads-panel{position:relative;z-index:1;margin-top:14px;padding:18px 0 0;border-top:1px solid var(--dashboard-line);border-right:0;border-bottom:0;border-left:0;background:transparent}
.dashboard-uploads-panel table{font-size:calc(12px*var(--fs,1))}
.dashboard-uploads-panel th{padding:11px 10px;color:var(--dashboard-dim);font-size:calc(11px*var(--fs,1));border-bottom:1px solid var(--dashboard-line)}
.dashboard-uploads-panel td{padding:13px 10px;color:var(--dashboard-muted);border-bottom:1px solid var(--dashboard-line-soft)}
.dashboard-uploads-panel td:first-child{color:var(--dashboard-text);font-weight:500}
.dashboard-uploads-panel tr:hover td{background:var(--dashboard-panel-strong)}
.dashboard-file{display:inline-flex;align-items:center;gap:8px}
.dashboard-file .ti{color:var(--dashboard-muted)}
.dashboard-uploads-panel tr:hover .dashboard-file .ti{color:var(--dashboard-gold)}
.dashboard-number{text-align:right;color:var(--dashboard-text)!important}
.dashboard-table-empty{text-align:center;color:var(--dashboard-dim)!important;padding:24px!important}
.dashboard-view .ti{display:inline-flex;width:16px;height:16px;align-items:center;justify-content:center;flex:0 0 16px;line-height:1}
@media(max-width:1100px){
  .dashboard-command-grid,.dashboard-pulse-grid,.dashboard-lower-grid{grid-template-columns:minmax(0,1fr)}
}
@media(max-width:760px){
  .dashboard-heading{align-items:flex-start;flex-direction:column}
  .dashboard-upload-btn{align-self:stretch}
  .dashboard-command-grid,.dashboard-pulse-grid,.dashboard-lower-grid{grid-template-columns:1fr}
  .dashboard-spotlight-metrics{gap:12px}
  .dashboard-hero-metric strong{font-size:calc(clamp(34px,10vw,52px)*var(--fs,1))}
  .dashboard-panel-head{flex-wrap:wrap}
  .dashboard-legend{width:100%}
}

/* ── Colour layer ───────────────────────────────────────────────────
   The app was black, grey and one gold, so every lead type, every agent and
   every tile looked the same. A `tone-*` class sets --tone; the components
   below read it. Meaning stays fixed: a lead type always wears its own tone,
   an agent always the same one, and green / amber / red remain states only. */
.tone-blue{--tone:var(--c-blue)} .tone-teal{--tone:var(--c-teal)}
.tone-violet{--tone:var(--c-violet)} .tone-pink{--tone:var(--c-pink)}
.tone-orange{--tone:var(--c-orange)} .tone-gold{--tone:var(--gold-2)}
.tone-none{--tone:var(--text-mute)}

.badge[class*="tone-"]{color:var(--tone);
  border-color:color-mix(in srgb, var(--tone) 32%, transparent);
  background:color-mix(in srgb, var(--tone) 12%, transparent)}
select[class*="tone-"]{color:var(--tone);
  border-color:color-mix(in srgb, var(--tone) 38%, transparent);
  background-color:color-mix(in srgb, var(--tone) 9%, var(--surface))}
select[class*="tone-"] option{color:var(--text);background:var(--surface)}

/* Agent avatar: initials on the agent's own tone. Decorative (the name is
   always beside it), so it is aria-hidden where it is rendered. */
.av{display:inline-grid;place-items:center;width:24px;height:24px;flex:none;
  border-radius:50%;margin-right:8px;vertical-align:middle;
  font-family:var(--font-display);font-weight:600;line-height:1;
  font-size:calc(9px*var(--fs,1));letter-spacing:.02em;
  color:var(--bg);background:var(--tone)}
.av::before{content:attr(data-i)}
.av.lg{width:40px;height:40px;font-size:calc(14px*var(--fs,1));margin-right:12px}
.with-av{display:inline-flex;align-items:center;min-width:0}

/* Section headings: the icon sits in a small gold chip instead of being one
   more grey glyph in a row of grey text. */
.card h2 > .ti:first-child{display:inline-grid;place-items:center;
  width:28px;height:28px;margin-right:8px;border-radius:8px;vertical-align:-6px;
  font-size:calc(15px*var(--fs,1));color:var(--gold);
  background:var(--tan)}

.kpi{transition:border-color .12s var(--ease-out),transform .12s var(--ease-out)}
.kpi.hoverable:hover{border-color:var(--border-2);transform:translateY(-2px)}

/* Rows answer the pointer a little more firmly, and links in tables pick up
   the accent on hover so it is clear what is clickable. */
tbody tr{transition:background-color .12s}
tbody tr:hover td{background:var(--hover)}
td a:hover{color:var(--gold-2)}
@media (prefers-reduced-motion: reduce){
  .kpi,.kpi.hoverable:hover{transition:none;transform:none}
  tbody tr{transition:none}
}

/* ── Depth layer ────────────────────────────────────────────────────
   The original system was deliberately flat: one hairline, no shadows, no
   gradients. It read as unfinished rather than restrained, so this layer adds
   depth in four places only — surfaces lift off the page, the primary action
   has weight, focus is a ring instead of a border tint, and the page has a
   light source. Everything is a token that flips with the theme; nothing here
   changes a size, so layouts and the one control height are untouched. */
:root{
  --elev-1: 0 1px 2px #00000033;
  --elev-2: 0 16px 40px -16px #000000b0;
  /* Focus, every control: a 2px gap in the surface colour, then 1.5px green. */
  --ring: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--brand);
  --ambient-a: #00000000;
  --ambient-b: #00000000;
  --card-top: #00000000;
  --cta-a: #ef8642;
  --cta-b: #ef8642;
  --on-cta: #1f1206;
}
:root[data-theme="light"]{
  --elev-1: 0 1px 2px #0e17220a;
  --elev-2: 0 14px 36px -16px #0e172238;
  --cta-a: #ecb15b;
  --cta-b: #d5863c;
  --on-cta: #271606;
}

/* A light source: two soft washes behind the top of every page. On .main, not
   body, so they scroll away with the page head instead of tinting the tables. */
.main{background:
  radial-gradient(900px 440px at 88% -120px, var(--ambient-a), transparent 70%),
  radial-gradient(760px 400px at 4% -100px, var(--ambient-b), transparent 70%);
  background-repeat:no-repeat}

/* Surfaces lift. The faint top highlight is what makes a dark card read as a
   raised plane rather than a hole. */
.card{box-shadow:var(--elev-1);
  background-image:linear-gradient(180deg, var(--card-top), transparent 64px)}
.card.hoverable:hover{box-shadow:var(--elev-2)}
.modal{box-shadow:var(--elev-2)}
.bulk-bar,.lead-savebar{box-shadow:var(--elev-2)}

/* Sidebar and top bar: quieter edges, more glass. */
.sidebar{background-image:linear-gradient(180deg, var(--ambient-b), transparent 320px)}
.topbar{backdrop-filter:blur(18px) saturate(160%)}
.nav a{transition:background-color .12s,color .12s,transform .12s var(--ease-out)}
.nav a:hover{transform:translateX(2px)}

/* Buttons have weight and answer the pointer. */
.btn{transition:background-color .15s,border-color .15s,box-shadow .2s var(--ease-out),
  transform .15s var(--ease-out)}
.btn:hover{transform:translateY(-1px)}
.btn:active{transform:scale(.97)}
.btn.primary{background-image:linear-gradient(180deg, var(--cta-a), var(--cta-b));
  color:var(--on-cta);border-color:var(--cta-border);font-weight:500;
  box-shadow:inset 0 1px 0 #ffffff40}
.btn.primary:hover{box-shadow:inset 0 1px 0 #ffffff55;filter:brightness(1.04)}
.btn.primary:active{filter:brightness(.96)}
.pager-num.is-current{background-image:linear-gradient(180deg, var(--gold-2), var(--gold));
  box-shadow:0 6px 16px -8px var(--gold)}

/* Focus is a ring you can see from across the form, not a 1px tint. */
input:focus,select:focus,textarea:focus,.search input:focus{box-shadow:var(--ring)}
.btn:focus-visible,a:focus-visible{outline:none;box-shadow:var(--ring);border-radius:var(--radius-sm)}
input,select,textarea{transition:border-color .15s,box-shadow .2s var(--ease-out)}

/* Tables: a header band so the columns have a top edge, and rows that round
   into the card instead of running square to its border. */
thead th{background:color-mix(in srgb, var(--text) 4%, transparent)}
thead th:first-child{border-top-left-radius:10px;border-bottom-left-radius:10px}
thead th:last-child{border-top-right-radius:10px;border-bottom-right-radius:10px}

.badge{font-weight:500}
.kpi .value{letter-spacing:-0.02em}
::selection{background:color-mix(in srgb, var(--gold-2) 35%, transparent)}
html{scrollbar-width:thin;scrollbar-color:var(--border-2) transparent}

@media (prefers-reduced-motion: reduce){
  .btn,.btn:hover,.nav a,.nav a:hover{transition:none;transform:none}
  input,select,textarea{transition:none}
}

/* ── Dashboard, rejoined ────────────────────────────────────────────
   The landing page used to be its own product: a private palette, its own
   restyled sidebar and top bar, square panels, mono numerals, a scroll-linked
   3D ornament and 2600px of forced height to scroll it through. It now wears
   the same tokens, cards and depth as every other page. The `dashboard-*`
   class names stay (the chart script and the tests address them); what they
   paint is the shared system.
   The palette is REMAPPED here rather than deleted, so every rule above that
   reads --dashboard-* follows the theme with no second set of literals. */
.dashboard-shell,
:root[data-theme="light"] .dashboard-shell{
  --dashboard-bg:var(--bg);
  --dashboard-panel:var(--surface);
  --dashboard-panel-strong:var(--surface-2);
  --dashboard-panel-soft:var(--surface);
  --dashboard-panel-deep:var(--bg-2);
  --dashboard-line:var(--rule);
  --dashboard-line-soft:var(--rule);
  --dashboard-text:var(--text);
  --dashboard-muted:var(--text-dim);
  --dashboard-dim:var(--text-mute);
  --dashboard-gold:var(--gold);
  --dashboard-gold-soft:var(--gold-2);
  --dashboard-green:var(--ok);
  --dashboard-red:var(--bad);
}
.dashboard-view{min-height:0}
.dashboard-view h1,.dashboard-view h2{font-family:var(--font-display)}
.dashboard-view h1{font-size:calc(clamp(26px,2.2vw,34px)*var(--fs,1));line-height:1.12;letter-spacing:-.02em}
.dashboard-heading{align-items:center;padding-bottom:4px;border-bottom:0}
.dashboard-upload-btn,.dashboard-secondary-btn{border-radius:var(--radius-sm)}
.dashboard-section-heading{margin:30px 0 12px}

/* Every panel is the shared card. */
.dashboard-spotlight,.dashboard-panel,.dashboard-metric-matrix,
.dashboard-log-panel,.dashboard-uploads-panel{
  background:var(--surface);border:1px solid var(--rule);border-radius:var(--radius);
  box-shadow:var(--elev-1);
  background-image:linear-gradient(180deg, var(--card-top), transparent 64px)}
.dashboard-trend-panel,.dashboard-performers-panel,
.dashboard-log-panel,.dashboard-uploads-panel{padding:20px}
.dashboard-uploads-panel{margin-top:16px}
.dashboard-command-grid,.dashboard-pulse-grid,.dashboard-lower-grid{gap:16px;align-items:stretch}

/* Today: two big figures, each on its own tone. */
.dashboard-spotlight{min-height:0;display:flex;flex-direction:column}
.dashboard-spotlight-metrics{height:auto;flex:1;align-items:center;padding-top:18px}
.dashboard-hero-metric strong,.dashboard-metric-value{
  font-family:var(--font-display);font-weight:600;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums}
.dashboard-metric-matrix{background-color:var(--rule);gap:1px;overflow:hidden}
.dashboard-metric-cell{background:var(--surface);min-height:118px}
.dashboard-metric-cell.is-featured{background:color-mix(in srgb, var(--gold) 9%, var(--surface))}
.dashboard-metric-cell:nth-child(2){background:color-mix(in srgb, var(--c-teal) 5%, var(--surface))}
.dashboard-metric-cell:nth-child(3){background:color-mix(in srgb, var(--c-orange) 5%, var(--surface))}
.dashboard-metric-cell:nth-child(4){background:color-mix(in srgb, var(--c-blue) 5%, var(--surface))}

/* Chart and leaderboard are one row of equal height; the chart fills its card
   instead of leaving a blank block underneath. */
.dashboard-trend-panel{display:flex;flex-direction:column}
.dashboard-chart-wrap{flex:1;min-height:260px;display:flex;flex-direction:column}
.dashboard-chart{flex:1;height:auto;min-height:240px}
.dashboard-chart-path{stroke-linecap:round;stroke-width:2.5}
.dashboard-panel-icon{color:var(--gold-2)}

/* Leaderboard: rank, avatar, name + bar, registrations — on one line. */
.dashboard-performer{grid-template-columns:22px 24px minmax(0,1fr) auto;gap:10px;padding:12px 0}
.dashboard-performer .av{margin-right:0}
.dashboard-performer-body>span,.dashboard-rank,.dashboard-performer-delta,
.dashboard-section-meta,.dashboard-open-count{font-family:var(--font-sans)}
.dashboard-score-line{height:4px;border-radius:999px;overflow:hidden;background:var(--sunk)}
.dashboard-score-line span{border-radius:999px;
  background:linear-gradient(90deg, var(--gold), var(--gold-2))}
.dashboard-performer-delta{padding:2px 8px;border-radius:999px;
  background:color-mix(in srgb, var(--ok) 10%, transparent)}

/* No side stripes: a tinted, fully bordered block says the same thing. */
.dashboard-health-item,.dashboard-coverage-meter{border-left:0;border-radius:var(--radius-sm);
  border:1px solid color-mix(in srgb, var(--gold) 28%, transparent);
  background:color-mix(in srgb, var(--gold) 8%, transparent)}
.dashboard-meter{height:6px;border-radius:999px;overflow:hidden;background:var(--sunk)}
.dashboard-meter i{border-radius:999px;background:linear-gradient(90deg, var(--gold), var(--gold-2))}
.dashboard-log-panel{border-left:1px solid var(--rule);border-top:1px solid var(--rule)}
.dashboard-log-row{min-height:42px}

/* Quick links: separate rounded tiles that pick up colour on hover. */
.dashboard-quick-links{gap:8px;background:none;border:0}
.dashboard-quick-links a{min-height:48px;border:1px solid var(--rule);border-radius:var(--radius-sm);
  background:var(--wash);transition:border-color .15s,background-color .15s,transform .15s var(--ease-out)}
.dashboard-quick-links a:hover{border-color:color-mix(in srgb, var(--gold) 40%, transparent);
  background:color-mix(in srgb, var(--gold) 7%, transparent);transform:translateY(-1px)}
.dashboard-quick-links a:nth-child(6n+1) .ti{color:var(--c-orange)}
.dashboard-quick-links a:nth-child(6n+2) .ti{color:var(--c-violet)}
.dashboard-quick-links a:nth-child(6n+3) .ti{color:var(--c-teal)}
.dashboard-quick-links a:nth-child(6n+4) .ti{color:var(--c-blue)}
.dashboard-quick-links a:nth-child(6n+5) .ti{color:var(--c-pink)}
.dashboard-quick-links a:nth-child(6n+6) .ti{color:var(--gold-2)}
.dashboard-uploads-panel th{border-bottom:0}
@media (prefers-reduced-motion: reduce){
  .dashboard-quick-links a,.dashboard-quick-links a:hover{transition:none;transform:none}
}

/* ── Upload flow ────────────────────────────────────────────────────
   Four screens, one task. */
.steps{display:flex;align-items:center;gap:0;list-style:none;margin:0 0 22px;padding:0;
  counter-reset:none;flex-wrap:wrap;row-gap:8px}
.step{display:flex;align-items:center;gap:9px;color:var(--text-mute);
  font-size:calc(12.5px*var(--fs,1))}
.step + .step::before{content:'';width:clamp(18px,5vw,56px);height:1px;margin:0 12px;
  background:var(--border-2)}
.step.is-done + .step::before,.step.is-current::before{background:var(--gold-dim)}
.step-n{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:50%;flex:none;
  border:1px solid var(--border-2);font-family:var(--font-display);font-weight:600;
  font-size:calc(11px*var(--fs,1));color:var(--text-dim)}
.step.is-done .step-n{border-color:transparent;color:var(--ok);
  background:color-mix(in srgb, var(--ok) 16%, transparent)}
.step.is-done{color:var(--text-dim)}
.step.is-current{color:var(--text);font-weight:500}
.step.is-current .step-n{border-color:transparent;color:var(--on-gold);
  background-image:linear-gradient(180deg, var(--gold-2), var(--gold));
  box-shadow:0 6px 14px -8px var(--gold)}

.dropzone{padding:56px 24px;transition:border-color .15s,background-color .15s}
.dz-icon{display:inline-grid;place-items:center;width:56px;height:56px;margin-bottom:14px;
  border-radius:16px;font-size:calc(24px*var(--fs,1));color:var(--gold-2);
  background:color-mix(in srgb, var(--gold) 12%, transparent)}
.dropzone.has-file{border-style:solid;border-color:color-mix(in srgb, var(--ok) 55%, transparent);
  background:color-mix(in srgb, var(--ok) 5%, transparent)}
.dropzone.has-file .dz-icon{color:var(--ok);background:color-mix(in srgb, var(--ok) 14%, transparent)}

.review-strip{margin-bottom:18px}
.review-strip .kpi .delta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* A check that found nothing is a line, not a card with a heading. */
.check-ok{display:flex;align-items:flex-start;gap:10px;padding:10px 14px;margin-bottom:10px;
  border-radius:var(--radius-sm);color:var(--text-dim);
  border:1px solid color-mix(in srgb, var(--ok) 26%, transparent);
  background:color-mix(in srgb, var(--ok) 6%, transparent);font-size:calc(13px*var(--fs,1))}
.check-ok > .ti{color:var(--ok);font-size:1.2em;margin-top:.1em}
.check-ok strong{color:var(--text)}
.check-ok + .card,.check-ok + .action-bar{margin-top:14px}

/* Duplicate handling shows the option in force; the others open on request. */
.dup-plan-card:not(.is-open) .dup-plan-opt:not(:has(input:checked)){display:none}
.dup-plan-card.is-open .dup-change{display:none}
.dup-change{float:right;margin:0 0 8px 12px}
.dup-plan{clear:both}
.msg-head{display:flex;align-items:center;flex-wrap:wrap;gap:6px}
.msg-head .av{margin-right:2px}

/* Docked action bar: the page's decision, reachable from wherever you are. */
.action-bar{position:sticky;bottom:14px;z-index:15;display:flex;align-items:center;gap:10px;
  flex-wrap:wrap;margin-top:16px;padding:10px 14px;border-radius:var(--radius);
  border:1px solid var(--gold-dim);background:var(--surface-2);box-shadow:var(--elev-2)}
.action-bar > span{margin-right:auto;color:var(--text-dim)}
.action-bar > span strong{color:var(--text)}

.dup-plan-body .badge{align-self:flex-start}
.step-l{white-space:nowrap}

/* Sign-in shares the page light and the weighted primary button. */
.login-wrap{background:radial-gradient(900px 520px at 50% -160px, var(--ambient-a), transparent 70%),radial-gradient(700px 460px at 12% 110%, var(--ambient-b), transparent 70%)}
.login-card{box-shadow:var(--elev-2)}

/* Settings groups are headings, not boxes: a card inside a card inside the
   page was three nested frames around one form. */
details.settings-group{background:none;border:0;box-shadow:none;margin-bottom:8px}
details.settings-group > summary{padding:14px 2px 12px;border-bottom:1px solid var(--rule);
  margin-bottom:14px;font-size:calc(15px*var(--fs,1))}
details.settings-group .settings-group-body{padding:0 0 10px}
.msg-none{margin:6px 0 2px;padding:8px 12px;border-radius:var(--radius-sm);
  border:1px dashed var(--border-2)}

/* ── Dashboard: figures with shape ──────────────────────────────────
   Clean was not enough: six text-only boxes and a bare line read as empty.
   Each tile now has an icon in its own tone, the two daily figures carry
   their 14-day shape and the change since yesterday, the rate is drawn as a
   ring, and the trend chart has mass under its lines. */
.tone-green{--tone:var(--ok)}
.dashboard-heading{padding:22px 24px;border:1px solid var(--rule);border-radius:var(--radius);
  background:var(--surface);
  box-shadow:var(--elev-1)}
.dash-date{margin-bottom:6px;color:var(--gold-2);font-size:calc(12.5px*var(--fs,1));font-weight:500}

.dash-stats{position:relative;z-index:1;display:grid;gap:16px;
  grid-template-columns:repeat(3,minmax(0,1fr))}
.dash-stats .dash-stat{position:relative;overflow:hidden;display:flex;flex-direction:column;
  align-items:stretch;gap:0;min-height:148px;padding:18px 20px;
  border:1px solid var(--rule);border-radius:var(--radius);
  background:var(--surface);
  box-shadow:var(--elev-1);
  transition:transform .2s var(--ease-out),border-color .2s var(--ease-out),box-shadow .2s var(--ease-out)}
.dash-stats .dash-stat:hover{transform:translateY(-2px);box-shadow:var(--elev-2);
  border-color:var(--border-2)}
.dash-stat-top{display:flex;align-items:center;gap:10px}
.dash-ic{display:inline-grid;place-items:center;width:32px;height:32px;flex:none;border-radius:10px;
  color:var(--gold);background:var(--tan)}
.dash-ic .ti{font-size:calc(17px*var(--fs,1));width:auto;height:auto;flex:none}
.dash-stats .dash-stat > strong,.dash-stats .dashboard-metric-value{
  margin-top:14px;font-size:calc(34px*var(--fs,1));line-height:1;
  font-family:var(--font-display);font-weight:600;letter-spacing:-.03em;color:var(--text)}
.dash-stats .dashboard-hero-metric.is-registered > strong{color:var(--ok)}
.dash-stats .dashboard-metric-value.is-green{color:var(--ok)}
.dash-stats .dashboard-metric-value.is-gold{color:var(--gold-2)}
.dash-stats .dashboard-metric-value.is-red{color:var(--bad)}
.dash-stat-sub,.dash-stats .dashboard-metric-detail{margin-top:8px;color:var(--text-dim);
  font-size:calc(12px*var(--fs,1));position:relative;z-index:1}
.dash-delta{color:var(--text-mute);white-space:nowrap}
.dash-delta.is-up{color:var(--ok)} .dash-delta.is-down{color:var(--bad)}
.dash-delta .ti{width:auto;height:auto;flex:none;font-size:1em;vertical-align:-1px;margin-right:1px}
/* The sparkline sits along the bottom of the tile, behind the caption. */
.dash-spark{position:absolute;left:0;right:0;bottom:0;width:100%;height:46px;pointer-events:none}
.dash-spark polyline{fill:none;stroke:var(--tone);stroke-width:1.6;vector-effect:non-scaling-stroke;
  stroke-linejoin:round;stroke-linecap:round;opacity:.9}
.dash-spark polygon{fill:color-mix(in srgb, var(--tone) 16%, transparent);stroke:none}
.dash-stat:has(.dash-spark){padding-bottom:50px}

.dash-stat-ring{flex-direction:row!important;align-items:center!important;justify-content:space-between;gap:14px!important}
.dash-ring{width:84px;height:84px;flex:none}
.dash-ring circle{fill:none;stroke-width:8}
.dash-ring-track{stroke:var(--sunk)}
.dash-ring-val{stroke:var(--tone);stroke-linecap:round;transition:stroke-dasharray .6s var(--ease-out)}

.dash-person{display:flex;align-items:center;margin-top:16px;min-width:0}
.dash-person > div{min-width:0}
.dash-stats .dashboard-metric-name{margin-top:0;font-size:calc(19px*var(--fs,1));color:var(--text)}
.dash-stats .dashboard-metric-cell.is-featured .dashboard-metric-detail{display:block;margin-top:4px}

.dashboard-chart-area{stroke:none}
.dashboard-chart-area.is-assigned{fill:color-mix(in srgb, var(--gold) 13%, transparent)}
.dashboard-chart-area.is-registered{fill:color-mix(in srgb, var(--ok) 13%, transparent)}

/* Leaderboard ranks: the podium is coloured, the rest are quiet. */
.dashboard-rank{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:50%;
  font-size:calc(10.5px*var(--fs,1));font-weight:600;color:var(--text-mute);
  background:var(--sunk)}
.dashboard-performer:nth-child(1) .dashboard-rank{color:var(--on-gold);
  background-image:linear-gradient(180deg, var(--gold-2), var(--gold))}
.dashboard-performer:nth-child(2) .dashboard-rank{color:var(--text);
  background:color-mix(in srgb, var(--text-dim) 34%, transparent)}
.dashboard-performer:nth-child(3) .dashboard-rank{color:var(--c-orange);
  background:color-mix(in srgb, var(--c-orange) 20%, transparent)}

@media(max-width:1100px){.dash-stats{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:620px){.dash-stats{grid-template-columns:1fr}}
@media (prefers-reduced-motion: reduce){
  .dash-stats .dash-stat,.dash-stats .dash-stat:hover{transition:none;transform:none}
  .dash-ring-val{transition:none}
}

/* ── Motion layer ───────────────────────────────────────────────────
   Navigation between pages and tabs is animated by the browser's View
   Transitions API. The shell (sidebar, top bar) is named so it stays put; only
   the content moves. The active sidebar row and the active tab are named too,
   so the highlight SLIDES to where you clicked instead of blinking across.
   Nothing here hides content: with no support, or with reduced motion, the
   page just appears. Kept short, because this plays on every click. */
@view-transition{navigation:auto}
.sidebar{view-transition-name:sidebar}
.topbar{view-transition-name:topbar}
.content{view-transition-name:content}
.nav a.active{view-transition-name:nav-active}
.perftabs a[role="tab"][aria-selected="true"]{view-transition-name:perftab-active}
#rtabs button[aria-selected="true"]{view-transition-name:rtab-active}

::view-transition-group(sidebar),::view-transition-group(topbar){animation:none}
::view-transition-old(sidebar),::view-transition-new(sidebar),
::view-transition-old(topbar),::view-transition-new(topbar){animation:none}
::view-transition-group(nav-active),::view-transition-group(perftab-active),
::view-transition-group(rtab-active){animation-duration:.32s;
  animation-timing-function:cubic-bezier(.23, 1, .32, 1)}

::view-transition-old(content){animation:vt-out .14s ease both}
::view-transition-new(content){animation:vt-in .3s cubic-bezier(.23, 1, .32, 1) both}
@keyframes vt-out{to{opacity:0;transform:translateY(-6px)}}
@keyframes vt-in{from{opacity:0;transform:translateY(12px)}}
/* Moving along a row of tabs slides sideways, in the direction you went.
   app.js stamps the direction on <html> for the duration of the transition. */
html[data-vt="fwd"]::view-transition-old(content){animation-name:vt-out-left}
html[data-vt="fwd"]::view-transition-new(content){animation-name:vt-in-right}
html[data-vt="back"]::view-transition-old(content){animation-name:vt-out-right}
html[data-vt="back"]::view-transition-new(content){animation-name:vt-in-left}
@keyframes vt-out-left{to{opacity:0;transform:translateX(-28px)}}
@keyframes vt-in-right{from{opacity:0;transform:translateX(36px)}}
@keyframes vt-out-right{to{opacity:0;transform:translateX(28px)}}
@keyframes vt-in-left{from{opacity:0;transform:translateX(-36px)}}

/* Figures draw themselves in. Transform and clip only, never opacity from 0,
   so a page where animations do not run still shows every number. */
.dash-stats .dash-stat{animation:rise .5s cubic-bezier(.23, 1, .32, 1) backwards}
.dash-stats .dash-stat:nth-child(2){animation-delay:.05s}
.dash-stats .dash-stat:nth-child(3){animation-delay:.1s}
.dash-stats .dash-stat:nth-child(4){animation-delay:.15s}
.dash-stats .dash-stat:nth-child(5){animation-delay:.2s}
.dash-stats .dash-stat:nth-child(6){animation-delay:.25s}
@keyframes rise{from{transform:translateY(14px)}}
.dash-ring-val{animation:ring-draw 1s cubic-bezier(.23, 1, .32, 1) .2s backwards}
@keyframes ring-draw{from{stroke-dasharray:0 188.5}}
.dash-spark,.dashboard-chart{animation:wipe-in .9s cubic-bezier(.23, 1, .32, 1) .15s backwards}
@keyframes wipe-in{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
.dashboard-score-line span,.dashboard-meter i,.bar > span,.goal-fill{
  transform-origin:left center;animation:grow-x .8s cubic-bezier(.23, 1, .32, 1) .2s backwards}
@keyframes grow-x{from{transform:scaleX(0)}}
.kpi{animation:rise .45s cubic-bezier(.23, 1, .32, 1) backwards}
.kpi:nth-child(2){animation-delay:.04s} .kpi:nth-child(3){animation-delay:.08s}
.kpi:nth-child(4){animation-delay:.12s} .kpi:nth-child(5){animation-delay:.16s}
.kpi:nth-child(6){animation-delay:.2s}
.steps .step.is-current .step-n{animation:pop .45s cubic-bezier(.23, 1, .32, 1) backwards}
@keyframes pop{from{transform:scale(.6)}}

@media (prefers-reduced-motion: reduce){
  @view-transition{navigation:none}
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}
  .dash-stats .dash-stat,.dash-ring-val,.dash-spark,.dashboard-chart,.kpi,
  .dashboard-score-line span,.dashboard-meter i,.bar > span,.goal-fill,
  .steps .step.is-current .step-n{animation:none}
}

/* Light theme: the dashboard's header band and tiles sit on white, where the
   dark theme's wash strengths turn muddy. Lighter washes, crisper edges. */
:root[data-theme="light"] .dash-attention{background:var(--surface)}

/* ── Audit fixes ────────────────────────────────────────────────────
   From the both-themes, three-widths audit. Grouped here so each is traceable
   to the finding it answers. */

/* A gradient fill always has the matching solid colour under it. If the
   gradient is ever dropped (forced colours, print, an override) the label
   still sits on its own colour instead of on whatever was beneath. */
.btn.primary{background-color:var(--cta-b)}
.avatar,.pager-num.is-current,.step.is-current .step-n,
.dashboard-performer:nth-child(1) .dashboard-rank{background-color:var(--gold)}

/* Keyboard focus is visible on everything that can take it, not just inputs
   and buttons: disclosure summaries, tabs, the sidebar, custom pickers. */
summary:focus-visible,[role="tab"]:focus-visible,[tabindex]:focus-visible,
.nav a:focus-visible,.ms-btn:focus-visible,select:focus-visible,
input[type="checkbox"]:focus-visible,input[type="radio"]:focus-visible{
  outline:none;box-shadow:var(--ring);border-radius:var(--radius-sm)}
/* Reach the page without tabbing through the whole sidebar first. */
.skip-link{position:absolute;left:12px;top:-60px;z-index:100;padding:9px 14px;
  border-radius:var(--radius-sm);background:var(--surface);color:var(--text);
  border:1px solid var(--gold-dim);box-shadow:var(--elev-2);transition:top .15s}
.skip-link:focus{top:12px}

/* ── Narrow screens ─────────────────────────────────────────────────
   Twelve pages scrolled sideways on a phone and five on a tablet. The cause
   was nearly always the same: a row of header buttons or filters that would
   not wrap, and a table wider than its card. */
@media(max-width:900px){
  .row,.page-head,.toolbar,.chips,.dashboard-panel-head{flex-wrap:wrap}
  .page-head{align-items:flex-start;gap:14px}
  .page-head > .row{width:100%}
  /* A long label wraps inside its button instead of pushing the page wide. */
  .btn{white-space:normal;height:auto;min-height:34px;line-height:1.25}
}
@media(max-width:760px){
  .content{padding:18px 14px}
  .topbar{padding:10px 14px;gap:10px}
  .card{padding:16px}
  /* A table scrolls inside its own card rather than dragging the page. */
  .card:has(> table),.card:has(> .table-wrap){overflow-x:auto}
  .card:has(> table) > table,.table-wrap > table,.scroll > table{min-width:520px}
  .page-head > div{min-width:0;overflow-wrap:anywhere}
  input,select,textarea{max-width:100%}
  h1{font-size:calc(23px*var(--fs,1))}
  .dashboard-heading{flex-direction:column;align-items:flex-start}
  .action-bar,.bulk-bar,.lead-savebar{bottom:8px}
  .col-pick-menu{grid-template-columns:1fr}
  .steps .step-l{display:none}
  .steps .step.is-current .step-l{display:inline}
  .review-strip{grid-template-columns:1fr 1fr}
}
/* Touch: controls are 34px for a mouse, which is under the 44px a finger
   needs. On a touch-first device they grow; the desktop height is unchanged. */
@media(pointer:coarse){
  input:not([type=checkbox]):not([type=radio]):not([type=file]),select,.btn,
  .search input,.ms-btn{height:44px;min-height:44px}
  .nav a{padding-top:12px;padding-bottom:12px}
  .pager-num{min-width:44px;height:44px}
  input[type=checkbox],input[type=radio]{min-width:20px;min-height:20px}
}
/* Flex children that hold long text or a table must be allowed to shrink. */
.slack .body{min-width:0;overflow-wrap:anywhere}


/* Job kind, from the booking id (parsing.job_kind). */
.badge.kind-rfq{--tone:var(--c-violet)} .badge.kind-hourly{--tone:var(--c-teal)}
.badge.kind-rfq,.badge.kind-hourly{color:var(--tone);font-family:var(--font-sans);
  border-color:color-mix(in srgb, var(--tone) 32%, transparent);
  background:color-mix(in srgb, var(--tone) 12%, transparent)}

/* ── on/off switch ─────────────────────────────────────────────
   A checkbox that is a SETTING (not a row selection) reads as a switch.
   Still a real <input type=checkbox>: forms, labels and keyboard unchanged. */
input[type=checkbox].switch{appearance:none;-webkit-appearance:none;flex:none;
  width:38px;height:22px;min-width:38px;margin:0;border-radius:99px;cursor:pointer;
  background:var(--sunk);border:1px solid var(--border-2);position:relative;
  transition:background .18s var(--ease-out),border-color .18s var(--ease-out);vertical-align:middle}
input[type=checkbox].switch::after{content:'';position:absolute;top:2px;left:2px;
  width:16px;height:16px;border-radius:50%;background:var(--surface);
  box-shadow:0 1px 3px #00000040;transition:transform .18s var(--ease-out)}
input[type=checkbox].switch:checked{background:var(--gold);border-color:var(--gold)}
input[type=checkbox].switch:checked::after{transform:translateX(16px)}
input[type=checkbox].switch:focus-visible{outline:none;box-shadow:var(--ring)}
@media(prefers-reduced-motion:reduce){input[type=checkbox].switch,input[type=checkbox].switch::after{transition:none}}

/* ── personal menu (sidebar foot) ──────────────────────────────── */
.me{position:relative;margin-top:auto}
.me-btn{display:flex;align-items:center;gap:10px;width:100%;padding:8px;border:1px solid transparent;
  border-radius:12px;background:transparent;color:var(--text);font:inherit;cursor:pointer;text-align:left}
.me-btn:hover,.me-btn[aria-expanded="true"]{background:var(--surface);border-color:var(--rule)}
.me-btn .avatar{flex:none}
.me-who{min-width:0;line-height:1.25}
.me-who b{display:block;font-weight:600;font-size:calc(13px*var(--fs,1));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.me-who span{color:var(--text-mute);font-size:calc(11.5px*var(--fs,1))}
.me-btn .ti-selector{margin-left:auto;color:var(--text-mute)}
/* fixed, not absolute: the sidebar is a scroll box and clipped the menu at its edge */
.me-menu{position:fixed;left:14px;bottom:86px;z-index:60;width:320px;max-width:calc(100vw - 24px);
  padding:6px;border:1px solid var(--rule);border-radius:14px;background:var(--surface);
  box-shadow:var(--shadow-lift),0 18px 40px -16px #00000055;
  transform-origin:bottom left;animation:mepop .16s var(--ease-out)}
@keyframes mepop{from{opacity:0;transform:translateY(6px) scale(.98)}to{opacity:1;transform:none}}
.me-menu a,.me-menu .me-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:9px;
  color:var(--text);font-size:calc(13px*var(--fs,1))}
.me-menu a:hover{background:var(--hover)}
.me-menu a .ti{color:var(--text-mute)}
.me-menu .me-row{justify-content:space-between;gap:12px;color:var(--text-dim)}
.me-menu .seg-opt{height:28px;padding:0 10px;font-size:calc(12px*var(--fs,1))}
.me-menu hr{border:0;border-top:1px solid var(--rule);margin:5px 4px}
html.nav-collapsed .me-who,html.nav-collapsed .me-btn .ti-selector{display:none}
html.nav-collapsed .me-btn{justify-content:center;padding:6px 0}
@media(prefers-reduced-motion:reduce){.me-menu{animation:none}}

/* Compact tables: a per-viewer density choice from the personal menu. */
html.compact td{padding-top:6px;padding-bottom:6px}
html.compact th{padding-top:6px;padding-bottom:6px}

/* ── page help popover (top bar "?") ───────────────────────────── */
.page-help{position:relative}
.page-help-btn{display:inline-grid;place-items:center;width:30px;height:30px;padding:0;
  border:1px solid var(--rule);border-radius:8px;background:transparent;color:var(--text-mute);cursor:pointer;font-size:15px}
.page-help-btn:hover,.page-help-btn[aria-expanded="true"]{color:var(--text);border-color:var(--border-2);background:var(--hover)}
.page-help-pop{position:absolute;right:0;top:calc(100% + 8px);z-index:30;width:min(360px,calc(100vw - 32px));
  padding:16px 18px;border:1px solid var(--rule);border-radius:14px;background:var(--surface);
  box-shadow:var(--shadow-lift),0 18px 40px -16px #00000055;animation:mepop .16s var(--ease-out);transform-origin:top right}
.page-help-pop h4{font-size:calc(15px*var(--fs,1));margin:0 0 4px}
.page-help-pop p{margin:0 0 10px;color:var(--text-dim);font-size:calc(13px*var(--fs,1))}
.page-help-pop ul{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:6px;font-size:calc(13px*var(--fs,1))}
.page-help-pop li::marker{color:var(--gold-2)}

/* ── dashboard greeting + day chips ────────────────────────────── */
.greet{font-family:var(--font-display);font-weight:600;font-size:calc(30px*var(--fs,1));
  letter-spacing:-0.02em;line-height:1.15;margin:0 0 4px;text-wrap:balance;max-width:30em}
.day-chips{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0 2px}
.day-chip{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:99px;
  border:1px solid var(--rule);background:var(--surface);color:var(--text-dim);font-size:calc(12.5px*var(--fs,1));white-space:nowrap}
.day-chip b{color:var(--text);font-weight:600}
.day-chip .ti{color:var(--gold-2)}
.day-chip.is-today{background:var(--gold);border-color:var(--gold);color:var(--on-gold)}
.day-chip.is-today b,.day-chip.is-today .ti{color:var(--on-gold)}

/* ── festival touches (per-viewer, off in the personal menu) ────────
   Only while a festival is near (main._festival_chips), and only as
   decoration: a string of lights under the top bar and a row of lamps on
   the dashboard greeting. Nothing moves under reduced motion. */
html.festive body.has-festival .topbar{box-shadow:0 1px 0 var(--rule)}
html.festive body.has-festival .topbar::after{content:'';position:absolute;left:0;right:0;bottom:-7px;height:8px;pointer-events:none;
  background:radial-gradient(circle at 50% 30%,var(--gold-2) 0 2px,transparent 2.5px) 0 0/34px 8px repeat-x;
  opacity:.75;animation:twinkle 2.4s ease-in-out infinite alternate}
@keyframes twinkle{from{opacity:.45}to{opacity:.9}}
.festive-lamps{display:none;gap:18px;margin-top:14px;line-height:1;user-select:none}
.festive-lamps svg{display:block;overflow:visible}
.festive-lamps .bowl{fill:#b5522a}
.festive-lamps .rim{stroke:var(--warn);stroke-width:1.6;stroke-linecap:round;fill:none}
.festive-lamps .flame{fill:#f5b942;filter:drop-shadow(0 0 4px #f5b942aa);transform-origin:16px 14px}
html.festive .festive-lamps{display:flex}
.festive-lamps .flame{animation:flicker 1.8s ease-in-out infinite alternate}
.festive-lamps span:nth-child(2n) .flame{animation-delay:.6s}
@keyframes flicker{from{transform:scale(1,1)}to{transform:scale(.92,1.1)}}
.fest-row span{font-size:24px;line-height:1}
.day-chip.fest{display:none}
html.festive .day-chip.fest{display:inline-flex}
@media(prefers-reduced-motion:reduce){
  html.festive body.has-festival .topbar::after,.festive-lamps .flame{animation:none}
}
/* With the greeting above it, the day's flow is the second line, not a shout. */
.dashboard-heading .greet ~ h1{font-size:calc(20px*var(--fs,1));font-weight:500;color:var(--text-dim);margin-top:4px}
.dashboard-heading .greet + .dash-date{margin:2px 0 0}
/* The sidebar is sticky, so the cards in .main (later in the DOM) paint over
   anything it opens. Lift it while the personal menu is open. */
.sidebar:has(.me-menu:not([hidden])){z-index:60}

/* ── Settings: one section at a time (Ethos-style) ────────────────
   A section list on the left, that section's cards on the right. Cards keep
   a title and two lines of explanation; the rest folds behind "Show more". */
.set-layout{display:grid;grid-template-columns:220px minmax(0,1fr);gap:32px;align-items:start}
.set-nav{position:sticky;top:84px;display:flex;flex-direction:column;gap:2px}
.set-nav a{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;
  color:var(--text-dim);font-weight:500;font-size:calc(13.5px*var(--fs,1));
  transition:background .15s var(--ease-out),color .15s var(--ease-out)}
.set-nav a .ti{color:var(--text-mute)}
.set-nav a:hover{background:var(--hover);color:var(--text)}
.set-nav a.on{background:var(--tan);color:var(--gold);font-weight:500}
.set-nav a.on .ti{color:var(--gold)}
.set-pane{display:flex;flex-direction:column;gap:16px;max-width:880px;animation:setin .22s var(--ease-out)}
@keyframes setin{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.set-pane-head h2{font-size:calc(24px*var(--fs,1));letter-spacing:-0.01em;margin:0}
.set-pane-head p{margin:4px 0 4px;color:var(--text-dim)}
.set-pane > .card{margin:0;padding:22px 24px;border-radius:var(--radius)}
.set-pane > .card > h2,.set-pane > .card h2{font-size:calc(17px*var(--fs,1));margin:0 0 6px;display:flex;align-items:center;gap:8px}
.set-pane > .card h2 > .ti{color:var(--gold-2)}
/* Sentence-case labels inside settings: the uppercase micro-label is for dense data, not forms. */
.set-pane .field label{text-transform:none;letter-spacing:0;font-size:calc(13px*var(--fs,1));
  font-weight:500;color:var(--text-dim)}
.set-pane p.hint.clamped{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
.set-pane .hint-more{border:0;background:none;padding:0;margin:-4px 0 12px;color:var(--gold-2);
  font:inherit;font-size:calc(12.5px*var(--fs,1));font-weight:600;cursor:pointer}
.set-pane .hint-more:hover{text-decoration:underline}
/* A switch row: the words on the left, the switch on the right. */
.set-pane label:has(> input.switch){display:flex;flex-direction:row-reverse;justify-content:space-between;
  align-items:center;gap:16px;padding:12px 0;margin:0;border-top:1px solid var(--rule)}
.set-sub{margin:10px 0 -4px}
.set-links{padding:6px!important;display:flex;flex-direction:column}
.set-link{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:10px;color:var(--text);
  font-size:calc(13.5px*var(--fs,1))}
.set-link + .set-link{border-top:1px solid var(--rule)}
.set-link > .ti:first-child{color:var(--gold-2);font-size:17px}
.set-link > span{flex:1}
.set-link .ti-chevron-right{color:var(--text-mute);transition:transform .15s var(--ease-out)}
.set-link:hover{background:var(--hover)}
.set-link:hover .ti-chevron-right{transform:translateX(2px)}
@media(max-width:900px){
  .set-layout{grid-template-columns:1fr;gap:16px}
  .set-nav{position:static;flex-direction:row;overflow-x:auto;gap:4px;padding-bottom:4px}
  .set-nav a{white-space:nowrap}
}
@media(prefers-reduced-motion:reduce){.set-pane{animation:none}}
.set-pane [id]{scroll-margin-top:86px}
/* A grid of small number boxes reads as a form to fill in; as rows (name left,
   box right) it reads as a list of settings, the way Ethos lays them out. */
.set-pane .grid.k3{display:flex!important;flex-direction:column;gap:0!important}
.set-pane .grid.k3 > .field{display:flex;align-items:center;justify-content:space-between;gap:16px;
  margin:0;padding:9px 0;border-top:1px solid var(--rule)}
.set-pane .grid.k3 > .field > label{margin:0}
.set-pane .grid.k3 > .field > input,.set-pane .grid.k3 > .field > select{width:170px;flex:none}
.set-panes{min-width:0}
.set-owned{margin:4px 0 12px;padding:10px 12px;border-radius:10px;background:var(--wash);color:var(--text-dim);font-size:calc(13px*var(--fs,1))}

/* ── avatars ─────────────────────────────────────────────────────── */
.avatar-wrap{position:relative;display:inline-flex;flex:none}
.avatar-img{object-fit:cover;padding:0;background:var(--surface-2)}
.av-head{display:flex;align-items:center;gap:16px;margin-bottom:16px}
.av-now img,.av-now .avatar{width:72px;height:72px;border-radius:50%;object-fit:cover;font-size:calc(26px*var(--fs,1));
  box-shadow:0 0 0 3px var(--surface),0 0 0 4px var(--rule)}
.av-pick{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:10px}
.av-opt{position:relative;cursor:pointer;border-radius:50%;aspect-ratio:1;display:block}
.av-opt input{position:absolute;opacity:0;pointer-events:none}
.av-opt img,.av-opt > span{display:grid;place-items:center;width:100%;height:100%;border-radius:50%;object-fit:cover;
  background:var(--surface-2);color:var(--text-mute);font-size:22px;
  transition:transform .15s var(--ease-out),box-shadow .15s var(--ease-out)}
.av-opt:hover img,.av-opt:hover > span{transform:translateY(-2px) scale(1.04)}
.av-opt input:checked + img,.av-opt input:checked + span{box-shadow:0 0 0 3px var(--surface),0 0 0 5px var(--gold)}
.av-opt input:focus-visible + img,.av-opt input:focus-visible + span{outline:none;box-shadow:var(--ring)}

/* The global uppercase micro-label is for form fields, not for these choice tiles. */
.av-pick label{text-transform:none;letter-spacing:0;font-weight:inherit;margin:0}

/* ── small menus on a button (Export ▾, ⋯) ───────────────────────── */
.menu-pop{position:relative}
.menu-pop > summary{list-style:none;cursor:pointer}
.menu-pop > summary::-webkit-details-marker{display:none}
.menu-pop-list{position:absolute;right:0;top:calc(100% + 6px);z-index:30;min-width:200px;padding:6px;
  border:1px solid var(--rule);border-radius:12px;background:var(--surface);box-shadow:var(--shadow-lift),0 14px 30px -14px #00000055;
  animation:mepop .14s var(--ease-out);transform-origin:top right}
.menu-pop-list a{display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:8px;color:var(--text);
  font-size:calc(13px*var(--fs,1));white-space:nowrap}
.menu-pop-list a:hover{background:var(--hover)}
.menu-pop-list a .ti{color:var(--text-mute)}

/* ── native <dialog> on the .modal look (Esc, focus trap and backdrop come free) ── */
dialog.modal:not([open]){display:none}
dialog.modal{margin:auto;color:var(--text);padding:24px}
dialog.modal::backdrop{background:#00000088;backdrop-filter:blur(4px)}
.dlg-form{display:flex;flex-direction:column;gap:12px;min-height:0}
.dlg-form .modal-body{display:flex;flex-direction:column;gap:16px}
.dlg-fld{display:flex;flex-direction:column;gap:6px;font-size:calc(12px*var(--fs,1));color:var(--text-dim)}
.dlg-set{border:0;margin:0;padding:0;min-width:0}
.dlg-set legend{padding:0;margin-bottom:8px;font-size:calc(12px*var(--fs,1));color:var(--text-dim)}
.dlg-opts{display:flex;flex-wrap:wrap;gap:8px 18px}
.dlg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
.dlg-opts label{display:flex;align-items:center;gap:8px;font-size:calc(13px*var(--fs,1));cursor:pointer}
.dlg-opts input{width:auto;flex:none;margin:0;accent-color:var(--gold)}

/* ── Custom reports (Performance) ── */
.rb-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(420px,1fr));gap:14px}
@media(max-width:560px){.rb-grid{grid-template-columns:1fr}}
.rb-card{display:flex;flex-direction:column;min-width:0}
.rb-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:8px}
.rb-head h2{margin:0}
.rb-head form{margin:0}
.rb-chart{position:relative;height:240px}
.rb-number{font-family:var(--font-display);font-size:calc(56px*var(--fs,1));font-weight:700;padding:18px 0;font-variant-numeric:tabular-nums}
.rb-table{margin-top:8px}
.rb-table summary{cursor:pointer}

/* ── Workflows ── */
.wf-grid{gap:14px;align-items:start}
.wf-acts{display:flex;flex-direction:column;gap:8px}
.wf-act{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:10px;border:1px solid var(--border);border-radius:12px;background:var(--surface-2)}
.wf-act input[name=a_text]{flex:1 1 220px}
.wf-act [hidden]{display:none}
.wf-item{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0;border-top:1px solid var(--rule)}
.wf-item > div:first-child{display:flex;flex-direction:column;gap:2px;min-width:0}
.wf-item.is-off{opacity:.6}
.wf-item form{margin:0}

/* ── Lead score chips, scoring rules editor ── */
.score-chip{display:inline-block;min-width:28px;padding:1px 7px;border-radius:99px;text-align:center;font-weight:700;
  font-size:calc(11.5px*var(--fs,1));font-variant-numeric:tabular-nums;color:var(--text-dim);background:var(--surface-2);border:1px solid var(--border)}
.score-chip.warm{color:var(--warn);border-color:color-mix(in srgb,var(--warn) 45%,transparent);background:color-mix(in srgb,var(--warn) 10%,transparent)}
.score-chip.hot{color:var(--ok);border-color:color-mix(in srgb,var(--ok) 45%,transparent);background:color-mix(in srgb,var(--ok) 10%,transparent)}
.score-chip.big{vertical-align:middle;font-size:calc(13px*var(--fs,1));padding:2px 10px;cursor:help}
.ed-score .ed-head,.ed-score .ed-row{grid-template-columns:minmax(160px,1.2fr) 130px minmax(120px,1fr) 90px 34px}

/* ── Leads board (Kanban) ── */
.view-mode{display:inline-flex;margin:0 6px 8px 0;vertical-align:top}
.view-mode .seg-opt{display:inline-flex;align-items:center;gap:6px;text-decoration:none}
.kanban{display:flex;gap:12px;overflow-x:auto;padding:2px 2px 12px;align-items:flex-start}
.kb-col{flex:0 0 268px;display:flex;flex-direction:column;gap:8px;padding:10px;border-radius:16px;
  background:var(--surface-2);border:1px solid var(--border);max-height:72vh}
.kb-head{display:flex;align-items:center;justify-content:space-between;padding:2px 4px}
.kb-n{font-style:normal;color:var(--text-mute);font-variant-numeric:tabular-nums}
.kb-list{display:flex;flex-direction:column;gap:8px;overflow-y:auto;min-height:72px;border-radius:12px;padding:2px}
.kb-list.drop-over{outline:2px dashed var(--gold);outline-offset:2px}
.kb-card{display:flex;flex-direction:column;gap:4px;padding:10px 12px;border-radius:12px;background:var(--surface);
  border:1px solid var(--border);color:var(--text);text-decoration:none;box-shadow:0 1px 0 var(--rule)}
.kb-card:hover{border-color:var(--gold-dim)}
.kb-card.dragging{opacity:.5}
.kb-card[draggable="true"]{cursor:grab}
.kb-owner{display:flex;align-items:center;gap:6px;font-size:calc(12px*var(--fs,1));color:var(--text-dim)}
.kb-more{font-size:calc(12px*var(--fs,1));padding:4px 6px}

/* ── Customize sidebar dialog, Pairs game ── */
.me-link{display:flex;align-items:center;gap:9px;width:100%;border:0;background:none;font:inherit;color:inherit;
  text-align:left;cursor:pointer;padding:8px 10px;border-radius:8px}
.me-link:hover{background:var(--hover)}
.nav-edit{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.nav-edit li{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px solid var(--border);border-radius:10px;background:var(--surface)}
.nav-edit li.dragging{opacity:.5}
.nav-grip{cursor:grab;color:var(--text-mute)}
.pairs{display:grid;grid-template-columns:repeat(4,minmax(0,92px));gap:10px;margin:18px 0}
.pair{aspect-ratio:1;border-radius:14px;border:1px solid var(--border-2);background:var(--surface-2);cursor:pointer;
  display:grid;place-items:center;font-size:32px;color:transparent;transition:transform .25s var(--ease-out),background .2s}
.pair.up,.pair.done{background:var(--surface);color:var(--gold-2);transform:rotateY(180deg) scaleX(-1)}
.pair.done{border-color:var(--gold);cursor:default}
.pair:focus-visible{outline:none;box-shadow:var(--ring)}
.pairs-stats{display:flex;gap:18px;color:var(--text-dim)}
@media(prefers-reduced-motion:reduce){.pair{transition:none}}

/* ── Nexi the mascot (base.html) ── */
.mascot{display:none;position:fixed;right:18px;bottom:16px;z-index:60;align-items:flex-end;gap:8px}
html.mascot-on .mascot{display:flex}
.mascot-btn{border:0;background:none;padding:0;cursor:pointer;animation:m-bob 3.2s ease-in-out infinite;
  filter:drop-shadow(0 6px 10px #0003)}
.mascot-btn:focus-visible{outline:none;box-shadow:var(--ring);border-radius:12px}
.m-body{fill:#14332F}
.m-roof{stroke:var(--gold)}
.m-pupil{fill:#14332F}
.m-smile{stroke:#E0B84C}
.m-dot{fill:#FF5A4E}
.m-eyes{transform-origin:32px 36px;animation:m-blink 5s infinite}
.mascot.cheer .mascot-btn{animation:m-jump .7s ease-out 2}
.mascot-say{position:relative;max-width:240px;padding:10px 30px 10px 12px;border-radius:14px 14px 4px 14px;
  background:var(--surface);border:1px solid var(--border-2);box-shadow:var(--shadow-lift);font-size:calc(13px*var(--fs,1));color:var(--text)}
.mascot-say[hidden]{display:none}
.mascot-x{position:absolute;top:4px;right:6px;border:0;background:none;color:var(--text-mute);cursor:pointer;font-size:16px;line-height:1}
@keyframes m-bob{50%{transform:translateY(-4px)}}
@keyframes m-blink{0%,92%,100%{transform:scaleY(1)}95%{transform:scaleY(.1)}}
@keyframes m-jump{30%{transform:translateY(-16px) rotate(-6deg)}60%{transform:translateY(0) rotate(4deg)}}
@media(prefers-reduced-motion:reduce){.mascot-btn,.m-eyes,.mascot.cheer .mascot-btn{animation:none}}
@media(max-width:640px){.mascot{right:10px;bottom:10px}.mascot-btn svg{width:42px;height:42px}}

/* ── Sidebar skyline: time of day + season + weather ── */
.sky{position:relative;height:64px;margin:auto 2px 0;border-radius:12px;overflow:hidden;border:1px solid var(--border);
  background:linear-gradient(180deg,#e4e9ee,#f9f7f1)}
.sky-city{position:absolute;inset:0;width:100%;height:100%}
.sky-b{fill:#d4d7ce}.sky-b2{fill:#c6cabf}
.sky-cap{fill:transparent}
.sky-w{fill:#ffffff;opacity:.7}
.sky-sun{fill:#e89e46}
.sky-moon-cut,.sky-star{fill:transparent}
.sky-tree circle{fill:#35966a}.sky-trunk{fill:#78541c}
.sky[data-tod="dawn"]{background:linear-gradient(180deg,#f3e7cb,#f9f7f1)}
.sky[data-tod="dawn"] .sky-sun{fill:#ecb15b;transform:translateY(14px)}
.sky[data-tod="dusk"]{background:linear-gradient(180deg,#ecd3ab,#f3e7cb)}
.sky[data-tod="dusk"] .sky-b{fill:#bfae8c}.sky[data-tod="dusk"] .sky-b2{fill:#b1a07e}
.sky[data-tod="dusk"] .sky-sun{fill:#d5863c;transform:translateY(16px)}
.sky[data-tod="dusk"] .sky-w.lit{fill:#fff3d6;opacity:1}
.sky[data-tod="night"]{background:linear-gradient(180deg,#d9cfb8,#eee7d6)}
.sky[data-tod="night"] .sky-b{fill:#b3a58a}.sky[data-tod="night"] .sky-b2{fill:#a69779}
.sky[data-tod="night"] .sky-w{fill:#c9bda3;opacity:.7}
.sky[data-tod="night"] .sky-w.lit{fill:#e89e46;opacity:1}
.sky[data-tod="night"] .sky-sun{fill:#fbf6ea}
.sky[data-tod="night"] .sky-moon-cut{fill:#ddd4be}
.sky[data-tod="night"] .sky-star{fill:#78541c;opacity:.4}
.sky[data-tod="night"] .sky-tree circle{fill:#5f7f66}
/* Dark theme: the same scene in the spec's purples. */
:root:not([data-theme="light"]) .sky{background:linear-gradient(180deg,#2b2646,#3d3660);border-color:var(--border)}
:root:not([data-theme="light"]) .sky-b{fill:#1d182d}:root:not([data-theme="light"]) .sky-b2{fill:#231e38}
:root:not([data-theme="light"]) .sky-w{fill:#3d3660;opacity:1}
:root:not([data-theme="light"]) .sky-w.lit{fill:#e0b068}
:root:not([data-theme="light"]) .sky[data-tod="night"]{background:linear-gradient(180deg,#120f1d,#2b2646)}
:root:not([data-theme="light"]) .sky[data-tod="night"] .sky-moon-cut{fill:#19152a}
:root:not([data-theme="light"]) .sky[data-tod="night"] .sky-sun{fill:#f3f5f8}
:root:not([data-theme="light"]) .sky[data-tod="night"] .sky-star{fill:#f3f5f8;opacity:.7}
.sky[data-season="winter"] .sky-cap{fill:#ffffff}
.sky[data-season="spring"] .sky-tree circle{fill:#f4a6c4}
.sky[data-season="autumn"] .sky-tree circle{fill:#e0893c}
.sky[data-season="autumn"][data-tod="night"] .sky-tree circle{fill:#7a4a24}
.sky-wx{position:absolute;left:8px;top:6px;display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:99px;
  background:color-mix(in srgb,var(--surface) 85%,transparent);color:var(--text);font-size:calc(11.5px*var(--fs,1));font-weight:600}
.sky-wx em{font-style:normal;font-weight:400;color:var(--text-mute)}
html.nav-collapsed .sky{display:none}
/* City landmarks (_sky_lm.html): the viewer's city replaces the generic row. */
.sky-lm{display:none;color:#c6cabf}
.sky[data-city="kolkata"] [data-lm="kolkata"],.sky[data-city="delhi"] [data-lm="delhi"],
.sky[data-city="mumbai"] [data-lm="mumbai"],.sky[data-city="bengaluru"] [data-lm="bengaluru"]{display:inline}
.sky[data-city] .sky-generic{display:none}
.sky[data-tod="dusk"] .sky-lm{color:#b1a07e}
.sky[data-tod="night"] .sky-lm{color:#a69779}
:root:not([data-theme="light"]) .sky-lm{color:#231e38}
:root:not([data-theme="light"]) .sky[data-tod="night"] .sky-lm{color:#3a3458}
.sky + .me{margin-top:0}
html.nav-collapsed .sky + .me{margin-top:auto}

/* ── Top search bar suggestions ── */
.tsearch{position:relative}
.tsearch-pop{position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:70;padding:6px;border-radius:12px;
  border:1px solid var(--rule);background:var(--surface);box-shadow:var(--shadow-lift),0 14px 30px -14px #00000055;
  max-height:420px;overflow:auto}
.tsearch-h{padding:8px 10px 4px;font-size:calc(10.5px*var(--fs,1));letter-spacing:0;text-transform:none;color:var(--text-mute)}
.tsearch-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:var(--text);font-size:calc(13px*var(--fs,1))}
.tsearch-item .ti{color:var(--text-mute)}
.tsearch-item span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tsearch-item em{font-style:normal;color:var(--text-mute);font-size:calc(12px*var(--fs,1));white-space:nowrap}
.tsearch-item:hover,.tsearch-item.is-active{background:var(--hover)}

/* ── The welcome after signing in (base.html) ── */
.nx-splash{position:fixed;inset:0;z-index:10000;display:grid;place-items:center;background:var(--bg);
  animation:nx-splash-out .5s ease 2.3s forwards;cursor:pointer}
.nx-splash-in{display:flex;flex-direction:column;align-items:center;gap:22px;padding:24px;text-align:center}
.nx-splash .nxl{width:min(340px,80vw)}
.nx-splash p{margin:0;max-width:30ch;font-family:var(--font-display);font-size:calc(22px*var(--fs,1));font-weight:600;
  color:var(--text);text-wrap:balance;animation:nx-splash-line .6s ease-out .9s both}
@keyframes nx-splash-out{to{opacity:0;visibility:hidden}}
@keyframes nx-splash-line{from{opacity:0;transform:translateY(8px)}}
@media(prefers-reduced-motion:reduce){.nx-splash{animation-delay:1.2s}.nx-splash *{animation:none !important}}

/* ── Bell (base.html) and the Today page ── */
.bell{position:relative}
.bell-btn{position:relative}
.bell-n{position:absolute;top:-5px;right:-6px;min-width:17px;height:17px;padding:0 4px;border-radius:99px;
  background:#e5484d;color:#fff;font-size:10.5px;font-weight:700;display:grid;place-items:center;line-height:1}
.bell-pop{position:absolute;right:0;top:calc(100% + 8px);z-index:60;width:min(360px,92vw);padding:8px;border-radius:12px;
  border:1px solid var(--rule);background:var(--surface);box-shadow:var(--shadow-lift),0 14px 30px -14px #00000055}
.bell-head{display:flex;align-items:center;justify-content:space-between;padding:4px 8px 8px}
.bell-read{border:0;background:none;color:var(--gold-2);cursor:pointer;font:inherit;font-size:calc(12px*var(--fs,1))}
.bell-list{list-style:none;margin:0;padding:0;max-height:360px;overflow:auto}
.bell-list a{display:block;padding:8px 10px;border-radius:8px;color:var(--text);font-size:calc(13px*var(--fs,1))}
.bell-list a:hover{background:var(--hover)}
.bell-list a.unread{font-weight:600}
.bell-list a.unread::before{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--gold);margin-right:7px;vertical-align:middle}
.bell-all{display:block;text-align:center;padding:8px;border-top:1px solid var(--rule);margin-top:6px;font-size:calc(12.5px*var(--fs,1))}
.today-grid{gap:14px;align-items:start;margin-bottom:14px}
.today-h{margin:14px 0 6px;font-size:calc(11px*var(--fs,1));letter-spacing:0;text-transform:none;color:var(--text-mute)}
.today-list{list-style:none;margin:0;padding:0}
.today-list li{display:flex;align-items:flex-start;gap:12px;padding:9px 0;border-top:1px solid var(--rule)}
.today-list li > div{display:flex;flex-direction:column;gap:2px;min-width:0}
.today-list form{margin:0}
.tick{width:24px;height:24px;border-radius:50%;border:1.5px solid var(--border-2);background:none;color:transparent;cursor:pointer;display:grid;place-items:center;padding:0}
.tick:hover{border-color:var(--gold);color:var(--gold-2)}
.today-ico{width:24px;height:24px;display:grid;place-items:center;color:var(--text-mute)}
.today-stat{display:flex;flex-direction:column;gap:4px;color:var(--text)}
.today-stat b{font-family:var(--font-display);font-size:calc(34px*var(--fs,1))}
.today-stat span{color:var(--text-dim)}

.check-inline{display:inline-flex;align-items:center;gap:6px;margin-top:6px;font-size:calc(12px*var(--fs,1));text-transform:none;letter-spacing:0}
.check-inline input{width:auto;margin:0}

/* ── Create lead dialog, import screens ── */
.create-grid{display:grid !important;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}
.create-grid input,.create-grid select{width:100%}
.create-prop{border-top:1px solid var(--rule);padding-top:10px}
.create-prop > summary{cursor:pointer;width:max-content}
.imp-steps{display:flex;gap:18px;flex-wrap:wrap;margin:0 0 16px;padding:0;list-style:none;color:var(--text-mute);font-size:calc(13px*var(--fs,1))}
.imp-steps li[aria-current="step"]{color:var(--text);font-weight:600}
.imp-table td{vertical-align:top}
.imp-table select{min-width:220px}
.imp-new{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px}
.imp-new[hidden]{display:none}
.imp-bar{height:10px;border-radius:99px;background:var(--surface-2);overflow:hidden;margin:12px 0}
.imp-bar > span{display:block;height:100%;background:var(--gold);transition:width .4s}

/* ── Levels, streaks, badges, confetti ── */
.ach{display:flex;flex-direction:column;gap:8px}
.ach-top{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.lvl-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 12px;border-radius:999px;font-weight:700;
  background:color-mix(in srgb,var(--gold) 18%,transparent);color:var(--gold-2);border:1px solid color-mix(in srgb,var(--gold) 45%,transparent)}
.streak{display:inline-flex;align-items:center;gap:5px;color:#e8590c;font-weight:600}
.lvl-bar{height:8px;border-radius:99px;background:var(--surface-2);overflow:hidden;max-width:420px}
.lvl-bar > span{display:block;height:100%;border-radius:99px;background:linear-gradient(90deg,var(--gold-2),var(--gold))}
.badges{display:flex;flex-wrap:wrap;gap:6px}
.badge-ico{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:999px;border:1px solid var(--border-2);font-size:calc(12px*var(--fs,1))}
.badge-ico .ti{color:var(--gold-2)}
.pf-ach{padding:14px 24px 0}
.today-ach{margin-bottom:14px}
.nx-confetti{position:fixed;top:-12px;width:9px;height:14px;z-index:9999;pointer-events:none;border-radius:2px;
  animation:nx-fall linear forwards}
@keyframes nx-fall{to{transform:translateY(105vh) rotate(720deg);opacity:.9}}

/* ── Status and kudos ── */
.status-form{display:flex;flex-direction:column;gap:10px;min-width:260px;padding:12px;right:0}
.status-form .dlg-opts{flex-direction:column;gap:6px}
.pf-status{display:inline-block;margin-top:8px}
.pf-status > summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.pf-status > summary::-webkit-details-marker{display:none}
.pf-status .menu-pop-list{left:0;right:auto}
.pf-kudos{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:14px 24px 0}
.kudos-form{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px}
.kudos-form input{flex:1 1 220px}

/* ── My account: Ethos-style profile header ── */
.pf-hero{padding:0;overflow:hidden;margin-bottom:16px}
.pf-cover{height:120px;background:
  radial-gradient(120% 140% at 0% 0%,color-mix(in srgb,var(--gold) 45%,transparent),transparent 60%),
  radial-gradient(90% 120% at 100% 100%,color-mix(in srgb,var(--gold-2) 35%,transparent),transparent 55%),
  var(--surface-2)}
.pf-main{display:flex;align-items:flex-start;gap:18px;padding:0 24px;margin-top:-46px;flex-wrap:wrap}
.pf-av{position:relative;width:104px;height:104px;border-radius:50%;flex:none;border:4px solid var(--surface);
  background:var(--surface);display:grid;place-items:center;overflow:visible}
.pf-av img,.pf-av .avatar{width:100%;height:100%;border-radius:50%;object-fit:cover;font-size:38px}
.pf-cam{position:absolute;right:2px;bottom:2px;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  background:var(--surface);border:1px solid var(--border-2);color:var(--text);font-size:15px}
.pf-av:hover .pf-cam{border-color:var(--gold)}
.pf-id{flex:1;min-width:220px;padding:58px 0 6px}   /* only the avatar overlaps the cover */
.pf-id h1{margin:0}
.pf-tags{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:10px}
.pf-tag{padding:3px 10px;border-radius:999px;border:1px solid var(--border-2);font-size:calc(12px*var(--fs,1))}
.pf-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;margin:18px 0 0;border-top:1px solid var(--rule);background:var(--rule)}
.pf-stats > div{background:var(--surface);padding:14px 24px;display:flex;flex-direction:column;gap:2px}
.pf-stats b{font-family:var(--font-display);font-size:calc(24px*var(--fs,1));font-variant-numeric:tabular-nums}
.pf-stats span{color:var(--text-mute);font-size:calc(12px*var(--fs,1))}
@media(max-width:640px){.pf-stats{grid-template-columns:1fr}}

/* ── Sign-in page: Google, and the password form folded away when it is off ── */
.login-card .btn.google-btn{display:flex;align-items:center;justify-content:center;gap:10px;background:var(--surface);
  color:var(--text);border:1px solid var(--border-2);box-shadow:none}
.login-card .btn.google-btn:hover{background:var(--surface-2);border-color:var(--gold);color:var(--text)}
.login-or{display:flex;align-items:center;gap:12px;margin:16px 0 6px;color:var(--text-mute);font-size:calc(12px*var(--fs,1))}
.login-or::before,.login-or::after{content:"";flex:1;border-top:1px solid var(--rule)}
.login-pw{margin-top:16px}
.login-pw > summary{cursor:pointer;color:var(--text-mute);font-size:calc(12px*var(--fs,1))}

/* ── Settings → Sign-in & security, My account sessions ── */
.sec-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(180px,300px);gap:20px;align-items:start;
  padding:14px 0;border-bottom:1px solid var(--rule)}
.sec-row p{margin:4px 0 0}
.sec-row input[type=number]{width:100px}
.sec-row textarea{width:100%;font-family:var(--font-mono,monospace)}
@media(max-width:700px){.sec-row{grid-template-columns:1fr;gap:8px}}
.rc-box{border:1px solid var(--gold);border-radius:12px;padding:14px;margin:0 0 14px;font-size:calc(13px*var(--fs,1))}
.rc-codes{display:grid;grid-template-columns:repeat(2,max-content);gap:6px 28px;margin:10px 0 0;padding-left:22px}
.sess-list{display:flex;flex-direction:column}
.sess-row{display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid var(--rule)}
.sess-row > .ti{font-size:20px;color:var(--text-mute)}
.sess-main{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}
.sess-row form{margin:0}

/* ── Leads: saved views as tabs ── */
.view-tabs{display:flex;align-items:flex-end;gap:2px;flex-wrap:wrap;border-bottom:1px solid var(--rule);margin:0 0 14px}
.view-tab{display:inline-flex;align-items:center;gap:4px;padding:8px 12px;margin-bottom:-1px;border-bottom:2px solid transparent;
  color:var(--text-dim);font-size:calc(13px*var(--fs,1));font-weight:500;cursor:pointer;white-space:nowrap}
.view-tab a{color:inherit;display:inline-flex;align-items:center;gap:6px}
.view-tab:hover{color:var(--text)}
.view-tab[aria-current="page"]{color:var(--text);border-bottom-color:var(--gold)}
.view-tab form{display:inline;margin:0}
.view-x{border:0;background:none;padding:2px;border-radius:6px;color:var(--text-mute);cursor:pointer;line-height:1;opacity:.5}
.view-tab:hover .view-x,.view-x:focus-visible{opacity:1}
.view-x:hover{background:var(--hover);color:var(--text)}
.view-add > summary{list-style:none}
.user-tabs .view-tab{border:0;background:none;font:inherit}
.view-tab em{font-style:normal;color:var(--text-mute);margin-left:2px}
tr[hidden]{display:none}
.view-add .menu-pop-list{left:0;right:auto;transform-origin:top left}
.view-form{display:flex;flex-direction:column;gap:10px;min-width:250px;padding:12px}
.view-form label{display:flex;flex-direction:column;gap:5px;font-size:calc(12px*var(--fs,1));color:var(--text-dim)}
.view-form label.check{flex-direction:row;align-items:center;gap:8px;color:var(--text)}
.view-form label.check input{width:auto;flex:none;margin:0}

/* ── Leads: quick filters on the toolbar, the rest in the All filters drawer ── */
.af-n{display:inline-grid;place-items:center;min-width:18px;height:18px;padding:0 5px;border-radius:99px;
  background:var(--gold);color:var(--on-gold);font-size:calc(11px*var(--fs,1))}
.toolbar .qf-in{width:150px}
.date-rng{display:inline-flex;gap:6px}
.toolbar .date-rng input{width:138px}
.menu-pop-list a[aria-current="true"]{color:var(--gold-2);font-weight:600}
dialog.drawer{position:fixed;inset:0 0 0 auto;margin:0;width:min(420px,100vw);max-width:none;height:100dvh;max-height:none;
  padding:0;border:0;border-left:1px solid var(--border-2);background:var(--surface);color:var(--text);
  box-shadow:-24px 0 60px -24px #000000aa}
dialog.drawer[open]{display:flex;flex-direction:column;animation:drawer-in .22s var(--ease-out)}
dialog.drawer::backdrop{background:#00000066;backdrop-filter:blur(2px)}
@keyframes drawer-in{from{transform:translateX(28px);opacity:0}}
@media(prefers-reduced-motion:reduce){dialog.drawer[open]{animation:none}}
.drawer-head{display:flex;align-items:center;justify-content:space-between;padding:18px 20px;border-bottom:1px solid var(--rule)}
.drawer-head h2{margin:0}
.drawer-body{flex:1;overflow-y:auto;padding:18px 20px;display:flex;flex-direction:column;gap:16px}
.drawer-fld{display:flex;flex-direction:column;gap:6px}
.drawer-fld .lab{font-size:calc(12px*var(--fs,1));color:var(--text-dim)}
.drawer-fld input,.drawer-fld select,.drawer-fld .ms,.drawer-fld .ms-btn{width:100%}
.drawer-fld .date-rng{display:flex}.drawer-fld .date-rng input{flex:1;min-width:0}
.qf-edit{display:flex;flex-direction:column;gap:10px;padding-top:16px;border-top:1px solid var(--rule)}
.drawer-foot{display:flex;align-items:center;gap:8px;padding:14px 20px;border-top:1px solid var(--rule)}

/* ── Settings row editors: holidays, statuses, custom properties ──── */
.ed-list{display:flex;flex-direction:column}
.ed-head,.ed-row{display:grid;gap:10px;align-items:center}
.ed-hol .ed-head,.ed-hol .ed-row{grid-template-columns:minmax(140px,1.4fr) 160px 160px 90px 34px}
.ed-welcome .ed-head,.ed-welcome .ed-row{grid-template-columns:130px minmax(200px,1fr) 34px}
.ed-status .ed-head,.ed-status .ed-row{grid-template-columns:minmax(200px,1fr) 150px 34px}
.ed-prop .ed-head,.ed-prop .ed-row{grid-template-columns:minmax(150px,1fr) 120px minmax(140px,1.1fr) 130px 110px 34px}
.ed-prop .ed-row.is-archived input,.ed-prop .ed-row.is-archived select:not([name=p_state]){opacity:.55}
.prop-fill{font-size:calc(11.5px*var(--fs,1));color:var(--text-mute);grid-column:1/-1;margin-top:-4px}
.kv-group th{padding-top:16px;font-size:calc(11px*var(--fs,1));letter-spacing:0;text-transform:none;color:var(--text-mute)}
.ed-vis .ed-head,.ed-vis .ed-row{grid-template-columns:minmax(180px,1fr) 220px}
.ed-head{padding:0 0 6px;font-size:calc(12px*var(--fs,1));font-weight:600;color:var(--text-mute)}
.ed-head em{font-style:normal;font-weight:400}
.ed-row{padding:8px 0;border-top:1px solid var(--rule)}
.ed-row.is-past{opacity:.55}
.ed-name{display:flex;align-items:center;gap:10px;min-width:0}
.ed-name .st-pill{flex:none;max-width:45%;overflow:hidden;text-overflow:ellipsis}
.ed-name input[readonly]{color:var(--text-mute);cursor:not-allowed}
.hol-when{font-size:calc(12.5px*var(--fs,1));color:var(--text-dim);white-space:nowrap}
.hol-when .is-today{display:inline-block;padding:2px 10px;border-radius:99px;background:var(--gold);color:var(--on-gold)}
.ed-del{display:grid;place-items:center;width:32px;height:32px;border:0;border-radius:8px;background:transparent;
  color:var(--text-mute);cursor:pointer}
.ed-del:hover{background:color-mix(in srgb, var(--bad) 12%, transparent);color:var(--bad)}
.ed-empty{padding:14px 0;color:var(--text-mute);border-top:1px solid var(--rule)}
@media(max-width:700px){
  .ed-head{display:none}
  .ed-hol .ed-row,.ed-prop .ed-row{grid-template-columns:1fr 1fr 34px}
  .ed-hol .ed-row input[name=h_name],.ed-prop .ed-row input[name=p_options]{grid-column:1/-1}
  .hol-when{display:none}
}

/* Status pill: the status's chosen tone (the app's category palette). */
.st-pill{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;border-radius:99px;white-space:nowrap;
  font-size:calc(12px*var(--fs,1));font-weight:600;color:var(--tone,var(--text-dim));
  background:color-mix(in srgb, var(--tone,var(--text-mute)) 13%, transparent);
  border:1px solid color-mix(in srgb, var(--tone,var(--text-mute)) 30%, transparent)}
.st-pill::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor}
/* The Leads table's status dropdown wears its pill. */
select.inline-status{width:auto;height:26px;min-height:0;padding:0 22px 0 10px;cursor:pointer;
  background-position:right 7px center}

/* ── SP Desk components ─────────────────────────────────────────────
   The spec's shared components, restyled once on top of the rules above.
   Colours are the tokens at the top of the file. Timings per the spec:
   hover 120ms, press 80ms, popover 140ms, modal 180ms, toggle 160ms,
   progress 500ms, theme switch 200ms. Hover = --hover / --surface-2, press =
   scale(.97) — the spec's "Proposed" state values were not available. */
html,body{transition:background-color .2s,color .2s}

/* Top bar: 36px search with a ⌘K hint; icon buttons are white hairline pills. */
.tsearch input{height:36px;border-radius:9px;padding-right:56px}
.tsearch-kbd{position:absolute;right:8px;top:50%;transform:translateY(-50%);pointer-events:none;
  padding:1px 6px;border:1px solid var(--border);border-radius:6px;background:var(--surface-2);
  font-family:var(--font-mono);font-size:calc(11px*var(--fs,1));color:var(--text-mute)}
.theme-toggle,.page-help-btn{width:34px;height:34px;border-radius:999px;
  background:var(--surface);border:1px solid var(--border);transition:background-color .12s,border-color .12s,color .12s}

/* Buttons: white hairline, radius 9; disabled at 55%. */
.btn{border-radius:9px;border-color:var(--border);font-weight:500;
  transition:background-color .12s,border-color .12s,box-shadow .12s,transform .12s var(--ease-out),filter .12s}
.btn:active{transition-duration:.08s}
.btn:disabled,.btn[disabled],.btn[aria-disabled="true"]{opacity:.55;cursor:not-allowed;transform:none;filter:none}

/* Segmented control: grey track, white active chip (34px overall). */
.seg-choice{background:var(--track);border:1px solid var(--border);border-radius:9px;padding:2px;gap:2px}
.seg-opt{height:28px;border-radius:7px;padding:0 12px;transition:background-color .12s,color .12s}
.seg-opt + .seg-opt{border-left:0}
.seg-opt.is-on{background:var(--surface);color:var(--text);font-weight:500;box-shadow:var(--elev-1)}
.me-menu .seg-opt{height:24px}

/* Every control focuses with the same green ring (keyboard only for buttons). */
input:focus,select:focus,textarea:focus{box-shadow:var(--ring)}
button:focus-visible,summary:focus-visible,[role="tab"]:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible{outline:none;box-shadow:var(--ring)}

/* Toggle 40×24 (brown when on), checkbox 18px, slider in the accent. */
input[type=checkbox].switch{width:40px;height:24px;min-width:40px;
  transition:background-color .16s var(--ease-out),border-color .16s var(--ease-out)}
input[type=checkbox].switch::after{width:18px;height:18px;transition:transform .16s var(--ease-out)}
input[type=checkbox]:not(.switch){width:18px;height:18px;flex:none}
input[type=checkbox]:not(.switch),input[type=radio],input[type=range]{accent-color:var(--gold)}

/* Tags radius 6, chips full, kbd radius 6 in the mono face. */
.badge{border-radius:6px}
kbd,.kbd,.nav a kbd,.cmdk kbd{border-radius:6px;font-family:var(--font-mono)}
.mono,[data-clock]{font-variant-numeric:tabular-nums}

/* Progress fills orange and eases over 500ms. */
.bar > span{background:var(--progress);transition:width .5s var(--ease-out)}

/* Stepper: finished steps are green check dots. */
.step.is-done .step-n{background:var(--brand);color:#fff;font-size:0}
.step.is-done .step-n::before{content:"\2713";font-size:calc(12px*var(--fs,1))}
.step.is-done + .step::before,.step.is-current::before{background:var(--brand)}

/* Initial avatars are green (a darker step so white initials stay readable). */
.avatar{background:color-mix(in srgb, var(--brand) 80%, #000);color:#fff}

/* Modal 12px radius on a plain dim backdrop; popovers and menus on --menu. */
.modal{border-radius:12px;border-color:var(--border);animation-duration:.18s}
.modal-backdrop{background:color-mix(in srgb, var(--backdrop) 55%, transparent);backdrop-filter:none;animation-duration:.18s}
dialog.modal::backdrop{background:color-mix(in srgb, var(--backdrop) 55%, transparent);backdrop-filter:none}
.me-menu,.menu-pop-list,.bell-pop,.page-help-pop,.tsearch-pop{background:var(--menu);border-color:var(--border);
  border-radius:12px;box-shadow:var(--shadow-lift);animation-duration:.14s}

/* Command palette: tan highlighted row with a green left edge. */
.cmdk-field input:focus{box-shadow:none}   /* the panel itself is the focused surface */
.cmdk-backdrop{background:color-mix(in srgb, var(--backdrop) 55%, transparent);backdrop-filter:none}
.cmdk-panel{background:var(--menu);border-color:var(--border);border-radius:12px;box-shadow:var(--elev-2);animation-duration:.14s}
.cmdk-item.is-active{background:var(--tan);box-shadow:inset 2px 0 0 var(--brand)}
.cmdk-item.is-active > .ti,.cmdk-item.is-active .cmdk-label{color:var(--gold)}

/* One orange action per screen: a filter strip's submit is a secondary button. */
.toolbar .btn.primary{background:var(--surface);background-image:none;color:var(--text);
  border-color:var(--border);box-shadow:none;filter:none}
.toolbar .btn.primary:hover{background:var(--surface-2)}

/* Sidebar shortcut keys stay out of the way until the row is pointed at. */
.nav a kbd{border:0;background:none;color:var(--text-mute);opacity:0;transition:opacity .12s}
.nav a:hover kbd,.nav a:focus-visible kbd{opacity:1}

/* Tags in sentence case read at 12px, the spec's smallest step. */
.badge{font-size:calc(12px*var(--fs,1))}

/* Initial avatars are green everywhere, like the spec. */
.av{background:color-mix(in srgb, var(--brand) 80%, #000);color:#fff}

/* Today: ask box, quick actions, setup card, then main column + right rail. */
.today-top{display:grid;gap:12px;margin-bottom:18px}
.today-ask{display:flex;align-items:center;gap:12px;width:100%;height:52px;padding:0 16px;border:1px solid var(--border);
  border-radius:12px;background:var(--surface);color:var(--text-mute);font:inherit;font-size:calc(15px*var(--fs,1));
  cursor:pointer;text-align:left;box-shadow:var(--elev-1);transition:border-color .12s,box-shadow .12s}
.today-ask:hover{border-color:var(--border-2)}
.today-ask > .ti{color:var(--gold);font-size:1.25em}
.today-ask span{flex:1}
.today-ask kbd{padding:2px 8px;border:1px solid var(--border);border-radius:6px;background:var(--surface-2);
  font-family:var(--font-mono);font-size:calc(11px*var(--fs,1));color:var(--text-mute)}
.today-try{display:flex;flex-wrap:wrap;gap:8px}
.today-try .chip{cursor:pointer;font:inherit;font-size:calc(12.5px*var(--fs,1));background:var(--surface);border-color:var(--border)}
.today-try .chip:hover{background:var(--tan);color:var(--gold);border-color:transparent}
.today-actions{display:flex;flex-wrap:wrap;gap:8px}
.today-setup{display:flex;gap:16px;align-items:flex-start;margin-bottom:14px;background:var(--tan);border-color:transparent}
.today-setup-ic{display:grid;place-items:center;width:40px;height:40px;flex:none;border-radius:50%;
  background:var(--surface);color:var(--gold);font-size:calc(19px*var(--fs,1))}
.today-setup h2{margin:2px 0 4px}
.today-setup p{margin:0 0 12px;color:var(--text-dim);max-width:70ch}
.today-cols{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);gap:14px;align-items:start}
.today-main,.today-rail{display:grid;gap:14px;min-width:0}
.today-rail .today-ach{margin:0}
@media (max-width:1000px){.today-cols{grid-template-columns:1fr}}

/* Empty states: one plain muted sentence, no illustration. */
.empty-state{padding:32px 24px;gap:4px}
.empty-state .es-icon{display:none}
.empty-state .es-title{font-family:var(--font-sans);font-size:calc(14px*var(--fs,1));font-weight:400;color:var(--text-mute)}

/* Page header: large title, then one muted sentence. */
.page-head .sub{color:var(--text-mute)}

@media (prefers-reduced-motion: reduce){
  html,body,.bar > span{transition:none}
  .modal,.modal-backdrop,.me-menu,.menu-pop-list,.page-help-pop,.cmdk-panel{animation-duration:.08s}
}

/* ── Quick links (base.html): Gmail and Slack on the right edge, AI beside search ── */
.qlinks{position:fixed;right:0;top:50%;transform:translateY(-50%);z-index:55;display:flex;flex-direction:column;gap:8px}
.qlinks a{display:grid;place-items:center;width:44px;height:44px;background:var(--surface);
  border:1px solid var(--rule);border-right:0;border-radius:12px 0 0 12px;box-shadow:var(--elev-1);
  transition:width .15s ease,background-color .15s ease}
.qlinks a:hover{width:52px;background:var(--surface-2)}
.qlinks a:focus-visible{outline:none;box-shadow:var(--ring)}
.qlinks svg{width:22px;height:22px}
html[data-qlinks="off"] .qlinks{display:none}
.ai-pill{display:inline-flex;align-items:center;gap:2px;padding:2px;margin-left:8px;flex:none;
  border:1px solid var(--rule);border-radius:999px;background:var(--surface)}
.ai-pill a{display:grid;place-items:center;width:30px;height:28px;border-radius:999px;color:var(--text)}
.ai-pill a:hover{background:var(--hover)}
.ai-pill a:focus-visible{outline:none;box-shadow:var(--ring)}
.ai-pill svg{width:17px;height:17px}
.ai-pill .ti{font-size:18px}
@media (max-width:900px){.ai-pill{display:none}}
@media (max-width:640px){.qlinks{display:none}}
@media print{.qlinks,.ai-pill{display:none}}
@media (prefers-reduced-motion: reduce){.qlinks a{transition:none}}

/* ── "+ New" (base.html top bar): the one primary action in the bar ── */
.new{position:relative}
.new-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 14px;cursor:pointer;
  border:1px solid var(--cta-border);border-radius:var(--radius-sm);background-color:var(--cta-b);
  background-image:linear-gradient(180deg, var(--cta-a), var(--cta-b));color:var(--on-cta);
  font:inherit;font-weight:600;font-size:calc(13px*var(--fs,1));box-shadow:inset 0 1px 0 #ffffff40}
.new-btn:hover{filter:brightness(1.04)}
.new-btn:focus-visible{outline:none;box-shadow:var(--ring)}
.new-pop{position:absolute;right:0;top:calc(100% + 8px);z-index:60;width:230px;padding:6px;border-radius:12px;
  border:1px solid var(--rule);background:var(--menu);box-shadow:var(--shadow-lift),0 14px 30px -14px #00000055;
  animation:mepop .16s var(--ease-out);transform-origin:top right}
.new-pop[hidden]{display:none}
.new-head{padding:6px 10px 4px;color:var(--text-mute);font-size:calc(12px*var(--fs,1))}
.new-item{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:0;border-radius:9px;
  background:none;color:var(--text);font:inherit;font-size:calc(13px*var(--fs,1));text-align:left;cursor:pointer}
.new-item:hover,.new-item:focus-visible{background:var(--hover);outline:none}
.new-item .ti{color:var(--text-mute)}
@media (max-width:640px){.new-btn{padding:0 10px}}

/* ── Nexi: menu, modes and outfits (base.html) ── */
.mascot-btn svg{overflow:visible}
.mascot-menu{position:absolute;right:0;bottom:66px;width:236px;padding:6px;border-radius:12px;
  border:1px solid var(--rule);background:var(--menu);box-shadow:var(--shadow-lift),0 14px 30px -14px #00000055;
  animation:mepop .16s var(--ease-out);transform-origin:bottom right}
.mascot-menu[hidden]{display:none}
.mm-head{padding:6px 10px 4px;color:var(--text-mute);font-size:calc(12px*var(--fs,1))}
.mm-item{display:block;width:100%;padding:8px 10px;border:0;border-radius:9px;background:none;cursor:pointer;
  color:var(--text);font:inherit;font-size:calc(13px*var(--fs,1));text-align:left}
.mm-item:hover,.mm-item:focus-visible{background:var(--hover);outline:none}
.mm-modes{display:flex;margin:6px 4px 2px}
.mm-modes .seg-opt{flex:1;height:28px;padding:0 4px;font-size:calc(12px*var(--fs,1))}
.m-fit{display:none}
html.festive:not([data-nexi-fit="off"]) body[data-fest="diwali"] .m-fit-diwali,
html.festive:not([data-nexi-fit="off"]) body[data-fest="holi"] .m-fit-holi,
html.festive:not([data-nexi-fit="off"]) body[data-fest="christmas"] .m-fit-christmas,
html.festive:not([data-nexi-fit="off"]) body[data-fest="newyear"] .m-fit-newyear,
html.festive:not([data-nexi-fit="off"]) body[data-fest="eid"] .m-fit-eid,
html.festive:not([data-nexi-fit="off"]) body[data-fest="tricolor"] .m-fit-tricolor,
html.festive:not([data-nexi-fit="off"]) body[data-fest="halloween"] .m-fit-halloween,
html.festive:not([data-nexi-fit="off"]) body[data-fest="festive"] .m-fit-festive,
html.festive:not([data-nexi-fit="off"]) body[data-fest="autumn"] .m-fit-festive,
html.nexi-fri .m-fit-fri{display:inline}
html[data-nexi="quiet"] .mascot-btn{animation:none}
html[data-nexi="lively"] .mascot{animation:nexi-stroll 28s ease-in-out infinite}
@keyframes nexi-stroll{0%,60%,100%{transform:none}68%,78%{transform:translateX(-140px)}86%{transform:translateX(-56px)}}
@media (prefers-reduced-motion: reduce){html[data-nexi="lively"] .mascot{animation:none}}

/* ── Record ID on the lead page (lead_detail.html) ── */
.rec-ids{display:flex;flex-wrap:wrap;gap:8px;margin-top:6px}
.rec-id{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 10px;border:1px solid var(--rule);
  border-radius:var(--radius-sm);background:var(--surface);color:var(--text-mute);font:inherit;
  font-size:calc(12px*var(--fs,1))}
.rec-id b{color:var(--text);font-weight:600;font-variant-numeric:tabular-nums}
button.rec-id{cursor:pointer}
button.rec-id:hover{background:var(--hover)}
button.rec-id:focus-visible{outline:none;box-shadow:var(--ring)}
.muted-id{background:none}

/* ── Reports library and Dashboards (report_library.html, dashboard_custom.html, _dash_switch.html) ── */
.lib-wrap{overflow-x:auto;margin-top:8px}
.lib-table{width:100%;border-collapse:collapse}
.lib-table th,.lib-table td{padding:10px 12px;border-bottom:1px solid var(--rule);text-align:left;vertical-align:middle}
.lib-table th{color:var(--text-mute);font-weight:500;font-size:calc(12px*var(--fs,1))}
.lib-act{display:flex;align-items:center;justify-content:flex-end;gap:6px;flex-wrap:wrap}
.lib-act form{margin:0}
.lib-add{display:inline-flex;align-items:center;gap:6px;margin:0}
.lib-add select{width:auto;max-width:180px}
.lib-builtin{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px;margin-top:10px}
.lib-bi{display:flex;align-items:flex-start;gap:10px;padding:12px;border:1px solid var(--rule);border-radius:var(--radius);
  color:var(--text);text-decoration:none;background:var(--surface)}
.lib-bi:hover{background:var(--hover)}
.lib-bi .ti{font-size:20px;color:var(--text-mute);margin-top:2px}
.lib-bi > span{display:flex;flex-direction:column;gap:2px}
.rb-link{color:inherit;text-decoration:none}
.rb-link:hover{text-decoration:underline}
.rb-one{grid-template-columns:minmax(0,1fr)}
.rb-one .rb-chart{height:360px}
.dash-switch{position:relative;display:inline-block;margin-bottom:6px}
.dash-switch-btn{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border:1px solid var(--rule);border-radius:999px;
  background:var(--surface);color:var(--text-dim);font:inherit;font-size:calc(13px*var(--fs,1));cursor:pointer}
.dash-switch-btn:hover{background:var(--hover)}
.dash-switch-btn:focus-visible{outline:none;box-shadow:var(--ring)}
.dash-switch-btn.is-title{padding:0;border:0;background:none;color:var(--text)}
.dash-switch-btn.is-title h1{margin:0}
.dash-switch-btn.is-title:hover{background:none}
.dash-menu{position:absolute;left:0;top:calc(100% + 6px);z-index:60;width:290px;max-width:92vw;padding:6px;border-radius:12px;
  border:1px solid var(--rule);background:var(--menu);box-shadow:var(--shadow-lift),0 14px 30px -14px #00000055}
.dash-menu[hidden]{display:none}
.dash-list{display:flex;flex-direction:column;max-height:320px;overflow-y:auto;border-top:1px solid var(--rule);
  border-bottom:1px solid var(--rule);margin:4px 0;padding:4px 0}
.dash-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;border:0;border-radius:9px;background:none;
  color:var(--text);font:inherit;font-size:calc(13px*var(--fs,1));text-align:left;text-decoration:none;cursor:pointer}
.dash-item:hover,.dash-item:focus-visible{background:var(--hover);outline:none}
.dash-item .ti{color:var(--text-mute)}
.dash-item .hint-sm{margin-left:auto}
.dash-item.on{background:var(--tan)}
.dash-wait{padding:8px 10px}
.dash-new{color:var(--text)}
.dash-add{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 14px}
.dash-add select{width:auto;max-width:320px}
@media (max-width:640px){.lib-act{justify-content:flex-start}.dash-menu{width:min(290px,92vw)}}

/* ── Settings rows, Ethos style (account.html): title + one line, control on the right ── */
.set-group{margin:16px 0 4px;color:var(--text-mute);font-family:var(--font-sans);font-size:calc(12px*var(--fs,1));font-weight:500}
.set-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:10px 0;border-top:1px solid var(--rule)}
.set-row > div,.set-row > span:first-child{display:flex;flex-direction:column;gap:2px;min-width:0}
label.set-row{cursor:pointer}
.set-rows .seg-choice{flex:none}
.set-range{width:180px;accent-color:var(--cta-b)}
.set-play{flex:none}
@media (max-width:560px){.set-row{flex-wrap:wrap}.set-range{width:100%}}
/* The bell, grouped by day */
.bell-day{padding:8px 10px 2px;color:var(--text-mute);font-size:calc(11.5px*var(--fs,1));font-weight:500;list-style:none}
.bell-gear{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:8px;color:var(--text-mute)}
.bell-gear:hover{background:var(--hover);color:var(--text)}
