/* ============================================================================
   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 */
  --primary-700: #2189a1;   /* darkened for text contrast on white */

  /* --- neutrals ------------------------------------------------------------ */
  --text-strong: #020617;   /* text/strong-950 */
  --text-sub:    #475569;   /* text/sub-600    */
  --icon-soft:   #94a3b8;   /* icon/soft-400   */
  --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);
  --line: var(--stroke-soft);
  --line-strong: var(--stroke-sub);
  --fg: var(--text-strong);
  --fg-dim: var(--text-sub);
  --fg-faint: var(--icon-soft);
  --accent: var(--primary-500);
  --accent-ink: var(--primary-700);

  /* --- 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: #6b7f8e;
    --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;
  }
}

:root[data-theme="dark"] {
  --primary-500: #45c3dd; --primary-200: #1e6d80; --primary-50: #0e2c34; --primary-700: #7fd8ea;
  --text-strong: #e8eef2; --text-sub: #9fb0bd; --icon-soft: #6b7f8e;
  --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;
}

* { 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: 14px; line-height: 20px; 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 */
  font-size: 11px; font-weight: 600; line-height: 16px;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-faint);
}

select, .btn {
  font: inherit; font-size: 14px; 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; }
.btn-primary { background: var(--primary-500); border-color: var(--primary-500); color: #fff; font-weight: 600; }
.btn-primary:hover { background: var(--primary-700); border-color: var(--primary-700); }
.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); overflow-x: auto;
}
.tab {
  font: inherit; font-size: 14px; 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); }
.tab.is-active { color: var(--primary-700); 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: 12px; line-height: 18px; color: var(--fg-faint); }
.sitefoot-meta { margin: 0; font-size: 12px; color: var(--fg-faint); font-variant-numeric: tabular-nums; }

.panel-head { margin-bottom: 16px; }
.panel-head h2 {
  /* Title/Title 1: 24 / 32, semibold */
  margin: 0 0 4px; font-size: 24px; line-height: 32px; font-weight: 600; letter-spacing: -0.02em;
}
.hint { margin: 0; color: var(--fg-dim); font-size: 14px; max-width: 74ch; }
h3 { font-size: 16px; line-height: 24px; 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: 24px; line-height: 32px; font-weight: 600; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.stat-l { font-size: 11px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-faint); }
.stat-l i { display: block; font-style: normal; text-transform: none; letter-spacing: -0.006em; font-weight: 400; font-size: 12px; }

/* ------------------------------------------------------------------ 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: 14px; }
table.grid th {
  text-align: left; font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--fg-faint); padding: 12px 16px;
  border-bottom: 1px solid var(--line); background: var(--bg-softer);
  position: sticky; top: 0; white-space: nowrap;
}
table.grid td { padding: 12px 16px; border-bottom: 1px solid var(--line); white-space: nowrap; }
table.grid tbody tr:last-child td { border-bottom: 0; }
table.grid tbody tr.clickable { cursor: pointer; }
table.grid tbody tr.clickable:hover { background: var(--hover); }
.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: 13px; }
.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: 11px; font-weight: 600; letter-spacing: 0.04em;
  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(--primary-700); background: var(--primary-50); }
.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); }

.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: 13px; }
.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: 12px; 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: 11px; width: 100%; }
table.heat th { color: var(--fg-faint); font-weight: 500; padding: 2px 4px; font-variant-numeric: tabular-nums; }
table.heat td {
  min-width: 32px; height: 30px; border-radius: var(--r-md); text-align: center;
  font-size: 10px; font-weight: 500; 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: 12px; 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;
}

/* 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; }

/* -------------------------------------------------------- calling calendar */

.cal-list {
  display: grid; gap: 10px; align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr));
}
.cal-row {
  display: grid; grid-template-columns: 84px 1fr; gap: 14px; align-items: start;
  background: var(--card); border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong); border-radius: var(--r-xl);
  box-shadow: var(--shadow-xs); padding: 14px 18px;
}
.cal-severe   { border-left-color: var(--error-500); }
.cal-moderate { border-left-color: var(--warning-500); }
.cal-mild     { border-left-color: var(--icon-soft); }
.cal-up       { border-left-color: var(--success-500); }
.cal-when { display: flex; flex-direction: column; gap: 2px; font-size: 12px; color: var(--fg-faint); font-variant-numeric: tabular-nums; }
.cal-when b { color: var(--fg); font-weight: 600; font-size: 13px; }
.cal-name { font-weight: 600; font-size: 15px; margin-bottom: 4px; }
.cal-head { font-size: 14px; color: var(--fg-dim); margin: 0; line-height: 20px; }
.cal-measured { margin-top: 8px; font-size: 12px; 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 {
  background: var(--card); border: 1px solid var(--line);
  border-left: 3px solid var(--icon-soft); border-radius: var(--r-xl);
  box-shadow: var(--shadow-xs); padding: 14px 18px;
}
.signal-critical { border-left-color: var(--error-500); }
.signal-warning  { border-left-color: var(--warning-500); }
.signal-info     { border-left-color: var(--primary-500); }
.signal-kind { font-size: 10px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-faint); margin-bottom: 5px; }
.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: 15px; margin-bottom: 6px; }
.signal-body { margin: 0 0 6px; font-size: 13px; color: var(--fg-dim); line-height: 19px; }
.signal-body:last-child { margin-bottom: 0; }
.signal-where { font-size: 11px; color: var(--fg-faint); margin-top: 8px; }

/* ---------------------------------------------------------------- messages */

