/* ══════════════════════════════════════════════════════════════════════
   kb.css — Samara Knowledge Base base stylesheet
   Dark mode only. Every page loads this. Pages add nothing but content.

   ── THE COLOUR RULE ───────────────────────────────────────────────────
   Hue must carry meaning. If a colour appears twice meaning two different
   things, it is wrong. Three tiers, in order of how much page they cover:

     Tier 1  STRUCTURE   Achromatic. ~95% of every page. Recedes.
                         Boxes, cards, tables and borders are ALWAYS
                         neutral — chrome never carries hue.
     Tier 2  COMPLEMENT  Blue #7cb2fb  ↔  Amber #f0b429  (221° / 41°).
                         Blue  = interaction. Links and focus. Nothing else.
                         Amber = attention. Callouts and "look here". Nothing else.
     Tier 3  DATA        --hue-a/b/c. Diagrams and legends ONLY, never chrome.
                         A page aliases them to domain meanings, e.g.
                         chemistry: --hue-a = oxygen, --hue-b = nitrogen.
                         Max three hues visible in any one diagram, and a
                         .legend is mandatory wherever they appear.

   Redundant encoding: hue is never the only signal. Diagrams also vary
   stroke weight, dash, and position, so they survive greyscale, print,
   and colour vision deficiency.

   Contrast: every foreground token below is ≥4.5:1 (WCAG AA, normal text)
   against --bg-raised, the lightest background on the page — so it passes
   against --bg-surface and --bg-canvas everywhere too. The neutral ramp is
   spaced on an even OKLCH lightness ladder (~5 L* between the three grounds)
   so depth reads deliberately rather than accidentally.
   ══════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: dark;

  /* ── Tier 1: structure ─────────────────────────────── contrast vs surface */
  --bg-canvas:      #0c0a09;   /* page ground — warm near-black, never #000 */
  --bg-surface:     #171412;   /* cards, callouts, table stripes    L* 19.4 */
  --bg-raised:      #242019;   /* hover state, nested blocks        L* 24.6 */
  --border:         #34302b;   /* quiet separators                  L* 31.2 */
  --border-strong:  #4a453f;   /* table rules, left accents         L* 39.3 */

  /* Body and headings are DIFFERENT colours. Headings punch; body relaxes.
     Body copy above ~15:1 on a dark ground haloes — glyph edges bloom and
     smear, which is the main fatigue driver in long-form dark reading.
     Splitting them lowers fatigue AND sharpens hierarchy at the same time. */
  --text-heading:   #ede8e2;   /* headings, bold terms, glyphs      13.3:1  */
  --text-primary:   #cfc8bf;   /* body copy — deliberately calm      9.8:1  */
  --text-secondary: #a8a19a;   /* captions, card body                6.4:1  */
  --text-muted:     #948c83;   /* formulae, tertiary labels          4.9:1  */

  /* ── Tier 2: the complementary pair ─────────────────────────────────────── */
  --accent:         #7cb2fb;   /* INTERACTION only                    8.0:1 */
  --emphasis:       #f0b429;   /* ATTENTION only                      9.4:1 */

  /* ── Tier 3: data hues — diagrams only ──────────────────────────────────── */
  --hue-a:          #fb7185;   /* rose                                6.5:1 */
  --hue-b:          #c0a8fd;   /* violet                              8.5:1 */
  --hue-c:          #4fd8c4;   /* teal                               10.0:1 */
  --hue-n:          var(--text-heading);   /* the neutral member of the set */

  /* Tints derive from hue + canvas, so one definition covers every surface. */
  --tint:            9%;   /* higher mixes go muddy on a near-black ground */
  --shadow:         rgba(0, 0, 0, 0.45);

  /* ── Typography ─────────────────────────────────────────────────────────── */
  --font-body:      'Nunito', system-ui, -apple-system, sans-serif;
  --font-mono:      ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --measure:        66ch;      /* research-backed single-column reading width */
  --radius:         8px;
}

