/* ============================================================
   OPS · PEZZA SKIN — ux-spec §4's promised token-file swap.
   Pezza design system v0.5.1: monochrome ink ramp, one accent
   (Crossfade Cyan) used like a cursor, Space Grotesk for UI,
   Space Mono for every technical value (the metadata register).
   Severity dots map onto Pezza's muted status colors.
   Tokens are BARE HSL CHANNELS — always wrap: hsl(var(--x) / a).
   ============================================================ */

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(/fonts/space-grotesk-var.woff2) format("woff2");
}
@font-face {
  font-family: "Space Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/space-mono-400.woff2) format("woff2");
}
@font-face {
  font-family: "Space Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/space-mono-700.woff2) format("woff2");
}

:root {
  /* —— Ink scale — the DS's full ramp, kept whole; --ink-200/--ink-700 are
     currently unreferenced by design, not by accident —— */
  --ink-1000: 240 5% 4%;
  --ink-900: 240 6% 7%;
  --ink-800: 240 6% 10%;
  --ink-700: 240 5.4% 14.5%;
  --ink-600: 240 5.5% 21.6%;
  --ink-500: 240 4.4% 35.3%;
  --ink-400: 240 3.6% 50.4%;
  --ink-300: 240 4.7% 66.7%;
  --ink-200: 240 5.5% 82.2%;
  --ink-150: 240 7.4% 89.4%;
  --ink-100: 240 7% 94%;
  --ink-50: 240 7% 97%;
  --ink-0: 0 0% 100%;

  /* —— Accent: Crossfade Cyan. A cursor, never decoration. —— */
  --accent: 170.3 100% 44.9%;
  --accent-dim: 170.1 87.8% 25%;

  /* —— Status (muted; the brand is not colorful). No success green: sev-0
     is ink on purpose — "ok" is the quiet default, colour is reserved for
     what needs attention, so the DS's --ok pair stays out of this skin. —— */
  --warn: 41.4 79.1% 56.9%;
  --err: 358.8 85.6% 64.7%;
  --warn-dim: 41.4 79.1% 29%;
  --err-dim: 358.8 85.6% 42%;

  /* —— Type: Grotesk for UI, Mono for metadata —— */
  --font-sans: "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Space Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --text-xs: 0.6875rem;
  --text-sm: 0.75rem;
  --text-base: 0.8125rem;
  --text-lg: 1rem;
  --tracking-wide: 0.08em;
  --tracking-wider: 0.18em;
  --tracking-mono: 0.02em;

  /* —— 4px spacing scale —— */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;

  /* —— Semantic aliases, light register —— */
  --bg: var(--ink-50);
  --bg-raised: var(--ink-0);
  --bg-sunken: var(--ink-100);
  --fg: var(--ink-1000);
  --fg-body: var(--ink-800);
  --fg-muted: var(--ink-600);
  --border: var(--ink-150);
  --border-strong: var(--ink-400); /* 3.8:1 on --bg — form boundaries are UI components, SC 1.4.11 wants 3:1 */
  --link: var(--accent-dim);

  /* —— Severity: 0 info · 1 low · 2 medium · 3 high · 4 critical
     mapped to Pezza status colors, AA-dim variants on light —— */
  --sev-0: var(--ink-400);
  --sev-1: var(--accent-dim); /* info = the accent family, per DS */
  --sev-2: var(--warn-dim);
  --sev-3: var(--err-dim);
  --sev-4: 358.8 85.6% 34%;
  /* the banner's wash is the warn hue at low alpha in BOTH registers (it never
     re-aliases to --warn-dim like --sev-2 does), hence its own name */
  --warn-surface: var(--warn);
}

/* —— Dark / stage register — the native register of the brand —— */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: var(--ink-1000);
    --bg-raised: var(--ink-800);
    --bg-sunken: var(--ink-900);
    --fg: var(--ink-0);
    --fg-body: var(--ink-150);
    --fg-muted: var(--ink-300);
    --border: var(--ink-800);
    --border-strong: var(--ink-400); /* ink-600 was 1.6:1 on the dark bg — fields had no perceivable boundary */
    --link: var(--accent);

    --sev-0: var(--ink-400);
    --sev-1: var(--accent);
    --sev-2: var(--warn);
    --sev-3: var(--err);
    --sev-4: 358.8 85.6% 72%;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  background: hsl(var(--bg));
  color: hsl(var(--fg-body));
}

