/* Inter Variable — self-hosted, no external requests (2026-07-28 rebrand).
   font-weight: 100 900 covers the whole variable axis, so every existing
   font-weight rule (400/600/700 etc.) already used across the app "just
   works" against this one file — no other CSS needed to change. */
@font-face {
  font-family: 'Inter Variable';
  src: url('/static/fonts/InterVariable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter Variable';
  src: url('/static/fonts/InterVariable-Italic.woff2') format('woff2');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

/* Manrope + IBM Plex Mono — the DESIGNED fonts, self-hosted (Nocturne Glass, 2026-09-26).
   Inter stays above as the fallback. Zero external requests. */
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/IBMPlexMono-400-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/IBMPlexMono-400-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/IBMPlexMono-500-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/IBMPlexMono-500-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/IBMPlexMono-600-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/IBMPlexMono-600-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap; src: url('/static/fonts/Manrope-200-800-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap; src: url('/static/fonts/Manrope-200-800-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

/* ==========================================================================
   ZED CRM — design system
   --------------------------------------------------------------------------
   Same family as Zed Payroll / Chat / Leads (warm near-black + ZED orange) so
   all in-house tools read as one product. Two deliberate departures, both
   because this is an operational screen people stare at for a full shift:

   1. The canvas is lifted off pure black (#0f1115) with layered surfaces.
      Pure black + bright text at 8h/day is genuinely fatiguing.
   2. Orange is reserved for BRAND and PRIMARY ACTIONS only — never for status.
      In the old CRM everything was blue-on-navy, so nothing stood out. Here
      status has its own unambiguous palette, because reading status at a
      glance IS the job.
   ========================================================================== */

:root {
  --bg:        #0b0f17;
  --surface:   #111827;
  --surface-2: #172136;
  --border:    #243146;
  --border-lit:#35476b;

  --text:      #e6ebf4;
  --text-dim:  #93a1b8;
  --text-mute: #6b7a94;

  --accent:      #2f7df6;   /* Azure Pulse — brand + primary actions (2026-07-28 rebrand) */
  /* `--brand` is referenced by delivery.ejs:68-74 for the selected bucket's
     outline and was NEVER declared, so selecting a Delivery bucket painted
     nothing at all. It is the same thing as the accent — brand + primary. */
  --brand:       var(--accent);
  --accent-soft: rgba(47,125,246,.14);
  /* Renders native widget internals (select arrow + popup list, date picker)
     dark — CSS can style the control box but not those parts. */
  color-scheme: dark;
  --accent-hover:#4da2ff;

  /* Status palette — each one distinct at a glance, even side by side */
  --st-new:      #8b95a7;   /* SALE_MADE  — unclaimed, neutral */
  --st-progress: #38bdf8;   /* IN_PROCESS — someone is on it (sky, kept distinct from the azure accent) */
  --st-review:   #f5b13d;   /* REVIEW     — needs agent action (the money lever) */
  --st-done:     #35c9a5;   /* PROCESSED  — awaiting supplier verification */
  --st-good:     #3ecf7a;   /* CONFIRMED  — revenue */
  --st-warn:     #ff8f5a;   /* PIN_WRONG  */
  --st-bad:      #f2545b;   /* CANCELED   */
  --st-call:     #a97bff;   /* CALL_BACK  */

  --team-zeds: #4d9fff;
  --team-zedx: #3ecf7a;

  --radius:   10px;
  --radius-lg:14px;
  --shadow:   0 4px 24px rgba(0,0,0,.35);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: "Inter Variable", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }

/* ---------- top bar ---------- */
.topbar {
  display: flex; align-items: center; gap: 18px;
  padding: 0 20px; height: 56px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 40;
}
.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 15px; letter-spacing: .01em; white-space: nowrap; }
/* The ZED mark is a transparent PNG (same asset as Payroll and Chat), so it
   sits on the bar directly — no gradient tile behind it. */
.brand-mark {
  width: 28px; height: 28px; flex: none;
  object-fit: contain; display: block;
}
/* Wordmark sized to sit level with the 28px mark beside it (was 15px, tiny
   next to the logo, from when a subtitle line shared the space — Raymond,
   2026-07-28: drop the subtitle, size the name to the mark). Grey-into-azure
   gradient text, echoing the re-tinted logo and the payslip's net-pay band,
   instead of flat white. */
.brand-name {
  font-size: 19px;
  background: linear-gradient(120deg, var(--text) 25%, var(--accent-hover) 100%);
  -webkit-background-clip: text; background-clip: text; color: var(--text); /* fallback if clip unsupported */
  -webkit-text-fill-color: transparent;
}

.nav { display: flex; gap: 2px; flex: 1; overflow-x: auto; }
.nav a {
  color: var(--text-dim); font-size: 13px; font-weight: 500;
  padding: 7px 13px; border-radius: 8px; white-space: nowrap;
}
.nav a:hover { color: var(--text); background: var(--surface-2); }
.nav a.active { color: var(--text); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }
.nav a .count {
  display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 99px;
  font-size: 11px; font-weight: 700; background: var(--accent-soft); color: var(--accent);
}

/* team badge — instant "whose data am I looking at" */
.team-badge {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12px; font-weight: 600; color: var(--text-dim);
  padding: 5px 11px; border-radius: 99px; border: 1px solid var(--border);
  background: var(--bg); white-space: nowrap;
}
.team-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--team-zeds); }
.team-dot.green { background: var(--team-zedx); }
.team-dot.grey  { background: var(--text-mute); }

.who { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--text-dim); white-space: nowrap; }
.who .role { text-transform: uppercase; letter-spacing: .05em; font-size: 10px; color: var(--text-mute); }

/* ---------- layout ---------- */
.wrap { max-width: 1500px; margin: 0 auto; padding: 22px 20px 90px; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 18px; flex-wrap: wrap; }
.page-head h1 { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -.01em; }
.page-head p { margin: 3px 0 0; color: var(--text-dim); font-size: 13px; }

/* ---------- stat cards ---------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 22px; }
.stat {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 15px 16px; position: relative; overflow: hidden;
}
.stat::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--st-new); }
.stat .n { font-size: 26px; font-weight: 700; line-height: 1.1; letter-spacing: -.02em; }
.stat .l { font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .06em; margin-top: 5px; }
.stat .sub { font-size: 11px; color: var(--text-mute); margin-top: 3px; }
.stat.new::before      { background: var(--st-new); }
.stat.progress::before { background: var(--st-progress); }
.stat.review::before   { background: var(--st-review); }
.stat.done::before     { background: var(--st-done); }
.stat.good::before     { background: var(--st-good); }
.stat.warn::before     { background: var(--st-warn); }
.stat.bad::before      { background: var(--st-bad); }
/* Roll-up totals sit visually apart from the per-status cards — they're the
   yardstick you check the individual statuses against, not another status. */
.stat.rollup { background: var(--surface-2); border-color: var(--border-lit); }
.stat.rollup::before { background: var(--accent); }
.stat.rollup .n { color: var(--text); }
.stat.rollup.done::before { background: var(--st-done); }
.stat.rollup.done .n { color: var(--st-done); }
.stat.good .n { color: var(--st-good); }
.stat.review .n { color: var(--st-review); }
.stat.bad .n  { color: var(--st-bad); }

/* Grey→azure gradient for neutral headings and figures, matching the wordmark
   (Raymond, 2026-07-28: flat bright white read as dull next to the rebrand).
   Deliberately NOT applied where colour already carries meaning — the good /
   review / bad / rollup-done figures keep their status colour, since a
   gradient there would destroy the signal. `-webkit-text-fill-color` beats
   `color`, so those must be excluded rather than overridden. */
.page-head h1,
.panel-head h2,
.stat:not(.good):not(.review):not(.bad):not(.rollup) .n,
.stat.rollup:not(.done) .n {
  background: linear-gradient(120deg, var(--text) 25%, var(--accent-hover) 100%);
  -webkit-background-clip: text; background-clip: text;
  color: var(--text); /* fallback where background-clip:text is unsupported */
  -webkit-text-fill-color: transparent;
  width: fit-content; /* keep the gradient ramp tight to the glyphs */
}

/* ---------- panels & tables ---------- */
.panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 18px; }
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 13px 16px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.panel-head h2 { margin: 0; font-size: 14px; font-weight: 650; }
.panel-body { padding: 16px; }

.tablewrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
/* NOTE: .tablewrap sets overflow-x:auto, which per spec forces overflow-y to
   `auto` as well — making it a scroll container. A sticky `th` therefore
   positions relative to THAT container, not the viewport, so `top: 56px`
   (the topbar height) pushed the header 56px down and it sat on top of the
   first row, hiding it. `top: 0` keeps the header where it belongs. */
th {
  text-align: left; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-mute); padding: 10px 14px; border-bottom: 1px solid var(--border);
  background: var(--surface); position: sticky; top: 0; z-index: 5;
}
td { padding: 11px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody tr:hover td { background: rgba(255,255,255,.022); }
tbody tr:last-child td { border-bottom: none; }
.t-strong { font-weight: 600; }
.t-dim { color: var(--text-dim); }
.t-mute { color: var(--text-mute); font-size: 12px; }
.t-mono { font-family: "SF Mono", ui-monospace, Menlo, monospace; font-size: 12px; }
.t-right { text-align: right; }
.nowrap { white-space: nowrap; }

/* ---------- status pills ---------- */
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 99px; font-size: 11px; font-weight: 650;
  white-space: nowrap; letter-spacing: .01em;
}
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.pill.new      { color: var(--st-new);      background: rgba(139,149,167,.14); }
.pill.progress { color: var(--st-progress); background: rgba(77,159,255,.14); }
.pill.review   { color: var(--st-review);   background: rgba(245,177,61,.15); }
.pill.done     { color: var(--st-done);     background: rgba(53,201,165,.14); }
.pill.good     { color: var(--st-good);     background: rgba(62,207,122,.15); }
.pill.warn     { color: var(--st-warn);     background: rgba(255,143,90,.15); }
.pill.bad      { color: var(--st-bad);      background: rgba(242,84,91,.15); }
.pill.call     { color: var(--st-call);     background: rgba(169,123,255,.15); }

