/* ============================================================================
   app.css — components. Every colour comes from tokens.css; none is declared
   here as a literal, so both themes resolve as a set.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-md);
  line-height: 1.5;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
}

/* Every figure on the page is mono with tabular digits — that is the rule that
   makes columns line up and stops numbers shimmying as they update. */
.num, td.num, .stat-v, .flow-n, .kpi-v { font-family: var(--num); font-variant-numeric: tabular-nums; }
/* Genuinely code — a config key, an env var — still wants a real monospace. */
code, kbd, pre { font-family: var(--mono); font-size: .94em; }

.ico { width: 1em; height: 1em; flex: none; }
.flow-arrow .ico { width: 15px; height: 15px; display: block; }

:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-sm); }
::selection { background: var(--surface-3); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ============================================================== app shell == */
.app { display: grid; grid-template-columns: var(--rail) minmax(0, 1fr); min-height: 100vh; }

.rail {
  position: sticky; top: 0; align-self: start; height: 100vh;
  display: flex; flex-direction: column;
  background: var(--surface); border-right: 1px solid var(--border);
}

.rail-top { padding: 18px 16px 14px; }
.logo { display: flex; align-items: center; gap: 9px; font-size: var(--t-md); font-weight: 600; letter-spacing: -0.01em; }
.logo-mark {
  width: 22px; height: 22px; border-radius: var(--r-sm); flex: none;
  background: var(--action); color: var(--ink-on);
  display: grid; place-items: center; font-family: var(--num); font-size: 11px; font-weight: 600;
}
.logo-sub { font-size: var(--t-xs); color: var(--ink-3); letter-spacing: .04em; margin-top: 3px; padding-left: 31px; }

.nav { flex: 1; overflow-y: auto; padding: 6px 10px; display: flex; flex-direction: column; gap: 1px; }
.nav-label {
  font-size: var(--t-xs); font-weight: 500; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3); padding: 16px 8px 6px;
}
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 8px; border-radius: var(--r-sm);
  color: var(--ink-2); text-decoration: none; font-size: var(--t-md); font-weight: 450;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.nav a:hover { background: var(--surface-2); color: var(--ink); }
.nav a[aria-current="page"] { background: var(--surface-3); color: var(--ink); font-weight: 550; }
.nav svg { width: 15px; height: 15px; flex: none; stroke-width: 1.6; }
.nav .count {
  margin-left: auto; font-family: var(--num); font-size: var(--t-xs);
  padding: 1px 6px; border-radius: 999px; background: var(--surface-3); color: var(--ink-2);
}
/* Work that is genuinely late is the one place the rail shouts: a filled red
   chip with a white figure, not a tinted one. It has to be readable from the
   other side of a desk. */
.nav .count.alert {
  background: var(--bad); color: #fff; font-weight: 700;
}

.rail-foot { padding: 10px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 1px; }
.whoami { display: flex; align-items: center; gap: 9px; padding: 8px; border-radius: var(--r-sm); }
.avatar {
  width: 26px; height: 26px; border-radius: 999px; flex: none; display: grid; place-items: center;
  background: var(--surface-3); color: var(--ink-2); font-family: var(--num); font-size: var(--t-xs); font-weight: 600;
}
.whoami-t { min-width: 0; }
.whoami-t b { display: block; font-size: var(--t-sm); font-weight: 550; }
.whoami-t span { display: block; font-size: var(--t-xs); color: var(--ink-3); }

/* ================================================================= topbar == */
.main { min-width: 0; display: flex; flex-direction: column; }

.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 24px; min-height: 57px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
}
.topbar h1 { font-size: var(--t-lg); font-weight: 600; letter-spacing: -0.015em; }
.topbar .sub { font-size: var(--t-sm); color: var(--ink-3); }
.grow { flex: 1 1 auto; }

.page { padding: 20px 24px 72px; display: flex; flex-direction: column; gap: 16px; }
.page.narrow { max-width: 880px; }

/* ================================================================ controls == */
.btn {
  appearance: none; cursor: pointer; font: inherit; font-size: var(--t-sm); font-weight: 500;
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 6px 11px; border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink); border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-1);
  transition: background .12s var(--ease), border-color .12s var(--ease), opacity .12s;
}
.btn:hover { background: var(--surface-2); }
.btn svg { width: 14px; height: 14px; stroke-width: 1.7; }
.btn:disabled { opacity: .45; cursor: not-allowed; }

.btn-primary { background: var(--action); color: var(--ink-on); border-color: var(--action); }
.btn-primary:hover { background: var(--action-hover); border-color: var(--action-hover); }
.btn-ghost { background: transparent; border-color: transparent; box-shadow: none; color: var(--ink-2); }
.btn-ghost:hover { background: var(--surface-2); color: var(--ink); }
.btn-danger { color: var(--bad); border-color: var(--border-strong); }
.btn-danger:hover { background: var(--bad-bg); border-color: var(--bad); }
.btn-lg { padding: 9px 16px; font-size: var(--t-md); }

.seg { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r); padding: 2px; gap: 1px; }
.seg button {
  appearance: none; cursor: pointer; font: inherit; font-size: var(--t-sm); font-weight: 500;
  color: var(--ink-2); background: none; border: 0; border-radius: var(--r-sm); padding: 4px 11px;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.seg button:hover { color: var(--ink); }
.seg button[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-1); }

.sel { position: relative; display: inline-flex; }
.sel select, .inp, .ta {
  appearance: none; font: inherit; font-size: var(--t-sm); color: var(--ink);
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  padding: 6px 10px; box-shadow: var(--shadow-1); width: 100%;
  transition: border-color .12s var(--ease);
}
.sel select { cursor: pointer; padding-right: 26px; }
.sel::after {
  content: ''; position: absolute; right: 9px; top: 50%; pointer-events: none;
  width: 5px; height: 5px; border-right: 1.4px solid var(--ink-3); border-bottom: 1.4px solid var(--ink-3);
  transform: translateY(-4px) rotate(45deg);
}
.sel.on select { border-color: var(--focus); }
.inp:hover, .ta:hover, .sel select:hover { border-color: var(--ink-3); }
.inp::placeholder, .ta::placeholder { color: var(--ink-3); }
.ta { resize: vertical; min-height: 84px; line-height: 1.55; font-size: var(--t-md); }
.inp.num-in { font-family: var(--num); }