a { color: hsl(var(--link)); text-decoration: none; }
a:hover { text-decoration: underline; }

/* --link, not --accent: the ring draws against the page background, and raw
   accent is 1.5:1 on the light scheme — invisible to the keyboard users it
   exists for. --link is the scheme-aware alias (5.1:1 light, 12.2:1 dark). */
:focus-visible {
  outline: 2px solid hsl(var(--link));
  outline-offset: 2px;
}

/* the metadata register: every technical value speaks Mono */
.num, td.num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-mono);
}

nav.top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid hsl(var(--border));
  background: hsl(var(--bg-raised));
  font-size: var(--text-sm);
}
nav.top .brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 700;
  color: hsl(var(--fg));
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
}
nav.top .brand img { display: block; height: 18px; width: auto; }
nav.top .brand .mark-light { display: block; }
nav.top .brand .mark-dark { display: none; }
@media (prefers-color-scheme: dark) {
  nav.top .brand .mark-light { display: none; }
  nav.top .brand .mark-dark { display: block; }
}
nav.top a { color: hsl(var(--fg-muted)); }
nav.top a.active { color: hsl(var(--fg)); }
nav.top .freshness {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-mono);
  color: hsl(var(--fg-muted));
  white-space: nowrap;
}

main { padding: var(--space-4); max-width: 1200px; margin: 0 auto; }

.empty-state {
  margin-top: var(--space-8);
  padding: var(--space-6);
  border: 1px dashed hsl(var(--border-strong));
  color: hsl(var(--fg-muted));
  font-size: var(--text-sm);
}
.empty-state ol { margin: var(--space-2) 0 0; padding-left: var(--space-6); }
.empty-state li { margin-top: var(--space-1); }
.empty-state code { font-family: var(--font-mono); }

.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  /* hue is not the only channel: 0-1 hollow, 2 solid, 3-4 solid + halo — in
     light mode sev 1/2/3 are luminance-identical, so a protanope reading dots
     by color alone saw one grey. The fill classes mirror the findings bands
     (routine / plan / act now). */
  background: transparent;
  border: 1.5px solid hsl(var(--sev-0));
}
.dot[data-sev="1"] { border-color: hsl(var(--sev-1)); }
.dot[data-sev="2"] { background: hsl(var(--sev-2)); border-color: hsl(var(--sev-2)); }
.dot[data-sev="3"] {
  background: hsl(var(--sev-3));
  border-color: hsl(var(--sev-3));
  box-shadow: 0 0 0 3px hsl(var(--sev-3) / 0.2);
}
.dot[data-sev="4"] {
  background: hsl(var(--sev-4));
  border-color: hsl(var(--sev-4));
  box-shadow: 0 0 0 3px hsl(var(--sev-4) / 0.3); /* critical carries the strongest halo */
}

.banner.amber {
  padding: var(--space-1) var(--space-4);
  background: hsl(var(--warn-surface) / 0.12);
  color: hsl(var(--sev-2));
  border-bottom: 1px solid hsl(var(--border));
  font-size: var(--text-sm);
}
.banner.amber a { color: inherit; text-decoration: underline; }

section.section { margin-bottom: var(--space-6); }
section.section h2 {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  color: hsl(var(--fg-muted));
  border-bottom: 1px solid hsl(var(--border));
  padding-bottom: var(--space-1);
  margin: 0 0 var(--space-2);
}
.rollup { margin-left: var(--space-2); font-size: var(--text-xs); }
.rollup.sev { color: hsl(var(--sev-2)); }
.warn-text { color: hsl(var(--sev-2)); text-transform: none; letter-spacing: normal; }
.hint { color: hsl(var(--fg-muted)); font-size: var(--text-sm); margin: var(--space-2) 0; }