/* ---------- buttons ---------- */
button, .btn {
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
  border-radius: 8px; padding: 8px 15px; border: 1px solid transparent;
  background: var(--accent); color: #14161a; transition: background .12s, border-color .12s;
}
button:hover, .btn:hover { background: var(--accent-hover); color: #14161a; }
button:disabled { opacity: .45; cursor: not-allowed; }
.btn-ghost { background: transparent; color: var(--text); border-color: var(--border-lit); }
.btn-ghost:hover { background: var(--surface-2); color: var(--text); border-color: var(--text-mute); }
.btn-sm { padding: 5px 11px; font-size: 12px; border-radius: 7px; }
.btn-good { background: var(--st-good); color: #08130d; }
.btn-good:hover { background: #5ddb92; color: #08130d; }
.btn-warn { background: var(--st-warn); color: #1a0d06; }
.btn-warn:hover { background: #ffa473; color: #1a0d06; }
.btn-bad  { background: var(--st-bad); color: #fff; }
.btn-bad:hover { background: #ff6b71; color: #fff; }
.btn-row { display: flex; gap: 6px; flex-wrap: wrap; }

/* ---------- forms ---------- */
.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 13px; }
.field label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--text-dim); }
input, select, textarea {
  font: inherit; font-size: 14px; width: 100%;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--border-lit); border-radius: 8px; padding: 9px 11px;
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
input::placeholder, textarea::placeholder { color: var(--text-mute); }
textarea { resize: vertical; min-height: 90px; line-height: 1.55; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 14px; }
/* Two panels side by side (Processing: New sales | Working on now). Collapses
   earlier than grid-2 because these hold tables, not label/value pairs. */
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; align-items: start; }
@media (max-width: 1180px) { .pair { grid-template-columns: 1fr; } }
.hint { font-size: 11px; color: var(--text-mute); margin-top: -8px; margin-bottom: 12px; }

.toolbar { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; }
.toolbar input, .toolbar select { width: auto; min-width: 150px; padding: 7px 10px; font-size: 13px; }

/* ---------- empty state ---------- */
.empty { padding: 52px 20px; text-align: center; color: var(--text-mute); }
.empty .icon { font-size: 30px; opacity: .35; margin-bottom: 10px; }
.empty h3 { margin: 0 0 5px; font-size: 14px; color: var(--text-dim); font-weight: 600; }
.empty p { margin: 0; font-size: 13px; }

/* ---------- sticky notes: always one keystroke away ---------- */
.notes-fab {
  position: fixed; right: 22px; bottom: 22px; z-index: 60;
  width: 50px; height: 50px; border-radius: 50%; border: none;
  background: var(--accent); color: #14161a; font-size: 21px;
  box-shadow: var(--shadow); display: grid; place-items: center; padding: 0;
}
.notes-fab:hover { background: var(--accent-hover); transform: translateY(-1px); }
.notes-panel {
  position: fixed; right: 0; top: 0; bottom: 0; width: 400px; max-width: 92vw; z-index: 70;
  background: var(--surface); border-left: 1px solid var(--border);
  box-shadow: -8px 0 40px rgba(0,0,0,.45);
  display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform .18s ease;
}
.notes-panel.open { transform: translateX(0); }
.notes-head { display: flex; align-items: center; justify-content: space-between; padding: 15px 16px; border-bottom: 1px solid var(--border); }
.notes-head h3 { margin: 0; font-size: 14px; font-weight: 650; }
.notes-head .close { background: none; border: none; color: var(--text-mute); font-size: 22px; cursor: pointer; padding: 0 4px; }
.notes-head .close:hover { color: var(--text); background: none; }
.notes-panel textarea {
  flex: 1; border: none; border-radius: 0; background: transparent;
  padding: 16px; font-size: 14px; line-height: 1.65; resize: none;
}
.notes-panel textarea:focus { box-shadow: none; border-color: transparent; }
.notes-foot { padding: 9px 16px; border-top: 1px solid var(--border); font-size: 11px; color: var(--text-mute); display: flex; justify-content: space-between; }
.notes-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 65; opacity: 0; pointer-events: none; transition: opacity .18s; }
.notes-backdrop.open { opacity: 1; pointer-events: auto; }

/* ---------- toast ---------- */
.toasts { position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%); z-index: 90; display: flex; flex-direction: column; gap: 8px; align-items: center; }
.toast {
  background: var(--surface-2); border: 1px solid var(--border-lit); color: var(--text);
  padding: 10px 17px; border-radius: 99px; font-size: 13px; font-weight: 500;
  box-shadow: var(--shadow); animation: rise .2s ease;
}
.toast.good { border-color: var(--st-good); color: var(--st-good); }
.toast.bad  { border-color: var(--st-bad);  color: var(--st-bad); }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------- login ---------- */
.login-wrap { min-height: 100vh; display: grid; place-items: center; padding: 20px; }
.login-card { width: 100%; max-width: 370px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 30px; box-shadow: var(--shadow); }
.login-card .brand { justify-content: center; margin-bottom: 6px; font-size: 17px; }
.login-card .tag { text-align: center; color: var(--text-mute); font-size: 12px; margin-bottom: 24px; }
.login-card button { width: 100%; padding: 10px; margin-top: 6px; }
.err { background: rgba(242,84,91,.12); border: 1px solid rgba(242,84,91,.4); color: #ff9096; padding: 9px 12px; border-radius: 8px; font-size: 13px; margin-bottom: 14px; }

/* ---------- misc ---------- */
.sale-detail dt { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-mute); margin-top: 12px; }
.sale-detail dd { margin: 3px 0 0; font-size: 14px; }
.divider { height: 1px; background: var(--border); margin: 16px 0; }
.claimed-by { font-size: 11px; color: var(--st-progress); }
.age { font-size: 11px; color: var(--text-mute); }
.age.stale { color: var(--st-review); font-weight: 600; }

@media (max-width: 820px) {
  .topbar { height: auto; flex-wrap: wrap; padding: 10px 14px; gap: 10px; }
  th { position: static; }
  .wrap { padding: 16px 12px 90px; }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
}

/* ---------- follow-ups: rows whose call timer has fired ---------- */
tr.due td { background: rgba(245,177,61,.055); }
tr.due td:first-child { box-shadow: inset 3px 0 0 var(--st-review); }
tr.due .age { color: var(--st-review); font-weight: 600; }

/* ---------- per-user watermark (security) ---------- */
.watermark {
  position: fixed; inset: 0; z-index: 60; pointer-events: none;
  overflow: hidden; display: flex; flex-wrap: wrap; gap: 46px 60px;
  transform: rotate(-24deg) scale(1.5); transform-origin: center;
  opacity: .05; user-select: none;
}
.watermark span { font-size: 12px; font-weight: 600; white-space: nowrap; color: var(--text); letter-spacing: .04em; }
@media print { .watermark { opacity: .16; } }

/* Clickable stat cards (Follow-ups: RTC / Done switch the Completed list).
   The selected one gets the same azure ring the active nav tab uses, so
   "which list am I looking at" reads the same way everywhere. */
a.stat { display: block; color: inherit; cursor: pointer; transition: border-color .15s ease, transform .15s ease; }
a.stat:hover { border-color: var(--border-lit); transform: translateY(-1px); }
a.stat.is-active { box-shadow: inset 0 0 0 1px var(--accent); border-color: var(--accent); }

/* ==========================================================================
   POLISH PASS — 2026-08-06
   One appended, fully-revertible block (delete it to roll back). Three parts:
     A · data-first legibility   B · quiet-craft layer   C · status-at-a-glance
   Sourced from the ui-ux-pro-max, ui-ux-design-pro and better-* skills.
   ========================================================================== */

/* ---- A · DATA-FIRST LEGIBILITY ------------------------------------------
   Tabular figures: numbers, IDs, dates, counts and money line up digit-for-
   digit down every column. Inter's tnum only touches digits, so mixed
   name+number cells are unaffected — safe to apply broadly. */
td, .stat .n, .stat .sub, .nav a .count, .age, .t-mono, .t-num,
.pill, input, .toolbar input, .toolbar select {
  font-variant-numeric: tabular-nums;
}
.t-num { font-variant-numeric: tabular-nums; }
/* Long tracking numbers in the mono column shouldn't crush together. */
.t-mono { letter-spacing: .01em; }

/* ---- B · QUIET-CRAFT LAYER ----------------------------------------------
   Tactile press (better-ui: 0.96–0.97, exact properties, never transition:all). */
button, .btn {
  transition: background .12s ease, border-color .12s ease,
              transform .08s ease, box-shadow .12s ease, color .12s ease;
}
button:active:not(:disabled), .btn:active { transform: scale(.97); }
.notes-fab:active { transform: translateY(-1px) scale(.96); }
/* Keyboard focus was only styled on inputs; every interactive element now gets
   a visible ring for keyboard nav. :focus-visible keeps it off for mouse use. */
a:focus-visible, button:focus-visible, .btn:focus-visible,
.nav a:focus-visible, a.stat:focus-visible, .team-badge:focus-visible,
.notes-fab:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 7px;
}
/* Row hover: a touch more presence, and it settles instead of flipping. */
tbody tr { transition: background .12s ease; }
tbody tr:hover td { background: rgba(255,255,255,.035); }
/* Loading-skeleton utility — for "Scan now", table loads, any pending data. */
.skeleton { position: relative; overflow: hidden; border-radius: 6px;
  background: var(--surface-2); color: transparent !important; }
.skeleton::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.06), transparent);
  animation: skeleton-sweep 1.15s ease-in-out infinite; }
.skel-line { height: 12px; margin: 7px 0; border-radius: 6px; }
@keyframes skeleton-sweep { 100% { transform: translateX(100%); } }
/* Respect reduced-motion everywhere. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
  button:active, .btn:active, .notes-fab:active { transform: none; }
}

/* ---- C · STATUS-AT-A-GLANCE ---------------------------------------------
   OKLCH-normalised: every chromatic status now sits at the same lightness
   (~0.755) so none shouts — REVIEW was 8.6:1 and CANCELED 4.7:1, now a tight
   6.1–7.9 band — while hue keeps each one distinct. `new` stays deliberately
   dim (it should recede). All still pass WCAG AA on the surface. */
:root {
  --st-progress: #39bdf9;   /* IN_PROCESS */
  --st-review:   #e4a126;   /* REVIEW (money lever) — eased down from shouting */
  --st-done:     #37caa6;   /* PROCESSED */
  --st-good:     #3cce79;   /* CONFIRMED */
  --st-warn:     #fd8d58;   /* PIN_WRONG */
  --st-bad:      #ff7377;   /* CANCELED — lifted out of the dim outlier */
  --st-call:     #be91ff;   /* CALL_BACK */
}
/* Pill background now derives from the status colour itself (one source of
   truth) rather than hand-written rgba() that drifts as colours change. */
.pill.new      { color: var(--st-new);      background: color-mix(in oklab, var(--st-new)      15%, transparent); }
.pill.progress { color: var(--st-progress); background: color-mix(in oklab, var(--st-progress) 15%, transparent); }
.pill.review   { color: var(--st-review);   background: color-mix(in oklab, var(--st-review)   16%, transparent); }
.pill.done     { color: var(--st-done);     background: color-mix(in oklab, var(--st-done)     15%, transparent); }
.pill.good     { color: var(--st-good);     background: color-mix(in oklab, var(--st-good)     15%, transparent); }
.pill.warn     { color: var(--st-warn);     background: color-mix(in oklab, var(--st-warn)     15%, transparent); }
.pill.bad      { color: var(--st-bad);      background: color-mix(in oklab, var(--st-bad)      15%, transparent); }
.pill.call     { color: var(--st-call);     background: color-mix(in oklab, var(--st-call)     15%, transparent); }
/* REVIEW is the money lever — any REVIEW-status row gets the same left-edge
   flag the follow-up "due" rows use, so it catches the eye in a long queue.
   (Add class="status-review" on the <tr> where the queue renders REVIEW rows.) */
tr.status-review td { background: color-mix(in oklab, var(--st-review) 6%, transparent); }
tr.status-review td:first-child { box-shadow: inset 3px 0 0 var(--st-review); }
/* Slim REVIEW callout on the single-record page — same gold left-flag language
   as the rows, so a monitor landing on a sale in revision sees the action-item
   state at a glance (agents already get the full "Needs correcting" panel). */
.review-callout {
  display: flex; align-items: center; gap: 9px;
  padding: 10px 14px; margin: -2px 0 16px; border-radius: 9px;
  background: color-mix(in oklab, var(--st-review) 9%, transparent);
  box-shadow: inset 3px 0 0 var(--st-review);
  font-size: 13px; color: var(--text-dim); line-height: 1.45;
}
.review-callout strong { color: var(--st-review); font-weight: 650; }


/* ==========================================================================
   NOCTURNE PASS — 2026-08-25
   ==========================================================================
   Brings the CRM onto the Claude Design "Nocturne" mockups
   (Payroll UI mockups-handoff_24AUG). Analysis: memory/ui-nocturne-refresh.md.

   🔑 THE PALETTE IS ALREADY IDENTICAL — the mockups were built FROM this file
   (mockup --color-bg #0b0f17 == our --bg; --color-accent #2f7df6 == our
   --accent). Nothing here changes a colour token. This is composition,
   typography and density only.

   APPLIES TO EVERY SCREEN. Trialled Dashboard-only first, then unscoped —
   which also let the one markup change be reverted, so this refresh touches
   NO .ejs file at all. 100% CSS, one appended block.
   ⚠️ public/ is shared by BOTH deployments: crm.zedenterprises.org AND
   returns.zedexbpo.com. Whatever lands here lands on both.

   ⚠️ ONE APPENDED BLOCK, LIKE THE 2026-08-06 POLISH PASS. Delete from the
   banner to EOF to revert completely.

   🔴 SIX THINGS THIS BLOCK DELIBERATELY DOES NOT DO, because pure CSS can
   break the privacy layer without ever opening a template:
     1. no `th:empty { display:none }`  — the empty <th> over a read-only
        outcome column is deliberate; hiding it desyncs thead from tbody for
        watcher roles and they read data under the wrong heading.
     2. no `:empty` placeholder on dd/td — that reintroduces the "Delivered —"
        lie sale-detail.ejs was written to prevent.
     3. no `td:nth-child()` sizing — managers get 6 Delivery columns, others 8;
        agents 6 on Sales, others 7. Column indexes are role-dependent here.
     4. no bare `.stat:hover` / `a.stat{cursor:pointer}` — agent tally cards are
        deliberately href-less and must not advertise navigation.
     5. nothing that creates a stacking context on body/.wrap/.topbar and no
        z-index >= 60 — that silently kills the per-user watermark.
     6. `--text-dim` is NOT dimmed — it paints the `______` withheld-phone
        marker, and lowering it turns "withheld" into "no phone on file".
   ========================================================================== */