.switch { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; font-size: var(--t-sm); }
.switch input { position: absolute; opacity: 0; pointer-events: none; }
.switch i {
  width: 30px; height: 18px; border-radius: 999px; background: var(--surface-3); position: relative;
  transition: background .16s var(--ease); flex: none;
}
.switch i::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 999px;
  background: var(--surface); box-shadow: var(--shadow-1); transition: transform .16s var(--ease);
}
.switch input:checked + i { background: var(--action); }
.switch input:checked + i::after { transform: translateX(12px); }

.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip input { position: absolute; opacity: 0; pointer-events: none; }
.chip span {
  display: block; cursor: pointer; font-size: var(--t-sm); color: var(--ink-2);
  border: 1px solid var(--border-strong); border-radius: 999px; padding: 5px 12px;
  background: var(--surface); transition: all .12s var(--ease); user-select: none;
}
.chip span:hover { border-color: var(--ink-3); color: var(--ink); }
.chip input:checked + span { background: var(--action); border-color: var(--action); color: var(--ink-on); }
.chip input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }

/* ================================================================== cards == */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-1); overflow: hidden; }

.text-left { text-align: left !important; }
.text-right { text-align: right !important; }
.text-center { text-align: center !important; }
.card-h { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 13px 16px; border-bottom: 1px solid var(--border); }
.card-h h2 { font-size: var(--t-md); font-weight: 600; letter-spacing: -0.01em; }
.card-h .hint { font-size: var(--t-sm); color: var(--ink-3); }
.card-b { padding: 16px; }
.card-b.flush { padding: 0; }

.grid { display: grid; gap: 16px; }
.grid.c2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid.c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid.c4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid.side { grid-template-columns: minmax(0, 1fr) 320px; align-items: start; }

/* ============================================================= stat tiles == */
/* Separate cards, each tinted with its own metric's hue — a flat directional
   wash and a matching border, so a tile is identifiable before a word is read.

   Sized to be scanned: this strip is the first thing on the board now, so it
   has to fit on one screen rather than dominate it. One size for every label,
   one for every value, one for every sub-line — the strip reads as a set, and
   no tile looks more important than its neighbour for reasons of type rather
   than of data. */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: 8px; }
.stat {
  position: relative; padding: 11px 13px 12px; border-radius: var(--r);
  display: flex; flex-direction: column; gap: 2px;
  background: linear-gradient(150deg, color-mix(in srgb, var(--tone, var(--border)) 13%, var(--surface)) 0%, var(--surface) 62%);
  border: 1px solid color-mix(in srgb, var(--tone, var(--border)) 22%, var(--border));
  transition: border-color .15s var(--ease);
}

/* A met goal turns the frame gold and puts a trophy in the corner. The border
   does the work: eight tiles read as a row of frames, and the gold ones are
   countable without reading a single figure. */
.stat.hit { border-color: color-mix(in srgb, var(--goal) 62%, transparent); }
.stat-win { position: absolute; top: 9px; right: 11px; font-size: 12px; line-height: 1; }

.stat-h { display: flex; align-items: flex-start; gap: 8px; min-height: 13px; }
.stat-l {
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-3); padding-right: 15px;
}
.stat-v { font-size: var(--t-xl); font-weight: 600; letter-spacing: -0.03em; line-height: 1.1; margin-top: 5px; }
.stat-d { font-size: var(--t-xs); color: var(--ink-3); display: flex; align-items: center; gap: 4px; }
.stat-d b { font-weight: 600; color: var(--ink-2); }

/* The target, always in the goal colour, always the last line. */
.stat-g {
  margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border);
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .03em;
  color: var(--goal); font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- meters -- */
/* A quantity as a count of lit segments out of twenty. Twenty is the number:
   enough that a fill reads as a proportion, few enough that you can actually
   count them — which is the whole advantage over a smooth bar. */
.meter { position: relative; display: flex; gap: 3px; height: 22px; }
.meter s {
  flex: 1; height: 100%; border-radius: 2px; background: var(--off);
  text-decoration: none;
}
.meter s.on { background: var(--tone, var(--series-1)); }
/* Where it should have reached by now. */
/* The goal mark, in the one gold used for every goal on the board. A
   surface-coloured halo keeps it visible whether it lands on a lit segment or
   an unlit one. */
.meter u {
  position: absolute; top: -3px; bottom: -3px; width: 2px; border-radius: 1px;
  background: var(--goal); box-shadow: 0 0 0 1.5px var(--surface);
  text-decoration: none;
}

/* ---------------------------------------------------------------- gauges -- */
/* An open ring of ticks, 270° from the lower left. Same argument as the meter:
   a count lands faster than a length. */
.gauge { display: block; width: 100%; max-width: 128px; margin: 0 auto; }
.gauge-wrap { text-align: center; color: var(--grade-none); }
.gauge-v {
  font-family: var(--num); font-variant-numeric: tabular-nums;
  font-size: var(--t-xl); font-weight: 600; letter-spacing: -0.03em;
  margin-top: -46px; margin-bottom: 26px; position: relative;
}
.gauge-n { font-size: var(--t-sm); color: var(--ink-3); }

/* A change, in the direction that is good for the thing it describes. */
.badge {
  font-family: var(--num); font-variant-numeric: tabular-nums;
  font-size: var(--t-xs); font-weight: 600;
  padding: 2px 7px; border-radius: var(--r-sm);
  color: var(--tone, var(--ink-2));
  background: color-mix(in srgb, var(--tone, var(--ink-3)) 16%, transparent);
}

