/* ============================================================================
   PureOutbound console.

   Colours, type scale, radii and shadows are the tokens published in the Figma
   design system (file YeyZdELT5qNTCSvR4U8Tx3), read from Figma variable
   definitions rather than sampled off a screenshot — so primary/base-500 here
   really is primary/base-500 there.

   Two deliberate departures from the Figma, both noted where they occur:
     * a dark theme derived from the same tokens, because the design is
       light-only and this console gets read at 2am on a dialer floor;
     * our own information architecture, because the product grew past the
       screens that were designed (ASR, blocked-vs-labelled, rotation, alerts).
   ========================================================================= */

:root {
  color-scheme: light dark;

  /* --- brand -------------------------------------------------- Figma tokens */
  --primary-500: #36b3ce;   /* primary/base-500   */
  --primary-200: #94dae2;   /* primary/light-200  */
  --primary-50:  #eaf8f9;   /* primary/lighter-50 */
  /* Darkened for contrast: 5.4:1 for white text on it, and 4.9:1 or better as
     link text on every surface. #2189a1 measured 4.07 and 3.72. */
  --primary-700: #1b7488;

  /* --- neutrals ------------------------------------------------------------ */
  --text-strong: #020617;   /* text/strong-950 */
  --text-sub:    #475569;   /* text/sub-600    */
  --icon-soft:   #5b6b80;   /* icon/soft-500, one step darker: 5.0:1 on the page grey - see --fg-faint */
  --bg-white:    #ffffff;   /* bg/white-0      */
  --bg-softer:   #f1f5f9;   /* bg/softer-100   */
  --bg-soft:     #e2e8f0;   /* bg/soft-200     */
  --stroke-soft: #e1e4ea;   /* stroke/soft-200 */
  --stroke-sub:  #cbd5e1;   /* stroke/sub-300  */

  /* --- state ------------------------------------------------- state/* tokens */
  --success-500: #10b981;  --success-50: #ecfdf5;  --success-700: #047857;  --success-200: #a7f3d0;
  --warning-500: #f59e0b;  --warning-50: #fffbeb;  --warning-700: #b45309;  --warning-200: #fde68a;
  --error-500:   #f43f5e;  --error-50:   #fff1f2;  --error-700:   #be123c;  --error-200:   #fecdd3;
  /* Blocking is its own diagnosis, so it gets its own hue rather than
     borrowing error red, which already means "performing badly". */
  --blocked-500: #8b5cf6;  --blocked-50: #f5f3ff;  --blocked-700: #6d28d9;

  /* --- page surfaces -------------------------------------------------------- */
  --page: var(--bg-softer);
  --card: var(--bg-white);
  --hover: var(--bg-softer);
  /* Row banding and group headers. Derived from the neutral ramp rather than a
     new hue: banding must be trackable by the eye and invisible to judgement,
     so it can never be mistaken for a status the way a tinted row would be. */
  --band: #fafbfc;
  --group-bg: var(--bg-softer);
  --line: var(--stroke-soft);
  --line-strong: var(--stroke-sub);
  --fg: var(--text-strong);
  --fg-dim: var(--text-sub);
  /* Secondary text: column headers, units, and every "N calls" under a figure.
     This was Figma's icon/soft-400, which is a fine colour for an ICON and
     2.56:1 against white — well under the 4.5:1 small text needs, while
     carrying most of the labels on the page. One step darker in light and one
     lighter in dark reaches 4.8:1 and 5.5:1 without touching the hierarchy: it
     still reads as quieter than body text, it is simply legible now. */
  --fg-faint: var(--icon-soft);
  --accent: var(--primary-500);
  /* Text on a solid fill of --primary-700, --success-700 or --fg-faint. White
     in light; in dark those fills turn light, so the text turns dark. White on
     the dark theme's teal measured 1.63:1. */
  --on-strong: #ffffff;
  /* Keyboard focus: at least 3:1 against every surface it lands on. */
  --focus: var(--primary-700);
  --accent-ink: var(--primary-700);
  /* --primary-700 is tuned to clear 4.5:1 on WHITE. On the tinted --primary-50
     card it only reaches 3.70:1, so figures set inside those cards — the
     carrier response-code counts, the warm/test pills — need one step darker
     again. Same hue, so the tint still reads as one family. */
  --accent-ink-strong: #186b7f;
  /* Daily-composition bands. A sequential ramp in the brand hue, stepped with
     scripts/validate_palette.js rather than by eye: adjacent pairs clear
     deltaE 16.5 under protanopia and 17.6 at normal vision. The pairing this
     replaced (primary-200 beside stroke-sub) measured 0.4 protan. */
  --band-reached:    #0e4f60;
  --band-answered:   #2f9fbc;
  --band-nocomplete: #8ed3e3;

  /* --- radii --------------------------------------------- border-radius/* */
  --r-xs: 4px; --r-md: 6px; --r-lg: 8px; --r-xl: 12px; --r-full: 9999px;

  /* --- shadows ------------------------------------------------- Shadows/* */
  --shadow-xs: 0 1px 2px #1018280d;
  --shadow-md: 0 16px 32px -12px #0e121b1a;

  /* --- type ------------------------------------------------- font-family/* */
  /* Haskoy is the designed face. It is not on Google Fonts and this ships to
     boxes that may have no internet, so it is asked for first and then falls
     through to a system stack rather than blocking on a webfont. */
  --font: Haskoy, "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont,
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;

  /* --- app shell ------------------------------------------------------------
     One content width for the whole app, centred on wide screens. The gutter
     expression keeps the header and tab bar full-bleed while their CONTENT
     lines up with the page below, so the logo sits on the same left edge as
     the first card instead of drifting to the window edge. */
  --shell: 1500px;
  --gutter: max(24px, calc((100% - var(--shell)) / 2));
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --primary-500: #45c3dd; --primary-200: #1e6d80; --primary-50: #0e2c34; --primary-700: #7fd8ea;
    --text-strong: #e8eef2; --text-sub: #9fb0bd; --icon-soft: #7e93a3;
    --bg-white: #131b21; --bg-softer: #0d1418; --bg-soft: #1d272e;
    --stroke-soft: #223039; --stroke-sub: #2d3d48;
    --success-500: #34d399; --success-50: #0d2a20; --success-700: #6ee7b7; --success-200: #14532d;
    --warning-500: #fbbf24; --warning-50: #2b210c; --warning-700: #fcd34d; --warning-200: #4a3410;
    --error-500: #fb7185; --error-50: #2e1319; --error-700: #fda4af; --error-200: #4c1d24;
    --blocked-500: #a78bfa; --blocked-50: #1e1733; --blocked-700: #c4b5fd;
    --shadow-xs: 0 1px 2px #0000004d;
    --shadow-md: 0 16px 32px -12px #00000066;
    /* Banding LIFTS in dark rather than dropping. A darker band on a near-black
       card sinks into the page and stops tracking the row, which is the only
       job it has. */
    --band: #182229;
    /* In dark the tinted card is the DARK surface and its ink is the light
       one, so "stronger" means lighter here, not darker. */
    --accent-ink-strong: #a5e6f3;
    /* Chosen against the dark surface, not derived from the light steps: on a
       near-black card the strongest band has to be the LIGHTEST. Validated at
       deltaE 21.9 protan / 22.4 normal. */
    --band-reached:    #8fe6f8;
    --band-answered:   #2f9fbc;
    --band-nocomplete: #1c4a59;
    --on-strong: #062c36;
    --focus: var(--primary-500);
  }
}

:root[data-theme="dark"] {
  --primary-500: #45c3dd; --primary-200: #1e6d80; --primary-50: #0e2c34; --primary-700: #7fd8ea;
  --text-strong: #e8eef2; --text-sub: #9fb0bd; --icon-soft: #7e93a3;
  --bg-white: #131b21; --bg-softer: #0d1418; --bg-soft: #1d272e;
  --stroke-soft: #223039; --stroke-sub: #2d3d48;
  --success-500: #34d399; --success-50: #0d2a20; --success-700: #6ee7b7; --success-200: #14532d;
  --warning-500: #fbbf24; --warning-50: #2b210c; --warning-700: #fcd34d; --warning-200: #4a3410;
  --error-500: #fb7185; --error-50: #2e1319; --error-700: #fda4af; --error-200: #4c1d24;
  --blocked-500: #a78bfa; --blocked-50: #1e1733; --blocked-700: #c4b5fd;
  --shadow-xs: 0 1px 2px #0000004d;
  --shadow-md: 0 16px 32px -12px #00000066;
  --band: #182229;
  --accent-ink-strong: #a5e6f3;
  --band-reached:    #8fe6f8;
  --band-answered:   #2f9fbc;
  --band-nocomplete: #1c4a59;
  --on-strong: #062c36;
  --focus: var(--primary-500);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

body {
  margin: 0;
  /* Column flex so the footer's margin-top:auto pins it to the window bottom on
     a short panel (Diagnostics, an empty History) instead of floating mid-page. */
  min-height: 100vh; display: flex; flex-direction: column;
  background: var(--page);
  color: var(--fg);
  font-family: var(--font);
  /* Paragraph/Small: 14 / 20, -0.6 tracking */
  font-size: 0.875rem; line-height: 1.25rem; letter-spacing: -0.006em;
  -webkit-font-smoothing: antialiased;
}

/* ------------------------------------------------------------------ chrome */

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; flex-wrap: wrap; padding: 12px var(--gutter);
  background: var(--card); border-bottom: 1px solid var(--line);
}

.brand { display: flex; align-items: center; }
/* The supplied lockup is a 161x20 bitmap. Rendered at its native size it is
   pixel-exact; height is fixed and width left auto so it never distorts. */
.brand .lockup { height: 20px; width: auto; display: block; }

.controls { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; }
.ctl { display: flex; flex-direction: column; gap: 4px; }
.ctl > span {
  /* Subheading/X Small: 12 / 16, semibold, wide tracking, uppercase.
     Was set at 11px despite this comment naming 12 - the token said one thing
     and the rule did another. */
  font-size: 0.75rem; font-weight: 600; line-height: 1rem;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim);
}

select, .btn {
  font: inherit; font-size: 0.875rem; color: var(--fg);
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 8px 12px; box-shadow: var(--shadow-xs);
}
select:hover, .btn:hover { border-color: var(--line-strong); }
select:focus-visible, .btn:focus-visible, .tab:focus-visible, a:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.btn { cursor: pointer; font-weight: 500; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
/* White on --primary-500 measured 2.50:1. This button writes caller IDs to a
   live dialer; it has to be the most legible control on the page, not the
   least. --primary-700 carries white at 4.6:1. */
.btn-primary { background: var(--primary-700); border-color: var(--primary-700); color: var(--on-strong); font-weight: 600; }
.btn-primary:hover { background: var(--accent-ink-strong); border-color: var(--accent-ink-strong); }
.btn-danger { background: transparent; border-color: var(--error-500); color: var(--error-500); }

.tabs {
  display: flex; gap: 4px; padding: 0 var(--gutter);
  background: var(--card); border-bottom: 1px solid var(--line);
  /* Wraps rather than scrolls: a scrolling bar clips the DID Health menu,
     and with the reports grouped under it the bar is short enough to wrap. */
  flex-wrap: wrap; position: relative; z-index: 30;
}
.tab {
  font: inherit; font-size: 0.875rem; font-weight: 500;
  background: none; border: 0; cursor: pointer; color: var(--fg-dim);
  padding: 12px 14px; border-bottom: 2px solid transparent; white-space: nowrap;
}
.tab:hover { color: var(--fg); }
/* --primary-700 on white measured 4.07:1 - under the floor on the one label
   that tells an operator which of nine pages they are looking at. */
.tab.is-active { color: var(--accent-ink-strong); border-bottom-color: var(--primary-500); font-weight: 600; }

main { padding: 24px var(--gutter) 48px; }

/* Footer. Same --gutter as the topbar and main so the three stay aligned to one
   edge, with the rule running full bleed across the window. */
.sitefoot {
  margin-top: auto; padding: 24px var(--gutter);
  background: var(--card); border-top: 1px solid var(--line);
}
.sitefoot-in { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.sitefoot .lockup { height: 18px; width: auto; display: block; opacity: 0.75; }
.sitefoot-note { margin: 0; flex: 1 1 320px; font-size: 0.75rem; line-height: 1.125rem; color: var(--fg-faint); }
.sitefoot-meta { margin: 0; font-size: 0.75rem; color: var(--fg-faint); font-variant-numeric: tabular-nums; }

.panel-head { margin-bottom: 16px; }
.panel-head h1, .panel-head h2 {
  /* Title/Title 1: 24 / 32, semibold */
  margin: 0 0 4px; font-size: 1.5rem; line-height: 2rem; font-weight: 600; letter-spacing: -0.02em;
}
.hint { margin: 0; color: var(--fg-dim); font-size: 0.875rem; max-width: 74ch; }
h3 { font-size: 1rem; line-height: 1.5rem; font-weight: 600; letter-spacing: -0.01em; margin: 0 0 8px; }

/* ----------------------------------------------------------------- summary */

.summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); gap: 16px; margin-bottom: 24px; }
.stat {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--shadow-xs);
  padding: 16px 20px; display: flex; flex-direction: column; gap: 4px;
}
.stat-v { font-size: 1.5rem; line-height: 2rem; font-weight: 600; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.stat-l { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim); }
.stat-l i { display: block; font-style: normal; text-transform: none; letter-spacing: -0.006em; font-weight: 400; font-size: 0.75rem; }

/* ------------------------------------------------------------------ tables */

.tablewrap {
  overflow-x: auto; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--shadow-xs);
}
table.grid {
  border-collapse: collapse; width: 100%; font-size: 0.875rem;
  /* Every figure in every grid, not just the cells that remembered to ask.
     Proportional digits make a column of numbers ragged on the decimal, which
     is the one thing a scanning eye uses to compare magnitude. */
  font-variant-numeric: tabular-nums;
}
table.grid th {
  /* Was 11px at --fg-faint on --bg-softer: 4.34:1, under the 4.5 floor, on
     every column header in the product. One step up in size and one darker in
     colour clears it without promoting the header above the data. */
  text-align: left; font-size: 0.75rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--fg-dim); padding: 11px 16px;
  border-bottom: 1px solid var(--line-strong); background: var(--bg-softer);
  position: sticky; top: 0; white-space: nowrap; z-index: 2;
}
table.grid td { padding: 11px 16px; border-bottom: 1px solid var(--line); }
/* Cells default to one line because most carry a figure; the ones that carry a
   sentence opt out. A table-wide nowrap is what pushed Carrier health 95px
   past its own wrapper and put a horizontal scrollbar inside a vertical one. */
table.grid td:not(.wrap) { white-space: nowrap; }
table.grid td.wrap { white-space: normal; max-width: 34ch; line-height: 1.45; }
table.grid tbody tr:last-child td { border-bottom: 0; }

/* Banding. 25 rows x 12 columns x 1,375px of travel needs more than a hairline
   to keep the eye on one row; a 2%-alpha tint is enough to track by and not
   enough to read as a state. */