/* ── Pico token bridge ──────────────────────────────────────────────────────
   Pico ships its own slate-blue dark palette. Left alone it renders tables,
   code and blockquotes in a cool grey that clashes with our warm stone.
   Rather than out-specify Pico rule by rule, we remap its tokens to ours
   once, here. Anything Pico styles now inherits the kb.css system for free.
   ──────────────────────────────────────────────────────────────────────── */

:root:not([data-theme=light]),
[data-theme=dark] {
  --pico-background-color:                    var(--bg-canvas);
  --pico-color:                               var(--text-primary);
  --pico-muted-color:                         var(--text-secondary);
  --pico-muted-border-color:                  var(--border);
  --pico-border-color:                        var(--border-strong);

  --pico-h1-color: var(--text-heading);
  --pico-h2-color: var(--text-heading);
  --pico-h3-color: var(--text-heading);
  --pico-h4-color: var(--text-heading);
  --pico-h5-color: var(--text-heading);
  --pico-h6-color: var(--text-secondary);

  /* Tables — warm stone, not slate. */
  --pico-table-border-color:                  var(--border);
  --pico-table-row-stripped-background-color: var(--bg-surface);

  /* Links inherit the one blue. */
  --pico-primary:                             var(--accent);
  --pico-primary-hover:                       var(--accent);
  --pico-primary-focus:                       color-mix(in oklab, var(--accent) 30%, transparent);
  --pico-primary-underline:                   color-mix(in oklab, var(--accent) 50%, transparent);
  --pico-primary-hover-underline:             var(--accent);
  --pico-text-selection-color:                color-mix(in oklab, var(--accent) 28%, transparent);

  --pico-code-background-color:               var(--bg-surface);
  --pico-code-color:                          var(--text-secondary);
  --pico-code-kbd-background-color:           var(--text-heading);
  --pico-code-kbd-color:                      var(--bg-canvas);

  --pico-blockquote-border-color:             var(--border-strong);
  --pico-blockquote-footer-color:             var(--text-muted);

  --pico-mark-background-color:               color-mix(in oklab, var(--emphasis) 30%, var(--bg-canvas));
  --pico-mark-color:                          var(--text-heading);

  --pico-del-color:                           var(--text-muted);
  --pico-ins-color:                           var(--hue-c);

  --pico-form-element-background-color:       var(--bg-surface);
  --pico-form-element-border-color:           var(--border-strong);
  --pico-form-element-placeholder-color:      var(--text-muted);
  --pico-form-element-active-border-color:    var(--accent);
}

/* ── Page ──────────────────────────────────────────────────────────────── */

html { background: var(--bg-canvas); }