/* ── The system's SPACING SCALE (theme.json `density: 0.7`). Read live from
      the Nocturne design system 2026-08-25; the earlier pass used ad-hoc px.
      ⚠️ Adopted as a SCALE, not as a density: values snap to the nearest step,
      but the CRM stays looser than `--space-2` where the system would tighten,
      because this is an 8h/shift operational screen, not a deck. ────────── */
:root {
  --space-1: 2.8px;  --space-2: 5.6px;  --space-3: 8.4px;
  --space-4: 11.2px; --space-6: 16.8px; --space-8: 22.4px;
}

/* ── Type: the mockup's base is 15px/1.55, with dense UI stepped DOWN from it
      rather than everything scaled up. ─────────────────────────────────── */
body { font-size: 15px; line-height: 1.55; }

/* Page title sits tight on its own baseline.
   🔑 WEIGHT IS 500, NOT 600 — `--font-heading-weight: 500` in the system's
   theme.json. The 600 here was inferred from the flattened prototype. */
.page-head h1 { font-weight: 500; letter-spacing: -.015em; line-height: 1.12; }
.page-head    { margin-bottom: var(--space-8); }
.page-head p  { margin-top: var(--space-3); font-size: 12px; }

/* Panel titles become micro-caps eyebrow labels, the single most structural
   typographic difference in the mockup.
   ⚠️ `.panel-head h2` is one of the three gradient-text targets (see the
   2026-07-28 rebrand block). Raising specificity here rather than editing that
   selector keeps this block append-only and one-line revertible — but the
   gradient still wins on fill, so the colour is restated explicitly. */
.panel-head h2 {
  font-size: 13px; font-weight: 500; line-height: 1.12;
  text-transform: uppercase; letter-spacing: .08em;
  background: none; -webkit-text-fill-color: var(--text); color: var(--text);
}

/* ── Stat tiles: label ABOVE the number, mono figure, de-carded.
      Achieved with flex `order` so NO .ejs file is touched — the markup order
      (.n then .l) is unchanged, only the paint order. ─────────────────────── */
.stat { display: flex; flex-direction: column; padding: var(--space-4) var(--space-6); }
.stat .l {
  order: 1; margin: 0 0 var(--space-2);
  font-size: 11.5px; text-transform: none; letter-spacing: .01em;
  color: var(--text-dim);
}
.stat .n {
  order: 2;
  font-family: "SF Mono", ui-monospace, Menlo, monospace;
  font-size: 27px; font-weight: 600; letter-spacing: -.01em;
}
.stat .sub { order: 3; margin-top: var(--space-2); }

/* The 3px status bar STAYS. It is the only status signal on four of the seven
   tones — removing it to match the mockup's borderless tiles would delete
   meaning, not decoration. */

/* ── Tables: lighter rules, denser type. `:first-child`/`:last-child` only —
      never nth-child, because column counts differ by role. ──────────────── */
/* 🔑 14px / 11px are the system's STATED values (`.table`, `.table th`); the
   13.5/10.5 here were inferred from the prototype and were both a half-step
   small. Horizontal padding stays 14px — action-button columns are sized
   button-width + 28px and tighten into a second line below that. */
table    { font-size: 14px; }
thead th { font-size: 11px; letter-spacing: .08em; padding: var(--space-3) 14px; }
tbody td { padding: var(--space-4) 14px; }


/* ── ROW RULES — the Nocturne signature, and the one part of the design this
      pass had identified but never built. ───────────────────────────────────
   The system paints the rule on the ROW as a 1px background strip that fades
   to transparent over 48px at each end, so the fade spans the whole row rather
   than restarting at every cell boundary. th/td keep a TRANSPARENT border, so
   the layout box is byte-for-byte what it was.

   🔴 HAZARD 7 — NOT ONE OF THE SIX, AND IT BITES EXACTLY HERE.
   The six hazards above are about privacy; this one is about MEANING. The CRM
   paints row-level meaning on `td` backgrounds:
       :347  tr.due td            — the connector's 10-MINUTE RE-CALL REMINDER
       :449  tr.status-review td  — REVIEW rows
   A `td` background paints OVER the row strip beneath it. Ported naively, the
   fading rule would VANISH on precisely those two rows — the ones the eye is
   hunting for — while looking perfect everywhere else. Same class of silent
   wrongness as the "Delivered —" lie.
   ⇒ The tint MOVES from the cell to the ROW, where it layers UNDER the rule
   instead of over it, and the cells are cleared. The 3px `td:first-child`
   stripes are box-shadows and are deliberately untouched. */
:root {
  --rule-fade: 48px;
  --rule-c:   color-mix(in srgb, var(--text) 8%, transparent);
  --tint-due: rgba(245,177,61,.055);                              /* mirrors :347 */
  --tint-rev: color-mix(in oklab, var(--st-review) 6%, transparent); /* mirrors :449 */
  --tint-hov: rgba(255,255,255,.035);                             /* mirrors :404 */
}

thead th, tbody td { border-bottom-color: transparent; }

thead tr {
  background: linear-gradient(to right, transparent,
    var(--border) var(--rule-fade),
    var(--border) calc(100% - var(--rule-fade)), transparent)
    no-repeat bottom / 100% 1px;
}

tbody tr {
  --row-tint: none;
  --row-rule: linear-gradient(to right, transparent,
    var(--rule-c) var(--rule-fade),
    var(--rule-c) calc(100% - var(--rule-fade)), transparent)
    no-repeat bottom / 100% 1px;
  background: var(--row-tint), var(--row-rule);
}
tbody tr:last-child { --row-rule: none; }

/* Cells cleared so the row strip is never covered. Same specificity as the
   base rules, later in the file — so these win by order, and deleting this
   block restores the originals exactly. */
tr.due td, tr.status-review td, tbody tr:hover td { background: transparent; }

tr.due           { --row-tint: linear-gradient(var(--tint-due), var(--tint-due)) no-repeat 0 0 / 100% 100%; }
tr.status-review { --row-tint: linear-gradient(var(--tint-rev), var(--tint-rev)) no-repeat 0 0 / 100% 100%; }
tbody tr:hover   { --row-tint: linear-gradient(var(--tint-hov), var(--tint-hov)) no-repeat 0 0 / 100% 100%; }

/* Hover on an already-tinted row stacks both, so a due call-back still reads as
   due while the cursor is on it. */
tr.due:hover {
  --row-tint: linear-gradient(var(--tint-hov), var(--tint-hov)) no-repeat 0 0 / 100% 100%,
              linear-gradient(var(--tint-due), var(--tint-due)) no-repeat 0 0 / 100% 100%;
}
tr.status-review:hover {
  --row-tint: linear-gradient(var(--tint-hov), var(--tint-hov)) no-repeat 0 0 / 100% 100%,
              linear-gradient(var(--tint-rev), var(--tint-rev)) no-repeat 0 0 / 100% 100%;
}


/* ==========================================================================
   NOCTURNE — LEFT RAIL (2026-08-25)
   ==========================================================================
   Moves the nav from a 56px top bar to a 216px left rail, matching the
   mockups (`grep -c '<header'` on Zed Payroll Mockups.dc.html returns 0 —
   31 of its 36 cards use a rail; it is the design's identity).

   🔑 ZERO TEMPLATE EDITS. The rail is a re-layout of the EXISTING
   `<header class="topbar">`, whose children are already brand / nav /
   team-badge / who. `src/views/partials/topbar.ejs` is NOT opened — and that
   matters more here than anywhere else in this file, because lines 5-53 of it
   are nothing but role gates (`roles:` on every entry,
   `links.filter(n => n.roles.includes(R))` at :54, the returns-mode swap, the
   `(n.badgeAll && R !== 'super_admin')` badge selector). That filter IS the
   navigation permission model. It stays byte-identical because we never touch it.

   The collapse toggle is injected by public/app.js — also not a template.
   ========================================================================== */

:root { --rail: 216px; --rail-collapsed: 64px; }

/* ⚠️ GUARDED on :has(.topbar). login.ejs has no topbar and error.ejs renders it
   conditionally — without this they would get a 216px empty column. */
body:has(> .topbar) {
  display: grid;
  /* 🔑 THE TRACK IS ALWAYS THE COLLAPSED WIDTH. The rail expands OVER the
     content on hover, never by resizing this column — if the track resized,
     every hover would reflow the whole page and a table someone is reading
     would jump sideways under the cursor. */
  grid-template-columns: var(--rail-collapsed) 1fr;
  align-items: start;
}
/* The watermark, the notes FAB/panel and the toast host are all position:fixed,
   and <script> is display:none, so none of them claim a grid cell. A grid body
   does NOT create a containing block for fixed children, so the watermark still
   covers the viewport — verified, not assumed. */

.topbar {
  flex-direction: column; align-items: stretch; gap: 3px;
  height: 100vh; position: sticky; top: 0;
  padding: 18px 12px 14px;
  border-bottom: 0; border-right: 1px solid var(--border);
  overflow-y: auto; overflow-x: hidden;
}
.brand { padding: 0 8px 14px; }
.nav { flex-direction: column; flex: 0 1 auto; gap: 2px; overflow: visible; }
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; font-size: 13.5px; white-space: nowrap;
}
.nav a .count { margin-left: auto; }

/* Route glyphs, keyed off href — no markup involvement. These are what makes a
   collapsed rail legible: the CRM nav is text-only, so without them a 64px rail
   would be blank. */
.nav a::before {
  content: "•"; flex: 0 0 18px; text-align: center;
  font-size: 13px; opacity: .75;
}
.nav a[href="/dashboard"]::before    { content: "▦"; }
.nav a[href="/sales"]::before        { content: "▤"; }
.nav a[href="/processing"]::before   { content: "⚑"; }
.nav a[href="/tracking"]::before     { content: "⌖"; }
.nav a[href="/delivery"]::before     { content: "▸"; }
.nav a[href="/followups"]::before    { content: "☎"; }
.nav a[href="/verification"]::before { content: "✓"; }
.nav a[href="/returns"]::before      { content: "↩"; }
.nav a[href="/trackus"]::before      { content: "⇄"; }
.nav a[href="/admin"]::before        { content: "⚙"; }

/* Identity cluster drops to the bottom of the rail, stacked. */
.team-badge { margin-top: auto; align-self: flex-start; }
.who {
  flex-direction: column; align-items: stretch; gap: 8px;
  padding-top: 12px; margin-top: 10px; border-top: 1px solid var(--border);
  min-width: 0;                       /* let the name wrap instead of overflowing */
}
/* "Chief Operating Officer SUPER ADMIN" is wider than a 216px rail, so the name
   and the role pill stack rather than clip. */
.who > span { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; line-height: 1.3; min-width: 0; overflow-wrap: anywhere; }
.who .role { font-size: 10px; }
.who .btn, .who .btn-ghost { align-self: stretch; text-align: center; }

/* ⚠️ `margin: 0` is load-bearing. The base rule (:~83) is
   `.wrap { max-width: 1500px; margin: 0 auto }` — and on a GRID ITEM those auto
   margins absorb the free space and centre a shrink-to-fit box instead of
   filling the column. Overriding max-width alone left the content 686px wide in
   a 1484px track. */
.wrap { max-width: none; margin: 0; padding: 26px 30px 60px; }