table.grid.zebra tbody tr:nth-child(even of :not(.rowgroup, .rowdrill)) { background: var(--band); }
table.grid tbody tr.clickable { cursor: pointer; }
table.grid tbody tr.clickable:hover { background: var(--hover); }
table.grid tbody tr.clickable:focus-visible {
  outline: 2px solid var(--focus); outline-offset: -2px; background: var(--hover);
}

/* Row groups: the answer to "which number do I pull" before a single column is
   read. Only rendered in the table's own ranked order - sorting a column
   flattens them, because a group header inside an arbitrary sort is a lie. */
table.grid tbody tr.rowgroup td {
  position: sticky; top: 41px; z-index: 1;
  padding: 7px 16px; background: var(--group-bg); border-bottom: 1px solid var(--line);
  border-top: 1px solid var(--line-strong);
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; color: var(--fg-dim);
  text-transform: uppercase;
}
table.grid tbody tr.rowgroup:first-child td { border-top: 0; }
table.grid tbody tr.rowgroup td b { color: var(--fg); font-weight: 600; }
/* The count reads as part of the title otherwise — "PULL NOW 1" looks like a
   label, not a heading and a quantity. */
.rg-n {
  display: inline-block; margin-left: 8px; padding: 1px 7px;
  border-radius: var(--r-full); background: var(--bg-soft); color: var(--fg-dim);
  font-variant-numeric: tabular-nums; letter-spacing: 0;
}
table.grid tbody tr.rowgroup td i {
  font-style: normal; text-transform: none; letter-spacing: 0; font-weight: 400;
  color: var(--fg-faint); margin-left: 8px;
}

/* Long lists: search and group chips above the table, and the rest of a group
   one click away inside it. See listTable() in app.js. */
.list-tools {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 0 0 12px;
}
.list-search {
  font: inherit; font-size: 0.875rem; width: min(100%, 300px); padding: 7px 12px;
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  background: var(--card); color: var(--fg);
}
.list-search:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.list-tools .tl-filters { flex: 1 1 auto; }
.chip-n { margin-left: 6px; font-variant-numeric: tabular-nums; opacity: .75; }
.list-count { margin-left: auto; font-size: 0.75rem; color: var(--fg-faint); font-variant-numeric: tabular-nums; }
/* Pages under a list: which rows these are, how many to a page, and the way through them. */
.list-tools { scroll-margin-top: 96px; }
.list-pager { margin-top: 12px; }
.list-pager[hidden] { display: none; }
.pager { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; font-size: 0.875rem; }
.pager-range { color: var(--fg-dim); font-variant-numeric: tabular-nums; }
.pager-size { padding-block: 6px; }
.pager-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-left: auto; }
.pager-btn { padding: 6px 12px; }
.pager-btn:disabled { opacity: .45; cursor: not-allowed; }
.pager-at { padding: 0 8px; color: var(--fg); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.paged-list > .list-pager { margin-top: 10px; }
.plan-sort { padding-block: 6px; }
.plan-filters { flex: 1 1 100%; }
#plan-pager { margin: 16px 0 28px; }
/* Area codes: all of them, or by state. */
/* Geography: a state's area codes, opened under the state table. */
.geo-state-link { font-weight: 600; color: var(--fg); }
.geo-state-link[aria-expanded="true"] { color: var(--accent-ink-strong); }
/* The row holding it is part of the state table but is not a data row. */
table.grid tbody tr.rowdrill > td { padding: 4px 16px 16px; background: var(--bg-softer); white-space: normal; }
table.grid tbody tr.rowdrill:hover > td { background: var(--bg-softer); }
.geo-drill { margin: 0; box-shadow: none; }
.geo-drill .card-head { align-items: center; }
#geo-drill-sub { margin: 0 0 12px; }
@media (max-width: 640px) {
  .pager-nav { margin-left: 0; width: 100%; flex-wrap: nowrap; }
  /* Previous, the page, Next: First and Last do not fit beside them on a phone. */
  .pager-nav > .pager-btn:first-child, .pager-nav > .pager-btn:last-child { display: none; }
  .pager-at { flex: 1 1 auto; text-align: center; }
}
@media (max-width: 640px) {
  .list-search { width: 100%; }
  .list-count { margin-left: 0; }
}

/* A rule between the column families - identity | measures | status - so the
   eye reads three groups rather than twelve peers. */
table.grid th.gstart, table.grid td.gstart { border-left: 1px solid var(--line); }

/* A phone-number column. Sized to its content rather than sharing the table's
   leftover width: Best number and Runner-up together were taking 819px — 59% of
   the table — to carry about 110px of glyphs. */
table.grid th.numcol, table.grid td.numcol { width: 1%; white-space: nowrap; }
.runner { font-weight: 500; }

.num { text-align: right; font-variant-numeric: tabular-nums; }
th.num { text-align: right; }
.did { font-weight: 600; font-variant-numeric: tabular-nums; }
.sub { color: var(--fg-faint); font-size: 0.8125rem; }
.muted { color: var(--fg-faint); }

.score { position: relative; }
.score-bar { position: absolute; inset: 4px auto 4px 6px; border-radius: var(--r-md); background: var(--primary-50); }
.score-v { position: relative; font-weight: 600; }

/* ------------------------------------------------------------------- pills */

.pill {
  display: inline-block; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.02em;
  padding: 3px 10px; border-radius: var(--r-full); text-transform: uppercase;
}
.pill-promote { color: var(--success-700); background: var(--success-50); }
.pill-keep    { color: var(--fg-dim);      background: var(--bg-softer); }
.pill-watch   { color: var(--warning-700); background: var(--warning-50); }
.pill-test    { color: var(--accent-ink-strong); background: var(--primary-50); }
.pill-warm    { color: var(--accent-ink-strong); background: var(--primary-50); }
.lifecycle { margin: 12px 0 16px; padding: 12px 14px; border-radius: 8px; background: var(--bg-softer); }
.lifecycle p { margin: 0 0 8px; }
.lifecycle .ops { display: flex; gap: 8px; flex-wrap: wrap; }
.lifecycle .ops button { font-size: 0.8125rem; padding: 7px 12px; }

/* The in-drawer lifecycle form, replacing two chained window.prompt() boxes. */
.lc-form {
  margin-top: 12px; padding: 14px; border-radius: var(--r-lg);
  background: var(--card); border: 1px solid var(--line-strong);
}
.lc-form h4 { margin: 0 0 6px; font-size: 0.875rem; }
.lc-why { margin: 0 0 12px; font-size: 0.8125rem; color: var(--fg-dim); line-height: 1.5; }
.lc-field { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; font-size: 0.8125rem; color: var(--fg-dim); }
.lc-field input {
  font: inherit; padding: 7px 10px; border: 1px solid var(--line-strong);
  border-radius: var(--r-md); background: var(--card); color: var(--fg);
}
.lc-field input[type="number"] { width: 84px; font-variant-numeric: tabular-nums; }
.lc-field input[type="text"] { flex: 1; min-width: 0; }
.lc-field input:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.lc-actions { display: flex; gap: 8px; margin-top: 4px; }
.ramp { display: flex; align-items: flex-end; gap: 3px; height: 34px; margin: 8px 0 4px; }
.ramp span { flex: 1; min-width: 6px; background: var(--primary-200, #bcd); border-radius: 2px 2px 0 0; opacity: .45; }
.ramp span.done { opacity: 1; background: var(--primary-500, #58a); }
.ramp span.today { opacity: 1; background: var(--primary-700, #246); }
.pill-rest    { color: var(--error-700);   background: var(--error-50); }
.pill-retire  { color: var(--error-700);   background: var(--error-50); }
.pill-unblock { color: var(--blocked-700); background: var(--blocked-50); }

/* The merged status cell: verb first, then only what is not ordinary. */
.statuscell { line-height: 1.35; }
.statuscell .st-trend { margin-left: 8px; font-size: 0.75rem; }
.statuscell .st-state {
  display: block; margin-top: 3px; font-size: 0.75rem; color: var(--fg-faint);
}

.health-stable    { color: var(--fg-faint); }
.health-improving { color: var(--success-700); font-weight: 500; }
.health-declining { color: var(--warning-700); font-weight: 500; }
.health-labelled  { color: var(--error-700);   font-weight: 600; }
.health-blocked   { color: var(--blocked-700); font-weight: 600; }
.health-unproven  { color: var(--fg-faint); font-style: italic; }

/* ------------------------------------------------------------------ charts */

.split {
  display: grid; gap: 16px; margin-top: 16px; align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
}
.split > .card > h3 { margin-top: 0; }

.bars { display: flex; flex-direction: column; gap: 4px; }
.bar-row { display: grid; grid-template-columns: 66px 56px 1fr 66px; align-items: center; gap: 10px; font-size: 0.8125rem; }
.bar-row > .k { color: var(--fg-dim); font-variant-numeric: tabular-nums; }
.bar-row > .v { text-align: right; font-variant-numeric: tabular-nums; font-weight: 500; }
.bar-track { background: var(--bg-soft); border-radius: var(--r-md); height: 18px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--primary-200); border-radius: var(--r-md); }
.bar-fill.peak { background: var(--primary-500); }
.bar-row > .n { color: var(--fg-faint); font-size: 0.75rem; text-align: right; font-variant-numeric: tabular-nums; }

#heatmap { overflow-x: auto; }
/* Stretch to the card. At a fixed 32px per cell the grid used about a fifth of
   the width and the rest of the card sat empty; min-width keeps it legible and
   the wrapper scrolls sideways on narrow screens. */
table.heat { border-collapse: separate; border-spacing: 3px; font-size: 0.75rem; width: 100%; }
table.heat th { color: var(--fg-dim); font-weight: 600; padding: 2px 6px; font-variant-numeric: tabular-nums; }
/* 10px was most of why this was hard to read, whatever the colours did. */
table.heat td {
  min-width: 34px; height: 32px; border-radius: var(--r-md); text-align: center;
  font-size: 0.75rem; font-weight: 600; color: #fff; font-variant-numeric: tabular-nums;
}
table.heat td.empty { background: var(--bg-soft); color: transparent; }

.heat-legend {
  display: flex; align-items: center; gap: 8px; margin-top: 14px;
  font-size: 0.75rem; color: var(--fg-faint); font-variant-numeric: tabular-nums;
}
.heat-ramp { display: flex; gap: 2px; }
.heat-ramp i { display: block; width: 24px; height: 10px; border-radius: 2px; }

/* The shaded figure inside a table cell. min-width keeps the chips a common
   size so the column still scans as a column, not a ragged edge. */
.heat-chip {
  display: inline-block; min-width: 54px; padding: 3px 8px; border-radius: var(--r-md);
  font-weight: 600; font-variant-numeric: tabular-nums; text-align: right;
}

/* The Geography map: the map with its legend, and a side panel for whichever
   state is under the pointer. The panel stacks under the map on a phone. */
.geo-map { display: grid; grid-template-columns: minmax(0, 1fr) 240px; gap: 20px; align-items: start; }
.geo-map-main { min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.geo-svg { display: block; width: 100%; height: auto; max-height: 520px; }
.geo-st {
  stroke: var(--card); stroke-width: 1; stroke-linejoin: round; cursor: pointer;
  transition: opacity .12s ease-out;
}
.geo-none { fill: var(--bg-soft); }
/* Too few calls to judge: shown, but quieter than the states that count. */
.geo-thin { opacity: .45; }
.geo-refusing { stroke: var(--error-700); stroke-width: 2.5; }
.geo-screening { stroke: var(--warning-700); stroke-width: 2; stroke-dasharray: 5 3; }
/* Lifting the picked state stops a dimmed state reading as "not picked". */
.geo-st.geo-on { opacity: 1; stroke: var(--fg); stroke-width: 2.5; }
.geo-svg:has(.geo-on) .geo-st:not(.geo-on):not(.geo-thin) { opacity: .55; }
.geo-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 24px; }
.geo-legend .heat-legend { margin-top: 0; flex-wrap: wrap; }
.geo-keys { list-style: none; margin: 0; padding: 0; gap: 6px 14px; }
.geo-keys .sw { width: 12px; height: 12px; }
.geo-key-refusing  { border: 2px solid var(--error-700); }
.geo-key-screening { border: 2px dashed var(--warning-700); }
.geo-key-thin      { background: var(--primary-200); opacity: .45; }
.geo-key-none      { background: var(--bg-soft); }

.geo-detail {
  display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; min-height: 180px;
  border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--band);
}
.geo-detail p { margin: 0; }
.gd-name { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 0.9375rem; }
.gd-figs { display: grid; grid-template-columns: repeat(3, auto); gap: 4px 14px; margin: 0; justify-content: start; }
.gd-figs dt { font-size: 0.75rem; color: var(--fg-faint); }
.gd-figs dd { margin: 0; font-size: 1rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.gd-figs dd.bad { color: var(--error-700); }
.gd-why { font-size: 0.8125rem; color: var(--fg-dim); }
.gd-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.gd-tip { font-size: 0.75rem; }
.geo-detail .linkish { align-self: flex-start; }

/* "Show in the table" lands on the row and marks it, then lets it go. */
tr.row-ping > td { animation: row-ping 1.6s ease-out; }
@keyframes row-ping { 0%, 30% { background: var(--primary-50); } 100% { background: transparent; } }
@media (prefers-reduced-motion: reduce) { tr.row-ping > td { animation: none; } .geo-st { transition: none; } }

@media (max-width: 780px) {
  .geo-map { grid-template-columns: 1fr; }
  .geo-detail { min-height: 0; }
  .geo-legend .heat-ramp i { width: 16px; }
}

/* Hold the figures together so they can be compared down the column, and let
   the two number columns take the slack instead of spreading everything out. */
#geo-table th:first-child, #geo-table td:first-child { width: 140px; }
#geo-table th:nth-child(2), #geo-table td:nth-child(2),
#geo-table th:nth-child(3), #geo-table td:nth-child(3),
#geo-table th:nth-child(4), #geo-table td:nth-child(4),
#geo-table th:nth-child(5), #geo-table td:nth-child(5) { width: 104px; }

/* Carrier refusals by state: ten columns, six of them a single figure.
   Sharing the width equally gave "Calls" a tenth of a wide screen while the
   three columns carrying actual prose — the codes, the numbers refused most
   here, the compliance note — were held to the same tenth and wrapped. Pinning
   each figure to what a figure needs hands the slack to the text, which is the
   only part of the row that can use it. */
#geo-state-table th:first-child, #geo-state-table td:first-child { width: 132px; }
#geo-state-table th:nth-child(2),  #geo-state-table td:nth-child(2),
#geo-state-table th:nth-child(3),  #geo-state-table td:nth-child(3),
#geo-state-table th:nth-child(4),  #geo-state-table td:nth-child(4),
#geo-state-table th:nth-child(5),  #geo-state-table td:nth-child(5),
#geo-state-table th:nth-child(6),  #geo-state-table td:nth-child(6),
#geo-state-table th:nth-child(7),  #geo-state-table td:nth-child(7) { width: 100px; }
/* Capping the figures handed the slack to the three text columns, and the
   codes took all of it: four chips on one row ran the table 250px past the
   card and pushed Compliance off the right edge. The chips wrap perfectly
   well, so the column is held to two rows of them and the other two text
   columns are held to what they need. A table that fits is worth more than
   one that keeps its chips on a single line. */
#geo-state-table th:nth-child(8),  #geo-state-table td:nth-child(8) { width: 300px; max-width: 300px; }
#geo-state-table th:nth-child(9),  #geo-state-table td:nth-child(9) { width: 190px; max-width: 190px; }
#geo-state-table th:nth-child(10), #geo-state-table td:nth-child(10) { width: 180px; max-width: 180px; }
#geo-state-table td:nth-child(9) { white-space: normal; }

/* ------------------------------------------------ one area code's numbers */

/* Nested a level inside the state drill, so it is inset and quieter: it has to
   read as belonging to the area-code row above it, not as a third card
   competing with the two it already sits inside. */
.ac-drill {
  margin: 10px 0 4px 20px; border-left: 3px solid var(--primary-500);
  background: var(--bg-softer);
}
.ac-drill .card-head h4 { margin: 0; font-size: 0.9375rem; font-weight: 600; }
.ac-local { margin-left: 8px; vertical-align: 1px; }
/* The comparison column: better than this area code's own average, or worse. */
#ac-drill-table td.up { color: var(--success-700); font-weight: 600; }
#ac-drill-table td.down { color: var(--error-700); font-weight: 600; }
#ac-drill-table th:nth-child(n+2), #ac-drill-table td:nth-child(n+2) { width: 116px; }

/* -------------------------------------------------------- calling calendar */

.cal-list {
  display: grid; gap: 10px; align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr));
}
.cal-row {
  --sev: var(--icon-soft);
  display: grid; grid-template-columns: 84px 1fr; gap: 14px; align-items: start;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
  box-shadow: var(--shadow-xs); padding: 14px 18px;
}
/* How much the day moves the numbers: a dot beside the date, and on the two
   that matter a border in the same hue, rather than a stripe down one side. */
.cal-severe   { --sev: var(--error-500); border-color: var(--error-200); }
.cal-moderate { --sev: var(--warning-500); border-color: var(--warning-200); }
.cal-mild     { --sev: var(--icon-soft); }
.cal-up       { --sev: var(--success-500); }
.cal-when { display: flex; flex-direction: column; gap: 2px; font-size: 0.75rem; color: var(--fg-faint); font-variant-numeric: tabular-nums; }
.cal-when b { color: var(--fg); font-weight: 600; font-size: 0.8125rem; display: inline-flex; align-items: center; gap: 6px; }
.cal-when b::before {
  content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--sev);
}
.cal-name { font-weight: 600; font-size: 0.9375rem; margin-bottom: 4px; }
.cal-head { font-size: 0.875rem; color: var(--fg-dim); margin: 0; line-height: 1.25rem; }
.cal-measured { margin-top: 8px; font-size: 0.75rem; display: flex; gap: 16px; flex-wrap: wrap; color: var(--fg-faint); font-variant-numeric: tabular-nums; }
.cal-measured .down { color: var(--error-700); font-weight: 600; }
.cal-measured .flat { color: var(--fg-dim); }
.cal-rule { height: 1px; background: var(--line); margin: 28px 0 24px; }

/* ----------------------------------------------------- alerts & advisories */

.signals { display: grid; gap: 12px; margin-bottom: 24px; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
.signal-card {
  --sev: var(--icon-soft);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
  box-shadow: var(--shadow-xs); padding: 14px 18px;
}
/* Severity is the word at the top, in its colour, with a dot before it; the
   two that need action also take a border in the same hue. */
.signal-critical { --sev: var(--error-500); border-color: var(--error-200); }
.signal-warning  { --sev: var(--warning-500); border-color: var(--warning-200); }
.signal-info     { --sev: var(--primary-500); }
/* Was 10px - under the 12px floor, on the word that says how bad this is. */
.signal-kind {
  display: flex; align-items: center; gap: 7px;
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--fg-dim); margin-bottom: 5px;
}
.signal-kind::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--sev); }
.signal-critical .signal-kind { color: var(--error-700); }
.signal-warning .signal-kind  { color: var(--warning-700); }
.signal-info .signal-kind     { color: var(--primary-700); }
.signal-title { font-weight: 600; font-size: 0.9375rem; margin-bottom: 6px; }
.signal-body { margin: 0 0 6px; font-size: 0.8125rem; color: var(--fg-dim); line-height: 1.1875rem; }
.signal-body:last-child { margin-bottom: 0; }
.signal-where { font-size: 0.75rem; color: var(--fg-dim); margin-top: 8px; }

/* ---------------------------------------------------------------- messages */

.banner {
  border: 1px solid var(--warning-200);
  border-radius: var(--r-xl); padding: 12px 16px; margin-bottom: 20px;
  font-size: 0.875rem; background: var(--warning-50); color: var(--fg);
}
.banner.bad { border-color: var(--error-200); background: var(--error-50); }
.banner p { margin: 0 0 6px; }
.banner p:last-child { margin-bottom: 0; }

/* A stack. Messages queue upward instead of overwriting one another. Raised
   clear of the sticky plan bar so the two never occupy the same pixels. */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  z-index: 60; display: flex; flex-direction: column-reverse; gap: 8px;
  align-items: center; max-width: min(560px, calc(100vw - 48px));
}
.toast-item {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
  padding: 12px 20px; box-shadow: var(--shadow-md); font-size: 0.875rem;
  animation: toast-in 180ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
.toast-item.bad  { border-color: var(--error-500); }
.toast-item.good { border-color: var(--success-500); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) { .toast-item { animation: none; } }

/* The rotation action bar. Sticky at the foot of the viewport because the
   decision sits above a 2,100px table and the evidence for it sits below. */
.plan-bar {
  position: sticky; bottom: 0; z-index: 20; margin-top: 16px;
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  padding: 14px 18px; background: var(--card);
  border: 1px solid var(--line-strong); border-radius: var(--r-xl);
  box-shadow: 0 -8px 24px -12px #0e121b26;
}
.pb-scope { flex: 1 1 340px; font-size: 0.875rem; color: var(--fg-dim); }
.pb-scope strong { color: var(--fg); }
/* ------------------------------------------------------------ rotation cards
   One change per card, read left to right as a sentence: calls to this area
   code / show this number now / and will show that one / which should do this.
   The card is a <label>, so a click anywhere on it toggles the change. */

.plan-stats { margin-bottom: 20px; }
.plan-arrow { color: var(--fg-faint); font-weight: 400; }
.plan-to { color: var(--success-700); }

.plan-tools { display: flex; gap: 10px; align-items: center; margin: 0 0 12px; font-size: 0.875rem; }

#plan-group-list .plan-group + .plan-group,
.plan-group + .plan-group { margin-top: 28px; }
.pg-head { margin-bottom: 12px; }
.pg-head h3 { margin: 0 0 2px; }
.pg-cards { display: flex; flex-direction: column; gap: 8px; }
/* Where a group's changes are, and what is ticked in it: read before the cards. */
.pg-places { margin: 6px 0 0; font-size: 0.8125rem; color: var(--fg-dim); }
.pg-sel { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: 6px 0 0; font-size: 0.8125rem; color: var(--fg-faint); }
.pg-part { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 10px 0; font-size: 0.8125rem; color: var(--fg-dim); }
.pg-sel > span:first-child { font-variant-numeric: tabular-nums; margin-right: 4px; }

.pc {
  display: grid; align-items: center; gap: 6px 20px;
  grid-template-columns: 24px minmax(150px, 1.1fr) minmax(170px, 1fr) 20px minmax(170px, 1fr) minmax(150px, 1fr);
  padding: 14px 18px; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
  box-shadow: var(--shadow-xs);
  transition: border-color 0.12s ease, opacity 0.12s ease;
}
.pc:hover { border-color: var(--line-strong); }
.pc:focus-within { outline: 2px solid var(--focus); outline-offset: 1px; }
/* Unticked: still readable, plainly not part of what Apply will do. */
.pc-off { opacity: 0.55; box-shadow: none; }
.pc-off .pc-new { text-decoration: line-through; text-decoration-color: var(--fg-faint); }

.pc-pick input {
  width: 20px; height: 20px; margin: 0; display: block;
  accent-color: var(--primary-700); cursor: pointer;
}
.pc-area, .pc-num, .pc-effect { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pc-k {
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-faint);
}
.pc-ac { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.pc-place { font-size: 0.9375rem; font-weight: 500; color: var(--fg-dim); letter-spacing: 0; }
.pc-num .did { font-size: 1rem; }
.pc-old { color: var(--fg-dim); font-weight: 500; }
.pc-new { color: var(--fg); }
/* How many numbers an area code shares its calls across, where a card adds
   one or switches one off. */
.pc-pool { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--fg); }
.pc-num .pill { align-self: flex-start; margin-top: 2px; }
.pc-arrow { font-size: 1.25rem; color: var(--fg-faint); text-align: center; }
.pc-rate { font-size: 1rem; font-variant-numeric: tabular-nums; }
.pc-rate b { color: var(--success-700); }
.pc-why {
  grid-column: 2 / -1; margin: 2px 0 0; font-size: 0.8125rem; color: var(--fg-dim);
}

.pg-bench .bench-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.bench-list li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px;
  padding: 10px 14px; border-radius: var(--r-lg); background: var(--bg-softer);
}