body {
  font-family: var(--font-body);
  max-width: var(--measure);
  margin: 0 auto;
  padding: 2rem 1.5rem 6rem;
  background: var(--bg-canvas);
  color: var(--text-primary);
  font-size: 1.1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* ── Typography ────────────────────────────────────────────────────────── */

h1, h2, h3, h4 { color: var(--text-heading); line-height: 1.3; }

/* A term bolded on first use is a micro-heading — give it the heading colour. */
strong, b { color: var(--text-heading); }

h2 {
  margin-top: 3rem;
  padding-bottom: 0.4rem;
  border-bottom: 2px solid var(--border-strong);
  display: inline-block;
  font-weight: 700;
}
h3 { font-weight: 700; }

/* Links are the only blue on the page. */
a { color: var(--accent); text-underline-offset: 0.2em; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* ── Breadcrumb ────────────────────────────────────────────────────────── */

nav[aria-label="breadcrumb"] {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin-bottom: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
}
nav[aria-label="breadcrumb"] a { text-decoration: none; }
nav[aria-label="breadcrumb"] a:hover { text-decoration: underline; }

/* ── Hero ──────────────────────────────────────────────────────────────── */

.hero {
  text-align: center;
  padding: 3rem 0 2rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 3rem;
}
.hero h1 {
  font-size: clamp(2rem, 5vw, 3rem);
  letter-spacing: -0.02em;
  line-height: 1.2;
  font-weight: 800;
}
.hero .tagline {
  font-size: 1.15rem;
  color: var(--text-secondary);
  max-width: 52ch;
  margin: 0.75rem auto 0;
  line-height: 1.5;
}

/* ── Model bar — the knowledge backbone ────────────────────────────────────
   A knowledge page is a rung on a ladder, and a rung that does not say what
   it stands on is a rung nobody can trust. Every knowledge page declares the
   mental models it REQUIRES (installed by earlier pages) and the ones it
   INSTALLS (available to later pages). The validator checks the chain, so a
   page that quietly assumes an un-taught concept fails the build.

   Chrome is deliberately quiet: an outline and no fill, so the bar reads as
   scaffolding rather than content. Prerequisites are links because they are
   navigation; installed models are plain text because they are this page.
   ──────────────────────────────────────────────────────────────────────── */

.model-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0.9rem 1.75rem;
  margin: 0 0 3rem;
  padding: 1.1rem 1.3rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.model-bar div { min-width: 0; }
.model-bar dt {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.model-bar dd {
  margin: 0.3rem 0 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text-heading);
}
/* Installed models are the page's own claim — weight them, do not colour them. */
.model-bar dd b { font-weight: 700; color: var(--text-heading); }
/* A rung-zero page stands on nothing. Say so quietly rather than hiding the row. */
.model-bar dd i { font-style: normal; color: var(--text-muted); }

/* ── Cards ─────────────────────────────────────────────────────────────────
   Uniform by design. Every card on every page has the same neutral chrome:
   same surface, same border, same radius. What differs between cards is
   their CONTENT, and that is the only thing a reader should have to scan.
   ──────────────────────────────────────────────────────────────────────── */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1rem;
  margin: 1.5rem 0;
}

.fg-card {
  background: var(--bg-surface);
  border-radius: var(--radius);
  padding: 1rem;
  text-align: center;
  transition: transform 180ms ease, box-shadow 180ms ease, background 180ms ease;
}
.fg-card:hover {
  transform: translateY(-3px);
  background: var(--bg-raised);
  box-shadow: 0 6px 18px var(--shadow);
}
.fg-card .fg-icon {
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--text-heading);
  margin-bottom: 0.3rem;
}
.fg-card .fg-name    { font-weight: 700; font-size: 0.9rem; }
.fg-card .fg-formula { font-size: 0.8rem; color: var(--text-muted); }

/* Opt-in ONLY: add `coded` to a .card-grid to let data hues tint the glyph.
   Use when the grid genuinely groups into ≤3 classes AND a .legend follows.
   Chrome still stays neutral — the hue touches the glyph, never the box. */
.card-grid.coded .fg-card[data-hue="a"] .fg-icon { color: var(--hue-a); }
.card-grid.coded .fg-card[data-hue="b"] .fg-icon { color: var(--hue-b); }
.card-grid.coded .fg-card[data-hue="c"] .fg-icon { color: var(--hue-c); }

/* ── Accent cards ───────────────────────────────────────────────────────────
   For 4–8 sibling concepts. Too many to hue-code, so they never are.
   The left rule warms to --emphasis on hover: motion marks focus, not colour.
   ──────────────────────────────────────────────────────────────────────── */

.rxn-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem;
  margin: 1.5rem 0;
}
.rxn-card {
  background: var(--bg-surface);
  border-left: 3px solid var(--border-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1rem 1.2rem;
  transition: transform 180ms ease, box-shadow 180ms ease, border-left-color 180ms ease;
}
.rxn-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px var(--shadow);
  border-left-color: var(--emphasis);
}
.rxn-card strong { color: var(--text-heading); }
.rxn-card small  { color: var(--text-secondary); }

/* ── Callout — the one place amber owns outright. Max 1 per section. ────── */