.banner {
  border: 1px solid var(--warning-200); border-left: 3px solid var(--warning-500);
  border-radius: var(--r-xl); padding: 12px 16px; margin-bottom: 20px;
  font-size: 14px; background: var(--warning-50); color: var(--fg);
}
.banner.bad { border-color: var(--error-200); border-left-color: var(--error-500); background: var(--error-50); }
.banner p { margin: 0 0 6px; }
.banner p:last-child { margin-bottom: 0; }

.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
  padding: 12px 20px; z-index: 60; box-shadow: var(--shadow-md); font-size: 14px;
}
.toast.bad  { border-color: var(--error-500); }
.toast.good { border-color: var(--success-500); }

.plan-head {
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  padding: 16px 20px; border: 1px solid var(--line); border-radius: var(--r-xl);
  background: var(--card); box-shadow: var(--shadow-xs); margin-bottom: 18px;
}
.lift { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.lift .to { color: var(--success-700); }
.lift .rel { font-size: 14px; color: var(--success-700); }

.empty { padding: 44px 20px; text-align: center; color: var(--fg-faint); }
.check { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--fg-dim); }
.bench { margin-top: 20px; font-size: 14px; color: var(--fg-dim); }
.bench li { margin-bottom: 4px; }

/* ------------------------------------------------------------------ drawer */

.scrim { position: fixed; inset: 0; background: #02061759; z-index: 40; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(580px, 100vw);
  background: var(--card); border-left: 1px solid var(--line);
  box-shadow: var(--shadow-md); z-index: 50; overflow-y: auto; padding: 24px 26px 44px;
}
.drawer-close {
  position: absolute; top: 14px; right: 16px; background: none; border: 0;
  color: var(--fg-dim); font-size: 26px; line-height: 1; cursor: pointer;
}
.drawer h2 { margin: 0 0 3px; font-size: 22px; font-weight: 600; letter-spacing: -0.02em; }
.drawer .reason { color: var(--fg-dim); margin: 0 0 10px; max-width: 62ch; font-size: 14px; }

.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; }
.kv dt { font-size: 10px; text-transform: uppercase; letter-spacing: 0.09em; color: var(--fg-faint); margin: 0 0 3px; font-weight: 600; }
.kv dd { margin: 0; font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; }

.trend { font-size: 13px; 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 */

.hero {
  display: flex; align-items: center; gap: 28px; flex-wrap: wrap;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--shadow-xs);
  padding: 24px 28px; margin-bottom: 20px;
}
.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: grid; place-items: center;
  font-size: 34px; font-weight: 600; letter-spacing: -0.03em; font-variant-numeric: tabular-nums;
}
.hero-text { flex: 1 1 320px; min-width: 0; }
.hero-label { font-size: 20px; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 6px; }
.hero-reason { margin: 0 0 12px; color: var(--fg-dim); font-size: 14px; max-width: 68ch; }
.hero-chips { display: flex; gap: 20px; flex-wrap: wrap; }
.hero-chip { display: flex; flex-direction: column; gap: 2px; }
.hero-chip .v { font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.hero-chip .l { font-size: 11px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--fg-faint); }
.hero-chip .d { font-size: 12px; font-variant-numeric: tabular-nums; }
.hero-chip .d.up { color: var(--success-700); }
.hero-chip .d.down { color: var(--error-700); }

/* 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. */
.dash-grid {
  display: grid; gap: 16px; align-items: start;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 1200px) { .dash-grid { 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: 14px; font-size: 12px; color: var(--fg-faint); }
.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; }
.chart .axis-label { fill: var(--fg-faint); font-size: 10px; }
.chart .area-answer { fill: var(--primary-500); opacity: .16; }
.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); }

/* 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: 13px; }
.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: 12px; }

.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: 20px; }

  main { padding: 16px var(--gutter) 32px; }
  .card { padding: 14px 16px; }
  .panel-head h2 { font-size: 20px; line-height: 28px; }

  /* Ring and text stack rather than squeezing the reason into a narrow column. */
  .hero { padding: 18px 16px; gap: 16px; }
  .hero-score, .ring { width: 96px; height: 96px; }
  .hero-chips { gap: 14px; }

  /* 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 {
  flex: 0 1 320px; min-width: 260px; align-self: stretch;
  display: flex; flex-direction: column; gap: 7px;
  padding-left: 24px; border-left: 1px solid var(--line);
}
.bd-head {
  font-size: 11px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--fg-faint); margin-bottom: 1px;
}
.bd-row { display: grid; grid-template-columns: 1fr 84px 34px; align-items: center; gap: 10px; font-size: 12px; }
.bd-l { color: var(--fg-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The centre line is zero: bars grow right for points gained, left for lost. */
.bd-track { position: relative; height: 8px; background: var(--bg-soft); border-radius: 999px; }
.bd-track::before {
  content: ''; position: absolute; left: 50%; top: -2px; bottom: -2px;
  width: 1px; background: var(--line);
}
.bd-bar { position: absolute; top: 0; bottom: 0; border-radius: 999px; }
.bd-bar.up { background: var(--success-500); }
.bd-bar.down { background: var(--error-500); }
.bd-v { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
/* 700, not 500: the 500s are fill weights and do not carry small text. */
.bd-v.up { color: var(--success-700); }
.bd-v.down { color: var(--error-700); }

@media (max-width: 900px) {
  .hero-breakdown { padding-left: 0; border-left: 0; border-top: 1px solid var(--line); padding-top: 16px; }
}