@media (max-width: 900px) {
  /* Stacked: area on top, then now → new on one line, then the effect. */
  .pc { grid-template-columns: 24px 1fr 20px 1fr; }
  .pc-area { grid-column: 2 / -1; }
  .pc-now { grid-column: 2; }
  .pc-effect { grid-column: 2 / -1; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; }
  .pc-pick { grid-row: 1 / span 3; align-self: start; padding-top: 4px; }
}
@media (max-width: 520px) {
  .pc { grid-template-columns: 24px 1fr; padding: 12px 14px; }
  .pc-arrow { display: none; }
  .pc-area, .pc-num, .pc-effect, .pc-why { grid-column: 2; }
  .pc-pick { grid-row: 1 / span 5; }
}
@media (prefers-reduced-motion: reduce) { .pc { transition: none; } }

.empty { padding: 44px 20px; text-align: center; color: var(--fg-faint); }
.check { display: flex; align-items: center; gap: 10px; font-size: 0.875rem; color: var(--fg-dim); cursor: pointer; }
/* Was a bare 13x13px native control gating a write to a live dialer. */
.check input {
  width: 20px; height: 20px; margin: 0; flex: none;
  accent-color: var(--primary-700); cursor: pointer;
}
/* ------------------------------------------------------------------ drawer */

.scrim { position: fixed; inset: 0; background: #02061759; z-index: 40; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(580px, 100vw);
  transition: width .14s ease-out;
  background: var(--card); border-left: 1px solid var(--line);
  box-shadow: var(--shadow-md); z-index: 50; overflow-y: auto; padding: 24px 26px 44px;
}
/* Close and Expand share one row pinned to the top right, so neither sits on
   top of the heading however wide the panel is. */
.drawer-tools {
  position: absolute; top: 12px; right: 14px; z-index: 2;
  display: flex; align-items: center; gap: 6px;
}
.drawer-close {
  background: none; border: 0; padding: 0 4px;
  color: var(--fg-dim); font-size: 1.625rem; line-height: 1; cursor: pointer;
}
.drawer-close:hover { color: var(--fg); }
.drawer-close:focus-visible, .drawer-size:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-md); }
.drawer-size {
  font: inherit; font-size: 0.75rem; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--fg-dim);
}
.drawer-size:hover { border-color: var(--line-strong); color: var(--fg); }
.drawer-size[aria-pressed="true"] {
  background: var(--primary-50); border-color: var(--primary-200, var(--line)); color: var(--accent-ink-strong);
}
/* Two arrows pushing apart, mirrored when the panel is already wide. */
.ds-ico {
  width: 11px; height: 11px; flex: none;
  border-left: 2px solid currentColor; border-bottom: 2px solid currentColor;
  border-top: 2px solid currentColor; border-right: 2px solid currentColor;
  border-radius: 2px; opacity: .65;
}
.drawer-size[aria-pressed="true"] .ds-ico { opacity: 1; }
.drawer h2 { margin: 0 0 3px; padding-right: 128px; font-size: 1.375rem; font-weight: 600; letter-spacing: -0.02em; }
.drawer #drawer-body > p:first-of-type, .drawer .drawer-sub { padding-right: 128px; }
.drawer .reason { color: var(--fg-dim); margin: 0 0 10px; max-width: 62ch; font-size: 0.875rem; }

.kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 10px; margin: 16px 0; }
.kv > div { background: var(--bg-softer); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 10px 12px; }
/* Was 10px at --fg-faint. These label the compliance run's own provenance -
   pack version, when it was last checked, how much of it can be trusted. */
.kv dt { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--fg-dim); margin: 0 0 3px; font-weight: 600; }
.kv dd { margin: 0; font-size: 1rem; font-weight: 600; font-variant-numeric: tabular-nums; }

.trend { font-size: 0.8125rem; font-variant-numeric: tabular-nums; }
.trend .up { color: var(--success-700); font-weight: 600; }
.trend .down { color: var(--error-700); font-weight: 600; }

code {
  font-family: var(--mono); font-size: .86em; background: var(--bg-softer);
  border: 1px solid var(--line); border-radius: var(--r-xs); padding: 1px 5px;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ============================================================ dashboard */

/* The hero reads top to bottom as one story: the verdict and why, then the
   figures it rests on. It used to be three columns (ring, text, ledger), with
   the reason floating in a stretched column and the tiles wearing coloured
   side stripes, and it read as three panels competing rather than one. */
.hero {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--shadow-xs);
  margin-bottom: 20px; overflow: hidden;
}
.hero-top { display: flex; align-items: flex-start; gap: 28px; padding: 24px 28px; }
.hero-score { position: relative; width: 120px; height: 120px; flex: none; }
.ring { width: 120px; height: 120px; transform: rotate(-90deg); }
.ring-track { fill: none; stroke: var(--bg-soft); stroke-width: 10; }
.ring-fill {
  fill: none; stroke: var(--primary-500); stroke-width: 10; stroke-linecap: round;
  /* 2*pi*52 */
  stroke-dasharray: 326.7; stroke-dashoffset: 326.7;
  transition: stroke-dashoffset .7s ease, stroke .3s ease;
}
.hero-num {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-size: 2.125rem; line-height: 1; font-weight: 600; letter-spacing: -0.03em; font-variant-numeric: tabular-nums;
}
.hero-num i { font-style: normal; font-size: 0.75rem; font-weight: 500; letter-spacing: 0; color: var(--fg-faint); margin-top: 4px; }
.hero-text { flex: 1 1 auto; min-width: 0; padding-top: 6px; }
.hero-label { font-size: 1.375rem; line-height: 1.75rem; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 6px; }
.hero-reason { margin: 0 0 8px; color: var(--fg); font-size: 1rem; line-height: 1.5rem; max-width: 70ch; }
.hero-scale { margin: 0; color: var(--fg-dim); font-size: 0.875rem; line-height: 1.3125rem; max-width: 80ch; }