/* An actual with its target beneath it, inside a table or a figure. Same shape
   wherever it appears, so the pair always reads as one scale. */
.of {
  display: block; font-size: var(--t-xs); font-weight: 600;
  font-family: var(--num); font-variant-numeric: tabular-nums;
}

/* Distance from goal, one scale, wherever it is carried — a figure, a gauge's
   ticks, a table cell. */
.g-on    { color: var(--grade-on); }
.g-near  { color: var(--grade-near); }
.g-under { color: var(--grade-under); }
.g-bad   { color: var(--grade-bad); }
.g-none  { color: var(--grade-none); }
.pf-n.g-none, .stat-v.g-none { color: var(--ink); }   /* an ungraded figure is still a figure */

/* ======================================================== the funnel flow == */
/* Each stage is a box the height of its goal, with the volume filling it from
   the bottom. The boxes narrow left to right because the goals do; how full
   each one is says how the month is going; and a fill that overruns its box is
   past goal, readable from across the room without a number.

   One shared scale across all four, so the funnel is a shape before it is a
   set of figures. */
.pf { display: grid; align-items: start; overflow-x: auto; column-gap: 6px; padding-top: 16px; text-align: center; }

.pf-col { position: relative; height: 150px; }

/* The goal's worth of bar, hatched. Drawing the shortfall rather than leaving
   it as empty space turns "how much is left" into a shape you can measure by
   eye — it is the same trick as a fuel gauge marking the empty half. */
.pf-bar {
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 100%; max-width: 68px; border-radius: 6px 6px 3px 3px;
  background-color: color-mix(in srgb, var(--ink) 5%, transparent);
  background-image: repeating-linear-gradient(45deg,
    color-mix(in srgb, var(--ink) 11%, transparent) 0 2px,
    transparent 2px 6px);
}

/* What is actually done, solid, growing from a baseline it never leaves — so
   the foot stays square while the head is rounded. */
.pf-got {
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 100%; max-width: 68px; border-radius: 6px 6px 3px 3px;
  transition: height .35s var(--ease);
}
/* Where a fill meets an overflow both edges go square, so the two read as one
   bar rather than two stacked with a notch between them. */
.pf-got.capped { border-radius: 0 0 3px 3px; }

/* Past goal, in gold rather than the stage colour — the same hatching as the
   shortfall, so the texture always means "not ordinary volume" and the colour
   says which kind: grey below is what is missing, gold above is what was won
   on top. Reusing the stage colour made it read as a bar on top of a bar. */
.pf-over {
  position: absolute; left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 68px; border-radius: 6px 6px 0 0;
  background-color: color-mix(in srgb, var(--goal) 26%, transparent);
  background-image: repeating-linear-gradient(45deg,
    color-mix(in srgb, var(--goal) 85%, transparent) 0 2px,
    transparent 2px 6px);
}

/* The rate as an arc, with the flow arrow in the hole. */
.pf-ring {
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 54px; height: 54px;
}
.pf-ring svg { display: block; width: 100%; height: 100%; }
.pf-ring circle { fill: none; stroke-width: 5.5; }
.pf-ring-t { stroke: var(--surface-3); }
.pf-ring-a { stroke: currentColor; stroke-linecap: round; }
/* The target rate, in the goal colour and heavy enough to actually see. */
.pf-ring-g { stroke: var(--goal); stroke-width: 3; stroke-linecap: round; }
.pf-arrow {
  position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; color: var(--ink-3);
}
.pf-arrow .ico { width: 15px; height: 15px; }

/* The goal: emoji, line, figure — laid out as one row with the line in the
   middle. The two ends sit outside the bar's own width on purpose, so when a
   fill grows past its goal the only thing crossing it is the rule itself. A
   number printed over a bar is unreadable exactly when it matters most. */
.pf-goal {
  position: absolute; left: 50%; transform: translateX(-50%); z-index: 2;
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 4px;
  line-height: 1; pointer-events: none;
}
/* Just past the bar on each side — far enough to read as crossing it, not so
   far that the rule becomes the widest thing in the column. Bar is 68px. */
.pf-goal span { flex: 0 1 84px; height: 0; border-top: 2px solid var(--goal); }
.pf-goal i { font-style: normal; font-size: 11px; flex: none; }
.pf-goal b {
  flex: none; font-family: var(--num); font-variant-numeric: tabular-nums;
  font-size: 10px; font-weight: 700; letter-spacing: 0; color: var(--goal);
}

/* Figure, then name, then how it stands — three lines, one per idea, rather
   than a figure with a goal wedged in beside it. */
.pf-n {
  font-family: var(--num); font-variant-numeric: tabular-nums;
  font-size: var(--t-xl); font-weight: 600; letter-spacing: -0.02em;
  color: var(--ink); padding-top: 14px;
}
/* The stage name, set as a label: caps and tracked, so the row of names reads
   as one band and never competes with the figure above it. */
.pf-l {
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-2);
  padding-top: 5px; line-height: 1.3;
}
/* The goal underneath, all in gold, with the emoji sitting on the text's own
   centre line rather than floating above it. */
.pf-goal-l {
  /* flex, not inline-flex: it is its own line under the name, not a tail on
     the end of it. */
  display: flex; align-items: center; justify-content: center; gap: 4px; margin-top: 4px;
  font-style: normal; font-size: var(--t-xs); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; color: var(--goal);
  font-family: var(--num); font-variant-numeric: tabular-nums;
}
.pf-goal-l::first-letter { font-size: 1.05em; }

@media (max-width: 620px) {
  .pf       { column-gap: 3px; }
  .pf-col   { height: 108px; }
  .pf-bar, .pf-got, .pf-over { max-width: 48px; }
  .pf-goal  { max-width: 58px; }
  .pf-ring  { width: 40px; height: 40px; }
  .pf-arrow .ico { width: 12px; height: 12px; }
  .pf-n     { font-size: var(--t-lg); }
  .pf-l     { font-size: var(--t-sm); }
}