.callout {
  background: var(--bg-surface);
  border-left: 4px solid var(--emphasis);
  border-radius: var(--radius);
  padding: 1.2rem 1.5rem;
  margin: 2rem 0;
  font-size: 0.95rem;
  color: var(--text-primary);
}
.callout strong { color: var(--emphasis); }

/* ── Tables ────────────────────────────────────────────────────────────── */

table { border-collapse: collapse; }
thead th {
  background: var(--bg-surface);
  color: var(--text-heading);
  font-weight: 700;
  border-bottom: 2px solid var(--border-strong);
}
tbody td { border-bottom: 1px solid var(--border); color: var(--text-secondary); }
tbody tr:last-child td { border-bottom: none; }

.comparison { width: 100%; }
.comparison td:first-child { font-weight: 600; white-space: nowrap; color: var(--text-heading); }
/* Symptom and cause columns carry sentences, not terms. nowrap suits a
   chemistry label and starves a troubleshooting table of width. */
.comparison.wrap td:first-child { white-space: normal; }

/* ── Diagrams ──────────────────────────────────────────────────────────────
   Inline SVG only. Never hardcode a hex in markup — use these classes so
   diagrams inherit the token system and stay consistent across domains.
   ──────────────────────────────────────────────────────────────────────── */

figure.diagram { margin: 2rem 0; text-align: center; }
figure.diagram svg { max-width: 100%; height: auto; }
figure.diagram figcaption {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin-top: 0.5rem;
}

.svg-label { fill: var(--text-heading); font-weight: 600; }
.svg-sub   { fill: var(--text-secondary); }
.svg-faint { fill: var(--text-muted); }
.svg-rule  { stroke: var(--border-strong); }

/* Data-hue helpers: .svg-text / .svg-line / .svg-box + .a | .b | .c | .n | .e */
.svg-text    { font-weight: 600; fill: var(--hue-n); }
.svg-text.a  { fill: var(--hue-a); }
.svg-text.b  { fill: var(--hue-b); }
.svg-text.c  { fill: var(--hue-c); }
.svg-text.e  { fill: var(--emphasis); }

.svg-line    { stroke: var(--hue-n); }
.svg-line.a  { stroke: var(--hue-a); }
.svg-line.b  { stroke: var(--hue-b); }
.svg-line.c  { stroke: var(--hue-c); }
.svg-line.e  { stroke: var(--emphasis); }

.svg-box     { fill: var(--bg-surface); stroke: var(--border-strong); }
.svg-box.a   { fill: color-mix(in oklab, var(--hue-a) var(--tint), var(--bg-canvas)); stroke: var(--hue-a); }
.svg-box.b   { fill: color-mix(in oklab, var(--hue-b) var(--tint), var(--bg-canvas)); stroke: var(--hue-b); }
.svg-box.c   { fill: color-mix(in oklab, var(--hue-c) var(--tint), var(--bg-canvas)); stroke: var(--hue-c); }
.svg-box.e   { fill: color-mix(in oklab, var(--emphasis) var(--tint), var(--bg-canvas)); stroke: var(--emphasis); }

/* ── Legend — mandatory wherever a data hue appears. ────────────────────── */

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  margin: 1.25rem 0;
  padding: 0;
  list-style: none;
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.legend li { display: flex; align-items: center; gap: 0.45rem; }
.legend .swatch {
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 3px;
  background: currentColor;
  flex: none;
}
.legend .a { color: var(--hue-a); }
.legend .b { color: var(--hue-b); }
.legend .c { color: var(--hue-c); }
.legend .n { color: var(--hue-n); }
.legend .e { color: var(--emphasis); }

/* ── Inline tile row (small diagram cards) ─────────────────────────────── */

.tile-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: center;
  margin: 1.5rem 0;
}
.tile {
  background: var(--bg-surface);
  padding: 1rem;
  border-radius: var(--radius);
  text-align: center;
  min-width: 110px;
}
.tile svg      { width: 100%; max-width: 96px; height: auto; }
.tile .t-name  { font-size: 0.85rem; font-weight: 600; color: var(--text-heading); }
.tile .t-sub   { font-size: 0.75rem; color: var(--text-muted); }