/* Five figures in one even row, divided by hairlines; colour only where a
   figure is bad news. */
/* Flex rather than a grid: columns grow to fill each row, so a wrapped row
   never leaves an empty cell showing the hairline colour through. */
.hero-stats {
  display: flex; flex-wrap: wrap;
  border-top: 1px solid var(--line); background: var(--line); gap: 1px;
}
.hs { flex: 1 1 190px; display: flex; flex-direction: column; gap: 3px; padding: 16px 20px; background: var(--card); min-width: 0; }
.hs-v { font-size: 1.5rem; line-height: 1.875rem; font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.hs-l { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim); }
.hs-warn .hs-v { color: var(--warning-700); }
.hs-bad .hs-v { color: var(--error-700); }
.hs .et-d { line-height: 1.0625rem; }

@media (max-width: 640px) {
  .hero-top { flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 18px 16px; }
  .hero-text { padding-top: 0; }
  .hero-breakdown { text-align: left; }
  .hs { flex-basis: 40%; padding: 12px 14px; }
  .hs-v { font-size: 1.25rem; line-height: 1.625rem; }
}

/* A fixed column count rather than auto-fit: the three cards below the time
   series are meant to fill one row exactly. auto-fit picks a track count from
   the available width and left a dead fourth column at 1500px, which pushed the
   hour chart onto a line of its own. */
/* Two columns, not three.
   The time series spans the row and there are exactly two cards beneath it, so
   a three-column grid left the third column empty and the pair sitting in the
   left two-thirds with dead space beside them. Two columns makes each of them
   half the width and fills the row. */
.dash-grid {
  /* `stretch`, not `start`: the pair beneath the chart carry different amounts
     of content (a 7-row legend against a 9-row bar list) and sizing each to its
     own content left one card visibly shorter than the one beside it. They are
     a row, so they share a baseline and a bottom edge. */
  display: grid; gap: 16px; align-items: stretch;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 780px)  { .dash-grid { grid-template-columns: 1fr; } }
/* Only the time series earns the full width - it is the one chart that is
   unreadable when squeezed. */
.card-wide { grid-column: 1 / -1; }
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--shadow-xs); padding: 18px 20px;
}
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
.card-head h3 { margin: 0; }
.legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 0.75rem; color: var(--fg-dim); }
.legend .sw { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.sw-answer { background: var(--primary-500); }
.sw-contact { background: var(--primary-200); }

.chart { width: 100%; height: auto; display: block; overflow: visible; }
.chart .grid-line { stroke: var(--line); stroke-width: 1; }
/* 9px authored lands at ~12.5px after the 1.39x viewBox upscale. Sized for
   where it is SEEN, not where it is written. */
/* 12px, now that charts are drawn at the width they are shown at rather than
   scaled from a fixed 960-wide drawing. */
.chart .axis-label { fill: var(--fg-dim); font-size: 0.75rem; }
.chart .line-answer { fill: none; stroke: var(--primary-500); stroke-width: 2; stroke-linejoin: round; }
.chart .line-contact { fill: none; stroke: var(--primary-200); stroke-width: 2; stroke-linejoin: round; stroke-dasharray: 4 3; }
.chart .dot { fill: var(--primary-500); }

/* ------------------------------------------------- the daily composition
   One hue, light to dark, because the three bands are positions in one funnel
   rather than three unrelated things. Steps were chosen with the CVD validator
   and not by eye: the obvious brand pairing put two bands 0.4 deltaE apart
   under protanopia, which is indistinguishable.
   A 1px surface-coloured stroke gives each band a hairline gap from the one
   below, so the boundary is a boundary and not a colour change. */
.chart .band { stroke: var(--card); stroke-width: 1; }
.chart .band-reached    { fill: var(--band-reached); }
.chart .band-answered   { fill: var(--band-answered); }
.chart .band-nocomplete { fill: var(--band-nocomplete); }
.chart .cross { stroke: var(--fg-dim); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
/* The trailing part day. Washed rather than hidden: the reader can still see
   what has happened so far today, and cannot mistake it for a collapse. */
.chart .partday { fill: var(--card); opacity: .62; pointer-events: none; }
.ct-part { font-weight: 400; color: var(--fg-faint); }

.chartwrap { position: relative; }
.charttip {
  position: absolute; top: 8px; z-index: 5; pointer-events: none;
  min-width: 210px; padding: 10px 12px;
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--r-lg); box-shadow: var(--shadow-md); font-size: 0.8125rem;
}
.ct-d { font-weight: 600; margin-bottom: 6px; }
.ct-row { display: grid; grid-template-columns: 10px 1fr auto; align-items: center; gap: 8px; padding: 2px 0; }
.ct-l { color: var(--fg-dim); }
.ct-v { font-variant-numeric: tabular-nums; font-weight: 600; }
.ct-sw { width: 10px; height: 10px; border-radius: 3px; display: block; }
.ct-total { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--line); grid-template-columns: 1fr auto; }
.ct-total .ct-l { color: var(--fg); font-weight: 600; }

/* The legend swatches, shared with the tooltip so one colour means one thing. */
.sw-reached    { background: var(--band-reached); }
.sw-answered   { background: var(--band-answered); }
.sw-nocomplete { background: var(--band-nocomplete); }

/* stacked health bar */
.stack { display: flex; height: 30px; border-radius: var(--r-md); overflow: hidden; margin-bottom: 14px; }
.stack > span { display: block; }
.stack-legend { display: grid; gap: 8px; }
.stack-row { display: grid; grid-template-columns: 12px 1fr auto auto; gap: 10px; align-items: center; font-size: 0.8125rem; }
.stack-row .sw { width: 12px; height: 12px; border-radius: 3px; }
.stack-row .n { font-variant-numeric: tabular-nums; font-weight: 600; }
.stack-row .pctv { font-variant-numeric: tabular-nums; color: var(--fg-faint); font-size: 0.75rem; }

.hb-promote { background: var(--success-500); }
.hb-keep    { background: var(--primary-500); }
.hb-test    { background: var(--primary-200); }
.hb-watch   { background: var(--warning-500); }
.hb-rest    { background: var(--error-500); }
.hb-retire  { background: var(--error-200); }
.hb-unblock { background: var(--blocked-500); }

.dash-section { margin-top: 28px; }
.dash-section h3 { margin-bottom: 12px; }

/* Calendar and weather side by side on the dashboard, stacking when narrow. */
.dash-pair {
  display: grid; gap: 28px; margin-top: 28px; align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
}
.dash-pair .dash-section { margin-top: 0; }
/* Inside a pair each list is already in its own column, so one card per row. */
.dash-pair .cal-list { grid-template-columns: 1fr; }

/* ------------------------------------------------------------------ mobile */

/* Phones. The grid floors above are clamped with min() so no track can push the
   page sideways; what is left is the chrome, which is laid out for a mouse. */
@media (max-width: 640px) {
  /* A phone cannot spare 24px each side for a shell that will never be wide
     enough to need centring. */
  :root { --gutter: 16px; }

  /* The controls need the full width to themselves; sharing a row with the
     lockup left each select about 80px wide. */
  .topbar { gap: 12px; padding: 12px var(--gutter); }
  .controls { width: 100%; gap: 10px; }
  .ctl { flex: 1 1 132px; }
  .ctl select { width: 100%; }
  .topbar .btn { flex: 1 1 auto; }

  /* 14px of padding on 20px of line box clears the 44px touch target. */
  .tab { padding: 14px 12px; }

  /* Six stacked cards is most of a screen before any content. Two up keeps the
     headline figures to a glance. */
  .summary { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-bottom: 16px; }
  .stat { padding: 12px 14px; }
  .stat-v { font-size: 1.25rem; }

  main { padding: 16px var(--gutter) 32px; }
  .card { padding: 14px 16px; }
  .panel-head h1, .panel-head h2 { font-size: 1.25rem; line-height: 1.75rem; }

  .hero-score, .ring { width: 96px; height: 96px; }

  /* The date column carries a short word and a date; 84px forced the date to
     wrap on every row. */
  .cal-row { grid-template-columns: 72px 1fr; gap: 10px; }
  .heat-chip { min-width: 46px; padding: 3px 6px; }
  .sitefoot-in { gap: 10px; }

  /* Tables still scroll sideways inside .tablewrap, but the desktop cell
     padding and column widths put only three columns on screen before the
     reader has to drag. */
  table.grid th, table.grid td { padding: 10px 12px; }
  #geo-table th:first-child, #geo-table td:first-child { width: 92px; }
  #geo-table th:nth-child(2), #geo-table td:nth-child(2),
  #geo-table th:nth-child(3), #geo-table td:nth-child(3),
  #geo-table th:nth-child(4), #geo-table td:nth-child(4),
  #geo-table th:nth-child(5), #geo-table td:nth-child(5) { width: 76px; }
}

/* ------------------------------------------------- health score breakdown */

/* Sits in the space to the right of the reason and chips. flex-basis rather
   than a width so it gives way and wraps under them on a narrow screen. */
.hero-breakdown {
  /* Beside the verdict on a wide screen; it wraps beneath it on a narrow one. */
  flex: 0 1 460px; min-width: min(300px, 100%); align-self: stretch;
  padding-left: 24px; border-left: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 0;
}
@media (max-width: 1000px) {
  .hero-top { flex-wrap: wrap; }
  .hero-breakdown { flex-basis: 100%; padding: 16px 0 0; border-left: 0; border-top: 1px solid var(--line); }
}
.bd-head {
  /* 12px at --fg-dim, not 11px at --fg-faint: this heading names the only
     thing in the hero that explains the number beside it, and it was the
     faintest, smallest type on the panel. */
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--fg-dim); margin-bottom: 3px;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.bd-head i {
  font-style: normal; text-transform: none; letter-spacing: 0; font-weight: 400;
  font-size: 0.75rem; color: var(--fg-faint);
}

/* The ledger. Three columns: what happened, what it cost, where that left you.
   The running balance is what turns a list of numbers into arithmetic you can
   follow without adding five figures in your head. */
.led-row {
  display: grid; grid-template-columns: 1fr 40px 34px; align-items: baseline;
  gap: 10px; font-size: 0.8125rem; padding: 3px 0;
}
.led-run {
  text-align: right; font-variant-numeric: tabular-nums;
  color: var(--fg-dim); font-size: 0.8125rem;
}
.led-base .led-run { font-weight: 600; color: var(--fg); }
.led-l { color: var(--fg); }
/* The sentence that makes the row mean something. It used to live in a title=
   attribute: invisible, untouchable, and unreadable by a screen reader. */
.led-l i {
  display: block; font-style: normal; font-size: 0.75rem; color: var(--fg-faint);
  line-height: 1.35; margin-top: 0;
}
.led-v { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; font-size: 0.8125rem; }
/* 700, not 500: the 500s are fill weights and do not carry small text. */
.led-v.up { color: var(--success-700); }
.led-v.down { color: var(--error-700); }
.led-v.flat { color: var(--fg-faint); }
.led-base { padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.led-base .led-l, .led-base .led-v { color: var(--fg-dim); }
/* A term worth zero points changed nothing; it stays visible so the ledger is
   complete, and recedes so it cannot be mistaken for a penalty. */
.led-nil .led-l { color: var(--fg-dim); }
.led-total {
  display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: 12px;
  margin-top: 5px; padding-top: 7px; border-top: 1px solid var(--line-strong);
  font-size: 0.875rem; font-weight: 600;
}
.led-total .led-v { font-size: 1rem; color: var(--fg); }
.led-total .led-l i {
  display: block; font-style: normal; font-weight: 400; font-size: 0.75rem;
  color: var(--fg-faint); margin-top: 2px; line-height: 1.4;
}

/* ------------------------------------------------------------ score scale
   Where this account sits on the scale it is judged against, and where a
   nominal account would sit. Both marks on one bar, because the second is the
   answer to "is 70 good" and that question has no answer without it. */
.scale { margin-top: 12px; }
.scale-bar {
  position: relative; height: 8px; border-radius: var(--r-full); overflow: hidden;
  display: flex; background: var(--bg-soft);
}
.scale-seg { display: block; height: 100%; }
.seg-at-risk         { background: var(--error-200); }
.seg-needs-attention { background: var(--warning-200); }
.seg-steady          { background: var(--primary-200); }
.seg-healthy         { background: var(--success-200); }
/* Markers sit above the segments, so the bar must not clip them. */
.scale-bar { overflow: visible; border-radius: var(--r-full); }
.scale-seg:first-child { border-radius: var(--r-full) 0 0 var(--r-full); }
.scale-seg:last-child  { border-radius: 0 var(--r-full) var(--r-full) 0; }
.scale-now, .scale-base { position: absolute; top: -3px; bottom: -3px; width: 2px; }
.scale-now {
  background: var(--fg); border-radius: 1px;
  /* A ring in the surface colour so the mark reads against any band under it. */
  box-shadow: 0 0 0 2px var(--card);
}
.scale-base { background: var(--fg-faint); opacity: .7; }
.scale-keys {
  display: flex; margin-top: 5px; font-size: 0.75rem; color: var(--fg-faint);
}
.scale-keys span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-right: 4px; }
.scale-note { margin: 7px 0 0; font-size: 0.75rem; color: var(--fg-faint); line-height: 1.4; }


/* --------------------------------------------------------- carrier health */

/* Score and status share one tone scale, so a colour means the same thing in
   the strip, the table and the drawer. PULL NOW is the only one that gets a
   filled badge: it is the only status that means stop what you are doing. */
.h-ok    { --tone: var(--success-500); --tone-bg: var(--success-50);  --tone-fg: var(--success-700); }
.h-warn  { --tone: var(--warning-500); --tone-bg: var(--warning-50);  --tone-fg: var(--warning-700); }
.h-bad   { --tone: var(--error-500);   --tone-bg: var(--error-50);    --tone-fg: var(--error-700); }
/* --on-strong, not white: in the dark theme the fill is a light pink. */
.h-veto  { --tone: var(--error-500);   --tone-bg: var(--error-700);   --tone-fg: var(--on-strong); }
.h-thin  { --tone: var(--line);        --tone-bg: var(--bg-softer);   --tone-fg: var(--fg-faint); }

.hscore {
  display: inline-block; min-width: 38px; padding: 3px 8px; border-radius: var(--r-md);
  font-weight: 700; font-variant-numeric: tabular-nums; text-align: center;
  background: var(--tone-bg); color: var(--tone-fg);
}
.hpill { background: var(--tone-bg); color: var(--tone-fg); }

/* The shape of the pool before any single number. One card split into equal
   columns, so the counts read as parts of one pool rather than five loose
   tiles; the status colour is a dot beside the label, where it identifies
   without shouting. */