/* ========================================================= the compare board */
/* A rule under cash splits the funnel counts above from the money below — two
   kinds of figure that happen to share a table. */
.rule { border-bottom: 2px solid var(--border-strong) !important; }
thead th .of { color: var(--ink-3); font-weight: 400; }
.legend.wrap { flex-wrap: wrap; row-gap: 4px; margin-bottom: 6px; }

/* The pinned period: a faint column wash and a gold header, so it stays
   findable while the eye runs across whichever row you came for. */
th.best, td.best { background: color-mix(in srgb, var(--goal) 8%, transparent); }
th.best .c-pin { color: var(--goal); }
th.best .c-pin .of { color: var(--goal); opacity: .85; }

/* A column header is the pin control. It has to look pressable without
   becoming a button in a row of labels. */
.c-pin {
  appearance: none; background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; cursor: pointer; text-align: right; width: 100%;
  letter-spacing: inherit; text-transform: inherit;
}
.c-pin:hover { color: var(--goal); }
.c-pin:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-sm); }

/* More columns on screen: a comparison is worth more the more of it you can
   see at once, and the figures are tabular so they stay readable tight. */
#c-body thead th, #c-body tbody td { padding-left: 9px; padding-right: 9px; }

/* The goal column reads as a reference, not as another period — its own ground,
   ruled off on both sides, in the one gold every goal uses. */
th.goal, td.goal {
  background: var(--surface-2); color: var(--goal);
  border-left: 1px solid var(--border); border-right: 1px solid var(--border);
}
th.goal .of { color: var(--goal); opacity: .8; }

/* ============================================================== recordings == */
/* A tile that reads as a video and is a link. There is no player here on
   purpose — the call lives in Fathom, and embedding it would mean loading a
   video on a page where somebody is scanning twenty of them. It looks
   pressable because pressing it does take you to the call. */
.tape { display: grid; grid-template-columns: repeat(auto-fill, minmax(216px, 1fr)); gap: 14px; }
.reel { display: flex; flex-direction: column; gap: 9px; }

.reel-v {
  position: relative; display: block; aspect-ratio: 16 / 9; border-radius: var(--r);
  background:
    radial-gradient(120% 100% at 50% 0%, color-mix(in srgb, var(--series-1) 22%, var(--surface-2)) 0%, var(--surface-2) 70%);
  border: 1px solid var(--border); overflow: hidden;
  transition: border-color .14s var(--ease), transform .14s var(--ease);
}
.reel-v:hover { border-color: var(--series-1); transform: translateY(-1px); }
.reel-v:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.reel-play {
  position: absolute; inset: 0; margin: auto; width: 46px; height: 46px;
  display: grid; place-items: center; border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 88%, transparent); color: var(--surface);
  transition: transform .14s var(--ease);
}
.reel-play .ico { width: 22px; height: 22px; margin-left: 1px; }
.reel-v:hover .reel-play { transform: scale(1.06); }

.reel-time {
  position: absolute; right: 8px; bottom: 8px;
  padding: 2px 6px; border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--ink) 78%, transparent); color: var(--surface);
  font-size: var(--t-xs); font-weight: 600; font-variant-numeric: tabular-nums;
}