/* ── AUTO-HIDE ON HOVER — his correction, 2026-08-25 ──────────────────────
   *"THE ONE IN THE MOCKUP IS AN AUTO HIDING SIDE BAR SO WHEN WE HOVER THE MOUSE
   OVER IT IT POPS AND WHEN WE HOVER BACK IT COLLAPSE"* — so the rail RESTS
   collapsed and opens on hover. The click toggle is gone.

   Three things this shape is deliberately buying:
   1. **No reflow.** The grid track stays 64px (above); only the rail's own
      width animates, and it paints over the content at the BASE z-index 40 —
      above the page, and deliberately below the watermark's 60 (hazard 5).
      No new stacking context is created anywhere.
   2. **`:focus-within`, not just `:hover`.** Tabbing into the nav opens the
      rail too. Hover-only would make the whole menu unreachable by keyboard.
   3. **A delay on the way CLOSED, none on the way open.** Brushing the cursor
      past the rail on the way to the table must not make it flap.
   ⚠️ The follow-up count badge stays visible at 64px — it is the connector's
   10-minute re-call reminder and losing it would break a real control. */

.topbar {
  width: var(--rail-collapsed);
  transition: width .16s ease .18s;          /* .18s delay applies to CLOSING */
}
/* The open rail floats OVER the page, so it needs elevation or it reads as if
   the table merged into it. Shadow only — no z-index change (still 40, below
   the watermark's 60) and no new stacking context. */
.topbar:hover,
.topbar:focus-within {
  width: var(--rail); transition-delay: 0s;
  box-shadow: 14px 0 34px -12px rgba(0,0,0,.62);
}

/* Resting (collapsed) presentation. Label text is hidden with font-size:0 on
   the anchor and restored on the glyph and the badge. */
.topbar:not(:hover):not(:focus-within) { padding: 18px 8px 14px; align-items: center; }
.topbar:not(:hover):not(:focus-within) :is(.brand-name, .team-badge, .who span) { display: none; }
.topbar:not(:hover):not(:focus-within) .nav a {
  font-size: 0; justify-content: center; padding: 9px 0; gap: 0; position: relative;
}
.topbar:not(:hover):not(:focus-within) .nav a::before { font-size: 15px; flex-basis: auto; }
.topbar:not(:hover):not(:focus-within) .nav a .count {
  margin: 0; position: absolute; transform: translate(11px, -11px);
  font-size: 10px; padding: 0 4px; min-width: 15px;
}
.topbar:not(:hover):not(:focus-within) .who { border-top: 0; align-items: center; }
/* "Sign out" does not fit 64px — becomes a glyph, with the word as its tooltip. */
.topbar:not(:hover):not(:focus-within) .who .btn { font-size: 0; padding: 7px 0; }
.topbar:not(:hover):not(:focus-within) .who .btn::before { content: "\23FB"; font-size: 14px; }

/* ── DUPLICATE CHECKER (2026-09-20) ────────────────────────────────────────
   The rail is 64px at rest and opens to --rail on hover/focus-within, so this
   follows the SAME pattern as .brand-name / .team-badge / .who span: hidden at
   rest, shown when the rail opens, with a glyph left behind so an agent can see
   the control exists at all.
   🔑 The answer stays readable because :focus-within holds the rail open while
      the cursor is still in the input — the submit handler never blurs it. */
.dupcheck {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  width: 100%; margin: 10px 0 2px;
}
.dupcheck #dupq { flex: 1 1 100%; min-width: 0; font-size: 12px; padding: 6px 8px; }
.dupcheck .btn { flex: 0 0 auto; }
.dupcheck-out { font-size: 12px; font-weight: 600; flex: 1 1 100%; }
.dupcheck-glyph {
  display: none;                      /* only the collapsed rail shows it */
  background: none; border: 0; padding: 0; cursor: pointer;
}

.topbar:not(:hover):not(:focus-within) .dupcheck { justify-content: center; margin: 8px 0; }
.topbar:not(:hover):not(:focus-within) .dupcheck :is(#dupq, .btn, .dupcheck-out) { display: none; }
.topbar:not(:hover):not(:focus-within) .dupcheck-glyph {
  display: block; font-size: 17px; line-height: 1; color: var(--text-dim);
}

/* Narrow screens: the rail is already collapsed, so only the content gutter
   needs to tighten. `.pair` collapses at this same breakpoint, so the two never
   disagree about what "narrow" means. */
@media (max-width: 1180px) {
  .wrap { padding: 20px 18px 60px; }
}

/* ── ANIMATED ZED MARK — port of his zed-logo-anim.jsx (2026-08-25) ─────────
   The mark is split down the middle and the two halves glide in from opposite
   sides; a 1.5px seam flashes as they meet. The motion lives in public/app.js
   (Web Animations API, same keyframes as the JSX); this is only the geometry.
   🔑 No template is touched — app.js replaces the existing `<img class=
   "brand-mark">` node with this wrapper at runtime.
   ⚠️ The `transform`s here sit on the SEAM and the wrapper, both deep inside
   `.topbar`. Hazard 5 is about a stacking context on body/.wrap/.topbar
   themselves — the watermark is a fixed-position SIBLING of the rail, so a
   transform on a logo half cannot affect it. */
.brand-anim { position: relative; width: 28px; height: 28px; flex: none; display: block; }
.brand-anim .brand-half { position: absolute; inset: 0; opacity: 0; }
.brand-anim .brand-half-l { clip-path: inset(0 50% 0 0); }
.brand-anim .brand-half-r { clip-path: inset(0 0 0 50%); }
.brand-anim .brand-half img { width: 100%; height: 100%; object-fit: contain; display: block; }
.brand-anim .brand-seam {
  position: absolute; left: 50%; top: -10%; bottom: -10%; width: 1.5px;
  transform: translateX(-50%); opacity: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(235,240,248,.95), transparent);
}

/* The mockup runs the mark at 52px on the sign-in card, not the rail's 28px. */
.login-card { position: relative; }
.login-card .brand-anim { width: 52px; height: 52px; }

/* "Signing you in" — his sign-in panel plays a 118px LOOPING mark while the
   credentials are checked. Sits inside the card at z-index 2; login pages carry
   no watermark (there is no signed-in user yet), so nothing to collide with. */
.signing-in {
  position: absolute; inset: 0; z-index: 2; border-radius: inherit;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-6);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
}
.signing-in p { margin: 0; color: var(--text-dim); font-size: 13px; letter-spacing: .02em; }
/* ⚠️ Must out-specify `.login-card .brand-anim` (0,2,0) above, or the big
   mark silently renders at the card's 52px — which is exactly what it did
   on the first run. */
.signing-in .brand-anim-lg { width: 118px; height: 118px; }

/* ==========================================================================
   AGENT DRILL-DOWN + AUDIT TRAIL — Nocturne mockup panels 12b / 9c
   ==========================================================================
   New components only. Nothing here re-styles an existing screen, and none of
   it touches the seven hazards: no `:empty`, no `nth-child` on cells, no
   `.stat:hover`, no z-index at all, and `--text-dim` is untouched (it paints
   the `______` withheld marker on this screen too).
   ========================================================================== */

/* Breadcrumb — the mockup's "Dashboard / Danny Wright". */
.crumb { font-size: 12px; color: var(--text-mute); margin-bottom: var(--space-3); }
.crumb a { color: var(--text-dim); text-decoration: none; }
.crumb a:hover { color: var(--accent-hover); }
.crumb .sep { opacity: .5; margin: 0 var(--space-1); }

/* Identity header: initials tile + name + meta line. */
.who-head { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.avatar {
  width: 44px; height: 44px; flex: none; border-radius: 12px;
  display: grid; place-items: center;
  font-size: 15px; font-weight: 600; letter-spacing: .02em;
  color: var(--accent-hover);
  background: var(--accent-soft); border: 1px solid var(--border-lit);
}

/* ── 7-day shape ─────────────────────────────────────────────────────────
   Bars are keyed on the OPERATIONAL day (the route uses opDayExpr), so a shift
   running past midnight stays in one column instead of splitting across two. */
.spark { display: flex; align-items: flex-end; gap: var(--space-2); padding: var(--space-6) var(--space-6) var(--space-4); height: 168px; }
.spark-col { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: var(--space-2); height: 100%; min-width: 0; }
.spark-n { font-family: "SF Mono", ui-monospace, Menlo, monospace; font-size: 12px; color: var(--text-dim); }
.spark-bar { flex: 1; width: 100%; display: flex; align-items: flex-end; }
.spark-bar i {
  display: block; width: 100%; border-radius: 5px 5px 0 0;
  background: linear-gradient(180deg, var(--accent-hover), var(--accent));
  min-height: 0; transition: height .18s ease;
}
.spark-col:hover .spark-bar i { background: linear-gradient(180deg, var(--accent-hover), var(--accent-hover)); }
.spark-d { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-mute); }

/* ── Audit trail ─────────────────────────────────────────────────────────── */
.trail-filters { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: var(--space-3) var(--space-6); border-bottom: 1px solid var(--border); }
.chip {
  padding: 5px 11px; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: 11.5px; line-height: 1.2;
  color: var(--text-dim); background: transparent; border: 1px solid var(--border);
}
.chip:hover { color: var(--text); border-color: var(--border-lit); background: var(--surface-2); }
.chip.on { color: var(--accent-hover); border-color: var(--accent); background: var(--accent-soft); }

.trail-list { list-style: none; margin: 0; padding: var(--space-2) 0; max-height: 420px; overflow-y: auto; }
.trail-row {
  display: grid; grid-template-columns: 140px 78px 1fr; gap: var(--space-4);
  align-items: baseline; padding: var(--space-3) var(--space-6);
  font-size: 13px;
}
/* Row rule as a fading strip, matching the Nocturne table treatment. */
.trail-row + .trail-row {
  background: linear-gradient(to right, transparent,
    var(--rule-c) var(--rule-fade),
    var(--rule-c) calc(100% - var(--rule-fade)), transparent) no-repeat top / 100% 1px;
}
.trail-at { font-size: 11.5px; white-space: nowrap; }
.trail-body { min-width: 0; overflow-wrap: anywhere; }
.trail-body a { color: var(--text); text-decoration: none; font-weight: 600; }
.trail-body a:hover { color: var(--accent-hover); }
.trail-note { font-size: 11.5px; margin-top: 3px; font-style: italic; }
.trail-row.is-filtered { display: none; }

@media (max-width: 1180px) {
  .trail-row { grid-template-columns: 1fr; gap: var(--space-1); }
  .trail-at { white-space: normal; }
}

/* ── Leaderboard "vs top" bar (Nocturne panel 12a) ───────────────────────────
   ⚠️ `.lb-rank` / `.lb-bar` are CLASSES on the cells, not `nth-child` sizing —
   hazard 3. This table has a fixed shape today, but keying widths off column
   POSITION is the habit that breaks the role-dependent tables elsewhere. */
.lb-rank { width: 46px; text-align: right; }
.lb-bar  { width: 180px; }
.bar {
  display: block; height: 8px; border-radius: 4px;
  background: var(--accent-soft); overflow: hidden;
}
.bar i {
  display: block; height: 100%; border-radius: 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-hover));
  min-width: 2px;
}

/* ── Activity log filters (Nocturne panel 9c) ───────────────────────────────
   The chips are LINKS, not buttons — each is a real filtered URL, so the view
   is shareable and the back button works. */
.filter-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-6); border-bottom: 1px solid var(--border);
}
.filter-row .lbl {
  font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-mute); margin-right: var(--space-1);
}
a.chip { text-decoration: none; display: inline-block; }

/* ── Admin users: expandable audit trail (Nocturne panel 9a) ────────────────
   The caret is a real <button> so it is keyboard-reachable; the expanded panel
   is a full-width row that spans every column. */