.hstrip {
  /* The dividers are the 1px gap showing the border colour through. Columns
     grow to fill every row, so a wrapped row never leaves an empty corner. */
  display: flex; flex-wrap: wrap; gap: 1px;
  margin-bottom: 20px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--shadow-xs); overflow: hidden;
}
.hcount { flex: 1 1 120px; display: flex; flex-direction: column; gap: 4px; padding: 14px 20px; background: var(--card); }
.hcount .n { font-size: 1.5rem; line-height: 1.875rem; font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.hcount .l {
  display: flex; align-items: center; gap: 7px;
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim);
}
.hcount .l::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--tone); }
.hcount.h-thin .l::before { background: var(--stroke-sub); }
/* Every card on the page clears whatever follows it — the per-number table sat
   flush against the carrier card. Stacked block margins collapse, so two cards
   in a row still sit 20px apart, not 40. */
#health-body > .card { margin-bottom: 20px; }
#health-baselines { margin-top: 8px; }

.veto-why { color: var(--error-700); font-weight: 600; }
.sixxx { color: var(--error-700); font-weight: 600; }

/* List quality. Its own card with its own rule stated on it, because the one
   thing an operator must not do is read these as a reason to rotate a number. */
/* Set apart by its heading and its "never lowers a score" pill, not a side
   stripe — the rest of this page dropped those. */
.listhealth { margin-top: 20px; }
.lh-row { display: grid; grid-template-columns: 190px 1fr 56px; gap: 12px; align-items: center; padding: 9px 0; }
.lh-row + .lh-row { border-top: 1px solid var(--line); }
.lh-id { display: flex; flex-direction: column; gap: 1px; font-size: 0.8125rem; }
.lh-bar { height: 8px; border-radius: 999px; background: var(--bg-soft); overflow: hidden; }
.lh-bar i { display: block; height: 100%; border-radius: 999px; background: var(--primary-500); }
.lh-bad .lh-bar i { background: var(--error-500); }
.lh-v { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.lh-why { grid-column: 1 / -1; margin: 0; font-size: 0.75rem; color: var(--fg-faint); }

/* Drawer: the workings. */
.hhead { display: flex; align-items: center; gap: 14px; margin: 4px 0 16px; }
.hhead .hscore { font-size: 1.25rem; min-width: 54px; padding: 8px 12px; }
.hstatus { font-size: 1rem; font-weight: 600; }
.hhead .hint { margin: 2px 0 0; }

.kv { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 20px; margin: 8px 0 18px; }
.kv-row { display: flex; justify-content: space-between; gap: 10px; font-size: 0.8125rem; padding: 4px 0; border-bottom: 1px solid var(--line); }
.kv-k { color: var(--fg-dim); }
.kv-v { font-variant-numeric: tabular-nums; font-weight: 500; }

.comps { display: flex; flex-direction: column; gap: 12px; }
.comp { display: grid; grid-template-columns: 1fr 90px 62px; gap: 10px; align-items: center; }
.comp-l { font-size: 0.8125rem; }
.comp-track { height: 8px; border-radius: 999px; background: var(--bg-soft); overflow: hidden; }
.comp-bar { display: block; height: 100%; border-radius: 999px; background: var(--primary-500); }
.comp-v { text-align: right; font-size: 0.75rem; font-variant-numeric: tabular-nums; color: var(--fg-dim); }
.comp-why { grid-column: 1 / -1; margin: -4px 0 0; font-size: 0.75rem; color: var(--fg-faint); }
/* A component with no data earned its points by default, not by performing. */
.comp-off .comp-bar { background: var(--line); }
.comp-off .comp-l { color: var(--fg-faint); }

@media (max-width: 640px) {
  .kv { grid-template-columns: 1fr; }
  .lh-row { grid-template-columns: 1fr 60px; }
  .lh-bar { grid-column: 1 / -1; }
  /* Three across rather than two: at 108px the five counts took three rows and
     pushed the table itself off the first screen. */
  .hcount { flex-basis: 30%; padding: 10px 12px; }
  .hcount .n { font-size: 1.125rem; line-height: 1.5rem; }
  .hcount .l { font-size: 0.75rem; letter-spacing: 0.04em; }
}

/* ---------------------------------------------------------- sortable tables */

.th-sort { cursor: pointer; user-select: none; position: relative; padding-right: 22px; }
.th-sort:hover { color: var(--fg); background: var(--hover, var(--bg-soft)); }
.th-sort:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* The caret is always in the DOM so the header does not change width on sort,
   which would shift every column the moment you clicked one. */
.th-sort::after {
  /* The only signal that a column sorts. At 10px and 0.25 alpha it was
     effectively invisible, so the table's one power feature was undiscoverable. */
  content: '↕'; position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  font-size: 0.75rem; opacity: 0.45;
}
.th-sort.sorted::after { content: '↑'; opacity: 1; color: var(--primary-700); }
.th-sort.sorted.sorted-desc::after { content: '↓'; }
.th-sort.sorted { color: var(--primary-700); }

/* ------------------------------------------------- response codes by carrier */

.carriers { margin-top: 20px; }
.car-row { padding: 14px 0; }
.car-row + .car-row { border-top: 1px solid var(--line); }
.car-group {
  margin: 18px 0 0; padding-top: 18px; border-top: 1px solid var(--line-strong);
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim);
}
.car-group + .car-row { padding-top: 10px; }
/* A trunk refusing materially more than its peers is the finding on this card. */
.car-outlier { background: var(--error-50); margin: 0 -20px; padding: 14px 20px; border-radius: var(--r-xl); }

.car-head { display: flex; align-items: baseline; gap: 22px; flex-wrap: wrap; }
.car-name { font-weight: 600; font-size: 0.9375rem; min-width: 120px; }
.car-stat { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 0.875rem; }
.car-stat i { font-style: normal; font-weight: 400; font-size: 0.75rem; letter-spacing: 0.05em;
              text-transform: uppercase; color: var(--fg-dim); margin-left: 5px; }
.car-stat.bad { color: var(--error-700); }
.car-outlier-why { margin: 8px 0 0; font-size: 0.8125rem; color: var(--error-700); max-width: 82ch; }

.car-codes { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }

/* Each code is a button so it is reachable by keyboard, not just hover: the
   explanation is the point of the card, and a mouse-only affordance hides it
   from anyone using a keyboard or a screen reader. */
.code {
  font: inherit; text-align: left; cursor: help; position: relative;
  display: flex; flex-direction: column; gap: 1px;
  padding: 6px 10px; border-radius: var(--r-md);
  border: 1px solid var(--line); background: var(--card);
}
.code b { font-size: 0.75rem; font-weight: 600; }
/* The count and the share are two different figures, and with only a space
   between them they read as one mangled number ("3,030 3.90%"). A rule and
   real space keep them apart; the share is the quieter of the two. */
.code-n {
  font-size: 0.75rem; color: var(--fg-dim); font-variant-numeric: tabular-nums;
  display: flex; align-items: baseline; gap: 7px;
}
.code-count { font-weight: 600; color: var(--fg); }
.code-rate { padding-left: 7px; border-left: 1px solid var(--line); color: var(--fg-faint); }
.code-reputation .code-rate { border-left-color: var(--error-200); }
.code-data .code-rate { border-left-color: var(--primary-200, var(--line)); }
/* Track is carried by colour AND stated in the tooltip - colour alone would be
   another thing to take on trust. */
.code-reputation { border-color: var(--error-200); background: var(--error-50); }
.code-reputation b { color: var(--error-700); }
.code-data { border-color: var(--primary-200, var(--line)); background: var(--primary-50); }
/* --primary-700 on --primary-50 measured 3.70:1. Body weight needs 4.5, and a
   figure inside a tinted card is exactly where a reader looks hardest. */
.code-data b { color: var(--accent-ink-strong); }

.code::after {
  content: attr(data-tip);
  position: absolute; left: 0; bottom: calc(100% + 8px); z-index: 40;
  width: 300px; white-space: pre-line;
  padding: 10px 12px; border-radius: var(--r-md);
  background: #0f172a; color: #fff; font-size: 0.75rem; line-height: 1.45; font-weight: 400;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.28);
  /* display:none, not just invisible: a hidden 300px explanation still
     counts toward the page width, and on a phone it pushed the Carrier health
     page 100px wider than the screen. */
  display: none;
}
.code:hover::after, .code:focus-visible::after { display: block; }
.code:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

/* Near the right edge the tooltip would run off the card. */
.car-codes .code:nth-last-child(-n+3)::after { left: auto; right: 0; }

@media (max-width: 640px) {
  .car-head { gap: 14px; }
  .code::after { width: min(280px, calc(100vw - 64px)); }
}

/* ------------------------------------------------------- executive summary */

.et-d { font-size: 0.75rem; color: var(--fg-faint); }
.et-d.up { color: var(--success-700); }
.et-d.down { color: var(--error-700); }

.exec-actions { margin-bottom: 16px; }
.exa { display: grid; grid-template-columns: 26px 1fr; gap: 12px; padding: 12px 0; }
.exa + .exa { border-top: 1px solid var(--line); }
.exa-mark {
  width: 22px; height: 22px; border-radius: 999px; display: grid; place-items: center;
  font-size: 0.8125rem; font-weight: 700; color: var(--on-strong); background: var(--fg-faint);
}
/* The 500s are FILL weights. White text on them measured 2.15:1 on amber and
   3.67:1 on rose — the worst contrast anywhere in the console, on the one
   component whose entire job is to be noticed. The 700s carry small text. */
.exa-critical .exa-mark { background: var(--error-700); }
.exa-warning  .exa-mark { background: var(--warning-700); }
.exa-ok       .exa-mark { background: var(--success-700); }
.exa-title { font-weight: 600; font-size: 0.9375rem; }
.exa-detail { margin: 3px 0 0; color: var(--fg-dim); font-size: 0.8125rem; max-width: 90ch; }
.exa-effect { margin: 3px 0 0; color: var(--fg-faint); font-size: 0.8125rem; max-width: 90ch; }

.dash-more { margin: 4px 0 20px; }
/* A button that reads as a link: it changes a tab, so it must not be an <a>. */
.linkish {
  font: inherit; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--primary-700); text-decoration: underline; text-underline-offset: 2px;
}
.linkish:hover { color: var(--fg); }

/* ------------------------------------------------ answer rate by carrier */

.split-flag {
  margin: 4px 0 12px; font-size: 0.8125rem; color: var(--error-700);
  background: var(--error-50); border: 1px solid var(--error-200);
  padding: 10px 12px; border-radius: var(--r-md); max-width: 92ch;
}
.csplit { display: flex; flex-direction: column; gap: 7px; margin-bottom: 18px; }
.cs-row { display: grid; grid-template-columns: 108px 1fr 52px 74px; gap: 10px; align-items: center; font-size: 0.8125rem; }
.cs-name { color: var(--fg-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cs-track { height: 8px; border-radius: 999px; background: var(--bg-soft); overflow: hidden; }
.cs-bar { display: block; height: 100%; border-radius: 999px; background: var(--primary-500); }
.cs-bar.bad { background: var(--error-500); }
.cs-v { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.cs-n { text-align: right; font-size: 0.75rem; color: var(--fg-faint); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .cs-row { grid-template-columns: 96px 1fr 48px; }
  .cs-n { display: none; }
}

/* ----------------------------------------------------- what the optimizer did
   Three columns in the order the question is asked: what was done, what is
   still running, what came back. Plain figures rather than cards - this block
   is already a card and a card inside a card is always wrong. */
.work { margin-bottom: 16px; }
.work .card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.wk-cols {
  display: grid; gap: 28px; margin-top: 4px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
.wk-col h4 {
  margin: 0 0 10px; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--fg-dim);
}
.wk-figs { display: flex; flex-direction: column; gap: 14px; }
.wk-fig { display: flex; flex-direction: column; gap: 1px; }
.wk-v { font-size: 1.5rem; font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; line-height: 1.15; }
.wk-l { font-size: 0.8125rem; color: var(--fg); }
.wk-s { font-size: 0.75rem; color: var(--fg-faint); line-height: 1.4; }
.wk-sub { margin: 0 0 6px; font-size: 0.8125rem; color: var(--fg-dim); }
.wk-sub + .wk-list { margin-bottom: 12px; }
.wk-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.wk-list li { font-size: 0.8125rem; }
.wk-list i {
  display: block; font-style: normal; font-size: 0.75rem; color: var(--fg-faint);
  line-height: 1.4; margin-top: 1px;
}
/* An empty column has to say WHY it is empty, or it reads as broken. */
.wk-none { margin: 0; font-size: 0.8125rem; color: var(--fg-faint); line-height: 1.5; max-width: 46ch; }

/* -------------------------------------------------------------- carrier mark
   The real logo when one has been supplied, a brand-hued monogram when not.
   Both occupy the same box so the row never reflows when a logo is added.
   Wide enough for a wordmark (US Cellular, Xfinity have no square mark) and
   left-aligned, so square marks and wordmarks start on the same edge and the
   carrier names after them line up. */
.car-mark {
  flex: none; width: 72px; height: 30px; display: grid; place-items: center start;
}
/* An explicit height: Simple Icons files carry only a viewBox, so with max-*
   alone a left-aligned image has no intrinsic size and collapses to 0x0. */
.car-logo { height: 22px; width: auto; max-width: 72px; object-fit: contain; object-position: left center; display: block; }
.car-mono {
  width: 30px; height: 30px; border-radius: var(--r-md);
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--tone) 14%, transparent);
  color: var(--tone);
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.01em;
}

/* ================================================= September review views */

/* ---------------------------------------------------------------- the lede
   The paragraph at the top of every tab. Sized as the most important text on
   the page after the title, because it is: it is what the page says. The tone
   is a small dot before the headline, not a fill or a side stripe: a tinted box
   on every page would make the one that is actually alarming look like the
   rest, and the text already says how bad it is. */
.lede {
  --lede-tone: var(--success-500);
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--shadow-xs);
  padding: 16px 20px; margin-bottom: 20px;
}
.lede-warning  { --lede-tone: var(--warning-500); }
.lede-critical { --lede-tone: var(--error-500); }
.lede-head { margin: 0; font-size: 1.0625rem; line-height: 1.625rem; font-weight: 600; letter-spacing: -0.01em; max-width: 90ch; }
.lede-head::before {
  content: ''; display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: var(--lede-tone); margin-right: 10px; vertical-align: 2px;
}
.lede-points { margin: 8px 0 0 19px; padding-left: 18px; color: var(--fg-dim); font-size: 0.875rem; line-height: 1.3125rem; max-width: 96ch; }
.lede-points li + li { margin-top: 3px; }
/* The second summary on a page (area codes, under the state table) reads as a
   subordinate one. */
.lede-sub { box-shadow: none; padding: 12px 16px; }
.lede-sub .lede-head { font-size: 0.9375rem; line-height: 1.375rem; }

.panel-sub { margin: 28px 0 12px; }
.panel-sub h3 { margin-bottom: 2px; }