table.rows { width: 100%; border-collapse: collapse; }
table.rows th {
  text-align: left;
  font-size: var(--text-xs);
  color: hsl(var(--fg-muted));
  font-weight: 500;
  padding: var(--space-1) var(--space-2);
}
table.rows th.num, table.rows td.num { text-align: right; }
tr.row td { padding: var(--space-1) var(--space-2); border-top: 1px solid hsl(var(--border)); }
tr.row:hover td { background: hsl(var(--bg-sunken)); } /* hover = sunken, per DS */
tr.row[data-href] { cursor: pointer; }
td.c-dot { width: 16px; }
td.c-name a { color: hsl(var(--fg)); font-weight: 500; }
td.c-kind { color: hsl(var(--fg-muted)); font-size: var(--text-xs); }
/* row actions rest as ink — accent-per-row is decoration, not a cursor (Pezza rule 1) */
td.c-links { text-align: right; white-space: nowrap; }
td.c-links a { margin-left: var(--space-2); font-size: var(--text-sm); color: hsl(var(--fg-muted)); }
td.c-links a:hover { color: hsl(var(--link)); }
/* Links in cells and the attention strip wear ink, not --link, so nothing but
   position said "this is a link" — and on the entity page the same c-name
   cell holds plain text. A muted underline is the one non-color affordance
   that survives both registers; hover restores the full-strength rule. */
td.c-name a,
td.c-links a,
td.num a,
p.attention a {
  text-decoration: underline;
  text-decoration-color: hsl(var(--border-strong));
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
td.c-name a:hover,
td.c-links a:hover,
td.num a:hover,
p.attention a:hover {
  text-decoration-color: currentColor;
}
a.chip { color: hsl(var(--fg-body)); }
a.chip:hover { color: hsl(var(--link)); }
td.c-chips { white-space: nowrap; }

th a.sort { color: hsl(var(--fg-muted)); }
th a.sort.active { color: hsl(var(--fg)); text-decoration: underline; text-decoration-color: hsl(var(--accent)); }
/* direction arrow on the active sort — the underline said WHICH, not which WAY */
th a.sort .sort-dir { margin-left: 2px; color: hsl(var(--fg-muted)); }

.owner-toggle { display: inline-flex; gap: var(--space-2); align-items: center; margin-left: var(--space-2); }
.owner-toggle a { color: hsl(var(--fg-muted)); font-size: var(--text-sm); }
.owner-toggle a.active { color: hsl(var(--fg)); text-decoration: underline; text-decoration-color: hsl(var(--accent)); }
/* spend's 30d/90d/mtd switch — without this, all three windows render identically
   and the current one is unknowable */
.rollup a.active { color: hsl(var(--fg)); text-decoration: underline; text-decoration-color: hsl(var(--accent)); }
.c-kind .owner { color: hsl(var(--fg-muted)); }

.chip {
  display: inline-block;
  margin-right: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-mono);
  color: hsl(var(--fg-body));
}
.chip[data-sev="2"] { color: hsl(var(--sev-2)); }
.chip[data-sev="3"] { color: hsl(var(--sev-3)); }
.chip[data-sev="4"] { color: hsl(var(--sev-4)); }
/* no opacity: the dim cost 26% of contrast and pushed 11px text below 4.5:1 in light */
.chip.missing { color: hsl(var(--sev-2)); }
/* spec §3 "numbers render dimmed, never hidden": demote to muted (7-11:1 in both
   schemes — dim without an opacity contrast failure), keep the value on screen */
.stale-data, td.stale-data, .chip.stale-data { color: hsl(var(--fg-muted)); font-style: italic; }

.error-text { color: hsl(var(--sev-3)); font-size: var(--text-xs); font-family: var(--font-mono); }
/* "unconfigured" is a calm state (runner keeps it off the banner) — rendering it
   in failure red contradicted the README's "listed calmly, a real failure in red" */
.status-note { color: hsl(var(--fg-muted)); font-size: var(--text-xs); font-family: var(--font-mono); }