.reel-b { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.reel-n { font-size: var(--t-md); font-weight: 600; }
.reel-m { font-size: var(--t-xs); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.reel-o { margin-top: 4px; }
.reel-a { display: flex; gap: 6px; }
.reel-a .btn { flex: 1; justify-content: center; padding: 5px 8px; font-size: var(--t-xs); }

/* ================================================== the closer's own board == */
/* Bars on the left, figures on the right. The bars answer "am I on track",
   which is a shape; the figures answer "what exactly", which is a number. */
.split-num { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 12px; }

.kpi-bars { display: flex; flex-direction: column; gap: 15px; }
.kbar-h, .kbar-f { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.kbar-h { font-size: var(--t-md); font-weight: 550; margin-bottom: 6px; }
.kbar-h b { font-family: var(--num); font-variant-numeric: tabular-nums; font-size: var(--t-lg); font-weight: 600; letter-spacing: -0.02em; }
/* The track holds everything. It is scaled to whichever is larger — the goal or
   the figure — so a bar past goal grows inside it and the card never has to
   clip anything. */
.kbar-track { position: relative; height: 9px; border-radius: 5px; background: var(--off); }
.kbar-track i { position: absolute; inset: 0 auto 0 0; border-radius: 5px; background: currentColor; }
/* The stretch past goal, in the goal's own gold. */
.kbar-track s { position: absolute; top: 0; bottom: 0; border-radius: 0 5px 5px 0; background: var(--goal); text-decoration: none; }
/* Where the goal sits on that scale — at the far right until it is beaten. */
.kbar-track u {
  position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px;
  border-radius: 1px; background: var(--goal); box-shadow: 0 0 0 1.5px var(--surface);
}
.kbar-f .over { color: var(--goal); font-weight: 700; }
.won { font-style: normal; font-size: 12px; }

/* Four states, and they mean pace rather than distance: on track is blue
   because it is a neutral "keep going", not a reward; gold is the reward, and
   it is the same gold every goal on this board uses. */
.t-hit     { color: var(--goal); }
.t-ontrack { color: var(--todo); }
.t-behind  { color: var(--warn); }
.t-far     { color: var(--bad); }
.t-none    { color: var(--ink-2); }
.kbar-f { margin-top: 6px; font-size: var(--t-xs); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.kbar-f em { font-style: normal; font-weight: 600; color: var(--goal); }

/* The number a closer actually came to look at. The only card on their board
   with the goal colour as its ground. */
.stat.pay {
  background: linear-gradient(150deg, color-mix(in srgb, var(--goal) 20%, var(--surface)) 0%, var(--surface) 70%);
  border-color: color-mix(in srgb, var(--goal) 45%, var(--border));
}
.pay-v {
  font-family: var(--num); font-variant-numeric: tabular-nums;
  font-size: var(--t-3xl); font-weight: 600; letter-spacing: -0.04em;
  line-height: 1.05; color: var(--goal); margin: 6px 0 4px;
}

/* Pace, as bars rather than rails. Two per window — yours and the floor's —
   each scaled to its OWN goal, so the two shapes are directly comparable.
   Scaling both to the floor's target would leave a closer's bar a fifth of the
   height and tell them nothing about themselves. */
.pace-set { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 20px; }
.pwin-h {
  font-size: var(--t-md); font-weight: 600; margin-bottom: 14px;
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
}
.pwin-h em {
  font-style: normal; font-size: var(--t-xs); font-weight: 500; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.pwin-bars { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

.pcol { text-align: center; }
.pcol-bar { position: relative; height: 116px; }

/* The goal, hatched, exactly as the funnel draws it — same idea, same look. */
.pcol-box {
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 100%; max-width: 46px; border-radius: 8px 8px 3px 3px;
  background-color: color-mix(in srgb, var(--ink) 5%, transparent);
  background-image: repeating-linear-gradient(45deg,
    color-mix(in srgb, var(--ink) 11%, transparent) 0 2px, transparent 2px 6px);
}
.pcol-fill {
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 100%; max-width: 46px; border-radius: 8px 8px 3px 3px;
  background: var(--tok); transition: height .35s var(--ease);
}
/* A bar past its goal takes the goal colour above the line, the same way the
   funnel marks an overrun. */
.pcol-fill.t-hit { background: linear-gradient(180deg, var(--goal) 0 var(--over, 0%), var(--tok) var(--over, 0%)); }

.pcol-goal {
  position: absolute; left: 50%; transform: translateX(-50%); z-index: 2;
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 3px;
  line-height: 1; pointer-events: none;
}
.pcol-goal span { flex: 0 1 54px; height: 0; border-top: 2px solid var(--goal); }
.pcol-goal i { font-style: normal; font-size: 10px; flex: none; }
.pcol-goal b {
  flex: none; font-family: var(--num); font-variant-numeric: tabular-nums;
  font-size: 9.5px; font-weight: 700; color: var(--goal);
}

.pcol-n {
  font-family: var(--num); font-variant-numeric: tabular-nums;
  font-size: var(--t-lg); font-weight: 600; letter-spacing: -0.02em; margin-top: 12px;
}
.pcol-l { font-size: var(--t-xs); color: var(--ink-3); margin-top: 2px; }

.chart.small { height: 190px; }

@media (max-width: 1000px) { .split-num { grid-template-columns: minmax(0, 1fr); } }

/* ===================================================== the by-closer table == */
/* Any rate column can be the one the floor is ranked on. The header is the
   control, and the live one is marked so you always know what "top" means —
   "who is best" has no answer until you say best at what. */
th.rank .c-pin { text-align: right; }
th.rank.on { color: var(--goal); }

/* The leader: a gold rail down their row and a cup by the name. The rail is on
   the first cell only, so it reads as a marker on the row rather than a box
   drawn around it. */
td.lead { background: color-mix(in srgb, var(--goal) 7%, transparent); }
td.name.lead { box-shadow: inset 3px 0 0 var(--goal); }
.lead-cup { font-style: normal; margin-right: 6px; }

/* ================================================================= tables == */
.tbl-wrap { overflow-x: auto; border-radius: inherit; }
table { width: 100%; border-collapse: collapse; }
thead th {
  position: sticky; top: 0; z-index: 1; text-align: right; white-space: nowrap;
  font-size: var(--t-xs); font-weight: 500; color: var(--ink-3); letter-spacing: .03em;
  padding: 9px 12px; background: var(--surface-2); border-bottom: 1px solid var(--border);
}
thead th:first-child, tbody td:first-child { text-align: left; }
tbody td { text-align: right; white-space: nowrap; padding: 9px 12px; border-bottom: 1px solid var(--border); font-size: var(--t-md); }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--surface-2); }
td.name { font-weight: 500; text-align: left; }
td.dim, .dim { color: var(--ink-3); }
td.wrap-cell { white-space: normal; min-width: 200px; }

th.text-left, td.text-left, .table th.text-left, .table td.text-left { text-align: left !important; }
th.text-right, td.text-right, .table th.text-right, .table td.text-right { text-align: right !important; }
th.text-center, td.text-center, .table th.text-center, .table td.text-center { text-align: center !important; }

/* A hairline bar under a figure — magnitude without a second chart. */
.bar-cell { position: relative; }
.bar-cell i { position: absolute; right: 12px; bottom: 4px; height: 2px; border-radius: 1px; background: var(--series-1); }

/* ================================================== pills, tags, statuses == */
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--t-xs); font-weight: 500; padding: 2px 8px; border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--ink-2); white-space: nowrap;
}
.pill.win  { background: var(--good-bg); color: var(--good); }
.pill.loss { background: var(--bad-bg);  color: var(--bad);  }
.pill.open { background: var(--warn-bg); color: var(--warn); }
.pill.void { background: var(--surface-3); color: var(--ink-3); }
.pill svg { width: 11px; height: 11px; stroke-width: 2; }

.dot { width: 6px; height: 6px; border-radius: 999px; flex: none; }

.note {
  display: flex; align-items: flex-start; gap: 9px; padding: 10px 13px;
  border-radius: var(--r); font-size: var(--t-sm); color: var(--ink-2);
  background: var(--surface-2); border: 1px solid var(--border);
}
.note svg { width: 14px; height: 14px; flex: none; margin-top: 1px; stroke-width: 1.8; }
.note b { color: var(--ink); font-weight: 600; }
.note.warn { background: var(--warn-bg); border-color: transparent; color: var(--warn); }
.note.warn b { color: var(--warn); }
.note.bad  { background: var(--bad-bg);  border-color: transparent; color: var(--bad);  }
.note.bad b { color: var(--bad); }
.note.good { background: var(--good-bg); border-color: transparent; color: var(--good); }
.note.good b { color: var(--good); }
.note.info { background: var(--info-bg); border-color: transparent; }

/* ============================================================ call queue == */
/* A closer's outstanding calls. The card itself carries the urgency, so the
   list can be scanned without reading a single word. */
/* One call is one line, always. A queue is read by scanning it, and a row that
   wraps to three lines turns twelve open calls into a page you have to scroll —
   at which point the queue stops being a list and starts being a chore. So
   nothing here wraps: the time, the name and the buttons hold their width and
   the middle column gives, truncating the email long before the row grows. */
.queue { display: flex; flex-direction: column; gap: 6px; }
.qcard {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14px;
  padding: 7px 12px; background: var(--surface);
  border: 1px solid var(--border); border-left: 3px solid var(--border-strong);
  border-radius: var(--r); transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
.qcard:hover { box-shadow: var(--shadow-1); }
/* The left edge carries how long a call has been sitting, so running an eye
   down the rail is enough: blue is fresh, amber has passed twelve hours, red
   has passed twenty-four. Two steps rather than one cliff — a closer watches
   it coming instead of finding it already late. */
.qcard.age-fresh { border-left-color: var(--todo); }
.qcard.age-due   { border-left-color: var(--warn); background: var(--warn-bg); }
.qcard.age-late  { border-left-color: var(--bad);  background: var(--bad-bg); }
.qcard.done      { opacity: .55; border-left-color: var(--good); }

.qtime { font-family: var(--num); font-size: var(--t-md); font-weight: 600; white-space: nowrap; }
.qtime span { font-size: var(--t-xs); font-weight: 400; color: var(--ink-3); margin-left: 6px; }

/* Name and detail share the line. The name never truncates — it is what the
   row is about — so the meta beside it is what gives when space runs out. */
.qwho { display: flex; align-items: baseline; gap: 10px; min-width: 0; overflow: hidden; }
.qname {
  font-weight: 550; font-size: var(--t-md); white-space: nowrap;
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.qmeta {
  font-size: var(--t-sm); color: var(--ink-3); display: flex; flex-wrap: nowrap;
  gap: 10px; min-width: 0; overflow: hidden; white-space: nowrap;
}
.qmeta span { flex: 0 0 auto; }
.qmeta .grow { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.qactions { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; justify-content: flex-end; }

/* Between a phone and a wide desktop the five buttons and the call's detail
   cannot both have the room they want, and the row is not allowed to grow. The
   buttons win — filing the call is the whole reason the row is here — so the
   detail gives way in order of how little it is missed: source and email first,
   then the name ellipsises rather than being cut mid-word. */
@media (max-width: 1180px) {
  .qcard { gap: 10px; }
  .qmeta { display: none; }
  .qactions { gap: 4px; }
  .qactions .btn { padding-left: 8px; padding-right: 8px; }
}

/* ================================================================= modal == */
.scrim {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 20px;
  background: color-mix(in srgb, var(--ink) 45%, transparent); backdrop-filter: blur(3px);
  animation: fade .16s var(--ease);
}
.modal {
  width: min(660px, 100%); max-height: min(86vh, 900px); display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-2); animation: rise .2s var(--ease);
}
.modal-h { display: flex; align-items: flex-start; gap: 12px; padding: 16px 18px 13px; border-bottom: 1px solid var(--border); }
.modal-h h2 { font-size: var(--t-lg); font-weight: 600; letter-spacing: -0.015em; }
.modal-h p { font-size: var(--t-sm); color: var(--ink-3); margin-top: 2px; }
.modal-b { padding: 18px; overflow-y: auto; display: flex; flex-direction: column; gap: 16px; }
.modal-f { display: flex; align-items: center; gap: 10px; padding: 13px 18px; border-top: 1px solid var(--border); }

@keyframes fade { from { opacity: 0 } }
@keyframes rise { from { opacity: 0; transform: translateY(8px) scale(.99) } }

/* ================================================================== forms == */
.fields { display: grid; gap: 14px; }
.fields.c2 { grid-template-columns: 1fr 1fr; }
.fg { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.fg > label { font-size: var(--t-sm); font-weight: 500; color: var(--ink-2); }
.fg > label em { font-style: normal; color: var(--bad); }
.fg .help { font-size: var(--t-xs); color: var(--ink-3); }
.fg .err { font-size: var(--t-xs); color: var(--bad); display: none; }
.fg.bad .err { display: block; }
.fg.bad .inp, .fg.bad .ta, .fg.bad select { border-color: var(--bad); }

/* A credential field's own controls, under the box they belong to. */
.fg > label .conn-set {
  font-style: normal; font-weight: 600; color: var(--good);
  font-family: var(--num); font-size: var(--t-xs); margin-left: 6px;
}
.conn-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.conn-row .btn { padding: 4px 10px; font-size: var(--t-xs); }
.conn-result { font-size: var(--t-xs); color: var(--ink-3); }
.conn-result.ok { color: var(--good); font-weight: 600; }
.conn-result.no { color: var(--bad); font-weight: 600; }

fieldset { border: 0; display: flex; flex-direction: column; gap: 12px; }
legend { font-size: var(--t-xs); font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); padding-bottom: 8px; width: 100%; border-bottom: 1px solid var(--border); }

/* ================================================================ charts == */
.chart { position: relative; width: 100%; }
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.gridline { stroke: var(--border); stroke-width: 1; }
.axis-t { fill: var(--ink-3); font-size: 11px; font-family: var(--num); font-variant-numeric: tabular-nums; letter-spacing: -0.005em; }
.avgline { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 3 3; opacity: .7; }

/* Inverted against the page rather than another dark card on a dark ground —
   a readout should look like it is floating above the chart, not set into it.
   Inverting through the ink tokens means it flips correctly in both themes
   without a second definition. */
.tip {
  position: absolute; z-index: 5; pointer-events: none; opacity: 0;
  transform: translate(-50%, -100%) translateY(-10px);
  background: var(--ink); color: var(--bg);
  border-radius: 999px; padding: 7px 13px; white-space: nowrap;
  box-shadow: var(--shadow-2);
  transition: opacity .12s var(--ease), transform .12s var(--ease);
}
.tip.on { opacity: 1; transform: translate(-50%, -100%) translateY(-13px); }
.tip .t-d { font-size: var(--t-xs); opacity: .62; margin-bottom: 2px; }
.tip .t-r { display: flex; align-items: center; gap: 7px; font-size: var(--t-sm); white-space: nowrap; }
.tip .t-r + .t-r { margin-top: 1px; }
.tip .t-k { width: 7px; height: 7px; border-radius: 999px; flex: none; }
.tip .t-v { margin-left: auto; padding-left: 10px; font-family: var(--num); font-weight: 600; }

.legend { display: flex; gap: 14px; align-items: center; }
.legend button { appearance: none; cursor: pointer; background: none; border: 0; font: inherit; display: flex; align-items: center; gap: 6px; font-size: var(--t-sm); color: var(--ink-2); padding: 0; }
.legend button[aria-pressed="false"] { opacity: .38; }
/* A rounded chip, not a hairline — big enough to carry a colour at a glance. */
.legend i { width: 11px; height: 11px; border-radius: 4px; }
/* The dashed series gets a dimmed chip, so the key matches its line. */
.legend button[data-s="revenue"] i { opacity: .6; }

/* Radar — a closer's skill profile. Axis labels are buttons: each opens that
   skill's week-by-week trend. */
.radar-wrap { display: flex; align-items: center; justify-content: center; padding: 6px 0; }
.radar-wrap svg { width: 100%; max-width: 430px; height: auto; }
.radar text { font-size: 10px; fill: var(--ink-2); font-family: var(--sans); }
.radar .rgrid { fill: none; stroke: var(--border); stroke-width: 1; }
.radar .rspoke { stroke: var(--border); stroke-width: 1; }
.radar .rarea { fill: var(--series-1); fill-opacity: .16; stroke: var(--series-1); stroke-width: 2; stroke-linejoin: round; }
.radar .rprev { fill: none; stroke: var(--ink-3); stroke-width: 1.5; stroke-dasharray: 3 3; }
.radar .rdot { fill: var(--series-1); stroke: var(--surface); stroke-width: 2; }

.skills { display: flex; flex-direction: column; gap: 1px; }
.skill {
  display: grid; grid-template-columns: minmax(0,1fr) 54px 40px; align-items: center; gap: 10px;
  padding: 7px 8px; border-radius: var(--r-sm); cursor: pointer; border: 0; background: none;
  font: inherit; text-align: left; color: var(--ink); width: 100%;
}
.skill:hover { background: var(--surface-2); }
.skill[aria-pressed="true"] { background: var(--surface-3); }
.skill-n { font-size: var(--t-md); display: flex; flex-direction: column; gap: 5px; min-width: 0; }
/* display:block — a bare inline span ignores height and the track vanishes. */
.skill-t { display: block; height: 4px; border-radius: 2px; background: var(--surface-3); overflow: hidden; }
.skill-t i { display: block; height: 100%; border-radius: 2px; background: var(--series-1); }
.skill-v { font-family: var(--num); font-size: var(--t-sm); font-weight: 600; text-align: right; }
.skill-delta { font-family: var(--num); font-size: var(--t-xs); text-align: right; }
.skill-delta.up { color: var(--good); } .skill-delta.down { color: var(--bad); }

/* ================================================================= login == */
.login { min-height: 100vh; display: grid; place-items: center; padding: 24px; background: var(--bg); }
.login-card { width: min(380px, 100%); display: flex; flex-direction: column; gap: 18px; }
.login-card .logo { justify-content: flex-start; }
.login h1 { font-size: var(--t-xl); font-weight: 600; letter-spacing: -0.02em; }
.login p.lede { font-size: var(--t-md); color: var(--ink-3); }
.demo-keys { display: flex; flex-direction: column; gap: 6px; }
.demo-key {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; cursor: pointer;
  font: inherit; font-size: var(--t-sm); padding: 9px 11px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--border); color: var(--ink);
}
.demo-key:hover { border-color: var(--ink-3); }
.demo-key b { font-weight: 550; }
/* :last-of-type, not `span` — the avatar is a span too, and a second auto
   margin would split the free space and centre the row. */
.demo-key > span:last-of-type { color: var(--ink-3); margin-left: auto; font-family: var(--num); font-size: var(--t-xs); }

/* ============================================================== utilities == */
.empty { padding: 40px 16px; text-align: center; color: var(--ink-3); font-size: var(--t-md); }
.empty svg { width: 22px; height: 22px; margin-bottom: 8px; stroke-width: 1.5; opacity: .6; }
.row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.col { display: flex; flex-direction: column; gap: 8px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
a.link { color: var(--series-1); text-decoration: none; }
a.link:hover { text-decoration: underline; }

.toast {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 80;
  display: flex; align-items: center; gap: 9px; padding: 10px 15px; border-radius: var(--r);
  background: var(--action); color: var(--ink-on); font-size: var(--t-sm); font-weight: 500;
  box-shadow: var(--shadow-2); animation: rise .2s var(--ease);
}

/* ============================================================ responsive == */
@media (max-width: 1180px) { .grid.side { grid-template-columns: minmax(0, 1fr); } .grid.c4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .rail { position: static; height: auto; flex-direction: row; align-items: center; gap: 8px; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border); }
  .rail-top { padding: 12px 14px; } .logo-sub { display: none; }
  .nav { flex-direction: row; padding: 8px; gap: 2px; }
  .nav-label { display: none; } .nav a { white-space: nowrap; }
  .rail-foot { border-top: 0; padding: 8px; } .whoami-t { display: none; }
  .grid.c2, .grid.c3, .grid.c4 { grid-template-columns: minmax(0, 1fr); }
  .page, .topbar { padding-left: 14px; padding-right: 14px; }
  .fields.c2 { grid-template-columns: 1fr; }
  .qcard { grid-template-columns: auto minmax(0,1fr); gap: 10px; }
  .qactions { grid-column: 1 / -1; justify-content: flex-start; flex-wrap: wrap; }
}

/* ============================================================================
   The admin's Closer view. Deliberately the loudest thing on the page — an
   admin who forgets which mode they're in is the one about to file a report
   on somebody's real call.
   ========================================================================== */
.preview-bar {
  position: sticky; top: 57px; z-index: 19;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 24px;
  background: var(--warn-bg); color: var(--warn);
  border-bottom: 1px solid var(--border);
  font-size: var(--t-sm);
}
.preview-bar b { font-weight: 650; }
/* Real data gets the calmer info colour — the amber is for "this isn't real". */
.preview-bar.real { background: var(--info-bg); color: var(--ink-2); }
.preview-bar.real b { color: var(--ink); }
.preview-bar .ico { width: 15px; height: 15px; flex: none; }
.preview-bar .sel select { background: var(--surface); border-color: var(--border-strong); color: var(--ink); }
.preview-bar .btn { background: var(--surface); }

@media (max-width: 900px) {
  .preview-bar { position: static; padding: 10px 14px; }
}

/* ========================================================== payments views == */

.gen-timeline {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 18px 20px;
}

.gen-tl-items {
  display: flex;
  flex-direction: column;
  gap: 12px;
  position: relative;
}

.gen-tl-node {
  display: flex;
  align-items: center;
  gap: 12px;
  position: relative;
}

.gen-tl-node:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 18px;
  bottom: -10px;
  width: 2px;
  background: var(--border);
}

.gen-tl-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--series-1);
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--border-strong);
  flex-shrink: 0;
  z-index: 1;
}