.expander {
  background: transparent; border: 0; cursor: pointer; padding: 2px 6px;
  color: var(--text-dim); font-size: 12px; line-height: 1;
}
.expander:hover { color: var(--accent-hover); }
.trail-cell { padding: 0 !important; background: var(--bg); }
.trail-cell .trail-list { max-height: 320px; }
.trail-cell .trail-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-3) var(--space-6); flex-wrap: wrap;
}
.trail-cell .trail-head h3 {
  margin: 0; font-size: 12px; font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase; color: var(--text);
}
.trail-loading { padding: var(--space-6); color: var(--text-mute); font-size: 12.5px; }

/* ==========================================================================
   VERIFICATION — THE ENROLMENT CELL (2026-09-21 refinement)
   His ask: "every error and everything is right on the face and it looks bad".
   One state per cell — the server picks it from filer_status, the 4 s poll flips
   it. Nothing is written on the face of a row except a pill; the reason waits
   behind "why?". Same tokens, same pills, same buttons as every other desk.
   ========================================================================== */
.enrol-td { width: 250px; min-width: 230px; }
.enrol-cell [data-st] { display: none; }
.enrol-cell[data-mode="idle"]     [data-st="idle"],
.enrol-cell[data-mode="failed"]   [data-st="idle"],
.enrol-cell[data-mode="existing"] [data-st="idle"],
.enrol-cell[data-mode="running"]  [data-st="running"] { display: block; }
/* the two "last run" pills — one shows, only in its mode */
.enrol-last, .enrol-existing { display: none; align-items: center; gap: 8px; margin-top: 7px; }
.enrol-cell[data-mode="failed"]   .enrol-last     { display: flex; }
.enrol-cell[data-mode="existing"] .enrol-existing { display: flex; }
.enrol-cell[data-mode="existing"] .enrol-go       { display: none; }   /* nothing to send to */
/* "why?" is a text link, not a button — it is the least important thing in the cell */
.enrol-why {
  background: none; border: 0; padding: 0; color: var(--text-mute);
  font-size: 11px; font-weight: 500; line-height: 1;
  text-decoration: underline dotted; text-underline-offset: 3px; cursor: pointer;
}
.enrol-why:hover { background: none; color: var(--accent-hover); }
/* running: pill · stop, then a 3px bar, then the service's one short phrase */
.enrol-run { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.enrol-bar { height: 3px; border-radius: 2px; margin-top: 8px; max-width: 220px; }
.enrol-bar i { transition: width .4s ease-out; }
.enrol-bar.indet i { width: 32%; animation: enrol-slide 1.1s ease-in-out infinite alternate; }
@keyframes enrol-slide { from { transform: translateX(0); } to { transform: translateX(212%); } }
.enrol-line { margin-top: 5px; font-size: 11px; max-width: 220px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* bounded by the cell, never by a fixed width — a fixed 250px clipped at the panel edge on a narrow pane */
.enrol-reason { font-size: 12px; color: var(--text-dim); line-height: 1.45; overflow-wrap: anywhere; margin-bottom: 7px; }
/* a low-confidence address split is flagged ON the button, before the pane is opened */
.enrol-flag { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--st-review); margin-left: 6px; vertical-align: middle; }
.enrol-addr { display: grid; gap: 5px; min-width: 220px; }
.enrol-addr-row { display: flex; gap: 5px; }
.enrol-addr-row [data-f="state"] { width: 56px; }
.enrol-addr-row [data-f="zip"]   { width: 80px; }
.enrol-check { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 2px; }
.enrol-addrline { font-size: 11px; }
/* .inp-sm was referenced by the panel but never defined — the address boxes rendered at the
   full 14px / 9px input size, which is why they looked enormous in the cell. */
.inp-sm { font-size: 12.5px; padding: 5px 8px; border-radius: 6px; }


/* ==========================================================================
   === NOCTURNE GLASS — 2026-09-26 ===
   ==========================================================================
   Port of the "Zed UI Mockups" glass refinement layer (glass.css + fontface)
   onto the CRM's real classes. ONE appended block — delete from this banner
   to EOF to revert. It OVERRIDES the earlier NOCTURNE PASS values rather than
   editing them. Both deployments (sales + returns) load this file.

   The seven hazards still hold (memory/ui-nocturne-refresh.md): no th:empty,
   no :empty placeholders, no td:nth-child sizing, no pointer on href-less
   .stat, no stacking context on body/.wrap/.topbar and no z-index >= 60 here,
   --text-dim untouched, row tints stay on the ROW under the fading rule.
   ========================================================================== */

:root {
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;
  --line: var(--border);                     /* admin.ejs <hr> referenced it, never defined */
  --accent-300: #90bbfc;
  --accent-900: #131f38;
  --glass-divider: rgba(148,163,184,.15);
  --t45: rgba(230,235,244,.45);
  --t50: rgba(230,235,244,.5);
}

/* ── 1. Ground + type ─────────────────────────────────────────────────────── */
body {
  font-family: "Manrope", "Inter Variable", system-ui, -apple-system, sans-serif;
  font-size: 15px; line-height: 1.55;
  background:
    radial-gradient(60% 50% at 85% 0%, rgba(47,125,246,.16), transparent 70%),
    radial-gradient(50% 45% at 0% 100%, rgba(145,132,217,.11), transparent 70%),
    radial-gradient(40% 35% at 60% 60%, rgba(52,211,153,.05), transparent 70%),
    var(--bg);
  background-attachment: fixed;
}
/* Every mono figure / id / timestamp: IBM Plex Mono replaces the SF Mono stacks. */
.t-mono, .stat .n, .stat .sub, .spark-n, .mono, .lb-rank, .trail-at, .age,
.emailbox textarea, code, .who-avatar, .avatar {
  font-family: var(--mono);
}
.t-mono { font-size: 12.5px; letter-spacing: 0; }

/* Flat headings and figures (the mockup has no gradient text). Same selector
   list as the 2026-07-28 rebrand rule so specificity ties and this, later, wins.
   The status-colour exclusions are untouched: good/review/bad/rollup-done keep
   their colour because they were never in that list. */
.page-head h1,
.panel-head h2,
.stat:not(.good):not(.review):not(.bad):not(.rollup) .n,
.stat.rollup:not(.done) .n {
  background: none; -webkit-background-clip: initial; background-clip: initial;
  -webkit-text-fill-color: currentColor; width: auto;
}
.page-head h1 { font-size: 20px; font-weight: 600; letter-spacing: -.015em; line-height: 1.12; color: var(--text); }
.wrap { padding: 28px 36px 40px; }

/* ── 2. Page head: title left, controls right, sub-line UNDER the row.
      `display:contents` lifts the <h1>/<p> out of their wrapper div so every
      screen gets the mockup composition with no template edit. The drill-down's
      .who-head (avatar + name block) is the one wrapper that must stay a box. ─ */
.page-head { align-items: center; gap: 14px; row-gap: 8px; margin-bottom: 26px; }
.page-head > div:first-child:not(.who-head) { display: contents; }
.page-head h1 { margin-right: auto; }
.page-head > .btn-row, .page-head > .toolbar, .page-head > form { margin-left: 0; }
.page-head p { order: 3; flex-basis: 100%; margin: 0; font-size: 12px; color: var(--t45); }
.page-head p strong { color: rgba(230,235,244,.75); }
.who-head { margin-right: auto; gap: 16px; }
.who-head p { margin-top: 3px; }
.who-head .avatar {
  width: 46px; height: 46px; border-radius: 50%; border: 0;
  background: var(--accent-900); color: var(--accent-300); font-size: 15px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 0 0 1px rgba(255,255,255,.08);
}
.crumb a { color: var(--t45); }
.crumb > span:last-child { color: rgba(230,235,244,.75); }

/* ── 3. Glass stat tiles ──────────────────────────────────────────────────── */
.stats { display: flex; flex-wrap: wrap; gap: 16px; margin: 0 0 28px -10px; }
.stat, .stat.rollup {
  min-width: 118px; padding: 12px 16px; border-radius: 16px; overflow: visible;
  border: 1px solid rgba(255,255,255,.12);
  background: linear-gradient(160deg, rgba(255,255,255,.10), rgba(255,255,255,.02) 55%, rgba(255,255,255,.05));
  -webkit-backdrop-filter: blur(18px) saturate(180%); backdrop-filter: blur(18px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), inset 0 -1px 1px rgba(255,255,255,.06),
              inset 1px 0 0 rgba(255,255,255,.06), 0 10px 28px -12px rgba(0,0,0,.7), 0 2px 6px -2px rgba(0,0,0,.4);
  isolation: isolate;
  transition: background .25s, box-shadow .25s, transform .25s cubic-bezier(.22,1,.36,1), border-color .25s;
}
/* The 3px status bar becomes the glass sheen; status now lives in the FIGURE
   colour (below) so no tone loses its signal. Listed with the tone selectors so
   the earlier `.stat.<tone>::before { background }` rules cannot repaint it. */
.stats .stat::before, .stat.rollup::before, .stat.rollup.done::before,
.stat.new::before, .stat.progress::before, .stat.review::before, .stat.done::before,
.stat.good::before, .stat.warn::before, .stat.bad::before {
  content: ""; position: absolute; inset: 0; width: auto; border-radius: inherit;
  pointer-events: none; z-index: -1; opacity: .9;
  background: radial-gradient(120% 70% at 20% 0%, rgba(255,255,255,.18), transparent 55%),
              radial-gradient(80% 60% at 100% 100%, rgba(144,187,252,.08), transparent 60%);
}
.stat:hover {
  transform: translateY(-2px); border-color: rgba(255,255,255,.2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35), inset 0 -1px 1px rgba(255,255,255,.08),
              0 16px 34px -14px rgba(0,0,0,.8), 0 0 0 1px rgba(144,187,252,.08);
}
a.stat:active { transform: scale(.97); }
/* Hazard 4: the lift is not a navigation affordance, the pointer is. */
a.stat:not([href]) { cursor: default; }
/* Selected tile (the active filter card). */
.stat.is-active, a.stat.is-active {
  border-color: rgba(144,187,252,.5);
  background: linear-gradient(160deg, rgba(47,125,246,.34), rgba(47,125,246,.10) 60%, rgba(144,187,252,.18));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4), inset 0 -1px 1px rgba(144,187,252,.25),
              0 0 0 1px rgba(47,125,246,.25), 0 12px 32px -10px rgba(47,125,246,.55);
}
.stat .l { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--t45); white-space: nowrap; margin: 0; }
.stat .n { font-size: 27px; font-weight: 600; margin-top: 6px; letter-spacing: 0; font-variant-numeric: tabular-nums; color: var(--text); }
.stat .sub { font-size: 11px; color: var(--t45); margin-top: 4px; }
/* Figure colour by tone — the app's own status tokens (brief §3). */
.stat.progress .n { color: var(--st-progress); }
.stat.warn .n     { color: var(--st-warn); }
.stat.done .n     { color: var(--st-done); }
.stat.rollup .n   { color: #4f95f7; }
.stat.rollup.done .n { color: var(--st-done); }
/* Plain label-over-number row (Processing 14c, agent My sales 14a): no tiles. */
.stats-plain { gap: 36px; margin-left: 0; }
.stats-plain .stat, .stats-plain .stat:hover {
  min-width: 0; padding: 0; border: 0; border-radius: 0; background: none;
  box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; transform: none;
}
.stats-plain .stat::before { display: none; }

/* ── 4. Glass panels ──────────────────────────────────────────────────────── */
.panel {
  border-radius: 12px; border-color: rgba(255,255,255,.1); margin-bottom: 22px;
  background-color: rgba(20,29,47,.45);
  background-image: linear-gradient(160deg, rgba(255,255,255,.07), rgba(255,255,255,.01) 45%, rgba(255,255,255,.03));
  -webkit-backdrop-filter: blur(20px) saturate(170%); backdrop-filter: blur(20px) saturate(170%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), inset 0 -1px 1px rgba(255,255,255,.05),
              inset 1px 0 0 rgba(255,255,255,.05), 0 18px 40px -22px rgba(0,0,0,.8);
}
.panel-head { align-items: baseline; padding: 16px 20px; gap: 12px; border-bottom-color: var(--glass-divider); }
.panel-head:has(form, button, .btn, input, select) { align-items: center; }
.panel-head h2 {
  font-size: 13px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  line-height: 1.12; color: var(--text);
}
.panel-head h2 .t-mute { color: var(--t45); font-size: inherit; }
.panel-head > .t-mute, .panel-head > span.t-mute, .panel-head > span.muted { font-size: 11.5px; color: rgba(230,235,244,.4); }
.panel-body { padding: 20px; }
/* Table-only panels sit on the ground (5a/5b/5h/8a/9c/12b): the head becomes
   the h6 eyebrow. `.panel-bare` is a class on the template; the two :has()
   forms catch the tile wrappers and head-only wrappers with no edit. */
.panel-bare, .panel:has(> .stats), .panel:has(> .panel-head:only-child), .panel:has(> #tabs) {
  background: none; border: 0; box-shadow: none; border-radius: 0; overflow: visible;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.panel:has(> .stats) { margin-bottom: 28px; }
.panel:has(> .stats) > .stats { margin-bottom: 0; }
.panel:has(> .panel-head:only-child) { margin-bottom: 16px; }
.panel-bare > .panel-head, .panel:has(> .panel-head:only-child) > .panel-head { padding: 0 0 12px; border-bottom: 0; }
.panel-bare > .panel-head h2 { color: var(--t50); }
.panel-bare > .panel-body { padding: 14px 0; }
/* Eyebrow OUTSIDE a glass card (5c Details, 8a Last 7 days). */
.panel-eyebrow { background: none; border: 0; box-shadow: none; border-radius: 0; overflow: visible; -webkit-backdrop-filter: none; backdrop-filter: none; }
.panel-eyebrow > .panel-head { padding: 0 0 10px; border-bottom: 0; }
.panel-eyebrow > .panel-head h2 { color: var(--t50); }
.panel-eyebrow > .panel-body, .panel-eyebrow > .spark {
  border-radius: 12px; border: 1px solid rgba(255,255,255,.1);
  background-color: rgba(20,29,47,.45);
  background-image: linear-gradient(160deg, rgba(255,255,255,.07), rgba(255,255,255,.01) 45%, rgba(255,255,255,.03));
  -webkit-backdrop-filter: blur(20px) saturate(170%); backdrop-filter: blur(20px) saturate(170%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), inset 0 -1px 1px rgba(255,255,255,.05),
              inset 1px 0 0 rgba(255,255,255,.05), 0 18px 40px -22px rgba(0,0,0,.8);
}
.panel-eyebrow > .panel-body { padding: 26px 28px; }
/* Verifier-away sits alone in a .pair → one 560px column (15h). */
.pair:has(> .panel:only-child) { grid-template-columns: minmax(0, 560px); }
.pair { gap: 0 22px; }

/* ── 5. Buttons: pill glass ───────────────────────────────────────────────── */
button, .btn {
  border-radius: 999px; font-size: 13px; font-weight: 500; padding: 7px 14px; line-height: 1.2;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 1px solid rgba(255,255,255,.14);
  -webkit-backdrop-filter: blur(16px) saturate(180%); backdrop-filter: blur(16px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), inset 0 -1px 1px rgba(255,255,255,.05),
              inset 1px 0 0 rgba(255,255,255,.05), 0 6px 16px -8px rgba(0,0,0,.7);
  transition: transform .2s cubic-bezier(.22,1,.36,1), box-shadow .2s, filter .2s, background .2s, border-color .2s, color .2s;
}
.btn-sm { padding: 5px 12px; font-size: 12px; border-radius: 999px; }
/* primary — every button that is not one of the named tones */
button:not(.btn-ghost):not(.btn-good):not(.btn-warn):not(.btn-bad):not(.chip):not(.expander):not(.enrol-why):not(.dupcheck-glyph):not(.tab):not(.close):not(.subtab),
.btn:not(.btn-ghost):not(.btn-good):not(.btn-warn):not(.btn-bad) {
  background: linear-gradient(180deg, rgba(92,156,255,.95), rgba(47,125,246,.9) 50%, rgba(33,98,210,.92));
  border-color: rgba(170,205,255,.45); color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5), inset 0 -2px 3px rgba(10,40,110,.35), 0 8px 22px -8px rgba(47,125,246,.7);
}
button:not(.btn-ghost):not(.btn-good):not(.btn-warn):not(.btn-bad):not(.chip):not(.expander):not(.enrol-why):not(.dupcheck-glyph):not(.tab):not(.close):not(.subtab):hover,
.btn:not(.btn-ghost):not(.btn-good):not(.btn-warn):not(.btn-bad):hover {
  background: linear-gradient(180deg, rgba(92,156,255,.95), rgba(47,125,246,.9) 50%, rgba(33,98,210,.92));
  color: #fff; transform: translateY(-1px); filter: brightness(1.1);
}
.btn-ghost, .btn-ghost:hover {
  background: linear-gradient(180deg, rgba(255,255,255,.1), rgba(255,255,255,.03));
  border-color: rgba(255,255,255,.14); color: var(--text); padding: 6px 14px;
}
.btn-ghost.btn-sm { padding: 5px 12px; }
.btn-ghost:hover { transform: translateY(-1px); filter: brightness(1.1); }
.btn-good, .btn-good:hover {
  background: linear-gradient(180deg, #22b35a, #16a34a 55%, #12873d); border-color: rgba(134,239,172,.45); color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45), inset 0 -2px 3px rgba(0,0,0,.25), 0 8px 22px -10px rgba(0,0,0,.7);
}
/* Send to revision / DQ'd / Bypass this shift / Clear undistributed — the
   screens (14c, 15h, 15g) draw these as tinted OUTLINE pills, not solid fills. */
.btn-warn, .btn-warn:hover { background: rgba(245,158,11,.16); border-color: rgba(245,158,11,.4); color: #fbbf24; }
.btn-bad,  .btn-bad:hover  { background: rgba(248,113,113,.15); border-color: rgba(248,113,113,.4); color: #f87171; }
.btn-warn:hover { background: rgba(245,158,11,.26); }
.btn-bad:hover  { background: rgba(248,113,113,.25); }
.btn-good:hover, .btn-warn:hover, .btn-bad:hover { transform: translateY(-1px); filter: brightness(1.05); }
button:active:not(:disabled), .btn:active { transform: scale(.96); }
/* Bare controls that must NOT become pills. */
.expander, .enrol-why, .dupcheck-glyph, .chip, .notes-head .close {
  -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: none; transition: none;
}
.expander, .enrol-why, .dupcheck-glyph { border: 0; border-radius: 6px; padding: 2px 6px; }
.expander, .enrol-why { display: inline-block; }   /* .dupcheck-glyph keeps its own display rules (rest-only) */
.enrol-why { padding: 0; }
.chip { border-radius: 999px; padding: 5px 11px; display: inline-flex; }
.notes-head .close {
  width: 30px; height: 30px; padding: 0; border-radius: 999px; font-size: 16px; color: var(--text);
  border: 1px solid rgba(255,255,255,.14);
  background: linear-gradient(180deg, rgba(255,255,255,.1), rgba(255,255,255,.03));
}
/* Text-only ghost links (Leaderboard →, show activity …) stay text. */
.panel-head a:not(.btn) { color: #4f95f7; }

/* ── 6. Inputs / selects / textareas ──────────────────────────────────────── */
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), select, textarea {
  background: linear-gradient(180deg, rgba(0,0,0,.18), rgba(255,255,255,.03));
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border: 1px solid rgba(255,255,255,.12); border-radius: 12px;
  box-shadow: inset 0 1px 2px rgba(0,0,0,.35), inset 0 -1px 0 rgba(255,255,255,.06);
  min-height: 36px; padding: 6px 11px; font-size: 14px; caret-color: var(--accent);
  transition: border-color .2s, box-shadow .2s;
}
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):focus, select:focus, textarea:focus {
  border-color: rgba(144,187,252,.6);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.3), 0 0 0 3px rgba(47,125,246,.22);
}
input::placeholder, textarea::placeholder { color: var(--t45); }
.toolbar input, .toolbar select { min-height: 32px; font-size: 12.5px; min-width: 110px; padding: 5px 10px; }
.toolbar input[name="q"] { width: 240px; }
.toolbar select[name="team_id"] { width: 130px; }
.toolbar select[name="range"] { width: auto; min-width: 110px; }
.field { gap: 6px; margin-bottom: 14px; }
.field label, .sale-detail dt {
  font-size: 11px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: var(--t50);
}
.field label label, .field .check-row { text-transform: none; letter-spacing: 0; font-size: 12.5px; color: rgba(230,235,244,.7); }
.field .check-row { display: flex; align-items: center; gap: 10px; }
.field .check-row input[type="checkbox"] { width: auto; }
.field .check-row .t-mute { font-size: 11.5px; }
/* mono fields: phones, PINs, IMEI, tracking numbers, IPs, usernames, settings */
#ph, #pin, #cell, #imei, #trk, .mUps, textarea[name="allowed_ips"], textarea[name="self_enrol_agents"],
#leadpool input[type="number"], input[name="phone"], input[name="username"], .tracknum-in {
  font-family: var(--mono); font-size: 13px;
}
textarea[name="allowed_ips"] { font-size: 12.5px; line-height: 1.6; min-height: 96px; }
.hint { color: var(--t45); }

/* ── 7. Pills ─────────────────────────────────────────────────────────────── */
.pill {
  font-size: 10.5px; padding: 3px 10px; border-radius: 7.5px; font-weight: 500; letter-spacing: .02em;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.18), inset 0 0 0 .5px rgba(255,255,255,.08);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.pill::before { display: none; }                       /* the mockup tags carry no dot */
form[action="/admin/nova-queue"] .pill::before { display: inline-block; }   /* "● OFF" (15i) */
.pill.ok { color: var(--st-good); background: color-mix(in oklab, var(--st-good) 15%, transparent); }
.pill.call { color: #b5aaf0; background: rgba(145,132,217,.18); }           /* Super Admin, violet */

form[action="/admin/nova-queue"] p { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: rgba(230,235,244,.65); }

/* ── 8. Avatars ───────────────────────────────────────────────────────────── */
.avatar { box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 0 0 1px rgba(255,255,255,.08); }

/* ── 9. Tables ────────────────────────────────────────────────────────────── */
table { font-size: 13.5px; }
thead th {
  font-size: 11px; font-weight: 500; letter-spacing: .08em; color: rgba(230,235,244,.6);
  padding: 8px 14px; background: transparent;
}
tbody td { padding: 10px 14px; }
thead tr { background-image: linear-gradient(to right, transparent, var(--glass-divider) var(--rule-fade), var(--glass-divider) calc(100% - var(--rule-fade)), transparent); }
td.t-strong > a, td > a[href^="/sales/"], td > a[href^="/returns/lead/"], .trail-body a, .work-card a.work-name {
  color: #4f95f7; font-weight: 600; text-decoration: none;
}
td .t-mute { font-size: 11.5px; color: var(--t45); margin-top: 2px; }
td .t-mono, .t-mono.t-mute { font-size: 12.5px; }
.age { color: #fbbf24; font-size: 12px; }               /* "since" / "waiting" in amber (15a, 14c, 5h) */
.age.stale { font-weight: 600; }
tr.is-zero { opacity: .45; }                            /* agent-log rows that are all zeros (15c) */
tr.due td:first-child, tr.status-review td:first-child { box-shadow: inset 3px 0 0 #fbbf24; }
td.empty { display: table-cell; text-align: center; padding: 40px; }
.t-right .btn-sm { vertical-align: middle; }

/* ── 10. Empty states ─────────────────────────────────────────────────────── */
.empty { padding: 60px 0; display: flex; flex-direction: column; align-items: center; gap: 10px; color: rgba(230,235,244,.4); font-size: 13px; text-align: center; }
.empty .icon {
  width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--glass-divider);
  display: grid; place-items: center; color: #34d399; font-size: 15px; opacity: 1; margin: 0;
}
.empty h3 { margin: 0; font-size: 14px; font-weight: 600; color: var(--text); }
.empty p { margin: 0; font-size: 12.5px; color: var(--t50); }
p.empty { padding: 44px 0; }

/* ── 11. Tab strips (Returns 15a, Track US 5g/15f, New sale "Send the code to") ─ */
.seg, .wrap .subtabs, #tabs {
  display: inline-flex; gap: 0; padding: 0; margin: 0 0 22px; overflow: hidden; width: auto;
  border: 1px solid var(--glass-divider); border-radius: 8px;
}
.seg-opt, .subtabs .subtab, #tabs .tab, #tabs .tab.btn-ghost {
  display: inline-flex; align-items: center; gap: 6px; position: relative;
  padding: 5px 11px; font-size: 12.5px; font-weight: 500; line-height: 1.4;
  color: rgba(230,235,244,.6); background: transparent; border: 0; border-radius: 0;
  box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; cursor: pointer; text-decoration: none;
}
.seg-opt + .seg-opt, .subtabs .subtab + .subtab, #tabs .tab + .tab { border-left: 1px solid var(--glass-divider); }
.seg-opt:hover, .subtabs .subtab:hover, #tabs .tab:hover { color: var(--text); background: rgba(255,255,255,.05); transform: none; filter: none; }
.seg-opt.active, .seg-opt:has(input:checked), .subtabs .subtab.on, #tabs .tab.active {
  color: var(--accent-300); background: rgba(47,125,246,.13); box-shadow: inset 0 0 0 1px var(--accent);
}
.seg-opt .t-mute, .subtabs .subtab .c, #tabs .tab .t-mute { font-family: var(--mono); font-size: 11px; color: var(--t45); opacity: 1; margin: 0; }
.seg-opt input[type="radio"] { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; pointer-events: none; }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ── 12. Notes panel + FAB ────────────────────────────────────────────────── */
.notes-fab {
  width: 48px; height: 48px; right: 28px; bottom: 28px; border-radius: 50%; font-size: 18px; padding: 0;
}
.notes-fab:hover { transform: translateY(-1px); }
.notes-panel {
  width: 380px; border-left: 1px solid rgba(255,255,255,.16); border-radius: 22px 0 0 22px;
  background: linear-gradient(160deg, rgba(40,52,78,.72), rgba(16,24,42,.62));
  -webkit-backdrop-filter: blur(40px) saturate(190%); backdrop-filter: blur(40px) saturate(190%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3), inset 0 -1px 1px rgba(255,255,255,.06),
              0 40px 90px -30px rgba(0,0,0,.9), 0 0 0 .5px rgba(255,255,255,.08);
}
.notes-head { padding: 18px 20px; gap: 10px; justify-content: flex-start; border-bottom-color: var(--glass-divider); }
.notes-head h3 { font-size: 14.5px; font-weight: 600; }
.notes-head h3 .t-mute { font-size: 12px; color: var(--t45); }
.notes-head .close { margin-left: auto; }
.notes-panel textarea {
  flex: 1; margin: 16px; padding: 12px 14px; font-size: 13px; line-height: 1.6; border-radius: 12px;
  background: linear-gradient(180deg, rgba(0,0,0,.18), rgba(255,255,255,.03));
  border: 1px solid rgba(255,255,255,.12);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.35), inset 0 -1px 0 rgba(255,255,255,.06);
}
.notes-panel textarea:focus { border-color: rgba(144,187,252,.6); box-shadow: inset 0 1px 2px rgba(0,0,0,.3), 0 0 0 3px rgba(47,125,246,.22); }
.notes-hint { padding: 0 20px 8px; font-size: 12px; color: var(--t45); }
.notes-foot { padding: 14px 20px; font-size: 11.5px; color: var(--t45); align-items: center; border-top-color: var(--glass-divider); }
.notes-foot span:last-child { font-family: var(--mono); font-size: 11px; }
#notesStatus { color: #34d399; }
#notesStatus::before { content: "● "; }
#notesStatus[data-state="typing"], #notesStatus[data-state="saving"] { color: var(--t45); }
#notesStatus[data-state="error"] { color: #f87171; }
.notes-backdrop { background: rgba(5,8,14,.55); -webkit-backdrop-filter: blur(6px) saturate(140%); backdrop-filter: blur(6px) saturate(140%); }

