/* Milestone Zen platform — dashboard styles.
   Brand theme (milestonetax.com): white background, dark ink, orange #ff6b04
   accents. Switched from the original dark look to light on 2026-07-21 (per
   Edwin). Good/bad delta colors stay green/red (semantic), tuned for white.
   Almost everything is driven by the :root vars + color-mix(var(--ink) …);
   a few dark-assuming hardcoded colors (team badges, dots) are set below. */

:root {
  --page:            #ffffff;
  --surface:         #f4f4f3;
  --ink:             #1a1a1a;
  --ink-2:           #524f4a;
  --ink-muted:       #736f68;
  --hairline:        #e5e3df;
  --border:          rgba(0, 0, 0, 0.10);
  --accent:          #ff6b04;
  --accent-ink:      #c25708;
  --good:            #0b7a0b;
  --bad:             #cc2b2b;
  --badge-bg:        #eaf5ec;
  --badge-border:    #bfe0c8;
  --stale-bg:        #fdf1e3;
  --stale-border:    #f0d6b3;
}

/* Dark theme — applied when <html data-theme="dark"> (top-right toggle).
   Restores the original committed dark look; overrides the light :root above.
   The user's choice is saved in localStorage['zenTheme'] and applied before
   first paint by an inline <head> script, so there's no flash. */
:root[data-theme="dark"] {
  --page:            #000000;
  --surface:         #171717;
  --ink:             #ffffff;
  --ink-2:           #c9c6c0;
  --ink-muted:       #8f8b84;
  --hairline:        #2c2a27;
  --border:          rgba(255, 255, 255, 0.09);
  --accent:          #ff6b04;
  --accent-ink:      #ff8044;
  --good:            #0ca30c;
  --bad:             #e66767;
  --badge-bg:        #17211a;
  --badge-border:    #2a4030;
  --stale-bg:        #2a1c0e;
  --stale-border:    #4a3218;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.45;
}

/* ---------- Header ---------- */
.site-header {
  position: relative;
  background: var(--surface);
  border-bottom: 1px solid var(--hairline);
  border-top: 3px solid var(--accent);
  padding: 18px 24px 14px;
  text-align: center;
}
.site-header .logo {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0;
}
.brand-accent { color: var(--accent); }
.site-header .tagline {
  margin: 2px 0 0;
  color: var(--ink-2);
  font-size: 14px;
}

/* ---------- Layout ---------- */
.layout {
  display: flex;
  min-height: calc(100vh - 80px);
}
.sidebar {
  flex: 0 0 230px;
  background: var(--surface);
  border-right: 1px solid var(--hairline);
  padding: 20px 14px;
}
.sidebar h2 {
  font-size: 16px;
  margin: 0 0 10px 8px;
}
.sidebar .nav-group-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 18px 8px 6px;
}
.sidebar .nav-user {
  padding: 2px 10px 6px;
  font-size: 12px;
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar a {
  display: block;
  padding: 8px 10px;
  border-radius: 8px;
  color: var(--ink-2);
  text-decoration: none;
  font-weight: 500;
}
.sidebar a.active {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent-ink);
  font-weight: 600;
}
.sidebar a:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.sidebar a.disabled {
  color: var(--ink-muted);
  cursor: default;
  pointer-events: none;
}
.sidebar .soon {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-muted);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 1px 6px;
  margin-left: 6px;
}

.main {
  flex: 1;
  padding: 22px 26px 48px;
  min-width: 0;
}

/* ---------- Collapsible sidebar ---------- */
.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 10px;
}
.sidebar-head h2 { margin: 0 0 0 8px; }
.sidebar-toggle,
.sidebar-show {
  border: 1px solid var(--hairline);
  background: var(--surface);
  color: var(--ink-2);
  border-radius: 8px;
  cursor: pointer;
  font: inherit;
  line-height: 1;
}
.sidebar-toggle { padding: 5px 9px; font-size: 15px; }
.sidebar-toggle:hover { color: var(--ink); border-color: var(--accent); }
.sidebar-show {
  display: none;
  position: fixed;
  top: 14px;
  left: 14px;
  z-index: 50;
  padding: 8px 12px;
  font-size: 16px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
}
.sidebar-show:hover { color: var(--ink); border-color: var(--accent); }
html.sidebar-collapsed .sidebar { display: none; }
html.sidebar-collapsed .sidebar-show { display: inline-flex; align-items: center; justify-content: center; }

/* ---------- Page head ---------- */
.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.page-head h1 { font-size: 22px; margin: 0; }
.page-head .page-date { color: var(--ink-2); font-size: 13.5px; margin-top: 2px; }

.page-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.range-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
}
.range-select {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 8px 10px;
  font: inherit;
  font-size: 13.5px;
  cursor: pointer;
}
.range-select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ---------- Lead-source multi-select ---------- */
.src-dropdown { position: relative; }
.src-button {
  background: var(--surface);
  color: var(--ink-2);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 8px 12px;
  font: inherit;
  font-size: 13.5px;
  cursor: pointer;
}
.src-button strong { color: var(--ink); font-weight: 600; }
.src-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  min-width: 210px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  padding: 10px;
}
.src-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border-radius: 6px;
  font-size: 14px;
  color: var(--ink);
  cursor: pointer;
}
.src-option:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.src-actions {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--hairline);
}
.src-actions button {
  border: 0;
  border-radius: 7px;
  padding: 7px 12px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.src-clear { background: none; color: var(--ink-2); }
.src-clear:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.src-apply { background: var(--accent); color: #000; font-weight: 700; }
.src-apply:hover { filter: brightness(1.06); }

.refresh-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 13px;
  color: var(--ink-2);
  white-space: nowrap;
}
.refresh-badge strong { color: var(--ink); font-weight: 600; }
.refresh-badge.stale { background: var(--stale-bg); border-color: var(--stale-border); }
.refresh-badge button {
  border: 0;
  background: none;
  color: var(--accent-ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
}

/* ---------- Sections & tiles ---------- */
.section-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 26px 2px 10px;
}
.section-label .section-note {
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink-muted);
  margin-left: 8px;
  font-size: 12.5px;
}

.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  gap: 14px;
}

.tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px 18px 14px;
  min-height: 96px;
}
.tile .tile-label {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0 0 6px;
}
.tile .tile-value {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--ink);
}
.tile .tile-note {
  font-size: 12.5px;
  color: var(--ink-muted);
  margin: 5px 0 0;
}
.tile .tile-compare {
  font-size: 12.5px;
  color: var(--ink-2);
  margin: 6px 0 0;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.cmp-delta { font-weight: 600; }
.cmp-delta.trend-good, .cmp-delta.trend-up { color: var(--good); }
.cmp-delta.trend-bad, .cmp-delta.trend-down { color: var(--bad); }
.cmp-delta.trend-flat { color: var(--ink-muted); }

/* ---------- Leaderboard roll-up header ---------- */
.rollup {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
}
.rollup-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 13px 15px;
}
.rollup-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0 0 4px;
}
.rollup-total {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
}
.rollup-split {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin: 7px 0 0;
  font-size: 12px;
  color: var(--ink-muted);
}
.rollup-split b { color: var(--ink-2); font-weight: 600; }
.rollup-split span { display: inline-flex; align-items: center; gap: 5px; }
.rollup-split span::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.rollup-split .dot-devin::before { background: #3f7fd0; }
.rollup-split .dot-tank::before { background: var(--accent); }
.rollup-split .dot-recovery::before { background: #8250d8; }

/* ---------- Leaderboard podium ---------- */
.podium {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 14px;
}
.podium-card {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--hairline);
  border-radius: 12px;
  padding: 14px 16px;
}
.podium-card.place-1 { border-left-color: #e8b923; }
.podium-card.place-2 { border-left-color: #c7ccd1; }
.podium-card.place-3 { border-left-color: #cd7f32; }
.podium-medal {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 14px;
  color: #000;
  background: var(--hairline);
}
.place-1 .podium-medal { background: #e8b923; }
.place-2 .podium-medal { background: #c7ccd1; }
.place-3 .podium-medal { background: #cd7f32; color: #fff; }
.podium-body { min-width: 0; }
.podium-name { margin: 0; font-weight: 600; }
.podium-stat { margin: 3px 0 0; font-size: 14px; color: var(--ink-2); }
.podium-stat strong {
  font-size: 22px;
  font-weight: 700;
  color: var(--ink);
  margin-right: 3px;
}
.podium-sub { margin: 3px 0 0; font-size: 12px; color: var(--ink-muted); }

/* ---------- Leaderboard table ---------- */
.board {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 6px 0;
  overflow-x: auto;
}
.board table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.board th {
  text-align: left;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding: 10px 16px;
  border-bottom: 1px solid var(--hairline);
}
.board td {
  padding: 9px 16px;
  border-bottom: 1px solid var(--hairline);
  color: var(--ink);
}
.board tr:last-child td { border-bottom: 0; }
.board td.num, .board th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.board tbody tr:hover { background: color-mix(in srgb, var(--ink) 4%, transparent); }

.board td.rank {
  width: 46px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.board td.rank.rank-top { color: var(--accent-ink); font-weight: 700; }

.board td.emp { white-space: nowrap; }
.board .emp-name { font-weight: 600; }

/* ---- Raw Leads (admin) ----------------------------------------------
   A wide record table rather than a KPI board: tighter type, top-aligned
   cells so a multi-line description does not centre against short cells,
   and the description column allowed to wrap while everything else stays
   on one line. Uses only existing vars, so both themes follow. */
body[data-page="rawleads"] .board table { font-size: 13px; }
body[data-page="rawleads"] .board td { vertical-align: top; }
body[data-page="rawleads"] .board td.emp { font-size: 12px; }
.rl-desc {
  max-width: 460px;
  min-width: 220px;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
  line-height: 1.4;
  color: var(--ink-2);
}
.rl-pager {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  margin: 10px 0 12px;
}
.rl-count { font-size: 13px; color: var(--ink-2); }
.rl-page-link {
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-ink);
  text-decoration: none;
  padding: 4px 10px;
  border: 1px solid var(--hairline);
  border-radius: 6px;
}
.rl-page-link:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.rl-note {
  margin: 0 0 12px;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 13px;
  color: var(--ink-2);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid var(--hairline);
}

/* Per-column filter row. Every control is server-submitted through the one
   form wrapping the table, so filters and paging can never disagree. */
.rl-filter-row th {
  padding: 6px;
  background: color-mix(in srgb, var(--ink) 3%, transparent);
  border-bottom: 1px solid var(--hairline);
  vertical-align: top;
}
.rl-f {
  width: 100%;
  min-width: 74px;
  box-sizing: border-box;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 5px 7px;
  font: inherit;
  font-size: 12px;
  font-weight: 400;
}
.rl-f:focus-visible, .rl-op:focus-visible, .rl-num:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.rl-numf { display: flex; gap: 4px; }

/* Affiliate clients list: the Apply / Clear row under the column filters.
   Reuses .rl-filter-row and .rl-f above, which are deliberately not scoped to
   the Raw Leads page. */
.aff-filteracts th { padding: 8px 6px 10px; background: color-mix(in srgb, var(--ink) 3%, transparent);
  border-bottom: 1px solid var(--hairline); font-weight: 400; text-align: left; }
.aff-filteracts .aff-btn { padding: 5px 12px; font-size: 12px; }
.aff-filteracts .aff-back { margin-left: 12px; font-size: 12px; }
.aff-filteracts .aff-hint { margin-left: 14px; }
.aff-listfilters { margin: 0; }

/* The clients-list "Custom range" From/To boxes, under the Created dropdown.
   Stacked rather than side by side: two native date inputs in a row need
   ~270px and would widen the last column of a nine-column table for everyone,
   including the affiliates who never open it.
   ⚠⚠ display:flex HERE DEFEATS THE `hidden` ATTRIBUTE — the same trap
   .aff-modal hit, where the dialog was permanently on screen. [hidden] is
   restated below and must stay. */
.aff-daterange { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
.aff-daterange[hidden] { display: none; }
.aff-daterange label { display: flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 400; color: var(--ink-2); white-space: nowrap; }
.aff-daterange label span { min-width: 32px; }
.aff-daterange .rl-f { min-width: 0; }

/* ---- Settled / Upcoming totals, beside the search box ---- */
.aff-searchrow { display:flex; align-items:flex-start; justify-content:space-between;
  gap:24px; flex-wrap:wrap; }
.aff-searchrow .aff-search { flex:1 1 380px; margin-bottom:0; }
.aff-txtotals { flex:0 1 auto; display:flex; align-items:flex-start; gap:28px;
  flex-wrap:wrap; }
.aff-txtile { display:flex; flex-direction:column; gap:2px; min-width:130px; }
.aff-txtile > span { font-size:.72rem; color:var(--ink-muted);
  text-transform:uppercase; letter-spacing:.06em; }
.aff-txtile > strong { font-size:1.25rem; font-weight:700; color:var(--good);
  line-height:1.15; }
.aff-txtile.is-upcoming > strong { color:var(--accent-ink); }
.aff-txtile > small { font-size:.72rem; color:var(--ink-muted); }
@media (max-width:900px) { .aff-txtotals { flex-basis:100%; } }

/* Intake form: the live Phase 1 fee under the Tax Authority boxes. It changes
   when both are ticked, so it is given a little weight rather than reading as
   another hint. */
.aff-feenote { margin-top: 8px; }
.aff-feenote strong { color: var(--accent-ink); font-size: .95rem; }
.aff-feenote small { display: block; margin-top: 2px; color: var(--ink-muted);
  font-size: .72rem; font-weight: 400; }
.rl-op, .rl-num {
  box-sizing: border-box;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 5px 4px;
  font: inherit;
  font-size: 12px;
  font-weight: 400;
}
.rl-op { width: 46px; cursor: pointer; }
.rl-num { width: 100%; min-width: 52px; }
.rl-descf { display: flex; gap: 6px; align-items: center; }
.rl-apply {
  background: var(--accent);
  color: #000;
  font-weight: 700;
  font-size: 12px;
  border: 0;
  border-radius: 6px;
  padding: 6px 12px;
  cursor: pointer;
  white-space: nowrap;
}
.rl-apply:hover { filter: brightness(1.06); }
.rl-clear {
  font-size: 12px;
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  padding: 6px 4px;
}
.rl-clear:hover { text-decoration: underline; }

.rl-export {
  font-size: 13px;
  font-weight: 700;
  color: #000;
  background: var(--accent);
  text-decoration: none;
  padding: 6px 12px;
  border-radius: 6px;
  white-space: nowrap;
}
.rl-export:hover { filter: brightness(1.06); }

/* Description preview + Expand toggle. */
.rl-expand {
  display: inline-block;
  margin-top: 3px;
  background: none;
  border: 1px solid var(--hairline);
  border-radius: 5px;
  color: var(--accent-ink);
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  padding: 1px 7px;
  cursor: pointer;
}
.rl-expand:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.team-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-2);
  vertical-align: middle;
}
.team-badge.team-tank {
  color: var(--accent-ink);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline));
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.team-badge.team-devin {
  color: #255fb0;
  border-color: #9dc0ef;
  background: rgba(60, 110, 190, 0.10);
}
.team-badge.team-recovery,
.team-badge.team-tim {
  color: #6f42c1;
  border-color: #d3c2f0;
  background: rgba(150, 110, 220, 0.10);
}

/* ---------- Team Lead Dashboard ---------- */
.team-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin: 6px 0 14px;
}
.team-name { font-size: 18px; font-weight: 600; margin: 0; }
.team-name .team-badge { margin-left: 0; font-size: 12px; padding: 2px 10px; }
.team-name strong { color: var(--accent-ink); }
.team-sub { color: var(--ink-muted); font-size: 13px; margin: 0; }
.team-stats { margin-bottom: 4px; }
.rec-link {
  color: var(--accent-ink);
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
}
.rec-link:hover { text-decoration: underline; }
.rec-link .ext { opacity: 0.5; font-size: 0.85em; }

/* Compact chrome on the team page so all four quadrants fit one view */
body[data-page="team"] .site-header { padding: 8px 24px 7px; }
body[data-page="team"] .site-header .logo { font-size: 20px; }
body[data-page="team"] .site-header .tagline { display: none; }
body[data-page="team"] .main { padding: 14px 22px 18px; }
body[data-page="team"] .page-head { margin-bottom: 8px; }
body[data-page="team"] .page-head h1 { font-size: 18px; }
body[data-page="team"] .team-head { margin: 4px 0 10px; }

/* 2×2 quadrant grid: Open ↖ · Failed ↗ · Contact-Made ↙ · Closed Won ↘ */
.team-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  align-items: start;
}
.quad {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  min-height: 0;
}
.quad-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--hairline);
  flex: 0 0 auto;
}
.quad-title {
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.quad-count { margin-left: 8px; color: var(--accent-ink); font-size: 15px; }
.quad-note { font-size: 11px; color: var(--ink-muted); white-space: nowrap; }
.quad-body { overflow: auto; max-height: 33vh; }
.quad-body table { width: 100%; border-collapse: collapse; font-size: 13px; }
.quad-body th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  text-align: left;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 7px 14px;
  border-bottom: 1px solid var(--hairline);
}
.quad-body td {
  padding: 5px 14px;
  border-bottom: 1px solid var(--hairline);
  color: var(--ink);
  white-space: nowrap;
}
.quad-body tr:last-child td { border-bottom: 0; }
.quad-body td.num, .quad-body th.num { text-align: right; font-variant-numeric: tabular-nums; }
.quad-body tbody tr:hover { background: color-mix(in srgb, var(--ink) 4%, transparent); }
.quad-body .board-empty { text-align: center; color: var(--ink-muted); padding: 18px; }

@media (max-width: 1000px) {
  .team-grid { grid-template-columns: 1fr; }
  .quad-body { max-height: 42vh; }
}

/* ---------- Announcements page ---------- */
.flash-ok {
  background: color-mix(in srgb, var(--good) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--good) 45%, var(--hairline));
  color: var(--ink);
  border-radius: 10px;
  padding: 10px 14px;
  margin-bottom: 16px;
  font-size: 14px;
}
.ann-form {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 6px;
}
.ann-input {
  flex: 1 1 320px;
  min-width: 200px;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 10px 12px;
  font: inherit;
}
.ann-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.ann-kind { flex: 0 0 auto; }
.ann-add {
  flex: 0 0 auto;
  border: 0;
  border-radius: 8px;
  background: var(--accent);
  color: #000;
  font: inherit;
  font-weight: 700;
  padding: 10px 16px;
  cursor: pointer;
}
.ann-add:hover { filter: brightness(1.06); }

.ann-list { display: flex; flex-direction: column; gap: 8px; }
.ann-item {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--ink-muted);
  border-radius: 10px;
  padding: 10px 14px;
}
.ann-item.ann-win { border-left-color: var(--accent); }
.ann-item.ann-warn { border-left-color: var(--bad); }
.ann-text { flex: 1 1 auto; font-weight: 600; }
.ann-item.ann-win .ann-text { color: var(--accent-ink); }
.ann-item.ann-warn .ann-text { color: var(--bad); }
.ann-when { color: var(--ink-muted); font-size: 12px; white-space: nowrap; }
.ann-del { margin: 0; }
.ann-remove {
  border: 1px solid var(--hairline);
  background: none;
  color: var(--ink-2);
  border-radius: 8px;
  width: 30px;
  height: 30px;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.ann-remove:hover { color: var(--bad); border-color: var(--bad); background: color-mix(in srgb, var(--bad) 12%, transparent); }

.board td.cancel.cancel-bad { color: var(--bad); font-weight: 600; }
.board td.cancel.cancel-good { color: var(--good); }
.board .board-empty {
  text-align: center;
  color: var(--ink-muted);
  padding: 22px 16px;
}

/* ---------- Leaderboard highlights ticker (scrolling marquee) ---------- */
.ticker {
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  margin-bottom: 8px;
  white-space: nowrap;
}
.ticker-track {
  display: inline-flex;
  align-items: center;
  animation-name: ticker-scroll;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform;
}
.ticker:hover .ticker-track { animation-play-state: paused; }
.ticker-item {
  display: inline-flex;
  align-items: center;
  padding: 6px 24px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-2);
  border-right: 1px solid var(--hairline);
}
.ticker-item.ticker-win { color: var(--accent-ink); }
.ticker-item.ticker-warn { color: var(--bad); }
@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* ---------- Leaderboard: compact "fits on one screen" layout ----------
   Scoped to the leaderboard page only (body[data-page="leaderboard"]) so the
   Business/Marketing dashboards keep their roomier spacing. Everything is
   tightened vertically so the roll-up + podium + full board fit without
   page scrolling on a normal display. */