.report-stats { margin-bottom: 20px; }
.stat-warn .stat-v { color: var(--warning-700); }
.panel .card + .card, .report-stats + .card { margin-top: 20px; }

/* A table inside a card: the card is already the frame.
   Visible overflow on wide screens so a code's explanation can rise out of the
   table instead of being clipped by it; scrolling again where the table cannot
   fit, which is where the scroll is needed. */
.tablewrap.flat { border: 0; box-shadow: none; border-radius: 0; overflow: visible; }
@media (max-width: 1100px) { .tablewrap.flat { overflow-x: auto; } }

@media (max-width: 640px) {
  #geo-states-card .card-head, #balance-body .card-head, #agents-body .card-head, #codes-block .card-head {
    flex-direction: column; align-items: flex-start; gap: 2px;
  }
}

.bad  { color: var(--error-700); }
.warn { color: var(--warning-700); }
td.bad, td .bad { font-weight: 600; }

tr.row-flag > td { background: color-mix(in srgb, var(--error-50) 70%, transparent); }
tr.row-watch > td { background: color-mix(in srgb, var(--warning-50) 60%, transparent); }
.row-why { display: block; font-size: 0.75rem; line-height: 1.0625rem; color: var(--fg-dim); white-space: normal; max-width: 36ch; margin-top: 3px; }
td .pill { margin-left: 8px; vertical-align: 1px; }

.refcell { min-width: 96px; }
.minibar { height: 4px; border-radius: 2px; background: var(--bg-soft); margin-top: 5px; overflow: hidden; }
.minibar i { display: block; height: 100%; background: var(--primary-200); }
.minibar i.bad { background: var(--error-500); }

td.chips { white-space: normal; }
td.chips .code { display: inline-flex; margin: 2px 6px 2px 0; padding: 4px 8px; }
.wn + .wn { margin-top: 2px; }

/* A bar with a reference mark: the team average, an even share. */
.refbar { position: relative; height: 8px; border-radius: 4px; background: var(--bg-soft); min-width: 120px; flex: 1 1 140px; }
.refbar-fill { position: absolute; inset: 0 auto 0 0; border-radius: 4px; background: var(--primary-500); }
.refbar-fill.bad { background: var(--error-500); }
.refbar-fill.warn { background: var(--warning-500); }
.refbar-fill.faint { background: var(--stroke-sub); }
.refbar-mark { position: absolute; top: -4px; bottom: -4px; width: 2px; margin-left: -1px; background: var(--fg); border-radius: 1px; }
.talkcell, .loadcell { display: flex; align-items: center; gap: 12px; min-width: 240px; }
.talk-v { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 48px; text-align: right; }
.loadcell .pill { margin-left: 0; min-width: 88px; text-align: center; }
.load-v { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 40px; text-align: right; white-space: nowrap; }
.refbar-fill.good { background: var(--success-500); }

/* Load balance: each card is a question, its answer in a sentence, then the evidence. */
.q-answer { margin: 0 0 16px; font-size: 1rem; line-height: 1.5rem; color: var(--fg-dim); max-width: 78ch; }
.q-answer b { color: var(--fg); font-weight: 700; }
.match-rows { display: grid; grid-template-columns: minmax(180px, max-content) minmax(120px, 1fr) max-content max-content; gap: 12px 20px; align-items: center; }
.match-row { display: contents; }
.match-name { font-weight: 600; }
.match-track { height: 14px; border-radius: 7px; background: var(--bg-soft); overflow: hidden; }
.match-track i { display: block; height: 100%; min-width: 3px; border-radius: 7px; }
.match-good { background: var(--success-500); }
.match-mid  { background: var(--primary-500); }
.match-far  { background: var(--fg-faint); }
.match-share, .match-ans { font-size: 0.875rem; color: var(--fg-dim); font-variant-numeric: tabular-nums; white-space: nowrap; }
.match-share b, .match-ans b { color: var(--fg); font-size: 1rem; }
@media (max-width: 720px) {
  .match-rows { grid-template-columns: 1fr 1fr; gap: 4px 12px; }
  .match-name, .match-track { grid-column: 1 / -1; }
  .match-name { margin-top: 10px; }
}

.gap-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 10px; }
.gap { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; padding: 10px 12px; border-radius: var(--r-lg); background: var(--bg-softer); }
.gap b { font-size: 1rem; font-variant-numeric: tabular-nums; }
.gap .sub { flex-basis: 100%; }

/* ------------------------------------------ account-wide response codes */
.codes-ok { margin: 0 0 12px; font-size: 0.875rem; color: var(--fg-dim); }
.codes-ok b { color: var(--fg); font-size: 1rem; }
.cb-group { margin: 10px 0 2px; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim); }
.cb-group:first-of-type { margin-top: 0; }
.codebars { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.cb-row { display: grid; grid-template-columns: minmax(170px, 220px) 1fr 64px; align-items: center; gap: 12px; }
.cb-row .code { flex-direction: row; justify-content: space-between; gap: 10px; }
.cb-track { height: 12px; border-radius: 6px; background: var(--bg-soft); overflow: hidden; }
.cb-track i { display: block; height: 100%; background: var(--stroke-sub); border-radius: 6px; }
.cb-reputation .cb-track i { background: var(--error-500); }
.cb-data .cb-track i { background: var(--primary-200); }
.cb-v { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; font-size: 0.875rem; }
.cb-reputation .cb-v { color: var(--error-700); }
/* The last rows' explanations open downward would be clipped by the page end;
   every one of these opens to the right of the chip instead. */
.codebars .code::after { left: calc(100% + 8px); bottom: auto; top: 0; }
@media (max-width: 640px) {
  .cb-row { grid-template-columns: 1fr 56px; }
  .cb-track { grid-column: 1 / -1; grid-row: 2; }
  .codebars .code::after { left: 0; top: calc(100% + 6px); }
}

/* --------------------------------------------------------- carrier upload */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0; margin: -1px;
}
.dropzone {
  display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center;
  padding: 28px 16px; margin: 16px 0; cursor: pointer;
  border: 2px dashed var(--line-strong); border-radius: var(--r-xl); background: var(--bg-softer);
  color: var(--fg-dim); font-size: 0.875rem;
}
.dropzone b { color: var(--fg); font-size: 0.9375rem; }
.dropzone:hover, .dropzone.is-over { border-color: var(--primary-500); background: var(--primary-50); }
.dropzone:focus-within { outline: 2px solid var(--focus); outline-offset: 2px; }
.drawer h4 { margin: 20px 0 8px; font-size: 0.875rem; }
/* A code chip's hidden 300px explanation still counts toward scroll width, so
   chips near the drawer's right edge gave it a sideways scrollbar. */
.drawer { overflow-x: hidden; }
/* Expanded. Capped well short of the viewport so the page it was opened from
   stays visible down the left: the panel is read against that table, not
   instead of it. */
.drawer.is-wide { width: min(1080px, 94vw); }
.drawer.is-wide .reason { max-width: 86ch; }
@media (prefers-reduced-motion: reduce) { .drawer { transition: none; } }
.up-maps { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 230px), 1fr)); gap: 8px 14px; margin: 10px 0 14px; }
.up-map { display: flex; flex-direction: column; gap: 4px; font-size: 0.75rem; font-weight: 600; color: var(--fg-dim); margin-bottom: 12px; }
.up-map select, .up-map input { font: inherit; font-size: 0.875rem; font-weight: 400; padding: 7px 9px; border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--card); color: var(--fg); }
.up-sample { max-height: 220px; overflow: auto; margin-bottom: 8px; }
.up-sample table.grid { font-size: 0.75rem; }
.up-go { margin-top: 14px; }
.banner.ok { border-color: var(--success-200); background: var(--success-50); }

.dropveil {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background: color-mix(in srgb, var(--primary-500) 18%, transparent);
  border: 3px dashed var(--primary-500); pointer-events: none;
}
.dropveil[hidden] { display: none; }
.dropveil div {
  padding: 16px 24px; border-radius: var(--r-xl); background: var(--card);
  box-shadow: var(--shadow-md); font-weight: 600; font-size: 1rem;
}

/* ====================================================== fix-first layout
   The fix leads. Its tab is first and set apart; the reports follow under a
   quiet label, as the evidence it is built from. */

.tabs { align-items: center; }
.tab-fix { color: var(--fg); font-weight: 600; }
.tab-fix.is-active { color: var(--accent-ink-strong); }
.tab-n {
  display: inline-grid; place-items: center; min-width: 22px; height: 20px; padding: 0 6px; margin-left: 6px;
  border-radius: var(--r-full); background: var(--primary-700); color: var(--on-strong);
  font-size: 0.75rem; font-weight: 700; font-variant-numeric: tabular-nums; vertical-align: 1px;
}
/* ------------------------------------------------------------ fix hero */
.fix-hero {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
  box-shadow: var(--shadow-xs); padding: 24px 28px; margin-bottom: 20px;
}
.fix-loading { margin: 0; color: var(--fg-dim); }
.fix-how { font-size: 0.875rem; color: var(--fg-dim); max-width: 96ch; }
.fix-how summary { cursor: pointer; width: fit-content; color: var(--accent-ink); font-size: 0.8125rem; }
.fix-how summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.fix-how p { margin: 8px 0 0; }
/* -------------------------------------------- a report's link to the fix */
.fix-cta {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 16px; margin: -8px 0 20px;
  background: var(--primary-50); border: 1px solid var(--primary-200); border-radius: var(--r-xl);
  font-size: 0.875rem;
}
.fc-mark {
  flex: none; width: 22px; height: 22px; display: grid; place-items: center; border-radius: 50%;
  background: var(--primary-700); color: var(--on-strong); font-size: 0.75rem; font-weight: 700;
}
.fc-text { flex: 1 1 300px; min-width: 0; }

@media (max-width: 640px) {
  .fix-hero { padding: 18px 16px; }
}

/* ---------------------------------------------------------- DID Health menu */
.tab-menu { position: relative; display: flex; }
.tab-menu-btn { display: inline-flex; align-items: center; gap: 6px; }
.tm-current:not(:empty) { font-weight: 500; color: var(--fg-dim); }
.tm-current:not(:empty)::before { content: '· '; }
.tm-caret {
  width: 7px; height: 7px; margin-left: 2px; margin-top: -3px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg);
  transition: transform .15s ease;
}
.tab-menu-btn[aria-expanded="true"] .tm-caret { transform: rotate(-135deg); margin-top: 3px; }
.tab-menu-list, .hmenu-list {
  position: absolute; top: calc(100% + 1px); left: 0; z-index: 40;
  min-width: 280px; max-width: calc(100vw - 32px); padding: 6px;
  background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-lg);
  box-shadow: var(--shadow-md); display: flex; flex-direction: column;
}
.tab-menu-list[hidden], .hmenu-list[hidden] { display: none; }
/* Menu items: an icon, then the label with its one-line description. */
.tab-item, .hm-item {
  display: flex; flex-direction: row; align-items: flex-start; gap: 10px; text-align: left;
  padding: 9px 12px; border-radius: var(--r-md); border-bottom: 0; white-space: normal;
  color: var(--fg); font-weight: 500;
}
.hm-item { font: inherit; font-size: 0.875rem; font-weight: 500; background: none; border: 0; cursor: pointer; width: 100%; }
.hm-item:hover, .hm-item:focus-visible { background: var(--bg-softer); outline: none; }
.hm-item:disabled { opacity: .5; cursor: not-allowed; }
.hm-item[hidden] { display: none; }
.tab-item .ico, .hm-item .ico { flex: none; width: 18px; height: 18px; margin-top: 1px; color: var(--accent-ink-strong); }
.ti-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.tab-item i, .hm-item i { font-style: normal; font-size: 0.75rem; font-weight: 400; color: var(--fg-faint); }
.tab-item:hover, .tab-item:focus-visible { background: var(--bg-softer); outline: none; }
.tab-item.is-active { background: var(--primary-50); color: var(--accent-ink-strong); border-bottom: 0; }
/* On a narrow screen the button can sit anywhere in the wrapped bar, so the
   menu hangs from the whole bar instead, full width, and cannot run off the
   edge of the page. */
@media (max-width: 640px) {
  .tab-menu { position: static; }
  .tab-menu-list { left: 16px; right: 16px; min-width: 0; max-width: none; }
}
@media (prefers-reduced-motion: reduce) { .tm-caret { transition: none; } }

/* ------------------------------------- how the rotation handles an issue */
.exa-handled {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: 8px 0 0; padding: 8px 12px; border-radius: var(--r-lg);
  background: var(--primary-50); font-size: 0.8125rem; color: var(--fg);
}
.exa-handled[hidden] { display: none; }
.eh-mark { flex: none; font-weight: 700; color: var(--accent-ink-strong); }
.eh-text { flex: 1 1 180px; min-width: 0; }

/* -------------------------------------------------------- change history */
.hcard {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
  box-shadow: var(--shadow-xs); padding: 16px 20px;
}
.hcard + .hcard { margin-top: 14px; }
.hcard-undone { background: var(--bg-softer); box-shadow: none; }
.hc-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.hc-head h3 { margin: 0; }
.hc-head .sub { margin: 2px 0 0; }
.hc-list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.hc-item {
  display: flex; align-items: baseline; justify-content: space-between; gap: 4px 16px; flex-wrap: wrap;
  padding: 7px 10px; border-radius: var(--r-md); background: var(--bg-softer); font-size: 0.875rem;
}
.hcard-undone .hc-item { background: var(--card); }
.hc-from { color: var(--fg-dim); font-weight: 500; }
.hc-undone .hc-to { text-decoration: line-through; text-decoration-color: var(--fg-faint); color: var(--fg-dim); }
.hcard > .linkish { margin-top: 8px; font-size: 0.875rem; }
.hc-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 14px; }