form button {
  margin-top: var(--space-4);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  padding: var(--space-1) var(--space-3);
  background: hsl(var(--bg-raised));
  color: hsl(var(--fg));
  border: 1px solid hsl(var(--border-strong));
  cursor: pointer;
}
form button:hover { background: hsl(var(--bg-sunken)); }
@media (prefers-reduced-motion: no-preference) {
  form button { transition: transform 120ms ease, background 120ms ease; }
  form button:active { transform: scale(0.97); } /* press = scale, no bounce */
}

form.filters {
  display: flex;
  flex-wrap: wrap; /* triage has 5 controls on this line — nowrap = horizontal scroll at 320px (SC 1.4.10) */
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  align-items: center;
}
form.filters input, form.filters select {
  font: inherit;
  font-size: var(--text-sm);
  padding: var(--space-1) var(--space-2);
  background: hsl(var(--bg-raised));
  color: hsl(var(--fg));
  border: 1px solid hsl(var(--border-strong));
}
form.filters button { margin-top: 0; }

/* Safari keeps its native triangle unless the -webkit pseudo is also cleared */
summary::-webkit-details-marker { display: none; }

/* visually-hidden page h1 — heading-nav identity without visual chrome */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

td.c-why details summary {
  cursor: pointer;
  list-style: none;
  font-size: var(--text-xs);
  color: hsl(var(--fg-muted));
}
/* the score breakdown was invisible as a feature — plain text with a suppressed
   marker gave the expandable "why" zero affordance */
td.c-why details summary::after { content: " ▸"; color: hsl(var(--fg-muted)); }
td.c-why details[open] summary::after { content: " ▾"; }
ul.breakdown { margin: var(--space-1) 0 0; padding-left: var(--space-4); font-size: var(--text-xs); }

.entity-head h1 {
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  margin: 0 0 var(--space-1);
  color: hsl(var(--fg));
}
.entity-head form button { margin-top: var(--space-2); }

.mtd { font-size: var(--text-lg); margin: 0 0 var(--space-2); color: hsl(var(--fg)); }

/* spend sparkline — the one waveform moment per view, so it wears the accent
   family; --link, not raw --accent, because raw accent is 1.5:1 on light bg
   and the bars ARE the data (SC 1.4.11 wants 3:1) */
svg.spark .spark-bar { fill: hsl(var(--link)); }
svg.spark .spark-bar.today { fill: none; stroke: hsl(var(--link)); stroke-width: 1; }

/* state-metric trend lines stay monochrome — the accent belongs to spend */
svg.trend path { stroke: hsl(var(--fg-muted)); }
td.c-trend { width: 104px; }

/* Map sections: one fixed geometry across every category table — auto layout
   put name/kind/score at a different x per section. Chips are the flexible
   column; everything else is pinned. */