body[data-page="leaderboard"] .site-header { padding: 8px 24px 7px; }
body[data-page="leaderboard"] .site-header .logo { font-size: 20px; }
body[data-page="leaderboard"] .site-header .tagline { display: none; }
body[data-page="leaderboard"] .main { padding: 12px 22px 14px; }
body[data-page="leaderboard"] .page-head { margin-bottom: 8px; }
body[data-page="leaderboard"] .page-head h1 { font-size: 18px; }
body[data-page="leaderboard"] .page-head .page-date { font-size: 12px; }
body[data-page="leaderboard"] .section-label { margin: 6px 2px 4px; }

body[data-page="leaderboard"] .rollup { gap: 8px; }
body[data-page="leaderboard"] .rollup-card { padding: 8px 12px; }
body[data-page="leaderboard"] .rollup-label { font-size: 10px; margin-bottom: 2px; }
body[data-page="leaderboard"] .rollup-total { font-size: 20px; }
body[data-page="leaderboard"] .rollup-split { margin-top: 3px; }

body[data-page="leaderboard"] .podium { gap: 10px; }
body[data-page="leaderboard"] .podium-card { padding: 8px 12px; gap: 10px; }
body[data-page="leaderboard"] .podium-medal { width: 32px; height: 32px; font-size: 12px; }
body[data-page="leaderboard"] .podium-name { font-size: 14px; }
body[data-page="leaderboard"] .podium-stat { font-size: 13px; margin-top: 1px; }
body[data-page="leaderboard"] .podium-stat strong { font-size: 18px; }
body[data-page="leaderboard"] .podium-sub { font-size: 11px; margin-top: 1px; }

body[data-page="leaderboard"] .board th { padding: 6px 14px; }
body[data-page="leaderboard"] .board td { padding: 3px 14px; font-size: 13px; }

/* ---------- Error strip ---------- */
.error-strip {
  background: var(--stale-bg);
  border: 1px solid var(--stale-border);
  border-radius: 10px;
  padding: 12px 16px;
  color: var(--ink-2);
  margin-bottom: 16px;
}

/* ---------- Login ---------- */
.login-body {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
.login-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 36px 40px;
  width: min(400px, 92vw);
  text-align: center;
}
.brand-mark {
  width: 52px;
  height: 52px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: var(--accent);
  color: #000;
  font-size: 26px;
  font-weight: 700;
  line-height: 52px;
}
.login-card h1 { font-size: 21px; margin: 0 0 4px; }
.login-sub { color: var(--ink-2); margin: 0 0 22px; font-size: 14px; }
.login-error {
  background: var(--stale-bg);
  border: 1px solid var(--stale-border);
  border-radius: 8px;
  padding: 9px 12px;
  font-size: 13.5px;
  color: var(--ink-2);
}
.login-card label {
  display: block;
  text-align: left;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
  margin-bottom: 6px;
}
.login-card input[type="email"],
.login-card input[type="password"] {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: var(--page);
  color: var(--ink);
  font: inherit;
  margin-bottom: 16px;
}
.login-card button {
  width: 100%;
  padding: 11px;
  border: 0;
  border-radius: 8px;
  background: var(--accent);
  color: #000;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.login-card button:hover { filter: brightness(1.06); }

/* ---------- Utility ---------- */
.hidden { display: none; }

.logout-form { margin: 0; }
button.linklike {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}
button.linklike:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }

/* ---------- Theme toggle (top-right, all pages) ---------- */
.theme-toggle {
  border: 1px solid var(--hairline);
  background: var(--surface);
  color: var(--ink-2);
  border-radius: 8px;
  padding: 6px 10px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  z-index: 40;
}
.theme-toggle:hover { color: var(--ink); border-color: var(--accent); }
.site-header .theme-toggle { position: absolute; top: 50%; right: 16px; transform: translateY(-50%); }
.login-body .theme-toggle { position: absolute; top: 16px; right: 18px; }

/* ---------- Sortable table headers (leaderboard + team dashboard) ---------- */
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--ink); }
th.sort-asc::after  { content: ' \25B2'; font-size: 0.8em; opacity: 0.75; }
th.sort-desc::after { content: ' \25BC'; font-size: 0.8em; opacity: 0.75; }

/* ---------- Team SMS — shared SMS inbox (body[data-page="sms"]) ----------
   Two panes that fill the viewport: the page itself never scrolls, the thread
   list and the message stream scroll independently. That needs an unbroken
   flex chain — body → .layout → .main → #sms-app → .sms-wrap → .quad →
   .quad-body — and EVERY link in it needs min-height:0, otherwise a flex item
   refuses to shrink below its content and the inner scrollbars never appear.
   Every colour here is an existing var (or a color-mix of one), so the
   dark-override block below needs no new entries. */

/* Compact chrome — same recipe as body[data-page="team"] above. */
body[data-page="sms"] .site-header { padding: 8px 24px 7px; }
body[data-page="sms"] .site-header .logo { font-size: 20px; }
body[data-page="sms"] .site-header .tagline { display: none; }
body[data-page="sms"] .main { padding: 12px 20px 14px; }
body[data-page="sms"] .page-head { margin-bottom: 8px; }
body[data-page="sms"] .page-head h1 { font-size: 18px; }
body[data-page="sms"] .page-head .page-date { font-size: 12px; }

/* Full-height chain. */
body[data-page="sms"] {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}
body[data-page="sms"] .site-header { flex: 0 0 auto; }
body[data-page="sms"] .layout {
  flex: 1 1 auto;
  min-height: 0;              /* beats .layout's hardcoded calc(100vh - 80px) */
  overflow: hidden;
}
body[data-page="sms"] .sidebar { overflow-y: auto; }
body[data-page="sms"] .main {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
body[data-page="sms"] .page-head,
body[data-page="sms"] .flash-ok,
body[data-page="sms"] .error-strip { flex: 0 0 auto; }
/* Lift the team page's 33vh cap — here the panes own the height. */
body[data-page="sms"] .quad-body {
  max-height: none;
  min-height: 0;
  flex: 1 1 auto;
}

#sms-app {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
.sms-wrap {
  display: grid;
  grid-template-columns: minmax(220px, 320px) minmax(0, 1fr);
  gap: 12px;
  flex: 1 1 auto;
  min-height: 0;
}
.sms-wrap > .quad { min-height: 0; min-width: 0; }

/* ----- Left pane: search, filters, conversation list ----- */
.sms-tools,
.sms-filters {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  padding: 8px 12px;
  border-bottom: 1px solid var(--hairline);
}
.sms-filters { gap: 5px; padding: 7px 12px; }
#sms-search {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 7px 10px;
  font: inherit;
  font-size: 13px;
}
#sms-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sms-go {
  flex: 0 0 auto;
  border: 1px solid var(--hairline);
  background: var(--page);
  color: var(--ink-2);
  border-radius: 8px;
  padding: 7px 11px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.sms-go:hover { color: var(--ink); border-color: var(--accent); }
.sms-filter {
  padding: 3px 11px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
  text-decoration: none;
}
.sms-filter:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.sms-filter.sms-filter-on {
  color: var(--accent-ink);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline));
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.sms-threads { overflow-y: auto; }
.sms-thread {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 1px 8px;
  padding: 8px 12px 9px;
  border-bottom: 1px solid var(--hairline);
  border-left: 3px solid transparent;
  color: var(--ink);
  text-decoration: none;
}
.sms-thread:hover { background: color-mix(in srgb, var(--ink) 4%, transparent); }
.sms-thread.sms-active {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-left-color: var(--accent);
}
.sms-thread-name {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: 13.5px;
  font-weight: 600;
}
.sms-thread-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sms-thread-when {
  font-size: 11.5px;
  color: var(--ink-muted);
  white-space: nowrap;
  text-align: right;
}
.sms-thread-prev {
  grid-column: 1;
  font-size: 12.5px;
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sms-thread .sms-prev-dir { color: var(--ink-muted); }
.sms-thread.sms-unread .sms-thread-prev { color: var(--ink); font-weight: 600; }
.sms-thread .sms-badge { grid-column: 2; justify-self: end; }

.sms-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 21px;
  padding: 1px 7px;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--hairline));
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--accent-ink);
  font-size: 11px;
  font-weight: 700;
  line-height: 1.5;
}
.sms-chip {
  flex: 0 0 auto;
  padding: 0 7px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: var(--page);
  color: var(--ink-muted);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.sms-chip-bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, var(--hairline)); }
.sms-chip-warn { color: var(--accent-ink); border-color: var(--stale-border); background: var(--stale-bg); }
/* ================= Today's Showdown (Leaderboard overlay) ================= */
.sd-open-btn {
  cursor: pointer;
  margin-left: 10px;
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--accent);
  color: #000;
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
.sd-open-btn:hover { filter: brightness(1.06); }

.sd-overlay {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: color-mix(in srgb, var(--page) 82%, transparent);
  backdrop-filter: blur(3px);
  animation: sd-fade .18s ease-out;
}
.sd-overlay.hidden { display: none; }
@keyframes sd-fade { from { opacity: 0; } to { opacity: 1; } }

/* ---- Reveal choreography -------------------------------------------------
   Everything below animates transform/opacity only (GPU-friendly, no layout
   thrash) and replays automatically on each reveal, because .hidden toggles
   display:none which resets CSS animations. Order:
     card pops -> sides fly in -> VS pops -> scores count up (JS)
     -> reps stagger -> crown drops -> bar fills -> winner keeps a slow pulse.
   All of it is switched off under prefers-reduced-motion at the end.       */