/* ----------------------------------------------------------- setup check */
.checklist { list-style: none; margin: 0 0 20px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.ck {
  display: grid; grid-template-columns: 28px 1fr; gap: 12px; align-items: start;
  padding: 14px 16px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
}
.ck-mark {
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  font-size: 0.8125rem; font-weight: 700; color: var(--on-strong); background: var(--success-700);
}
.ck-warn .ck-mark { background: var(--warning-700); }
.ck-bad .ck-mark { background: var(--error-700); }
.ck-title { margin: 2px 0 0; font-weight: 600; font-size: 0.9375rem; }
.ck-detail { margin: 3px 0 0; font-size: 0.875rem; color: var(--fg-dim); max-width: 90ch; }
.ck-tech { margin: 5px 0 0; font-family: var(--mono); font-size: 0.75rem; color: var(--fg-faint); }
.ck-more summary { cursor: pointer; font-size: 0.875rem; font-weight: 500; color: var(--primary-700); margin-bottom: 10px; }
.ck-more .hint { margin-bottom: 10px; }

/* --------------------------------------------------------------- timeline */
.tl-card { padding: 0; overflow: hidden; margin-bottom: 24px; }
.tl-stats { border-top: 0; border-bottom: 1px solid var(--line); }
.ht-up { color: var(--success-700); }
.ht-down { color: var(--error-700); }
.ht-flat { color: var(--fg); }
.tl-chart-wrap { padding: 16px 20px 12px; }
.tl-chart-wrap .legend { margin-bottom: 6px; }
.tl-chart { width: 100%; height: auto; display: block; overflow: visible; }
.tl-chart .grid-line { stroke: var(--line); stroke-width: 1; }
.tl-chart .axis-label { fill: var(--fg-dim); font-size: 0.75rem; }
.tl-line { fill: none; stroke: var(--primary-500); stroke-width: 2.5; stroke-linejoin: round; }
.tl-mark-applied { stroke: var(--accent-ink-strong); stroke-width: 1.5; stroke-dasharray: 4 3; }
.tl-mark-problem { fill: var(--error-500); stroke: var(--card); stroke-width: 1.5; }
.sw.tl-sw-line { background: var(--primary-500); }
.sw.tl-sw-problem { background: var(--error-500); border-radius: 50%; }
.sw.tl-sw-applied { background: var(--accent-ink-strong); width: 3px; }

.tl-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.tl-head h3 { margin: 0; }
.tl-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.tl-chip {
  font: inherit; font-size: 0.8125rem; cursor: pointer; padding: 5px 12px; border-radius: var(--r-full);
  border: 1px solid var(--line-strong); background: var(--card); color: var(--fg-dim);
}
.tl-chip[aria-pressed="true"] { background: var(--primary-700); border-color: var(--primary-700); color: var(--on-strong); }
.tl-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* A vertical line of events: date, a marker on the line, then what happened. */
.tl { list-style: none; margin: 0; padding: 0; position: relative; }
.tl-item { display: grid; grid-template-columns: 64px 28px 1fr; gap: 0 12px; position: relative; padding-bottom: 18px; }
.tl-item::before {
  content: ''; position: absolute; left: 89px; top: 26px; bottom: 0; width: 2px; background: var(--line);
}
.tl-item:last-child::before { display: none; }
.tl-date { font-size: 0.8125rem; color: var(--fg-dim); padding-top: 4px; text-align: right; font-variant-numeric: tabular-nums; }
.tl-dot {
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; z-index: 1;
  font-size: 0.8125rem; font-weight: 700; color: var(--on-strong); background: var(--fg-faint);
}
.tl-bad .tl-dot { background: var(--error-700); }
.tl-good .tl-dot { background: var(--success-700); }
.tl-info .tl-dot { background: var(--primary-700); }
.tl-body { min-width: 0; padding-top: 2px; }
.tl-title { margin: 0; font-weight: 600; font-size: 0.9375rem; }
.tl-detail { margin: 3px 0 0; font-size: 0.875rem; color: var(--fg-dim); max-width: 90ch; }
.tl-handled { margin: 6px 0 0; font-size: 0.8125rem; padding: 6px 10px; border-radius: var(--r-md); display: inline-block; }
.tl-handled.is-handled { background: var(--success-50); color: var(--success-700); }
.tl-handled.is-open { background: var(--warning-50); color: var(--warning-700); }
.tl-effect { margin: 4px 0 0; font-size: 0.875rem; color: var(--fg); }
.tl-body .hcard { margin-top: 10px; }
.tl-empty { padding: 24px; text-align: center; color: var(--fg-faint); }

@media (max-width: 640px) {
  .tl-item { grid-template-columns: 26px 1fr; }
  .tl-date { grid-column: 2; grid-row: 1; text-align: left; padding-top: 0; }
  .tl-dot { grid-column: 1; grid-row: 1 / span 2; }
  .tl-body { grid-column: 2; }
  .tl-item::before { left: 12px; }
  .tl-chart-wrap { padding: 12px; }
}

/* ---------------------------------------------------------- phone layout
   From the mobile review. A heading and its note side by side left each a
   narrow column on a phone; they stack. The rotation's Apply bar, pinned to the
   bottom of the screen, took nearly a third of a phone's height; it tightens to
   a line of text and one row of controls. */
@media (max-width: 640px) {
  .card-head, .bd-head, .tl-head, .hc-head { flex-direction: column; align-items: flex-start; gap: 4px; }
  .bd-head i { text-align: left; }
  .plan-bar { gap: 8px 12px; padding: 10px 12px; }
  .pb-scope { flex-basis: 100%; font-size: 0.8125rem; line-height: 1.125rem; }
  .plan-bar .check { flex: 1 1 160px; font-size: 0.8125rem; }
  .plan-bar .btn-primary { flex: none; }
}

/* ============================================================ phone menu
   Up to 760px the header is the logo, the page you are on and a menu button,
   and stays at the top while the page scrolls. The navigation and the
   controls are moved into #mobile-panel by app.js; this lays them out there. */
.page-name, .menu-btn { display: none; }
.mobile-panel[hidden] { display: none; }

@media (max-width: 760px) {
  .topbar {
    position: sticky; top: 0; z-index: 45;
    /* 6px around the 44px button makes the bar exactly 56px, which is where
       the menu panel starts. */
    flex-wrap: nowrap; gap: 12px; padding: 6px var(--gutter); height: 56px;
  }
  .brand { flex: none; }
  .page-name {
    display: block; flex: 1 1 auto; min-width: 0; text-align: right;
    font-size: 0.875rem; font-weight: 600; color: var(--fg-dim);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .menu-btn {
    display: grid; place-items: center; flex: none; width: 44px; height: 44px; margin-right: -8px;
    background: none; border: 0; border-radius: var(--r-md); cursor: pointer; color: var(--fg);
  }
  .menu-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .mb-bars { display: flex; flex-direction: column; gap: 5px; width: 22px; }
  .mb-bars i { display: block; height: 2px; border-radius: 1px; background: currentColor; transition: transform .2s ease, opacity .2s ease; }
  /* The three bars fold into a cross while the menu is open. */
  .menu-open .mb-bars i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .menu-open .mb-bars i:nth-child(2) { opacity: 0; }
  .menu-open .mb-bars i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  /* The panel covers the page under the header and scrolls on its own; the
     page behind it does not scroll while it is open. */
  .mobile-panel {
    position: fixed; top: 56px; left: 0; right: 0; bottom: 0; z-index: 44;
    overflow-y: auto; overscroll-behavior: contain;
    background: var(--card); border-top: 1px solid var(--line);
    padding: 8px var(--gutter) 32px;
  }
  body.menu-open { overflow: hidden; }
  .mp-label {
    margin: 16px 0 6px; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em;
    text-transform: uppercase; color: var(--fg-faint);
  }

  /* Pages: a list, the current one tinted. DID Health's reports are listed
     under it in place rather than behind a second menu. */
  .mobile-panel nav.tabs {
    display: flex; flex-direction: column; align-items: stretch; gap: 2px;
    padding: 0; border: 0; background: none; position: static;
  }
  .mobile-panel .tab {
    text-align: left; padding: 12px 12px; border-radius: var(--r-md); border-bottom: 0;
    font-size: 1rem; color: var(--fg);
  }
  .mobile-panel .tab.is-active { background: var(--primary-50); color: var(--accent-ink-strong); }
  .mobile-panel .tab-menu { flex-direction: column; position: static; }
  .mobile-panel .tab-menu-btn { pointer-events: none; color: var(--fg-dim); font-size: 0.8125rem; font-weight: 600;
    letter-spacing: 0.04em; text-transform: uppercase; padding-bottom: 4px; }
  .mobile-panel .tab-menu-btn.is-active { background: none; }
  .mobile-panel .tm-caret, .mobile-panel .tm-current { display: none; }
  .mobile-panel .tab-menu-list {
    display: flex; position: static; min-width: 0; max-width: none;
    padding: 0 0 0 12px; border: 0; border-left: 2px solid var(--line); margin-left: 12px;
    box-shadow: none; background: none;
  }
  .mobile-panel .tab-item { font-size: 0.9375rem; padding: 10px 12px; }

  /* Controls: full-width selects, then the actions. */
  .mobile-panel .controls { display: flex; flex-direction: column; align-items: stretch; gap: 12px; width: 100%; }
  /* The phone rule above sizes each control by flex-basis for a row; in this
     column that basis became a 132px height. */
  .mobile-panel .ctl, .mobile-panel .controls .btn { flex: none; }
  .mobile-panel .ctl select { width: 100%; padding: 10px 12px; font-size: 1rem; }
}
@media (max-width: 760px) and (prefers-reduced-motion: reduce) { .mb-bars i { transition: none; } }

/* ------------------------------------------------- Tools and the account
   Icon over label, beside the selects. */
.hmenu { position: relative; display: flex; }
.hmenu-right { left: auto; right: 0; }
.hdr-actions { display: flex; align-items: flex-end; gap: 4px; }
.icon-btn {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  min-width: 64px; padding: 6px 8px; border: 0; border-radius: var(--r-lg); background: none;
  font: inherit; font-size: 0.75rem; font-weight: 600; color: var(--fg-dim); cursor: pointer;
}
.icon-btn .ib-ico { width: 22px; height: 22px; color: var(--fg); }
.icon-btn .ib-label { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.icon-btn:hover, .icon-btn[aria-expanded="true"] { background: var(--bg-softer); color: var(--fg); }
.icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.hm-head {
  display: flex; flex-direction: column; gap: 1px; padding: 8px 12px 10px; margin-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.hm-head b { font-size: 0.875rem; }
.hm-head i { font-style: normal; font-size: 0.75rem; color: var(--fg-faint); }
#account-menu, #tools-menu { min-width: 260px; }

/* Account forms, in the drawer. */
.acct-form { display: flex; flex-direction: column; gap: 4px; margin-top: 16px; max-width: 360px; }
.acct-form input { font: inherit; font-size: 1rem; padding: 9px 11px; border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--card); color: var(--fg); }
.acct-actions { display: flex; gap: 10px; margin-top: 8px; }
.acct-msg { margin: 4px 0 0; font-size: 0.8125rem; min-height: 18px; }
.acct-msg.bad { color: var(--error-700); }

@media (max-width: 760px) {
  /* In the phone menu: each menu becomes a heading with its items under it. */
  .mobile-panel .hdr-actions { flex-direction: column; align-items: stretch; gap: 0; width: 100%; }
  .mobile-panel .hmenu { flex-direction: column; }
  .mobile-panel .icon-btn {
    pointer-events: none; flex-direction: row; align-items: center; min-width: 0; padding: 0;
    margin: 16px 0 6px; font-size: 0.75rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-faint);
  }
  .mobile-panel .icon-btn .ib-ico { display: none; }
  .mobile-panel .hmenu-list {
    display: flex; position: static; min-width: 0; max-width: none; padding: 0;
    border: 0; box-shadow: none; background: none;
  }
  .mobile-panel .hm-item { font-size: 0.9375rem; padding: 11px 12px; }
  .mobile-panel .hm-head { padding: 0 12px 8px; }
  /* The name is the first line of the section already; the heading is just Account. */
  .mobile-panel #account-btn .ib-label { display: none; }
  .mobile-panel #account-btn::before { content: 'Account'; }
}

/* Number detail: the verdict, then each result as a sentence-sized row. */
.drawer h3 { margin: 24px 0 8px; }
.dq-verdict { margin: 12px 0 0; }
.dq-verdict .pill { margin: 0 0 10px; display: inline-block; }
.dq-verdict .reason { font-size: 0.9375rem; line-height: 1.4375rem; color: var(--fg); margin-bottom: 6px; }
.dq-hint { margin: 0 0 12px; }
.dq-rows { display: grid; gap: 14px; margin: 0 0 12px; }
.dq-row { display: grid; grid-template-columns: 1fr auto; gap: 6px 12px; align-items: baseline; }
.dq-label { font-weight: 600; }
.dq-v { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dq-v b { font-size: 1rem; }
.dq-change { display: block; font-size: 0.8125rem; color: var(--fg-dim); }
.dq-change.up { color: var(--success-700); font-weight: 600; }
.dq-change.down { color: var(--error-700); font-weight: 600; }
.dq-track { grid-column: 1 / -1; height: 10px; border-radius: 5px; background: var(--bg-soft); overflow: hidden; }
.dq-track i { display: block; height: 100%; min-width: 3px; border-radius: 5px; }
.dq-good { background: var(--success-500); }
.dq-mid  { background: var(--primary-500); }
.dq-sale { background: var(--primary-700); }
.dq-rest { background: var(--fg-faint); }
.cause-code { display: block; font-size: 0.75rem; }

/* ------------------------------------------------------------- loading */
.busy { position: fixed; inset: 0 0 auto 0; z-index: 60; pointer-events: none; }
.busy[hidden] { display: none; }
.busy-bar { height: 3px; overflow: hidden; background: var(--primary-200); }
.busy-bar i { display: block; width: 40%; height: 100%; background: var(--primary-700); animation: busy-run 1.1s ease-in-out infinite; }
.busy-note {
  display: flex; align-items: center; gap: 10px; width: max-content; max-width: calc(100vw - 32px);
  margin: 116px auto 0; padding: 9px 16px; border-radius: 999px;
  background: #0f172a; color: #fff; font-size: 0.875rem; border: 1px solid rgb(255 255 255 / .18);
  box-shadow: 0 6px 20px rgb(15 23 42 / .22);
}
.busy-spin { flex: none; width: 14px; height: 14px; border-radius: 50%; border: 2px solid rgb(255 255 255 / .35); border-top-color: #fff; animation: busy-turn .8s linear infinite; }
main[aria-busy="true"] .panel:not([hidden]) { opacity: .55; transition: opacity .2s; }
@keyframes busy-run { from { transform: translateX(-100%); } to { transform: translateX(250%); } }
@keyframes busy-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .busy-bar i { animation: none; width: 100%; opacity: .6; }
  .busy-spin { animation-duration: 2.4s; }
}
@media (max-width: 760px) { .busy-note { margin-top: 68px; } }

/* ------------------------------------------------------------ downloads
   The same control on every report table: see export.js. */
.dl { position: relative; margin-left: auto; }
.list-count + .dl { margin-left: 0; }
.dl > summary { list-style: none; display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; user-select: none; }
.dl > summary::-webkit-details-marker { display: none; }
.dl[open] > summary { border-color: var(--line-strong); background: var(--hover); }
.dl-ico { display: inline-flex; color: var(--fg-dim); }
.dl-list {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30; min-width: 168px; padding: 6px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-md);
  display: grid; gap: 2px;
}
.dl-item {
  font: inherit; font-size: 0.875rem; color: var(--fg); text-align: left; cursor: pointer;
  background: none; border: 0; border-radius: var(--r-md); padding: 8px 10px;
}
.dl-item:hover, .dl-item:focus-visible { background: var(--hover); outline: none; }
.dl-item:focus-visible { box-shadow: inset 0 0 0 2px var(--focus); }
/* A table with no toolbar of its own: the control alone, tucked above it. */
.list-tools.dl-only { margin: 0 0 8px; min-height: 0; }
.drawer .list-tools.dl-only { margin-top: 2px; }
.plan-tools .dl { margin-left: 0; }

/* -------------------------------------------------- numbers: the filters */
.num-filters {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 16px; margin: 0; padding: 14px 16px;
  border-top: 1px solid var(--line);
}
.num-filters[hidden] { display: none; }
.nf { display: grid; gap: 4px; min-width: 0; }
.nf-l { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-dim); }
.nf-s { min-width: 168px; max-width: 100%; padding-block: 7px; }
/* A filter that is narrowing the list says so without being read. */
.nf-s.is-set { border-color: var(--primary-700); box-shadow: inset 0 0 0 1px var(--primary-700); }
.nf-count { margin-left: auto; align-self: center; font-size: 0.875rem; color: var(--fg-dim); font-variant-numeric: tabular-nums; }
.num-filters .linkish { align-self: center; }
@media (max-width: 760px) {
  .nf { flex: 1 1 44%; }
  .nf-s { width: 100%; min-width: 0; }
  .nf-count { margin-left: 0; flex: 1 1 100%; }
}

/* The share beside a count on the dashboard: people reached, as a rate. */
.hs-rate {
  margin-left: 10px; font-size: 0.8125rem; line-height: 1; font-weight: 600; letter-spacing: 0; vertical-align: middle;
  padding: 4px 8px; border-radius: var(--r-full); background: var(--primary-50); color: var(--accent-ink-strong); white-space: nowrap;
}

/* ------------------------------------------- the number drawer, in blocks
   Each answer in its own card with its own heading, so the eye can find where
   one stops and the next starts. */
.dq-top { padding: 0 34px 4px 0; }
.dq-top .sub { margin: 0; }
.dq-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; margin: 16px 0 6px; }
.dq-tile {
  display: grid; gap: 2px; padding: 10px 12px; min-width: 0;
  background: var(--bg-softer); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.dq-tile b { font-size: 1.25rem; line-height: 1.5rem; font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.dq-tile span { font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-dim); }
.dq-tile i { font-style: normal; font-size: 0.75rem; color: var(--fg-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dq-card { margin: 14px 0 0; border: 1px solid var(--line); border-radius: var(--r-xl); background: var(--card); overflow: hidden; }
.dq-head { padding: 11px 16px 10px; background: var(--band); border-bottom: 1px solid var(--line); }
.drawer .dq-head h3 { margin: 0; font-size: 0.9375rem; line-height: 1.375rem; font-weight: 600; }
.dq-sub { margin: 2px 0 0; font-size: 0.8125rem; line-height: 1.1875rem; color: var(--fg-dim); }
.dq-body { padding: 16px; }
.dq-body > :first-child { margin-top: 0; }
.dq-body > :last-child { margin-bottom: 0; }
.dq-body .dq-rows:last-child, .dq-body .tablewrap:last-child { margin-bottom: 0; }
.dq-body .lifecycle { margin: 0; padding: 0; background: none; }
.dq-checks { margin: 0; display: grid; gap: 4px; }
.dq-checks dt { font-weight: 600; font-size: 0.875rem; }
.dq-checks dd { margin: 0 0 10px; color: var(--fg-dim); font-size: 0.875rem; line-height: 1.3125rem; }
.dq-checks dd:last-child { margin-bottom: 0; }
/* The client's own disposition codes. */
.dispo-code { font-family: var(--mono); font-size: 0.8125rem; }
.dispo-pill { margin-left: 8px; font-size: 0.6875rem; }
.dispo-share { white-space: nowrap; }
.dispo-bar { display: inline-block; width: 64px; height: 8px; margin-right: 8px; border-radius: 4px; background: var(--bg-soft); overflow: hidden; vertical-align: middle; }
.dispo-bar i { display: block; height: 100%; min-width: 2px; border-radius: 4px; background: var(--primary-500); }
@media (max-width: 560px) {
  .dq-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dispo-bar { display: none; }
}
.tl-dl { display: flex; gap: 8px; flex-wrap: wrap; }
.tl-dl .dl { margin-left: 0; }
/* The reason for a change: on every card, set off from the numbers above it. */
.pc-why { padding-top: 8px; margin-top: 6px; border-top: 1px dashed var(--line); line-height: 1.25rem; }
.pc-why b { color: var(--fg); font-weight: 600; }
/* Geography by time of day. */
.th-sub { display: block; font-style: normal; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--fg-faint); }
.gh-best { font-weight: 700; color: var(--success-700); background: var(--success-50); }
.gh-all td { background: var(--band); }
.gh-ref { min-width: 260px; }
.gh-ref .pill { margin-right: 8px; }
.gh-detail { display: block; margin-top: 4px; font-size: 0.8125rem; color: var(--fg-dim); }

/* ------------------------------------------- what a change is based on
   Best practice, or the account's own call results: on every change, every
   group, and as a notice above them when the first is carrying the fix. */
.basis {
  display: inline-block; margin-right: 8px; padding: 2px 8px; border-radius: var(--r-full); vertical-align: 1px;
  font-size: 0.6875rem; line-height: 1.125rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; white-space: nowrap;
  border: 1px solid transparent;
}
.basis-practice { background: var(--bg-softer); border-color: var(--line-strong); color: var(--fg-dim); }
.basis-calls { background: var(--success-50); border-color: var(--success-200); color: var(--success-700); }
.basis-early { background: var(--warning-50); border-color: var(--warning-200); color: var(--warning-700); }
.basis-set { margin-left: 10px; }
.basis-set .basis { margin-right: 4px; }
.basis-note {
  margin: 18px 0 6px; padding: 14px 18px; border-radius: var(--r-xl);
  background: var(--band); border: 1px solid var(--line);
}
.basis-note-strong { background: var(--warning-50); border-color: var(--warning-200); }
.bn-head { margin: 0 0 6px; font-size: 1rem; line-height: 1.5rem; font-weight: 600; color: var(--fg); }
.bn-body { margin: 0 0 10px; max-width: 86ch; font-size: 0.9375rem; line-height: 1.4375rem; color: var(--fg); }
.bn-split { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.bn-split li { display: grid; grid-template-columns: 190px 110px 1fr; gap: 4px 10px; align-items: baseline; font-size: 0.875rem; line-height: 1.3125rem; }
.bn-split li .basis { justify-self: start; margin: 0; }
.bn-split li b { font-variant-numeric: tabular-nums; white-space: nowrap; }
.bn-split li span:last-child { color: var(--fg-dim); }
.sh-est { margin: 6px 0 0; font-size: 0.875rem; color: var(--fg-dim); max-width: 80ch; }
.sh-basis { margin: 14px 0 0; font-size: 0.875rem; line-height: 1.375rem; color: var(--fg-dim); max-width: 68ch; }
@media (max-width: 760px) {
  .bn-split li { grid-template-columns: 1fr; }
  .basis-set { display: block; margin: 4px 0 0; }
}

/* The two weekend switches on Day & time. */
.weekend-choices { display: flex; flex-wrap: wrap; gap: 12px 28px; margin: 0 0 16px; padding: 14px 16px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl); }
.weekend-choices:empty { display: none; }
.wk { display: flex; align-items: flex-start; gap: 10px; flex: 1 1 320px; cursor: pointer; }
.wk input { margin-top: 3px; width: 16px; height: 16px; accent-color: var(--primary-700); flex: none; }
.wk-text { display: grid; gap: 2px; }
.wk-text b { font-weight: 600; }
.wk-text i { font-style: normal; font-size: 0.8125rem; line-height: 1.1875rem; color: var(--fg-dim); }
/* A state's compliance flags, in the Geography table. */
.cmp-cell { min-width: 0; }
.cmp-cell .pill { margin-right: 6px; }
.cmp-cell .linkish { display: block; margin-top: 4px; font-size: 0.8125rem; }

/* The five figures for a set of calls, outside the number drawer. */
.acct-tiles { margin: 0 0 18px; }
.acct-tiles .dq-tile { background: var(--card); padding: 12px 14px; }
.acct-tiles .dq-tile b { font-size: 1.375rem; line-height: 1.75rem; }
.nf-sum { margin: -4px 0 12px; }
.nf-sum-head { margin: 0 0 8px; font-size: 0.8125rem; font-weight: 600; color: var(--fg-dim); }
.time-metric { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 0 0 14px; }
.time-metric .nf-l { margin-right: 4px; }

/* The Numbers filters, folded into one bar above the list. */
.nf-box { margin: 0 0 12px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl); }
.nf-box[hidden] { display: none; }
.nf-bar { display: flex; align-items: center; gap: 6px 12px; flex-wrap: wrap; padding: 10px 16px; cursor: pointer; list-style: none; user-select: none; }
.nf-bar::-webkit-details-marker { display: none; }
.nf-bar::after { content: ""; width: 7px; height: 7px; margin-left: auto; border-right: 2px solid var(--fg-dim); border-bottom: 2px solid var(--fg-dim); transform: rotate(45deg); transition: transform .15s; }
.nf-box[open] > .nf-bar::after { transform: rotate(-135deg); }
.nf-bar:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-xl); }
.nf-title { font-weight: 600; }
.nf-state { display: flex; gap: 10px; flex-wrap: wrap; font-size: 0.8125rem; color: var(--fg-dim); }
.nf-on { font-weight: 600; color: var(--primary-700); }
.nf-box .nf-sum { margin: 0; padding: 0 16px 14px; }
@media (prefers-reduced-motion: reduce) { .nf-bar::after { transition: none; } }
.nf-ico { flex: none; color: var(--primary-700); margin-right: -2px; }