table.map-cols { table-layout: fixed; }
table.map-cols col.w-dot { width: 24px; }
table.map-cols col.w-name { width: 170px; }
table.map-cols col.w-kind { width: 170px; }
table.map-cols col.w-score { width: 64px; }
table.map-cols col.w-links { width: 118px; }
table.map-cols td.c-name,
table.map-cols td.c-kind { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* chips may wrap within their flexible column rather than forcing overflow */
table.map-cols td.c-chips { white-space: normal; }

/* Findings bands: every band/group renders its own table, so they share one
   fixed geometry — without it the metric/value/observed columns landed at a
   different x per severity band. */
table.findings-cols { table-layout: fixed; }
table.findings-cols col.w-dot { width: 24px; }
table.findings-cols col.w-metric { width: 210px; } /* "expected: Lighthouse perf" in mono */
table.findings-cols col.w-val { width: 170px; }
table.findings-cols col.w-obs { width: 88px; }
table.findings-cols col.w-links { width: 44px; }
table.findings-cols td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Entity metrics: one fixed-layout table for every domain so the value, trend
   and observed columns sit at the same x in every group — auto layout sized
   them per-section from content, which read as random. */
table.metrics { table-layout: fixed; }
table.metrics col.w-dot { width: 24px; }
table.metrics col.w-val { width: 170px; } /* fits "tagged static_site" in mono */
table.metrics col.w-trend { width: 104px; }
table.metrics col.w-obs { width: 88px; }
table.metrics col.w-links { width: 44px; }
table.metrics td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.metrics tr.domain th {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  color: hsl(var(--fg-muted));
  border-bottom: 1px solid hsl(var(--border));
  padding: var(--space-4) var(--space-2) var(--space-1); /* --space-5 doesn't exist; an unresolvable var() zeroes the whole shorthand */
}

.budget { margin-bottom: var(--space-2); font-size: var(--text-sm); }
.budget-label { display: block; margin-bottom: var(--space-1); }
.budget-bar { position: relative; height: 10px; background: hsl(var(--bg-sunken)); border: 1px solid hsl(var(--border)); max-width: 480px; }
/* --fg-muted, not --ink-500: ink-500 is pinned to the light register and lands
   at 2.6:1 on the dark bar — the fill is the data, it must re-alias per scheme */
.budget-fill { height: 100%; background: hsl(var(--fg-muted)); } /* monochrome until a threshold speaks */
.budget-fill[data-sev="2"] { background: hsl(var(--sev-2)); }
.budget-fill[data-sev="4"] { background: hsl(var(--sev-4)); }
.budget-tick { position: absolute; top: -2px; bottom: -2px; width: 2px; }
.budget-tick.soft { background: hsl(var(--sev-2)); }
.budget-tick.hard { background: hsl(var(--sev-4)); }

p.attention {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
  padding: var(--space-2) var(--space-3);
  border: 1px solid hsl(var(--border-strong));
  background: hsl(var(--bg-raised));
  font-size: var(--text-sm);
}
p.attention .attention-label {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  color: hsl(var(--fg-muted));
}
p.attention a { color: hsl(var(--fg)); font-weight: 500; }
p.attention .attention-more { margin-left: auto; color: hsl(var(--fg-muted)); font-weight: 400; }

/* disclosure blocks read as controls, not headings: bordered bar, hover, +/− */
details.agent-prompt summary,
details.archived-section summary {
  cursor: pointer;
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  color: hsl(var(--fg));
  background: hsl(var(--bg-raised));
  border: 1px solid hsl(var(--border-strong));
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-2);
  list-style: none;
}
details.agent-prompt summary:hover,
details.archived-section summary:hover {
  background: hsl(var(--bg-sunken));
}
details.agent-prompt summary::after,
details.archived-section summary::after {
  content: "expand +";
  float: right;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: hsl(var(--fg-muted));
}
details.agent-prompt[open] summary::after,
details.archived-section[open] summary::after {
  content: "collapse −";
}
details.agent-prompt summary .rollup { text-transform: none; letter-spacing: normal; font-weight: 400; }
details.agent-prompt textarea {
  width: 100%;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-mono);
  line-height: 1.5;
  color: hsl(var(--fg-body));
  background: hsl(var(--bg-sunken));
  border: 1px solid hsl(var(--border));
  padding: var(--space-2);
  resize: vertical;
}
details.agent-prompt button { margin-top: var(--space-2); }

details.archived-section .row td { opacity: 0.7; }
tr.cluster-cont td { border-top-color: transparent; } /* clustered findings read as one entity block */

/* Between the mobile collapse and full width the fixed metric columns can
   truncate the longest labels (hygiene.missing.eval.*). A title only helps
   mouse users; letting the label wrap gives keyboard and touch users the
   same text, at the cost of a taller row for those few labels. */
@media (min-width: 641px) and (max-width: 900px) {
  table.findings-cols td.c-kind,
  table.metrics td.c-name { white-space: normal; }
}