@keyframes sd-card-in {
  from { opacity: 0; transform: translateY(22px) scale(.94); }
  60%  { transform: translateY(-4px) scale(1.01); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes sd-from-left  { from { opacity: 0; transform: translateX(-34px); } to { opacity: 1; transform: none; } }
@keyframes sd-from-right { from { opacity: 0; transform: translateX(34px); }  to { opacity: 1; transform: none; } }
@keyframes sd-pop {
  0%   { opacity: 0; transform: scale(.4) rotate(-12deg); }
  70%  { opacity: 1; transform: scale(1.18) rotate(3deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}
@keyframes sd-rise { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }
@keyframes sd-crown-drop {
  0%   { opacity: 0; transform: translateY(-16px) scale(.7); }
  65%  { opacity: 1; transform: translateY(3px) scale(1.08); }
  100% { opacity: 1; transform: none; }
}
/* The winning card breathes so the room can see who is ahead from across the
   floor without reading the numbers.
   INSET glow, not an outward one: .sd-card sets overflow:auto and the winning
   side sets overflow:hidden (for the sheen), both of which clip an outward
   box-shadow. Inset shadows, border-color and background are never clipped —
   and none of them touch `transform`, so this can run alongside the entrance
   animation without the two fighting over the same property. */
@keyframes sd-pulse-tank {
  0%, 100% {
    border-color: color-mix(in srgb, var(--accent) 55%, var(--hairline));
    background: color-mix(in srgb, var(--accent) 7%, var(--page));
    box-shadow: inset 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent);
  }
  50% {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 19%, var(--page));
    box-shadow: inset 0 0 30px 3px color-mix(in srgb, var(--accent) 32%, transparent);
  }
}
@keyframes sd-pulse-devin {
  0%, 100% {
    border-color: rgba(63, 127, 208, .55);
    background: color-mix(in srgb, #3f7fd0 7%, var(--page));
    box-shadow: inset 0 0 0 0 rgba(63, 127, 208, 0);
  }
  50% {
    border-color: #3f7fd0;
    background: color-mix(in srgb, #3f7fd0 19%, var(--page));
    box-shadow: inset 0 0 30px 3px rgba(63, 127, 208, .32);
  }
}
/* The score itself beats in time. Nothing else animates .sd-score's transform,
   so this is safe to run forever. */
@keyframes sd-score-beat {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.07); }
}
/* The crown badge glows on its own cycle. box-shadow only — .sd-crown's transform
   is already owned by sd-crown-drop, and two animations on one property means the
   later one silently wins. */
   Keep the spread under ~14px: the winning card is overflow:hidden and its top
   padding is 16px, so a wider glow gets clipped square across the top. */
@keyframes sd-crown-glow-tank {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); }
  50%      { box-shadow: 0 0 12px 2px color-mix(in srgb, var(--accent) 50%, transparent); }
}
@keyframes sd-crown-glow-devin {
  0%, 100% { box-shadow: 0 0 0 0 rgba(63, 127, 208, .6); }
  50%      { box-shadow: 0 0 12px 2px rgba(63, 127, 208, .5); }
}
/* One light sweep across the winning card as it lands. */
@keyframes sd-sheen { from { transform: translateX(-130%) skewX(-18deg); } to { transform: translateX(330%) skewX(-18deg); } }

.sd-card { animation: sd-card-in .5s cubic-bezier(.22, 1.2, .36, 1) both; }
.sd-head { animation: sd-rise .45s ease-out .06s both; }
.sd-side { animation: sd-rise .45s ease-out both; }
.sd-side.sd-tank  { animation-name: sd-from-left;  animation-delay: .14s; }
.sd-side.sd-devin { animation-name: sd-from-right; animation-delay: .14s; }
.sd-vs span { animation: sd-pop .5s cubic-bezier(.22, 1.4, .36, 1) .3s both; }
.sd-vs p { animation: sd-rise .4s ease-out .46s both; }
.sd-reps li { animation: sd-rise .34s ease-out both; }
.sd-reps li:nth-child(1) { animation-delay: .56s; }
.sd-reps li:nth-child(2) { animation-delay: .64s; }
.sd-reps li:nth-child(3) { animation-delay: .72s; }
.sd-reps li:nth-child(4) { animation-delay: .80s; }
.sd-month { animation: sd-rise .4s ease-out .5s both; }
.sd-bar   { animation: sd-rise .4s ease-out .8s both; }
.sd-foot  { animation: sd-rise .4s ease-out .88s both; }

.sd-crown { animation: sd-crown-drop .5s cubic-bezier(.22, 1.4, .36, 1) .74s both; }

.sd-side.sd-winning { position: relative; overflow: hidden; }
/* Entrance first, then the pulse takes over — they animate different properties
   (transform vs border/background/inset-shadow) so neither overrides the other. */
.sd-side.sd-tank.sd-winning  { animation: sd-from-left  .45s ease-out .14s both, sd-pulse-tank  2.2s ease-in-out .9s infinite; }
.sd-side.sd-devin.sd-winning { animation: sd-from-right .45s ease-out .14s both, sd-pulse-devin 2.2s ease-in-out .9s infinite; }
.sd-side.sd-winning .sd-score { animation: sd-score-beat 2.2s ease-in-out .9s infinite; }
.sd-side.sd-winning .sd-team { text-shadow: 0 0 18px color-mix(in srgb, currentColor 45%, transparent); }

/* Make the winner unmistakable from across the room: thicker frame, a larger
   glowing score, and a badge that pulses on its own cycle. */
.sd-side.sd-winning { border-width: 3px; }
.sd-side.sd-tank.sd-winning  .sd-score { text-shadow: 0 0 26px color-mix(in srgb, var(--accent) 55%, transparent); }
.sd-side.sd-devin.sd-winning .sd-score { text-shadow: 0 0 26px rgba(63, 127, 208, .55); }
.sd-side.sd-winning .sd-score { font-size: 78px; }
.sd-side.sd-tank.sd-winning  .sd-crown { animation: sd-crown-drop .5s cubic-bezier(.22, 1.4, .36, 1) .74s both, sd-crown-glow-tank  2.2s ease-in-out 1.3s infinite; }
.sd-side.sd-devin.sd-winning .sd-crown { animation: sd-crown-drop .5s cubic-bezier(.22, 1.4, .36, 1) .74s both, sd-crown-glow-devin 2.2s ease-in-out 1.3s infinite; }
.sd-side.sd-winning::after {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 42%; height: 100%;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ink) 12%, transparent), transparent);
  animation: sd-sheen 1.1s ease-out .55s 1 both;
  pointer-events: none;
}

/* The score is JS-animated (countUp), so it only needs to not jitter. */
.sd-score { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .sd-overlay, .sd-card, .sd-head, .sd-side, .sd-vs span, .sd-vs p, .sd-reps li,
  .sd-month, .sd-bar, .sd-foot, .sd-crown,
  .sd-side.sd-tank.sd-winning, .sd-side.sd-devin.sd-winning,
  .sd-side.sd-winning .sd-score,
  .sd-side.sd-tank.sd-winning .sd-crown, .sd-side.sd-devin.sd-winning .sd-crown,
  :root[data-theme="dark"] .sd-side.sd-devin.sd-winning {
    animation: none !important;
  }
  .sd-side.sd-winning::after { display: none; }
  .sd-bar-fill { transition: none; }
}

.sd-card {
  position: relative;
  width: min(1040px, 100%);
  max-height: 100%;
  overflow: auto;
  padding: 22px 26px 18px;
  border: 1px solid var(--border);
  border-radius: 16px;
  background: var(--surface);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .45);
}
.sd-close {
  position: absolute;
  top: 10px; right: 14px;
  border: 0; background: none; cursor: pointer;
  color: var(--ink-muted);
  font-size: 26px; line-height: 1;
  font-family: inherit;
}
.sd-close:hover { color: var(--ink); }

.sd-head { text-align: center; margin-bottom: 16px; }
.sd-head h2 {
  margin: 0;
  font-size: 30px;
  letter-spacing: .04em;
  color: var(--ink);
}
.sd-head h2 span { color: var(--accent-ink); }
.sd-head p { margin: 4px 0 0; font-size: 12.5px; color: var(--ink-muted); text-transform: uppercase; letter-spacing: .08em; }