/* ══════════════════════════════════════════════════════════════════════════
   OPERATIONS COMPONENTS
   A runbook is read under pressure, by someone who is already having a bad
   day. Everything below optimises for "where am I, what do I do next, how do
   I know it worked" — never for looking rich.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Document metadata bar ─────────────────────────────────────────────────
   A procedure with no owner and no review date is a liability, not a
   procedure; a report with no as-of date is an anecdote. Both non-knowledge
   types carry this bar under the hero, and validate.py fails them without it.
   ──────────────────────────────────────────────────────────────────────── */

.doc-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.9rem 1.5rem;
  margin: 1.5rem 0 2.5rem;
  padding: 1.1rem 1.3rem;
  background: var(--bg-surface);
  border-radius: var(--radius);
}
.doc-meta div { min-width: 0; }
.doc-meta dt {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.doc-meta dd {
  margin: 0.2rem 0 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-heading);
}

/* ── Procedure — the operations backbone ───────────────────────────────────
   Ordered, numbered, one action per step. The number is the only ornament:
   an operator mid-incident navigates by position, not by decoration.

   There is deliberately NO green/amber/red status palette. Green and red
   would each become a second meaning for a hue that already has a job
   (teal --hue-c and rose --hue-a are DATA), and red/green is the worst
   possible pair for the ~8% of men with a red-green deficiency. A step is
   either ordinary — neutral — or it demands attention, which is precisely
   what amber already means everywhere else on this site. Two states, one
   hue, no new rules to remember.
   ──────────────────────────────────────────────────────────────────────── */