.gen-tl-dot.first {
  background: var(--series-2);
}

.gen-tl-info {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.gen-tl-day {
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--ink);
}

.gen-tl-lbl {
  font-size: var(--t-xs);
  color: var(--ink-3);
}

.gen-tl-amt {
  font-size: var(--t-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.gen-tl-foot {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--t-sm);
}

.gen-tl-foot b {
  font-size: var(--t-md);
  color: var(--series-2);
  font-variant-numeric: tabular-nums;
}

.gen-result-card {
  max-width: 620px;
  margin: 20px auto;
}

.gen-check-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto;
  border-radius: 50%;
  background: var(--good-bg);
  color: var(--good);
  display: flex;
  align-items: center;
  justify-content: center;
}

.gen-check-icon .ico {
  width: 28px;
  height: 28px;
}

.gen-link-box {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 10px 14px;
  margin-bottom: 16px;
}

.gen-url-text {
  font-family: var(--font-mono, monospace);
  font-size: var(--t-xs);
  color: var(--series-1);
  word-break: break-all;
  flex: 1;
  text-align: left;
}

.gen-url-short {
  font-family: var(--font-mono, monospace);
  font-size: var(--t-xs);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
}

.gen-res-meta {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  text-align: left;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 14px 18px;
  font-size: var(--t-sm);
}