/* ── 13. Sign-in (4h) + the signing-in overlay ────────────────────────────── */
.login-wrap { background: radial-gradient(ellipse 62% 48% at 50% 36%, rgba(47,125,246,.09), transparent 70%), #0b0f17; }
.login-card {
  width: 364px; max-width: 100%; display: flex; flex-direction: column; gap: 12px;
  border-radius: 14px; padding: 38px 34px 30px; border: 1px solid var(--glass-divider);
  background-color: rgba(20,29,47,.72);
  background-image: linear-gradient(160deg, rgba(255,255,255,.07), rgba(255,255,255,.01) 45%, rgba(255,255,255,.03));
  -webkit-backdrop-filter: blur(20px) saturate(170%); backdrop-filter: blur(20px) saturate(170%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), inset 0 -1px 1px rgba(255,255,255,.05), 0 24px 60px rgba(0,0,0,.45);
}
.login-card .brand { flex-direction: column; gap: 16px; margin-bottom: 16px; padding: 0; }
.login-card .brand-mark { width: 52px; height: 52px; }
.login-card .brand-name { font-size: 19px; font-weight: 600; letter-spacing: .01em; color: var(--text); }
.login-card .field { margin: 0; gap: 0; }
.login-card .field label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.login-card .err { background: none; border: 0; padding: 0; margin: 0; font-size: 12.5px; color: #f87171; }
.login-card button { margin-top: 6px; width: 100%; }
.signing-in {
  gap: 30px; border-radius: 14px;
  background: radial-gradient(ellipse 70% 55% at 50% 44%, rgba(47,125,246,.10), transparent 72%), #0b0f17;
}
.signing-in p { margin: 0; font-size: 12px; letter-spacing: .26em; text-transform: uppercase; color: #66a3ff; }
.signing-in .zp-track { width: 120px; height: 2px; border-radius: 2px; overflow: hidden; background: rgba(148,163,184,.15); margin-top: -18px; }
.signing-in .zp-bar { width: 40%; height: 100%; border-radius: 2px; background: var(--accent); animation: zpLoad 1.4s ease-in-out infinite; }
@keyframes zpLoad { 0% { transform: translateX(-120%); } 100% { transform: translateX(320%); } }

/* ── 14. THE RAIL — glass, SVG route icons, kickers, footer ───────────────── */
.topbar {
  padding: 20px 14px 16px; gap: 2px; border-right: 0;
  background: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.015));
  -webkit-backdrop-filter: blur(24px) saturate(170%); backdrop-filter: blur(24px) saturate(170%);
  box-shadow: inset -1px 0 0 rgba(255,255,255,.08), inset 0 1px 0 rgba(255,255,255,.1);
  transition: width .45s cubic-bezier(.22,1,.36,1) .18s;         /* delay applies to CLOSING */
}
.topbar:hover, .topbar:focus-within {
  transition-delay: 0s;
  box-shadow: inset -1px 0 0 rgba(255,255,255,.08), inset 0 1px 0 rgba(255,255,255,.1), 14px 0 34px -12px rgba(0,0,0,.62);
}
.topbar:not(:hover):not(:focus-within) { padding: 20px 14px 16px; align-items: stretch; }
.brand { padding: 0 5px 16px; gap: 10px; }
.brand-mark, .brand-anim { width: 26px; height: 26px; }
.brand-name {
  font-size: 15px; font-weight: 600; letter-spacing: 0; color: var(--accent-300);
  background: none; -webkit-background-clip: initial; background-clip: initial; -webkit-text-fill-color: currentColor;
}
/* Everything but the icons fades. */
.brand-name, .nav-label, .nav-group, .team-badge, .who > span, .who .btn, .dupcheck { transition: opacity .35s ease .12s; }
.topbar:not(:hover):not(:focus-within) :is(.nav-label, .nav-group, .team-badge) { opacity: 0; transition: opacity .25s ease; }
.topbar:not(:hover):not(:focus-within) span.brand-name { display: inline; opacity: 0; transition: opacity .25s ease; }
.topbar:not(:hover):not(:focus-within) span.team-badge { display: inline-flex; opacity: 0; }
.topbar:not(:hover):not(:focus-within) .who > span { display: flex; opacity: 0; transition: opacity .25s ease; }
.topbar:not(:hover):not(:focus-within) .who .who-avatar { display: grid; opacity: 1; }
.topbar:not(:hover):not(:focus-within) .who > span > span { display: block; }   /* the name/role children, out-specifying the old `.who span` hide */
.topbar:not(:hover):not(:focus-within) .who .btn { display: none; }
.topbar:not(:hover):not(:focus-within) .who .btn::before { content: none; }

.nav-group {
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: rgba(230,235,244,.4);
  padding: 14px 10px 4px; white-space: nowrap;
}
.nav-group:first-child { padding-top: 4px; }
.nav a, .topbar:not(:hover):not(:focus-within) .nav a {
  position: relative; isolation: isolate; display: flex; align-items: center; gap: 12px;
  padding: 7px 10px; border-radius: 12px; font-size: 13.5px; font-weight: 500; justify-content: flex-start;
  color: var(--text); border: 1px solid transparent; background: none; box-shadow: none;
  transition: background .25s, box-shadow .25s, transform .25s cubic-bezier(.22,1,.36,1), border-color .25s;
}
.nav a:hover {
  color: var(--text);
  background: linear-gradient(160deg, rgba(255,255,255,.08), rgba(255,255,255,.02));
  border-color: rgba(255,255,255,.09); box-shadow: inset 0 1px 0 rgba(255,255,255,.16);
}
.nav a:active { transform: scale(.97); }
.nav a.active {
  color: #dbe8ff; border-color: rgba(144,187,252,.45);
  background: linear-gradient(160deg, rgba(47,125,246,.42), rgba(47,125,246,.14) 60%, rgba(144,187,252,.22));
  -webkit-backdrop-filter: blur(16px) saturate(180%); backdrop-filter: blur(16px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.42), inset 0 -1px 1px rgba(144,187,252,.3),
              0 8px 22px -8px rgba(47,125,246,.6), 0 1px 3px rgba(0,0,0,.4);
}
.nav a::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: -1; opacity: 0;
  background: radial-gradient(120% 70% at 20% 0%, rgba(255,255,255,.18), transparent 55%),
              radial-gradient(80% 60% at 100% 100%, rgba(144,187,252,.08), transparent 60%);
  transition: opacity .25s;
}
.nav a.active::after { opacity: 1; }
.nav-label { white-space: nowrap; }
.nav a .count { margin-left: auto; font-family: var(--mono); font-weight: 600; }
.topbar:not(:hover):not(:focus-within) .nav a .count {
  position: absolute; left: 22px; top: 1px; transform: none; margin: 0;
  font-size: 9.5px; padding: 0 4px; min-width: 15px; line-height: 15px; text-align: center;
}
/* Route icons: CSS masks keyed off href (the Payroll technique). currentColor
   tints them, so hover/active come for free. The fallback dot is declared on
   the <a>, never on ::before — a custom property set directly on the pseudo
   would shadow every per-href override. */