.sd-body {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 14px;
  align-items: stretch;
}
.sd-side {
  padding: 16px 18px;
  border: 2px solid var(--hairline);
  border-radius: 14px;
  text-align: center;
  background: var(--page);
  transition: border-color .2s ease;
}
/* Team colours match the board badges: Tank orange, Devin blue. */
.sd-side.sd-tank.sd-winning  { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--page)); }
.sd-side.sd-devin.sd-winning { border-color: #3f7fd0;       background: color-mix(in srgb, #3f7fd0 8%, var(--page)); }
.sd-team {
  margin: 0 0 2px;
  font-size: 17px;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.sd-tank .sd-team  { color: var(--accent-ink); }
.sd-devin .sd-team { color: #255fb0; }
.sd-score { font-size: 68px; font-weight: 800; line-height: 1; color: var(--ink); }
.sd-score-label { font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-muted); }
.sd-month {
  display: flex;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 8px;
  font-size: 12px;
  color: var(--ink-2);
}
.sd-month strong { color: var(--ink); }
.sd-reps { list-style: none; margin: 12px 0 0; padding: 0; text-align: left; }
.sd-reps li {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 5px 2px;
  border-top: 1px solid var(--hairline);
  font-size: 13px;
}
.sd-reps li span { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-reps li b { color: var(--ink); }
.sd-reps li.sd-more span { color: var(--ink-muted); font-style: italic; }
.sd-crown {
  display: inline-block;
  margin: 0 0 10px;
  padding: 7px 20px;
  border-radius: 999px;
  background: var(--accent);
  color: #000;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.sd-devin .sd-crown { background: #3f7fd0; color: #fff; }
/* Rendered on BOTH sides and only made invisible on the loser, so the two cards'
   team names stay on the same baseline. display:none would shunt the losing
   card's whole contents up by the height of the badge. */
.sd-crown[hidden] { display: inline-block; visibility: hidden; }

.sd-vs {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  min-width: 92px;
}
.sd-vs span {
  display: flex; align-items: center; justify-content: center;
  width: 62px; height: 62px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--page);
  font-weight: 800;
  letter-spacing: .04em;
}
.sd-vs p { margin: 8px 0 0; font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-muted); text-align: center; }

.sd-bar {
  display: flex;
  height: 12px;
  margin-top: 16px;
  border-radius: 999px;
  overflow: hidden;
  background: #3f7fd0;                 /* the remainder IS Devin's share */
}
.sd-bar-fill { background: var(--accent); transition: width .4s ease; }

.sd-foot {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 10px;
  font-size: 11.5px;
  color: var(--ink-muted);
  letter-spacing: .05em;
  text-transform: uppercase;
}

@media (max-width: 820px) {
  .sd-body { grid-template-columns: 1fr; }
  .sd-vs { flex-direction: row; gap: 12px; min-width: 0; }
  .sd-vs span { width: 44px; height: 44px; font-size: 13px; }
  .sd-score { font-size: 52px; }
  .sd-head h2 { font-size: 23px; }
}

.sms-chip-good {
  color: var(--good);
  border-color: color-mix(in srgb, var(--good) 40%, var(--hairline));
  background: color-mix(in srgb, var(--good) 8%, transparent);
}

/* ----- "Mark as handled" ----- */
.sms-pane-actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}
.sms-handled-note {
  font-size: 11.5px;
  color: var(--ink-muted);
  white-space: nowrap;
}
.sms-handled-btn {
  cursor: pointer;
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--page);
  color: var(--ink-2);
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  white-space: nowrap;
}
.sms-handled-btn:hover { border-color: color-mix(in srgb, var(--good) 45%, var(--border)); color: var(--good); }
.sms-handled-btn:disabled { opacity: .55; cursor: default; }
.sms-handled-btn.is-handled {
  background: color-mix(in srgb, var(--good) 12%, transparent);
  border-color: color-mix(in srgb, var(--good) 45%, var(--border));
  color: var(--good);
}
@media (max-width: 900px) {
  .sms-handled-note { display: none; }   /* the chip in the list still says who */
}

/* ----- Right pane: head, stream, composer ----- */
.sms-pane { min-width: 0; }
.sms-pane-head { align-items: center; }
.sms-pane-id { min-width: 0; }
.sms-pane-head .quad-title {
  font-size: 15px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
}
#sms-thread-sub {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin: 2px 0 0;
  font-size: 12px;
  color: var(--ink-muted);
}
#sms-thread-sub .sms-sub-phone { font-variant-numeric: tabular-nums; }
.sms-back {
  display: none;
  align-items: center;
  margin-bottom: 2px;
  color: var(--accent-ink);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}

.sms-stream-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.sms-stream {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: 12px 14px 6px;
  overflow-y: auto;
  list-style: none;
}
/* Sticky day separator. No top margin on purpose: when it sticks, its own
   opaque background has to cover the whole band or bubbles show through
   above it. */
.sms-day {
  position: sticky;
  top: 0;
  z-index: 2;
  margin: 0 0 8px;
  padding: 7px 0 5px;
  background: var(--surface);
  color: var(--ink-muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-align: center;
}
/* Bodies are attacker-controlled text: pre-wrap, never nl2br, never linkified.
   The bubble is a flex column so the template's indentation whitespace is
   dropped instead of being preserved by pre-wrap. */
.sms-bubble {
  display: flex;
  flex-direction: column;
  margin: 0 0 10px;
  white-space: pre-wrap;
}
.sms-bubble.sms-in { align-items: flex-start; }
.sms-bubble.sms-out { align-items: flex-end; }
.sms-bubble-body {
  max-width: 78%;
  padding: 8px 12px;
  border-radius: 14px;
  font-size: 13.5px;
  line-height: 1.42;
  overflow-wrap: anywhere;
}
.sms-in .sms-bubble-body {
  background: var(--page);
  border: 1px solid var(--hairline);
  border-bottom-left-radius: 5px;
}
.sms-out .sms-bubble-body {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-bottom-right-radius: 5px;
}
.sms-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 3px 8px;
  margin: 3px 3px 0;
  font-size: 11px;
  color: var(--ink-muted);
  white-space: normal;
}
.sms-status {
  padding: 0 7px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-weight: 600;
}
.sms-status-ok { background: var(--badge-bg); border-color: var(--badge-border); color: var(--ink-2); }
.sms-status-bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, var(--hairline)); }
.sms-status-wait { color: var(--ink-muted); }
.sms-meta .sms-err { color: var(--bad); font-weight: 600; }
.sms-meta .sms-who { color: var(--ink-2); }
.sms-media {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-width: 78%;
  margin-top: 6px;
}
.sms-media img, img.sms-media {
  display: block;
  max-width: 210px;
  max-height: 210px;
  border: 1px solid var(--hairline);
  border-radius: 10px;
}
.sms-media .sms-file {
  padding: 6px 10px;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: var(--page);
  color: var(--accent-ink);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
  white-space: normal;
}

.sms-empty {
  margin: 0;
  padding: 22px 16px;
  color: var(--ink-muted);
  font-size: 13px;
  text-align: center;
}
#sms-empty {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
}
#sms-empty strong { color: var(--ink-2); font-size: 14px; }

.sms-banner {
  flex: 0 0 auto;
  margin: 0;
  padding: 9px 14px;
  border-top: 1px solid var(--hairline);
  background: var(--stale-bg);
  color: var(--ink-2);
  font-size: 12.5px;
}
.sms-banner.sms-blocked {
  background: color-mix(in srgb, var(--bad) 12%, transparent);
  color: var(--bad);
  font-weight: 600;
}
/* Advisory, not a blocker: amber, and it never disables the composer. Distinct
   from .sms-blocked so "be careful" never reads as "you cannot send". */
.sms-banner.sms-caution {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent-ink);
  border-top: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  font-weight: 600;
}
.sms-composer {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  gap: 10px;
  padding: 10px 12px;
  border-top: 1px solid var(--hairline);
}
#sms-body {
  flex: 1 1 auto;
  min-width: 0;
  height: 62px;
  resize: none;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 9px 11px;
  font: inherit;
  font-size: 13.5px;
}
#sms-body:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
#sms-body:disabled {
  background: var(--surface);
  color: var(--ink-muted);
  cursor: not-allowed;
}
.sms-composer-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  flex: 0 0 auto;
}
#sms-segments {
  font-size: 11px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
#sms-send {
  border: 0;
  border-radius: 10px;
  background: var(--accent);
  color: #000;
  font: inherit;
  font-weight: 700;
  padding: 9px 20px;
  cursor: pointer;
}
#sms-send:hover:enabled { filter: brightness(1.06); }
#sms-send:disabled {
  background: var(--surface);
  border: 1px solid var(--hairline);
  color: var(--ink-muted);
  cursor: not-allowed;
}

/* The shared .hidden utility must still beat the display: values set above —
   an id or a second class outranks a bare .hidden, so restate it here. */
#sms-empty.hidden,
#sms-banner.hidden,
#sms-caution.hidden,
#sms-handled-note.hidden,
#sms-handled-form.hidden,
#sms-unread.hidden,
#sms-composer.hidden,
.sms-badge.hidden,
.sms-chip.hidden,
.sms-thread.hidden,
.sms-media.hidden { display: none; }

/* Narrow: one column showing the list OR the open thread, never both.
   Driven by #sms-app[data-thread] — empty means "nothing open". */
@media (max-width: 900px) {
  body[data-page="sms"] .sms-wrap { grid-template-columns: minmax(0, 1fr); }
  body[data-page="sms"] #sms-app[data-thread=""] .sms-pane { display: none; }
  body[data-page="sms"] #sms-app:not([data-thread=""]) .sms-list { display: none; }
  body[data-page="sms"] .sms-back { display: inline-flex; }
  body[data-page="sms"] .sms-bubble-body,
  body[data-page="sms"] .sms-media { max-width: 88%; }
}