.gen-res-meta span {
  font-size: var(--t-xs);
  color: var(--ink-3);
  display: block;
}

.gen-res-meta b {
  color: var(--ink);
}

.btn-sm {
  padding: 4px 8px;
  font-size: var(--t-xs);
  height: auto;
}

.row-clickable {
  cursor: pointer;
}

.row-clickable:hover {
  background: var(--surface-2) !important;
}

.badge.warn {
  background: var(--warn-bg);
  color: var(--warn);
  border: 1px solid var(--warn);
}

.row-age-red {
  background: rgba(239, 68, 68, 0.08) !important;
  border-left: 3px solid #ef4444 !important;
}

.row-age-red:hover {
  background: rgba(239, 68, 68, 0.16) !important;
}

.row-age-orange {
  background: rgba(249, 115, 22, 0.08) !important;
  border-left: 3px solid #f97316 !important;
}

.row-age-orange:hover {
  background: rgba(249, 115, 22, 0.16) !important;
}




/* ------------------------------------------------------------------ fold -- */
/* Calls booked further out are reference, not work, so they arrive folded.
   <details> rather than a button and a class: the open state is the element's
   own, it survives a re-render without being tracked anywhere, and a keyboard
   reaches it for free. */
.fold-card { padding: 0; }
.fold > summary {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 13px 16px; cursor: pointer; list-style: none;
  transition: background .12s var(--ease);
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary:hover { background: var(--surface-2); }
.fold > summary h2 { font-size: var(--t-md); font-weight: 600; letter-spacing: -0.01em; }
.fold > summary .hint { font-size: var(--t-sm); color: var(--ink-3); }
/* The chevron is the affordance — it points where opening will take you. */
.fold > summary svg { color: var(--ink-3); transform: rotate(90deg); transition: transform .15s var(--ease); }
.fold[open] > summary svg { transform: rotate(-90deg); }
.fold[open] > summary { border-bottom: 1px solid var(--border); }

.fold-day + .fold-day { margin-top: 16px; }
.fold-day-h {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 7px;
  font-size: var(--t-sm); font-weight: 600;
}
.fold-day-h .hint { font-weight: 400; color: var(--ink-3); }
.fold-more { margin-top: 14px; font-size: var(--t-sm); color: var(--ink-3); }

/* A booked call is not overdue and must not borrow the colour of one. Grey
   rail, full contrast text: quiet, not disabled. */
.qcard.age-ahead { border-left-color: var(--border-strong); }

/* ------------------------------------------------------- credential boxes -- */
/* Masked without type="password". Browsers and password managers autofill a
   password input on sight, and a settings page full of them invites exactly
   the silent overwrite that makes a pasted key save as something else. */
.inp.masked { -webkit-text-security: disc; text-security: disc; font-family: var(--num); letter-spacing: .04em; }
.inp.masked.unmasked { -webkit-text-security: none; text-security: none; }