.nav a { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3C/svg%3E"); }
.nav a::before, .topbar:not(:hover):not(:focus-within) .nav a::before {
  content: ""; flex: 0 0 16px; width: 16px; height: 16px; font-size: 0; opacity: .8;
  background: currentColor;
  -webkit-mask: var(--glyph) center / contain no-repeat; mask: var(--glyph) center / contain no-repeat;
}
.nav a:hover::before, .nav a.active::before { opacity: 1; }
.nav a[href="/dashboard"]    { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='8' height='10' rx='1.5'/%3E%3Crect x='13' y='3' width='8' height='6' rx='1.5'/%3E%3Crect x='13' y='11' width='8' height='10' rx='1.5'/%3E%3Crect x='3' y='15' width='8' height='6' rx='1.5'/%3E%3C/svg%3E"); }
.nav a[href="/sales"]        { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 17l6-6 4 4 8-8'/%3E%3Cpath d='M15 7h6v6'/%3E%3C/svg%3E"); }
.topbar[data-role="agent"] .nav a[href="/sales"] { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='8' cy='7.5' r='3'/%3E%3Cpath d='M2.5 19c0-3 2.5-5.5 5.5-5.5'/%3E%3Cpath d='M13 20v-4M17 20v-8M21 20v-12'/%3E%3C/svg%3E"); }
.nav a[href="/sales/new"]    { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.5' y='3.5' width='17' height='17' rx='3'/%3E%3Cpath d='M12 8v8M8 12h8'/%3E%3C/svg%3E"); }
.nav a[href="/processing"]   { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 11a8 8 0 0 0-14.5-4.5L4 8'/%3E%3Cpath d='M4 4v4h4'/%3E%3Cpath d='M4 13a8 8 0 0 0 14.5 4.5L20 16'/%3E%3Cpath d='M20 20v-4h-4'/%3E%3C/svg%3E"); }
.nav a[href="/tracking"]     { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s7-6.2 7-11.5A7 7 0 0 0 5 9.5C5 14.8 12 21 12 21z'/%3E%3Ccircle cx='12' cy='9.5' r='2.5'/%3E%3C/svg%3E"); }
.nav a[href="/delivery"]     { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6h11v10h-11zM13.5 9.5h4l3 3.5v3h-7'/%3E%3Ccircle cx='6.5' cy='17.5' r='1.8'/%3E%3Ccircle cx='17' cy='17.5' r='1.8'/%3E%3C/svg%3E"); }
.nav a[href="/followups"]    { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 4h3l2 5-2.5 1.5a11 11 0 0 0 5 5L14 13l5 2v3a2 2 0 0 1-2 2A15 15 0 0 1 3 6a2 2 0 0 1 2-2z'/%3E%3Cpath d='M15 3h6v6M21 3l-6 6'/%3E%3C/svg%3E"); }
.nav a[href="/verification"] { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3l7 3v5c0 4.5-3 8.2-7 10-4-1.8-7-5.5-7-10V6z'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E"); }
.nav a[href="/trackus"]      { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 21V4'/%3E%3Cpath d='M5 4h13l-2.5 4L18 12H5'/%3E%3C/svg%3E"); }
.nav a[href="/admin"]        { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='10' cy='8' r='3.5'/%3E%3Cpath d='M3.5 20c0-3.6 2.9-6.5 6.5-6.5 1.2 0 2.3.3 3.2.9'/%3E%3Cpath d='M18 13l3 1.2v2.4c0 2-1.3 3.4-3 4-1.7-.6-3-2-3-4v-2.4z'/%3E%3C/svg%3E"); }
.topbar[data-mode="returns"] .nav a[href="/admin"] { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h10M18 7h2M4 17h4M12 17h8'/%3E%3Ccircle cx='16' cy='7' r='2'/%3E%3Ccircle cx='10' cy='17' r='2'/%3E%3C/svg%3E"); }
.nav a[href="/admin/activity"] { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12h4l3-7 4 14 3-7h4'/%3E%3C/svg%3E"); }
.nav a[href="/returns"]      { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 14 4 9l5-5'/%3E%3Cpath d='M4 9h10.5a5.5 5.5 0 0 1 0 11H11'/%3E%3C/svg%3E"); }
.nav a[href="/returns/labels"] { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12V4h8l10 10-8 8z'/%3E%3Ccircle cx='7.5' cy='8.5' r='1.3'/%3E%3C/svg%3E"); }
.nav a[href="/returns/closed"] { --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='m8 12.5 2.8 2.8L16 10'/%3E%3C/svg%3E"); }

/* Rail footer: 28px initials avatar + name / role line + Sign out ghost. */
.team-badge { font-size: 11px; padding: 4px 10px; border-color: var(--glass-divider); background: transparent; margin: 0 0 10px; align-self: flex-start; white-space: nowrap; }
.who {
  flex-direction: row; align-items: center; gap: 9px; margin-top: 0;
  padding: 12px 8px 0; border-top: 1px solid var(--glass-divider);
}
.topbar:not(:hover):not(:focus-within) .who { border-top: 1px solid var(--glass-divider); align-items: center; padding: 12px 4px 0; }
.nav + .dupcheck, .nav + .team-badge, .dupcheck + .team-badge { margin-top: auto; }
.who-avatar {
  flex: 0 0 28px; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  background: var(--accent-900); color: var(--accent-300); font-size: 10.5px; font-weight: 600; letter-spacing: .02em;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 0 0 1px rgba(255,255,255,.08);
}
.who > span { flex: 1 1 auto; gap: 1px; font-size: 12.5px; line-height: 1.25; color: var(--text); overflow: hidden; }
.who-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.who .role { font-size: 10.5px; letter-spacing: .04em; color: var(--t45); }
.who .btn, .who .btn-ghost { flex: 0 0 auto; align-self: center; font-size: 12px; padding: 5px 11px; }

/* ── 15. Per-screen composition ───────────────────────────────────────────── */
/* New sale (14b/15p/15q): centred 640px form card, footer row with the primary right. */
.wrap-form { display: grid; justify-content: center; align-content: start; }
.wrap-form > * { width: 640px; max-width: 100%; }
.wrap-form .page-head { margin-bottom: 22px; }
.wrap-form .panel-body { padding: 24px 26px; }
.wrap-form .grid-2 { gap: 0 14px; }
.wrap-form .field label { margin-bottom: 0; }
.form-foot { display: flex; justify-content: flex-end; border-top: 1px solid var(--glass-divider); padding-top: 16px; margin-top: 4px; }
.seg-field { align-items: flex-start; }
.seg-field .seg { margin: 0; }
.field .seg-opt { text-transform: none; letter-spacing: 0; font-size: 12.5px; font-weight: 500; color: rgba(230,235,244,.6); }
/* Processing (14c): the working-on card. */
.work-list { padding: 18px 20px; display: flex; flex-direction: column; gap: 14px; }
.work-card { display: flex; flex-direction: column; gap: 12px; }
.work-card + .work-card { border-top: 1px solid var(--glass-divider); padding-top: 14px; }
.work-top { display: flex; gap: 14px; align-items: flex-start; }
.work-top > div:first-child { margin-right: auto; min-width: 0; }
.work-name { font-size: 14px; }
.work-addr { font-size: 11.5px; color: var(--t45); margin-top: 3px; }
.work-phone { font-family: var(--mono); font-size: 12px; color: rgba(230,235,244,.6); margin-top: 3px; }
.work-svc { text-align: right; flex: none; font-size: 13px; font-weight: 600; }
.work-held { font-size: 11.5px; color: #fbbf24; margin-top: 3px; font-weight: 400; }
.work-card .btn-row { gap: 8px; }
.work-card .btn-row .btn-ghost { margin-left: auto; }
/* Drill-down (8a): the 7-day bars. */
.spark { height: 150px; padding: 20px 24px 16px; gap: 22px; }
.spark-n { font-size: 11px; color: rgba(230,235,244,.6); }
.spark-d { font-size: 10.5px; letter-spacing: 0; text-transform: none; color: rgba(230,235,244,.4); }
.spark-bar i { background: rgba(47,125,246,.35); border-radius: 5px 5px 0 0; max-width: 52px; margin: 0 auto; }
.spark-col:hover .spark-bar i { background: rgba(47,125,246,.55); }
.spark-col:last-child .spark-bar i { background: var(--accent); }
.spark-col:last-child .spark-n, .spark-col:last-child .spark-d { color: var(--accent-300); }
/* Leaderboard (9c). */
.lb-rank { color: var(--accent-300); font-weight: 600; }
.bar { background: rgba(47,125,246,.12); }
.bar i { background: var(--accent); }
/* Users & access expander (12b) + activity log (13b). */
.trail-cell {
  padding: 20px 24px !important; background: rgba(19,31,56,.4);
  border: 1px solid rgba(47,125,246,.3); border-top: 0; border-radius: 0 0 12px 12px;
}
.trail-cell .trail-head { padding: 0 0 16px; }
.trail-cell .trail-head h3 { font-size: 13px; font-weight: 600; color: var(--t50); }
.trail-row { grid-template-columns: 170px 110px 1fr; padding: 9px 4px; font-size: 12.5px; }
.trail-row + .trail-row { background: none; border-top: 1px solid var(--glass-divider); }
.trail-at { font-size: 11.5px; color: var(--t50); }
.trail-body { color: rgba(230,235,244,.75); }
.trail-body .t-strong { color: var(--text); }
.trail-filters, .filter-row { border-bottom-color: var(--glass-divider); padding: 10px 20px; }
.panel-list tbody td { padding: 10px 14px; }
.panel-list td:last-child .btn { background: none; border: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; color: #4f95f7; padding: 0; font-size: 12px; }
.panel-list td:last-child .btn:hover { transform: none; filter: none; color: var(--accent-hover); }
/* Track US (5g/15f): the inline <style> in trackus.ejs is out-specified here. */
.muted { color: var(--t45); }
.small { font-size: 12px; }
#todayGroup .panel-head .muted { font-family: var(--mono); }
.ta-r { text-align: right; }
.emailbox .panel-head h3 { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
/* Sale detail (5c): the details grid. */
.sale-detail.grid-2 { gap: 22px 40px; }
.sale-detail dt { margin-top: 0; }
.sale-detail dd { margin-top: 5px; font-size: 14px; }
/* Returns (15a–15g): work-screen tables, lead pool grid. */
#leadpool .panel-body > .grid-2 { grid-template-columns: 1.3fr 1fr; gap: 22px; }
#leadpool .btn-row { gap: 8px; flex-wrap: wrap; align-items: center; }
#leadpool .tablewrap { border-top: 1px solid var(--glass-divider); }
.row { display: flex; gap: 8px; align-items: center; }
.dupcheck #dupq { border-radius: 10px; }

/* ── 16. Motion ───────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .stat:hover, button:hover, .btn:hover, .nav a:active, a.stat:active, .notes-fab:hover { transform: none; filter: none; }
  .signing-in .zp-bar { animation: none; }
}
@media (max-width: 1180px) {
  .wrap { padding: 20px 18px 40px; }
  .wrap-form > * { width: 100%; }
}

/* ── GLASS FIX-UPS (Cael, 2026-09-26, after visual review) ─────────────────
   1. Link tiles (Sales / Delivery / Follow-ups filters are <a class="stat">) were
      `display:block` from the 2026-08-06 polish pass, so the flex `order` that
      puts the LABEL ABOVE the figure never applied to them — number-first on
      those screens, label-first everywhere else. Same box for every tile now.
   2. The duplicate-checker's submit is `.btn-ghost`, not `.btn`, so the resting
      rail never hid it and the pill poked out of the 64px rail. */
a.stat, a.stat.is-active { display: flex; flex-direction: column; }
.topbar:not(:hover):not(:focus-within) .dupcheck :is(#dupq, .btn, .btn-ghost, button[type="submit"], .dupcheck-out) { display: none; }
/* 3. Rail label fallback: the label fade relies on app.js wrapping each link's text in
      .nav-label. A page that reaches the rail before app.js runs (or without it) must
      still rest icon-only, so a link with no wrapper collapses its text the old way. */
.topbar:not(:hover):not(:focus-within) .nav a:not(:has(.nav-label)) { font-size: 0; }
/* 4. Status pills `neutral` (Pending / Call back) and `info` (In process / Processed) come from
      lib/statuses.js STATUS_TONE and NEVER had a rule — they rendered as bare outlines while the
      mockup tints every status (5b: Pending slate, Processed green, In process amber). Slate for
      the neutral bucket, the PROCESSED teal (the tile colour for the same status) for info. */
.pill.neutral { color: #cbd5e1; background: rgba(148,163,184,.18); }
.pill.info    { color: var(--st-done); background: color-mix(in oklab, var(--st-done) 15%, transparent); }

/* ── ZED shell embedded mode (2026-09-30) ─────────────────────────────────────────────────────
   Added to <html> by a one-line detector when this app is framed inside app.zedenterprises.net.
   Hides ONLY the inner wordmark (the shell already shows one); the app's own nav, refresh and
   logout stay exactly where they are. A direct visit never gets the class, so nothing changes there. */
.embedded .topbar .brand { display: none; }