/* mobile: read-only glance — ux-spec §4: tables collapse to definition-list rows */
@media (max-width: 640px) {
  main { padding: var(--space-2); }

  /* Changing display on table parts strips their implicit ARIA roles in most
     engines, so the markup carries explicit role=table/row/columnheader/cell
     — the collapse is visual only. The header row is hidden visually, NOT with
     display:none, so each collapsed cell keeps its column header for AT
     ("kind: static_site") instead of losing the association entirely. */
  table.rows, table.rows tbody { display: block; }
  table.rows tr:not(.row) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  tr.row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    column-gap: var(--space-2);
    row-gap: var(--space-1);
    padding: var(--space-2) 0;
    border-top: 1px solid hsl(var(--border));
  }
  tr.row td { display: inline-block; border-top: none; padding: 0; }
  td.c-name { order: 1; }
  td.c-dot { order: 0; }
  td.c-kind { order: 2; }
  td.num { order: 3; margin-left: auto; }
  td.c-links { order: 4; }
  td.c-chips { order: 9; flex-basis: 100%; white-space: normal; }
  td.c-why { order: 10; flex-basis: 100%; }
  /* sparkline had no order, so it defaulted to 0 and rendered before the
     metric name; empty trend cells otherwise still contribute flex gaps */
  td.c-trend { order: 5; }
  td.c-trend:empty { display: none; }

  /* sort links live in the header row — the collapse must not delete the page's
     primary affordance. This band is also 200% zoom on a 1280px screen. */
  table.rows tr:not(.row):has(a.sort) {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
    white-space: normal;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    padding: var(--space-1) 0;
  }
  table.rows tr:not(.row):has(a.sort) th { display: inline-block; padding: 0; }

  /* the domain group rows replaced the per-section h2s, so unlike the column
     header they must survive the collapse — without this, mobile loses the
     CI / Dependencies / Site grouping entirely */
  table.metrics tr.domain { position: static; width: auto; height: auto; overflow: visible; clip-path: none; display: block; }
  table.metrics tr.domain th {
    display: block;
    padding: var(--space-4) 0 var(--space-1);
    border-bottom: none;
  }
}

/* ————————————————————————————————————————————————————————————————————
   LCARS-inspired chrome (ops-ux §4: "the LCARS-inspired treatment, when
   earned, is a token-file + layout-chrome swap" — earned: tokens audited,
   zero hardcoded colors, contrast verified). Pezza discipline holds
   throughout: the geometry does the evoking — rails, end-caps, asymmetric
   pills — while INK does the coloring. No new hues, accent stays a cursor.
   ———————————————————————————————————————————————————————————————————— */

/* Section headings become rails: a rounded end-cap block, the label, then a
   rule running to the margin — the LCARS elbow abstracted to one line. */
section.section h2 {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-bottom: none;
  padding-bottom: 0;
  min-height: 14px;
}
section.section h2::before {
  content: "";
  flex: 0 0 26px;
  height: 10px;
  background: hsl(var(--fg-muted));
  border-radius: 999px 0 0 999px;
}
section.section h2::after {
  content: "";
  flex: 1 1 auto;
  height: 2px;
  min-width: var(--space-4);
  background: hsl(var(--border));
}
/* warning sections carry a status-colored cap — muted status hue, not accent */
section.section.warn h2::before { background: hsl(var(--sev-2)); }

/* domain group rows inside the entity table carry a smaller cap, so the page
   speaks one chrome language (inline-block: safe inside a table cell) */
table.metrics tr.domain th::before {
  content: "";
  display: inline-block;
  width: 18px;
  height: 8px;
  background: hsl(var(--fg-muted));
  border-radius: 999px 0 0 999px;
  margin-right: var(--space-2);
}

/* Buttons wear the asymmetric LCARS end-cap: rounded on the leading edge,
   squared where the console continues. Press behavior unchanged (scale .97). */
form button {
  border-radius: 999px 3px 3px 999px;
  padding-left: var(--space-4);
}

/* The degradation banner reads as an alert rail: thick warn cap, rounded end. */
.banner.amber {
  border-left: 14px solid hsl(var(--sev-2));
  border-radius: 999px 0 0 999px;
  border-bottom: none;
  margin-bottom: var(--space-2);
}

/* The freshness chip is the one live readout — pill it like a console lamp. */
a.freshness {
  border: 1px solid hsl(var(--border-strong));
  border-radius: 999px;
  padding: 1px var(--space-3);
}