/* ------------------------------------------- the response codes' own window

   One row of presets above the two code cards. Deliberately quieter than the
   header's Window control: that one re-scores the whole account, this one
   moves two cards, and they must not look like the same control. */
.range-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  margin: 0 0 12px;
}
.range-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.rchip {
  font: inherit; font-size: 0.8125rem; line-height: 1; cursor: pointer;
  padding: 7px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--fg-dim);
}
.rchip:hover { border-color: var(--stroke-sub); color: var(--fg); }
.rchip.is-on {
  background: var(--accent-soft, var(--primary-50)); border-color: var(--primary-200, var(--line));
  color: var(--accent-ink-strong); font-weight: 600;
}
.rchip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.range-custom { display: flex; flex-wrap: wrap; align-items: end; gap: 8px; }
.range-custom label { display: flex; flex-direction: column; gap: 3px; }
.range-custom span { font-size: 0.6875rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-faint); }
.range-custom input {
  font: inherit; font-size: 0.8125rem; padding: 6px 8px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--card); color: var(--fg);
}
.range-said { font-size: 0.75rem; color: var(--fg-faint); margin-left: auto; text-align: right; }
@media (max-width: 640px) {
  .range-said { margin-left: 0; text-align: left; flex-basis: 100%; }
}

/* --------------------------------------- one area code's day, in its drill */

.ac-hours { display: flex; flex-direction: column; gap: 10px; margin: 0 0 14px; }
.ach-windows { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
.ach-w {
  position: relative; display: flex; flex-direction: column; gap: 2px;
  padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--card);
}
.ach-w.is-best { border-color: var(--ok-300, var(--stroke-sub)); background: var(--ok-50, var(--bg-soft)); }
.ach-w.is-thin { background: var(--bg-soft); }
.ach-l { font-size: 0.6875rem; color: var(--fg-faint); display: flex; flex-direction: column; gap: 1px; }
.ach-l i { font-style: normal; font-size: 0.625rem; color: var(--fg-faint); opacity: 0.85; }
.ach-v { font-size: 1.0625rem; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--fg); }
.ach-w.is-thin .ach-v { font-size: 0.8125rem; font-weight: 400; }
.ach-best {
  position: absolute; top: 8px; right: 9px;
  font-size: 0.5625rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ok-700, var(--fg-dim));
}
.ach-lines { display: flex; flex-direction: column; gap: 5px; }
.ach-lines p { margin: 0; font-size: 0.8125rem; color: var(--fg-dim); display: flex; flex-wrap: wrap; align-items: baseline; gap: 7px; }
.ach-lines b { color: var(--fg); font-weight: 600; }
@media (max-width: 760px) {
  .ach-windows { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The hours table's own By state / By area code toggle, under its heading. */
.scope-chips { margin: 0 0 10px; }

/* ------------------------------------------------- sub-tabs within a panel

   One control grouping a long page's blocks. The first cut was a text row
   with a hairline underline, and readers did not find it: against a white
   page it read as a caption, not as the switch that decides what the page is
   showing. It is now a raised segmented control in its own tray - a shape
   that is unmistakably pressable - and the chosen segment is a lifted card
   with the accent down its top edge. */
.subtabs {
  display: inline-flex; flex-wrap: wrap; gap: 4px;
  margin: 0 0 22px; padding: 5px;
  background: var(--bg-softer); border: 1px solid var(--line);
  border-radius: 14px;
}
.subtab {
  font: inherit; text-align: left; cursor: pointer;
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 16px 10px; border: 1px solid transparent; border-radius: 10px;
  background: none; color: var(--fg-dim);
  font-size: 0.875rem; font-weight: 600;
}
.subtab i {
  font-style: normal; font-size: 0.6875rem; font-weight: 400;
  color: var(--fg-faint); letter-spacing: 0.01em;
}
.subtab:hover { background: rgba(255, 255, 255, 0.6); color: var(--fg); }
.subtab.is-on {
  background: var(--card); border-color: var(--line);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 2px 8px rgba(15, 23, 42, 0.08);
  color: var(--accent-ink-strong);
  /* The accent on the top edge, so the chosen segment is readable as chosen
     even where the lift itself is lost (high contrast, print, a dark ground). */
  box-shadow: inset 0 3px 0 var(--accent), 0 1px 2px rgba(15, 23, 42, 0.06), 0 2px 8px rgba(15, 23, 42, 0.08);
  padding-top: 10px;
}
.subtab.is-on i { color: var(--fg-dim); }
.subtab:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .subtab:hover { background: rgba(255, 255, 255, 0.06); }
}
:root[data-theme="dark"] .subtab:hover { background: rgba(255, 255, 255, 0.06); }

/* The first card in a view sits straight under the control, which already
   provides the separation a top margin would otherwise have to. */
.subview > .card:first-child, .subview > .panel-sub:first-child { margin-top: 0; }

@media (max-width: 760px) {
  .subtabs { display: flex; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; max-width: 100%; }
  .subtabs::-webkit-scrollbar { display: none; }
  .subtab { white-space: nowrap; }
  .subtab i { display: none; }
}

/* A caller ID printed anywhere on Geography opens its own report. Styled as
   the number it already was, plus the dotted underline the rest of the app
   uses for "there is more behind this" — a filled link colour on six numbers
   per row would turn the table into a page of links. */
.did-open {
  font: inherit; font-weight: 600; font-variant-numeric: tabular-nums;
  padding: 0; background: none; border: 0; cursor: pointer;
  color: inherit; text-align: inherit;
  border-bottom: 1px dotted var(--stroke-sub);
}
.did-open:hover { color: var(--accent-ink); border-bottom-style: solid; }
.did-open:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 3px; }
.did-open.runner { font-weight: 500; }