ol.procedure > li { list-style: none; }
ol.procedure {
  list-style: none;
  counter-reset: step;
  padding: 0;
  margin: 2rem 0;
}
.procedure > li {
  counter-increment: step;
  position: relative;
  background: var(--bg-surface);
  border-left: 3px solid var(--border-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1.1rem 1.3rem 1.1rem 3.5rem;
  margin-bottom: 0.9rem;
}
.procedure > li::before {
  content: counter(step);
  position: absolute;
  left: 1rem;
  top: 1.05rem;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 50%;
  background: var(--bg-raised);
  color: var(--text-heading);
  font-size: 0.85rem;
  font-weight: 800;
  line-height: 1.7rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.procedure > li > h3 { margin: 0 0 0.35rem; font-size: 1rem; }
.procedure > li > p  { margin: 0.4rem 0; font-size: 0.95rem; }
.procedure > li > p:last-child { margin-bottom: 0; }

/* Attention: destructive, irreversible, or safety-critical. Amber, because
   amber means attention. If most steps are marked, none of them are. */
.procedure > li.danger { border-left-color: var(--emphasis); }
.procedure > li.danger::before { background: var(--emphasis); color: var(--bg-canvas); }
.procedure > li.danger > h3    { color: var(--emphasis); }

/* Verification — "how you know the step worked". Give every step one. */
.verify {
  margin-top: 0.6rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--border);
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.verify p { margin: 0.2rem 0; font-size: inherit; }

/* ── Checklist — gates to pass before starting, not steps to perform ───── */

ul.checklist { list-style: none; padding: 0; margin: 1.5rem 0; }
.checklist li { list-style: none; }   /* Pico sets this on the li — out-specify it */
.checklist li {
  position: relative;
  padding: 0.5rem 0 0.5rem 2rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.95rem;
}
.checklist li:last-child { border-bottom: none; }
.checklist li::before {
  content: "";
  position: absolute;
  left: 0.3rem;
  top: 0.85rem;
  width: 0.85rem;
  height: 0.85rem;
  border: 2px solid var(--border-strong);
  border-radius: 3px;
}

/* ── Command and code blocks ──────────────────────────────────────────────
   Monospace is the one place a second typeface earns its keep: it tells the
   reader "type this exactly", which prose cannot.
   ──────────────────────────────────────────────────────────────────────── */

pre {
  background: var(--bg-surface);
  border-left: 3px solid var(--border);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 0.9rem 1.1rem;
  margin: 0.8rem 0;
  overflow-x: auto;
  font-size: 0.85rem;
}
pre code {
  font-family: var(--font-mono);
  color: var(--text-secondary);
  background: none;
  padding: 0;
}
code, kbd, samp { font-family: var(--font-mono); font-size: 0.88em; }

/* ══════════════════════════════════════════════════════════════════════════
   REPORT COMPONENTS
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Metrics — the headline row ────────────────────────────────────────────
   Figures use tabular lining numerals so digits align vertically. A report
   is read by comparing numbers down a column, and proportional digits
   quietly break that comparison.

   Direction is a glyph, not a colour. "Up" is not universally good — rising
   yield is good, rising failure rate is not — so colouring direction encodes
   an opinion the data has not earned. Amber marks the figures that need the
   reader's attention. That is the whole state system.
   ──────────────────────────────────────────────────────────────────────── */

.metric-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(155px, 1fr));
  gap: 1rem;
  margin: 2rem 0;
}
.metric {
  background: var(--bg-surface);
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
}
.metric .m-value {
  font-size: 1.9rem;
  font-weight: 800;
  line-height: 1.1;
  color: var(--text-heading);
  font-variant-numeric: tabular-nums lining-nums;
}
.metric .m-unit  { font-size: 0.9rem; font-weight: 600; color: var(--text-secondary); }
.metric .m-label { margin-top: 0.4rem; font-size: 0.8rem; color: var(--text-muted); }
.metric .m-delta {
  margin-top: 0.5rem;
  font-size: 0.8rem;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
/* The one flagged figure per row that the reader must not miss. */
.metric.flag        { border-left: 3px solid var(--emphasis); padding-left: 0.95rem; }
.metric .m-delta.flag { color: var(--emphasis); }

/* ── Findings — one claim, its evidence, its confidence ──────────────────
   Confidence is stated in words, not implied by styling. A finding that
   looks as solid as it is uncertain is how a report misleads.
   ──────────────────────────────────────────────────────────────────────── */

.finding {
  background: var(--bg-surface);
  border-left: 3px solid var(--border-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1.1rem 1.3rem;
  margin: 1.2rem 0;
}
.finding .f-tag {
  display: block;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 0.3rem;
}
.finding h3 { margin: 0 0 0.4rem; font-size: 1rem; }
.finding p  { margin: 0.4rem 0; font-size: 0.95rem; }
.finding p:last-child { margin-bottom: 0; }
.finding .f-confidence { font-size: 0.82rem; color: var(--text-muted); }

/* ── Numeric tables ──────────────────────────────────────────────────────
   Numbers right-align and share a digit width; labels stay left. Without
   this, a column of figures cannot be scanned for magnitude.
   ──────────────────────────────────────────────────────────────────────── */

th.num, td.num {
  text-align: right;
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}
table.data td.num { color: var(--text-heading); font-weight: 600; }
table.data td:first-child { color: var(--text-primary); }

/* ── Chart marks — extends the diagram classes above ────────────────────── */

.svg-grid  { stroke: var(--border); stroke-width: 1; }
.svg-axis  { stroke: var(--border-strong); stroke-width: 1.5; }
.svg-bar   { fill: var(--border-strong); }
.svg-bar.e { fill: var(--emphasis); }
.svg-bar.a { fill: var(--hue-a); }
.svg-bar.b { fill: var(--hue-b); }
.svg-bar.c { fill: var(--hue-c); }
.svg-num   { fill: var(--text-heading); font-weight: 700; font-variant-numeric: tabular-nums; }

/* ── Provenance — a report without sources is an opinion ────────────────── */

.sources { font-size: 0.85rem; color: var(--text-muted); padding-left: 1.2rem; }
.sources li { margin: 0.45rem 0; }
.as-of { font-size: 0.82rem; color: var(--text-muted); font-style: italic; }

/* ── Page list — index and hub navigation ─────────────────────────────────
   An index is read by scanning titles, so it is a list, not a grid: one row
   per page at full measure, description underneath. The card grid is for
   sibling *concepts*; pointed at an index it squeezes a 25-word description
   into a 150px column and the whole page becomes unreadable.

   Domain headings are NOT links. A heading rendered in link blue reads as
   chrome that has been coloured, and blue is reserved for interaction. The
   link to the hub sits below the list, small, where a link belongs.
   ──────────────────────────────────────────────────────────────────────── */

ul.page-list { list-style: none; padding: 0; margin: 1.5rem 0; }
.page-list li {
  list-style: none;
  padding: 0.95rem 0;
  border-bottom: 1px solid var(--border);
}
.page-list li:last-child { border-bottom: none; }
.page-list .p-type {
  display: block;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 0.15rem;
}
.page-list .p-title { font-size: 1.02rem; font-weight: 700; }
.page-list .p-desc  { font-size: 0.9rem; color: var(--text-secondary); margin: 0.25rem 0 0; }

.hub-more { font-size: 0.9rem; margin-top: 1rem; }

/* ── Footer ────────────────────────────────────────────────────────────── */

.page-footer {
  margin-top: 4rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
  font-size: 0.85rem;
  color: var(--text-muted);
}

/* ── Motion — reveal on scroll entry, then static. Never animate while reading. */

@keyframes fade-up {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}
.reveal {
  animation: fade-up 0.7s ease both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}
@supports not (animation-timeline: view()) {
  .reveal { animation: none; opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .reveal { animation: none; opacity: 1; transform: none; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Mobile ────────────────────────────────────────────────────────────── */

@media (max-width: 480px) {
  body { padding: 1rem 1rem 4rem; }
  .card-grid { grid-template-columns: repeat(3, 1fr); }
  .rxn-grid  { grid-template-columns: 1fr; }
  .hero      { padding: 1.5rem 0 1rem; }
  .metric-row { grid-template-columns: 1fr 1fr; }
  .doc-meta   { grid-template-columns: 1fr 1fr; }
  .metric .m-value { font-size: 1.5rem; }
  .procedure > li { padding-left: 3.1rem; }
}

/* ── Print — the page is dark on screen and black-on-white on paper.
   Hue collapses; meaning survives via dash, weight, and position. ──────── */

@media print {
  :root {
    --bg-canvas: #fff; --bg-surface: #fff; --bg-raised: #fff;
    --text-heading: #000; --text-primary: #111; --text-secondary: #333; --text-muted: #555;
    --border: #bbb; --border-strong: #888;
    --accent: #000; --emphasis: #000;
    --hue-a: #000; --hue-b: #000; --hue-c: #000;
  }
  html, body { background: #fff; color: #000; max-width: 100%; font-size: 11pt; }
  .hero { padding: 1rem 0; }
  .fg-card, .rxn-card, .tile, figure.diagram, .model-bar { break-inside: avoid; }
  .fg-card, .tile { border: 1px solid #999; }   /* fills vanish on paper */

  /* Operations and report chrome — same story: fills go, outlines return. */
  .procedure > li, .finding, .metric, .doc-meta, pre { border: 1px solid #999; }
  .procedure > li, .finding, .metric, .page-list li { break-inside: avoid; }
  .procedure > li::before { background: #fff; color: #000; border: 1px solid #000; }
  .procedure > li.danger { border: 2px solid #000; }
  .procedure > li.danger::before { background: #000; color: #fff; }
  .metric.flag { border-left: 3px solid #000; }
  .svg-bar, .svg-bar.a, .svg-bar.b, .svg-bar.c { fill: #666; }
  .svg-bar.e { fill: #000; }
  .callout { background: none; border: 2px solid #000; }
  .callout strong { color: #000; }
  .svg-box, .svg-box.a, .svg-box.b, .svg-box.c, .svg-box.e { fill: #fff; stroke: #000; }
}