/* ---------- Dark-theme overrides for the few hardcoded (non-var) colors ---------- */
:root[data-theme="dark"] .team-badge.team-devin {
  color: #7fb2ff;
  border-color: #33507a;
  background: rgba(60, 110, 190, 0.13);
}
:root[data-theme="dark"] .team-badge.team-recovery,
:root[data-theme="dark"] .team-badge.team-tim {
  color: #c3a3ff;
  border-color: #4a3a6b;
  background: rgba(150, 110, 220, 0.14);
}
:root[data-theme="dark"] .rollup-split .dot-devin::before { background: #7fb2ff; }
:root[data-theme="dark"] .rollup-split .dot-recovery::before { background: #b98cff; }
/* Showdown: the Devin blues are raw hex tuned for a white page, and .sd-side sits
   on --page (#000 in dark). Re-state them with the same values the Devin badge and
   dot already use above, so all four stay in sync. */
:root[data-theme="dark"] .sd-devin .sd-team { color: #7fb2ff; }
:root[data-theme="dark"] .sd-bar { background: #7fb2ff; }
:root[data-theme="dark"] .sd-side.sd-devin.sd-winning {
  border-color: #7fb2ff;
  background: color-mix(in srgb, #7fb2ff 10%, var(--page));
}
/* The light-theme pulse uses #3f7fd0, which barely reads on a black page — give
   dark its own keyframes in the lighter blue the dark badge/dot already use. */
@keyframes sd-pulse-devin-dark {
  0%, 100% {
    border-color: rgba(127, 178, 255, .55);
    background: color-mix(in srgb, #7fb2ff 8%, var(--page));
    box-shadow: inset 0 0 0 0 rgba(127, 178, 255, 0);
  }
  50% {
    border-color: #7fb2ff;
    background: color-mix(in srgb, #7fb2ff 22%, var(--page));
    box-shadow: inset 0 0 30px 3px rgba(127, 178, 255, .34);
  }
}
:root[data-theme="dark"] .sd-side.sd-devin.sd-winning {
  animation: sd-from-right .45s ease-out .14s both, sd-pulse-devin-dark 2.2s ease-in-out .9s infinite;
}
:root[data-theme="dark"] .sd-devin .sd-crown { background: #7fb2ff; color: #000; }
:root[data-theme="dark"] .ann-remove:hover {
  color: #fff;
  background: color-mix(in srgb, var(--bad) 18%, transparent);
}

/* ---------- Small screens ---------- */
@media (max-width: 860px) {
  .layout { flex-direction: column; }
  .sidebar {
    flex: none;
    border-right: 0;
    border-bottom: 1px solid var(--hairline);
  }
  .refresh-badge { white-space: normal; }
}



/* First of the month gets a divider and a month name instead of a day number. */
.enroll-col.is-month .enroll-x { font-weight: 700; color: var(--ink); }

/* ---- Phase 1 enrollments per day (Business Overview) ---------------------
   Hand-rolled bars: the app is dependency-free and stays that way. A whole
   year of daily bars lives in a horizontal scroller; --bw is the per-bar width
   that zen.js changes on wheel-zoom. Only .enroll-barbox flexes, so a bar's
   height is a true percentage of the gridlines beside it. */
.enroll-wrap {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 0;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 12px 12px 8px;
  margin: 0 0 4px;
}
.enroll-axis {
  flex: 0 0 auto;
  width: 34px;
  height: 210px;
  padding-bottom: 20px;              /* matches .enroll-x height */
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-end;
  padding-right: 6px;
  font-size: 10px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.enroll-axis span { transform: translateY(-50%); line-height: 1; }
.enroll-axis span:first-child { transform: none; }
.enroll-axis span:last-child { transform: translateY(-100%); }

.enroll-scroll {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  overscroll-behavior-x: contain;
}
.enroll-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.enroll-chart { position: relative; width: max-content; min-width: 100%; height: 210px; }
.enroll-grid {
  position: absolute;
  inset: 0 0 20px 0;                 /* sits above the date labels */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  pointer-events: none;
}
.enroll-grid i { display: block; border-top: 1px solid color-mix(in srgb, var(--ink) 9%, transparent); }

.enroll-cols { position: relative; display: flex; align-items: stretch; gap: 2px; height: 100%; }
.enroll-col { flex: 0 0 var(--bw, 13px); width: var(--bw, 13px); display: flex; flex-direction: column; }
.enroll-barbox { flex: 1 1 auto; display: flex; align-items: flex-end; }
.enroll-bar {
  width: 100%;
  background: color-mix(in srgb, var(--accent) 60%, transparent);
  border-radius: 2px 2px 0 0;
}
.enroll-col.is-current .enroll-bar { background: var(--accent); }
.enroll-col:hover .enroll-bar { background: var(--accent); }
.enroll-col.is-month { border-left: 1px solid color-mix(in srgb, var(--ink) 16%, transparent); }
.enroll-x {
  height: 20px;
  line-height: 20px;
  font-size: 10px;
  color: var(--ink-2);
  white-space: nowrap;
  text-align: center;
  overflow: visible;
}
/* zen.js hides labels that would collide at the current zoom. */
.enroll-col.hide-label .enroll-x { visibility: hidden; }

.enroll-zoom { position: absolute; top: 8px; right: 10px; display: flex; gap: 4px; }
.enroll-zoom button {
  width: 24px; height: 24px; line-height: 1;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  color: var(--ink);
  font-size: 14px; font-weight: 700;
  cursor: pointer;
}
.enroll-zoom button:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.enroll-foot { margin: 0 0 18px; font-size: 11px; color: var(--ink-2); }

/* Delete-from-Five9 removal history: outcome tones. */
.rm-good { color: var(--good); font-weight: 600; }
.rm-warn { color: var(--accent-ink); font-weight: 600; }
.rm-bad  { color: var(--bad); font-weight: 600; }
.rm-muted { color: var(--ink-2); }

/* ==================================================================
   AFFILIATE CLIENT VIEW (affiliate.php)
   Read-only replica of the Salesforce Opp record page: a highlights
   bar, Details/Related tabs, two-column field grids and related-list
   tables. Theme vars only — no new colors, no charting library, and
   nothing here is interactive beyond the tab toggle.
   ================================================================== */

.aff-bar { display:flex; align-items:center; justify-content:space-between;
  gap:12px; margin:0 0 12px; }
.aff-back { color:var(--accent-ink); text-decoration:none; font-size:.9rem; }
.aff-back:hover { text-decoration:underline; }
.aff-readonly { font-size:.72rem; letter-spacing:.06em; text-transform:uppercase;
  color:var(--ink-muted); border:1px solid var(--hairline); border-radius:999px;
  padding:3px 10px; }

.aff-warn { background:var(--stale-bg); border:1px solid var(--stale-border);
  border-radius:8px; padding:10px 14px; margin:0 0 14px; font-size:.9rem; }

/* ---- highlights bar ---- */
.aff-hero { background:var(--surface); border:1px solid var(--hairline);
  border-radius:12px; padding:16px 20px; margin:0 0 16px; }
.aff-hero-id { display:flex; align-items:baseline; gap:10px; margin-bottom:12px; }
.aff-hero-obj { font-size:.72rem; text-transform:uppercase; letter-spacing:.08em;
  color:var(--ink-muted); }
.aff-hero-name { margin:0; font-size:1.5rem; font-weight:700; color:var(--ink); }
/* ⚠ gap 28->20 and min-width 110->100 when the Affiliate Rep field was added
   (2026-08-28), which took the ACCOUNT hero from 6 fields to 7. MEASURED, not
   guessed: at 28/110 the seventh field pushed "Account Owner" onto a second
   row ON ITS OWN at 1280px (hero 42px -> 111px). It still fitted at 1366px, so
   this is a narrow-laptop-only break and easy to miss on a wide monitor. At
   20/100 all seven sit on one row at 1280 with both the widest owner name in
   the org and a typical one.
   ⚠⚠ THIS CLASS IS SHARED WITH THE OPP HERO, which is squeezed beside the
   500px DocuSign block (see .aff-hero-ds). Verified there too: at 1280 the opp
   hero is unchanged (1 row, 214px); at 1366 it is 10px SHORTER, never taller.
   ⚠ A long affiliate rep AND a long owner name still wrap to two rows. That is
   genuinely too much content for one row and is the right outcome. */
.aff-hero-fields { display:flex; flex-wrap:wrap; gap:20px; }
.aff-hero-fields > div { display:flex; flex-direction:column; gap:2px; min-width:100px; }
.aff-hero-fields span { font-size:.72rem; color:var(--ink-muted); }
.aff-hero-fields strong { font-size:.95rem; font-weight:600; color:var(--ink); }

/* ---- DocuSign progress: Sent -> Viewed -> Signed, in the opp hero ----
   Two tracks (CSA, Payment Authorization). The hero became a flex row to hold
   them; .aff-hero-main is everything that was there before. */
.aff-hero { display:flex; align-items:flex-start; justify-content:space-between;
  gap:32px; flex-wrap:wrap; }
.aff-hero-main { flex:1 1 420px; min-width:0; }
/* The two tracks sit SIDE BY SIDE (Edwin, 2026-08-28) — stacked, they pushed
   the hero taller than the details beside them. */
/* ⚠ 500px, not more: the five hero fields need ~784px to stay on ONE row
   (measured), and at a 1366/1400 laptop width anything wider here pushes them
   onto a second row and makes the hero taller than it was before the trackers
   existed. Each track still gets ~237px, ample for three steps. */
.aff-hero-ds { flex:0 1 500px; display:flex; gap:26px; min-width:0; }
.aff-hero-ds .aff-dstrack { flex:1 1 0; min-width:0; }
/* Below ~1100px the pair drops under the details rather than squeezing them;
   below ~620px there is no room for two, so they stack. */
@media (max-width:1100px) { .aff-hero-ds { flex-basis:100%; } }
@media (max-width:620px)  { .aff-hero-ds { flex-direction:column; gap:15px; } }

.aff-dstrack-h { display:flex; align-items:baseline; gap:8px; margin-bottom:9px; }
.aff-dstrack-h span { font-size:.72rem; color:var(--ink-muted);
  text-transform:uppercase; letter-spacing:.06em; }
.aff-dstrack-h em { font-style:normal; font-size:.68rem; font-weight:700;
  color:var(--bad); text-transform:uppercase; letter-spacing:.04em; }
/* ⚠ "Not sent" is a neutral fact, not a failure. Only Voided and Declined earn
   the red — otherwise every untouched opp reads as though something broke. */
.aff-dstrack.is-none .aff-dstrack-h em { color:var(--ink-muted); font-weight:600; }

.aff-dssteps { display:flex; list-style:none; margin:0; padding:0; }
.aff-dssteps li { position:relative; flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; align-items:center; gap:6px; }
/* The connector runs from the previous dot to this one, behind both. It is
   filled when THIS step has been reached, so the line always ends at the
   furthest dot that is lit. */
.aff-dssteps li + li::before { content:""; position:absolute; height:2px;
  top:5px; left:-50%; right:50%; background:var(--hairline); }
.aff-dssteps li.is-done + li.is-done::before { background:var(--accent); }
.aff-dssteps li i { position:relative; z-index:1; width:12px; height:12px;
  box-sizing:border-box; border-radius:50%; border:2px solid var(--hairline);
  background:var(--surface); }
.aff-dssteps li.is-done i { border-color:var(--accent); background:var(--accent); }
.aff-dssteps li span { font-size:.68rem; color:var(--ink-muted); white-space:nowrap; }
.aff-dssteps li.is-done span { color:var(--ink); font-weight:600; }

/* A voided or declined envelope turns the reached part of the track red, so a
   dead document never reads as progress. */
.aff-dstrack.is-voided .aff-dssteps li.is-done i,
.aff-dstrack.is-declined .aff-dssteps li.is-done i { border-color:var(--bad);
  background:var(--bad); }
.aff-dstrack.is-voided .aff-dssteps li.is-done + li.is-done::before,
.aff-dstrack.is-declined .aff-dssteps li.is-done + li.is-done::before {
  background:var(--bad); }

/* ---- tabs ---- */
.aff-tabs { display:flex; gap:4px; border-bottom:2px solid var(--hairline);
  margin:0 0 18px; }
.aff-tab { background:none; border:0; border-bottom:3px solid transparent;
  margin-bottom:-2px; padding:9px 18px; font:inherit; font-size:.95rem;
  color:var(--ink-muted); cursor:pointer; }
.aff-tab:hover { color:var(--ink); }
.aff-tab.is-on { color:var(--accent-ink); border-bottom-color:var(--accent);
  font-weight:600; }

/* ---- layout ---- */
.aff-cols { display:grid; grid-template-columns:minmax(0,2.1fr) minmax(0,1fr); gap:16px; }
@media (max-width:1000px) { .aff-cols { grid-template-columns:1fr; } }
.aff-main, .aff-side { display:flex; flex-direction:column; gap:14px; min-width:0; }

/* ---- section card ---- */
.aff-sec { background:var(--surface); border:1px solid var(--hairline);
  border-radius:12px; padding:14px 18px 16px; }
.aff-sec h3 { margin:0 0 12px; font-size:.95rem; font-weight:700; color:var(--ink);
  padding-bottom:8px; border-bottom:1px solid var(--hairline); }
.aff-count { color:var(--ink-muted); font-weight:400; }
.aff-sec.is-internal { border-color:color-mix(in srgb, var(--bad) 32%, var(--hairline)); }
.aff-internal { display:inline-block; font-size:.62rem; font-weight:700;
  letter-spacing:.07em; color:var(--bad);
  border:1px solid color-mix(in srgb, var(--bad) 45%, transparent);
  border-radius:4px; padding:1px 5px; margin-left:6px; vertical-align:middle; }

/* ---- field grid: two columns, filled left-to-right like the SF layout ---- */
.aff-grid { display:grid; grid-template-columns:repeat(2, minmax(0,1fr));
  column-gap:32px; }
@media (max-width:760px) { .aff-grid { grid-template-columns:1fr; } }
.aff-stack { display:flex; flex-direction:column; }
.aff-f { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
  gap:10px; align-items:start; padding:7px 0;
  border-bottom:1px solid color-mix(in srgb, var(--hairline) 55%, transparent); }
.aff-stack .aff-f { grid-template-columns:1fr; gap:2px; }
.aff-fl { font-size:.8rem; color:var(--ink-muted); }
.aff-fv { font-size:.88rem; color:var(--ink); word-break:break-word; }
.aff-empty { display:inline-block; min-height:1em; }
.aff-f.aff-total .aff-fl, .aff-f.aff-total .aff-fv { font-weight:700; }

.aff-longtext { font-size:.88rem; line-height:1.55; color:var(--ink);
  white-space:normal; }

/* ---- related tables ---- */
.aff-rel-table { width:100%; border-collapse:collapse; font-size:.85rem; }
.aff-rel-table th { text-align:left; font-weight:600; color:var(--ink-muted);
  font-size:.76rem; text-transform:uppercase; letter-spacing:.04em;
  padding:6px 10px 6px 0; border-bottom:1px solid var(--hairline); }
.aff-rel-table td { padding:8px 10px 8px 0; border-bottom:1px solid
  color-mix(in srgb, var(--hairline) 55%, transparent); color:var(--ink);
  vertical-align:top; }
.aff-rel-table tr:last-child td { border-bottom:0; }
.aff-rel-table .num { text-align:right; padding-right:14px; }
.aff-rel-table a { color:var(--accent-ink); text-decoration:none; }
.aff-rel-table a:hover { text-decoration:underline; }
.aff-mono { font-family:ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:.78rem; color:var(--ink-muted); }

/* ---- status pills ---- */
.aff-pill { display:inline-block; font-size:.75rem; padding:2px 9px;
  border-radius:999px; border:1px solid var(--hairline); white-space:nowrap; }
.aff-pill.tone-good { color:var(--good);
  background:color-mix(in srgb, var(--good) 10%, transparent);
  border-color:color-mix(in srgb, var(--good) 35%, transparent); }
.aff-pill.tone-bad { color:var(--bad);
  background:color-mix(in srgb, var(--bad) 10%, transparent);
  border-color:color-mix(in srgb, var(--bad) 35%, transparent); }
.aff-pill.tone-warn { color:var(--accent-ink);
  background:color-mix(in srgb, var(--accent) 10%, transparent);
  border-color:color-mix(in srgb, var(--accent) 35%, transparent); }
.aff-pill.tone-neutral { color:var(--ink-2); }

/* ---- notes + files ---- */
.aff-note { padding:10px 0; border-bottom:1px solid
  color-mix(in srgb, var(--hairline) 55%, transparent); }
.aff-note:last-child { border-bottom:0; padding-bottom:0; }
.aff-note h4 { margin:0 0 2px; font-size:.88rem; color:var(--accent-ink); }
.aff-note-meta { margin:0 0 6px; font-size:.75rem; color:var(--ink-muted); }
.aff-note-body { margin:0; font-size:.86rem; line-height:1.5; color:var(--ink); }

.aff-files { list-style:none; margin:0; padding:0; }
.aff-files li { display:flex; align-items:center; gap:10px; padding:8px 0;
  border-bottom:1px solid color-mix(in srgb, var(--hairline) 55%, transparent); }
.aff-files li:last-child { border-bottom:0; }
.aff-file-ico { flex:0 0 auto; font-size:.62rem; font-weight:700; letter-spacing:.05em;
  color:var(--ink-muted); border:1px solid var(--hairline); border-radius:4px;
  padding:3px 6px; }
/* Now a link (the document opens in a new tab), so it needs to look like one. */
.aff-file-name { flex:1 1 auto; font-size:.86rem; color:var(--ink);
  word-break:break-word; text-decoration:none; }
a.aff-file-name:hover, a.aff-file-name:focus-visible { color:var(--accent-ink);
  text-decoration:underline; }
.aff-file-meta { flex:0 0 auto; font-size:.75rem; color:var(--ink-muted); }
.aff-hint { margin:10px 0 0; font-size:.76rem; color:var(--ink-muted); }

/* ---- search / empty states ---- */
.aff-search-wrap { max-width:1100px; }
.aff-lede { margin:0 0 14px; font-size:.9rem; color:var(--ink-2); max-width:70ch; }
.aff-search { display:flex; gap:8px; margin:0 0 18px; max-width:560px; }
.aff-search .ann-input { flex:1 1 auto; }
.aff-none { margin:6px 0 0; font-size:.86rem; color:var(--ink-muted); }
.aff-results { margin-top:10px; }

/* ---- affiliate: accounts list + account detail (added 2026-08-26) ---- */
.aff-secbar { display:flex; align-items:center; justify-content:space-between;
  gap:12px; flex-wrap:wrap; margin:0 0 12px; }
.aff-secbar .section-label { margin:0; }
/* One button style for this page. Search used to carry a class with no rule at
   all (`ann-post` — the announcements button is `.ann-add`), so it rendered as
   a bare browser button beside the styled one. */
/* One button style for this page. Search once carried a class with no rule at
   all (`ann-post` — the announcements button is `.ann-add`), so it rendered as
   a bare browser button beside the styled one. Used by the landing page's
   Create New Client link and the create form's submit. */
.aff-btn { display:inline-block; background:var(--accent); color:#fff; border:0;
  border-radius:8px; padding:9px 16px; font:inherit; font-size:.9rem;
  font-weight:600; cursor:pointer; line-height:1.2; white-space:nowrap;
  text-decoration:none; }
.aff-btn:hover { background:var(--accent-ink); color:#fff; }

/* Admin-only "preview as" bar. Deliberately looks like scaffolding, not a
   finished control — it disappears once affiliates have real logins. */
.aff-asbar { display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  background:var(--stale-bg); border:1px solid var(--stale-border);
  border-radius:8px; padding:10px 14px; margin:0 0 14px; }
.aff-asbar label { font-size:.82rem; font-weight:600; color:var(--ink-2); }
.aff-asbar select { max-width:340px; }
.aff-asbar .aff-hint { margin:0; }

.aff-pager { display:flex; align-items:center; gap:14px; margin-top:12px;
  font-size:.85rem; }
.aff-pager a { color:var(--accent-ink); text-decoration:none; }
.aff-pager a:hover { text-decoration:underline; }
.aff-pager span { color:var(--ink-muted); }
.aff-addr { margin:-6px 0 14px; }

/* ==================================================================
   AFFILIATE — CREATE NEW CLIENT FORM (rebuilt 2026-08-27)
   A real 12-column grid with explicit spans, so every section lines
   up on the same rhythm.

   ⚠ The first build reused `.ann-input` from the announcements bar.
   That is a FLEX class (`flex:1 1 320px; min-width:200px`) and inside
   a grid its 200px floor fought the tracks, so columns went ragged and
   short fields (ZIP, State) were as wide as long ones. `.aff-cin`
   below is grid-native: width:100%, no min-width, no flex.
   ================================================================== */

.aff-flash { background:var(--badge-bg); border:1px solid var(--badge-border);
  color:var(--good); border-radius:8px; padding:10px 14px; margin:0 0 14px;
  font-size:.9rem; font-weight:600; }

.aff-chero { display:flex; flex-direction:column; gap:6px; }
.aff-chero-note { margin:0; font-size:.88rem; color:var(--ink-2); max-width:80ch; }

.aff-cform { display:flex; flex-direction:column; gap:14px; max-width:1080px; }

/* ---- the grid ---- */
.aff-cgrid { display:grid; grid-template-columns:repeat(12, minmax(0, 1fr));
  gap:16px 20px; align-items:start; }
.f1, .f2 { grid-column:span 2; }   /* short fields: State, ZIP */
.f3  { grid-column:span 3; }
.f4  { grid-column:span 4; }
.f6  { grid-column:span 6; }
.f12 { grid-column:span 12; }
@media (max-width:1000px) { .f3 { grid-column:span 4; } }
@media (max-width:860px)  { .f3, .f4 { grid-column:span 6; } .f1, .f2 { grid-column:span 3; } }
@media (max-width:560px)  { .f1, .f2, .f3, .f4, .f6 { grid-column:span 12; } }

/* ---- one field ---- */
.aff-cfield { display:flex; flex-direction:column; gap:6px; min-width:0; }
.aff-cfield > span { font-size:.78rem; font-weight:600; color:var(--ink-2);
  letter-spacing:.01em; }
.aff-cfield > span em { color:var(--bad); font-style:normal; }
.aff-cfield > span small { font-weight:400; color:var(--ink-muted);
  margin-left:6px; font-size:.75rem; }
/* ---- "are you sure you want to charge" dialog (both invoice forms) ----
   ⚠ .aff-modal sets display:flex, which on its own defeats the [hidden]
   attribute, so the hidden state is restated explicitly. */
.aff-modal { position:fixed; inset:0; z-index:80; display:flex;
  align-items:center; justify-content:center; padding:20px;
  background:rgba(0,0,0,.62); }
.aff-modal[hidden] { display:none; }
.aff-modal-box { width:100%; max-width:460px; background:var(--surface);
  border:1px solid var(--hairline); border-radius:10px; padding:22px 24px;
  box-shadow:0 18px 50px rgba(0,0,0,.45); }
.aff-modal-box h4 { margin:0 0 10px; font-size:1.08rem; color:var(--ink); }
.aff-modal-body { margin:0 0 10px; color:var(--ink); font-size:.95rem;
  line-height:1.45; }
.aff-modal-warn { margin:0 0 18px; color:var(--bad); font-weight:600;
  font-size:.85rem; line-height:1.4; }
.aff-modal-acts { display:flex; gap:10px; flex-wrap:wrap; }

/* Phase 1 invoice: a card is charged the moment the form is submitted, so the
   payment-date box is replaced by this. Red because it is telling the affiliate
   money is about to move, not labelling a field. Sized to sit on the same
   baseline as the inputs beside it so the row does not jump. */
.aff-immediate { color:var(--bad); font-weight:700; font-size:.92rem;
  letter-spacing:.02em; padding:9px 0; }

/* Grid-native input: fills its track exactly, never overflows it. */
.aff-cin { width:100%; box-sizing:border-box; background:var(--page); color:var(--ink);
  border:1px solid var(--hairline); border-radius:8px; padding:9px 11px;
  font:inherit; font-size:.9rem; height:38px; }
select.aff-cin { cursor:pointer; }
.aff-cin:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }

.aff-cnote { margin:0; align-self:center; font-size:.8rem; color:var(--ink-muted); }

/* ---- money: $ affix, right-aligned figures so columns of numbers line up ---- */
.aff-cmoney { position:relative; display:block; }
.aff-cmoney i { position:absolute; left:11px; top:0; height:38px; display:flex;
  align-items:center; font-style:normal; font-size:.88rem; color:var(--ink-muted);
  pointer-events:none; }
.aff-cmoney .aff-cin { padding-left:24px; text-align:right;
  font-variant-numeric:tabular-nums; }

/* ---- checkbox pair, aligned with the fields beside it ---- */
.aff-cchecks { display:flex; gap:10px; }
.aff-ccheck { display:flex; align-items:center; gap:7px; height:38px; padding:0 12px;
  border:1px solid var(--hairline); border-radius:8px; background:var(--page);
  font-size:.88rem; cursor:pointer; flex:1 1 auto; }
.aff-ccheck input { margin:0; accent-color:var(--accent); }
.aff-ccheck:hover { border-color:color-mix(in srgb, var(--accent) 45%, var(--hairline)); }

/* ---- years as toggle chips: 22 checkboxes were a wall, these read as tags ---- */
.aff-years { display:flex; flex-wrap:wrap; gap:8px; }
.aff-year { position:relative; display:inline-block; }
.aff-year input { position:absolute; opacity:0; width:0; height:0; }
.aff-year span { display:inline-block; padding:6px 13px; border:1px solid var(--hairline);
  border-radius:999px; background:var(--page); font-size:.84rem;
  font-variant-numeric:tabular-nums; cursor:pointer; user-select:none;
  transition:background .12s, border-color .12s, color .12s; }
.aff-year span:hover { border-color:color-mix(in srgb, var(--accent) 50%, var(--hairline)); }
.aff-year input:checked + span { background:var(--accent); border-color:var(--accent);
  color:#fff; font-weight:600; }
.aff-year input:focus-visible + span { outline:2px solid var(--accent); outline-offset:2px; }

/* ---- totals: a summary strip, not three more form fields ---- */
.aff-ctotalsec { background:color-mix(in srgb, var(--accent) 5%, var(--surface));
  border-color:color-mix(in srgb, var(--accent) 28%, var(--hairline)); }
.aff-ctotals { display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:14px; }
@media (max-width:640px) { .aff-ctotals { grid-template-columns:1fr; } }
.aff-ctotals > div { display:flex; flex-direction:column; gap:3px;
  background:var(--page); border:1px solid var(--hairline); border-radius:10px;
  padding:12px 14px; }
.aff-ctotals span { font-size:.75rem; font-weight:600; color:var(--ink-muted);
  text-transform:uppercase; letter-spacing:.04em; }
.aff-ctotals output { font-size:1.3rem; font-weight:700; color:var(--ink);
  font-variant-numeric:tabular-nums; }
.aff-ctotals .is-net output { color:var(--good); }
.aff-ctotals .is-net output.is-neg { color:var(--bad); }

/* ---- submit ---- */
.aff-csubmit { display:flex; align-items:center; gap:20px; padding:4px 0 8px; }
.aff-csubmit .aff-btn { padding:11px 26px; font-size:.95rem; }

.aff-errlist { margin:8px 0 0 18px; padding:0; }
.aff-errlist li { margin:3px 0; }
.aff-cownersec { border-color:color-mix(in srgb, var(--accent) 40%, var(--hairline)); }
.aff-cmaxia { margin-top:14px; padding-top:14px;
  border-top:1px solid color-mix(in srgb, var(--hairline) 70%, transparent); }

/* ---- affiliate: send-for-signature buttons + confirmation (2026-08-27) ---- */
.aff-sendbar { display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin:0 0 16px; }
/* In the top bar the buttons sit opposite the back link, so the standalone
   bottom margin would double up on .aff-bar's own. */
.aff-bar .aff-sendbar { margin:0; justify-content:flex-end; }
/* Quieter than the primary Create button: sending a legal document should not
   be the loudest thing on the page. */
.aff-btn-quiet { background:var(--surface); color:var(--accent-ink);
  border:1px solid color-mix(in srgb, var(--accent) 45%, var(--hairline)); }
.aff-btn-quiet:hover { background:color-mix(in srgb, var(--accent) 12%, var(--surface));
  color:var(--accent-ink); }

.aff-confirm { border-color:color-mix(in srgb, var(--accent) 45%, var(--hairline));
  background:color-mix(in srgb, var(--accent) 5%, var(--surface)); margin-bottom:16px; }
.aff-confirm-blurb { margin:0 0 14px; font-size:.9rem; color:var(--ink-2); max-width:70ch; }
.aff-confirm-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(240px,1fr));
  gap:12px 24px; margin-bottom:16px; }
.aff-confirm-grid > div { display:flex; flex-direction:column; gap:3px; }
.aff-confirm-grid span { font-size:.75rem; font-weight:600; color:var(--ink-muted);
  text-transform:uppercase; letter-spacing:.04em; }
.aff-confirm-grid strong { font-size:.95rem; color:var(--ink); }
.aff-confirm-sub { margin:0 0 6px; font-size:.8rem; font-weight:700;
  text-transform:uppercase; letter-spacing:.04em; color:var(--ink-muted); }
.aff-confirm-to { margin-bottom:16px; }
.aff-missing { color:var(--bad); font-style:italic; }

/* ---- affiliate: editing an opp in place (2026-08-27) ----
   The edit form reuses the READ view's grid (.aff-grid/.aff-f) so the two
   modes line up field for field — only the value cell changes. */
.aff-fedit { align-items:center; min-height:44px; }
.aff-fedit .aff-fl { padding-top:0; }
.aff-fedit .aff-fv { max-width:340px; }
.aff-fedit .aff-fl label { cursor:pointer; }
/* The chips need the full width of the row, not the 340px value column. */
.aff-fedit .aff-fv:has(.aff-years) { max-width:none; }
.aff-fedit .aff-years { padding:2px 0; }

/* A locked field still shows its value, plus the reason it cannot be changed. */
.aff-locked .aff-fv { color:var(--ink-muted); }
.aff-lock { display:inline-block; margin-left:6px; font-size:.68rem;
  letter-spacing:.04em; text-transform:uppercase; color:var(--ink-muted);
  border:1px solid var(--hairline); border-radius:999px; padding:1px 7px;
  white-space:nowrap; vertical-align:middle; }

.aff-echk { display:inline-flex; align-items:center; cursor:pointer; }
.aff-echk input { width:17px; height:17px; margin:0; cursor:pointer;
  accent-color:var(--accent); }

.aff-editbar { display:flex; align-items:center; gap:18px; flex-wrap:wrap;
  padding:4px 0 8px; }
.aff-editbar .aff-btn { padding:11px 26px; font-size:.95rem; }
.aff-editbar .aff-hint { margin:0; }

/* ---- affiliate: Create Invoice (Unity) form (2026-08-27) ---- */
.aff-upay { margin:0 0 14px; }
.aff-upay .aff-year span { padding:7px 16px; }
#aff-ucard, #aff-uach { margin-bottom:4px; }

/* ---- affiliate: Phase 2 invoice form (2026-08-27) ---- */
.aff-u2opts { display:flex; flex-direction:column; gap:8px; margin:0 0 12px; }
.aff-u2opt { display:flex; align-items:center; gap:10px; padding:9px 13px;
  border:1px solid var(--hairline); border-radius:9px; background:var(--page);
  cursor:pointer; font-size:.88rem; }
.aff-u2opt:has(input:checked) { border-color:var(--accent);
  background:color-mix(in srgb, var(--accent) 7%, var(--page)); }
.aff-u2opt input { accent-color:var(--accent); }
.aff-u2preview { margin:12px 0 4px; }
#u2-newcard, #u2-newach, #u2-newach2 { margin-bottom:8px; }
