/* ============================================================================
   COMMUNICATION DESIGN SYSTEM — comms-layer.css
   ----------------------------------------------------------------------------
   A communication layer for reports, presentations, documentation and public-
   facing assets. Built ONLY from agnt design-system tokens (vendor/bennyr).

   THE ONE RULE (inherited from agnt-ds): consume the tokens, never fork them.
   This file adds what agnt-ds lacks for COMMUNICATION work — data
   visualisation, findings/narrative patterns, report and slide surfaces — and
   defines nothing that a token can already express. Every colour here is a
   var(--…). The only literal hex lives in the chart-series ramp below, because
   a validated categorical palette IS a design token (see STYLE-GUIDE +
   dataviz validation). Load AFTER agnt-stylesheet.css:

     <link rel="stylesheet" href="vendor/bennyr/agnt-stylesheet.css">
     <link rel="stylesheet" href="comms-layer.css">

   Sections
     1.  Tokens (series / sequential / diverging / status / chrome)
     1b. Interactive accent — the AA-safe text-on-accent pair + the base
         components that use it (.btn-primary, steppers, menu checks)
     2.  Figure frame (title, subtitle, source, legend, plot)
     3.  Chart chrome (axes, gridlines, labels, tooltip) + annotation layer
     4.  Bar & column charts
     5.  Line & area charts
     6.  Donut / part-to-whole
     7.  Sparkline   ·   7b. Expanded pack (waterfall, funnel, slope, dumbbell,
                          scatter, heatmap; barChart/stackedColumn reuse §4)
     8.  Stat tiles, hero figure, meter
     9.  Findings & narrative (exec summary, finding card, insight, recommend)
     10. Print / PDF (chart)
     11. Report / document     12. Presentation / deck     13. Web sections
     14. Print / PDF (deck & report paging)
     15. Flowchart / journey   16. Report-grade data tables
     17. Formal document layer (admonitions, footnotes, numbering, print chrome)
     18. Diagram pack (timeline, gantt, 2×2 quadrant, org tree)
     19. Structure diagrams (pyramid, layer stack, nested, venn)
   ========================================================================== */


/* ============================================================================
   1. TOKENS — chart palette + interactive accent
   ----------------------------------------------------------------------------
   The categorical series palette is the dataviz validated reference instance,
   stepped for light and dark surfaces. Assigned in FIXED order, never cycled.
   Chart chrome (ink, grid, axis, surface) maps onto agnt text/line/bg tokens
   so charts inherit light/dark with the rest of the system. Status maps onto
   agnt's own semantic tokens — a status colour never impersonates a series.
   ========================================================================== */

/* IMPORTANT — nested-token resolution.
   A custom property whose value references another custom property (e.g.
   --chart-surface: var(--bg2)) resolves that inner var() at the scope where the
   OUTER property is DECLARED, not where it is used. So an alias declared only on
   :root would freeze to the dark token even under body.light-mode. Every
   mode-dependent alias below is therefore declared in BOTH :root (dark) and
   body.light-mode (light). Mode-independent values (geometry, the sequential
   ramp) are declared once. Verified by render in both modes. */

:root {
  /* --- mode-independent --- */
  /* Sequential (single hue, light→dark) — magnitude / heatmaps / choropleth */
  --seq-100: #cde2fb; --seq-200: #9ec5f4; --seq-300: #6da7ec;
  --seq-400: #3987e5; --seq-500: #256abf; --seq-600: #184f95; --seq-700: #0d366b;
  /* Geometry the SVG marks read via var() */
  --mark-radius: 4px;   /* rounded data-end */
  --line-weight: 2px;
  --spacer:      2px;   /* surface gap between touching marks */

  /* Brand mark — masked so it recolours with the theme. url() resolves relative
     to this stylesheet, so it is correct from pages in any subdirectory. */
  --brand-mark: url(assets/logo.svg);

  /* --- DARK (agnt is dark-first; :root == dark) --- */
  /* Categorical series — dark-surface steps (validated on #161618) */
  --series-1: #3987e5; --series-2: #199e70; --series-3: #c98500; --series-4: #008300;
  --series-5: #9085e9; --series-6: #e66767; --series-7: #d55181; --series-8: #d95926;

  /* Diverging poles — blue (low) ↔ red (high); neutral gray midpoint */
  --div-low: var(--series-1); --div-mid: var(--line2); --div-high: var(--series-6);
  /* Status — mapped onto agnt semantics (reserved; icon+label, never alone) */
  --stat-good: var(--green); --stat-warning: var(--amber);
  --stat-serious: var(--coral); --stat-critical: var(--red);
  /* Chart chrome — inherited from agnt tokens */
  --chart-surface: var(--bg2); --chart-ink: var(--text); --chart-ink-2: var(--text2);
  --chart-muted: var(--text3); --chart-grid: var(--line); --chart-axis: var(--line2);
  --chart-track: var(--bg4);

  /* --- Interactive accent — the AA-safe text-on-accent pair (issue #1) ---
     --accent is a BRAND colour. The system only guarantees it 3:1 against the
     page, which is enough for a border or a fill but NOT for a label sitting
     ON it: white on the default dark --accent (#7B6EF6) measures 3.89:1,
     below AA's 4.5:1. Terracotta-style warm brands are worse (~3.1:1).

     So anything that puts TEXT on an accent fill reads this pair instead —
     derived from existing tokens, never invented:
       fill  = --accent2  the accent the system already guarantees is AA text
                          against --bg (it is the link colour in both schemes)
       label = --bg       the page ground itself
     Contrast is symmetric, so inverting a pair that passes as text-on-page
     passes as text-on-fill: 7.32:1 dark, 7.46:1 light. A rebrand that keeps
     --accent2 readable as a link therefore gets a compliant button for free.
     Override the pair directly if you want a different fill; validate any
     override with `node tools/contrast.mjs`. */
  --accent-interactive:    var(--accent2);
  --on-accent-interactive: var(--bg);
}

body.light-mode {
  /* Categorical series — light-surface steps (validated on #F7F7F5) */
  --series-1: #2a78d6; --series-2: #1baf7a; --series-3: #eda100; --series-4: #008300;
  --series-5: #4a3aa7; --series-6: #e34948; --series-7: #e87ba4; --series-8: #eb6834;

  /* Same aliases, re-declared so their inner var() resolves against light tokens */
  --div-low: var(--series-1); --div-mid: var(--line2); --div-high: var(--series-6);
  --stat-good: var(--green); --stat-warning: var(--amber);
  --stat-serious: var(--coral); --stat-critical: var(--red);
  --chart-surface: var(--bg2); --chart-ink: var(--text); --chart-ink-2: var(--text2);
  --chart-muted: var(--text3); --chart-grid: var(--line); --chart-axis: var(--line2);
  --chart-track: var(--bg4);
  --accent-interactive:    var(--accent2);
  --on-accent-interactive: var(--bg);
}

/* Convenience: paint a mark by slot. Fills use fill-*, strokes stroke-*. */
.fill-1{fill:var(--series-1)} .fill-2{fill:var(--series-2)} .fill-3{fill:var(--series-3)}
.fill-4{fill:var(--series-4)} .fill-5{fill:var(--series-5)} .fill-6{fill:var(--series-6)}
.fill-7{fill:var(--series-7)} .fill-8{fill:var(--series-8)}
.stroke-1{stroke:var(--series-1)} .stroke-2{stroke:var(--series-2)} .stroke-3{stroke:var(--series-3)}
.stroke-4{stroke:var(--series-4)} .stroke-5{stroke:var(--series-5)} .stroke-6{stroke:var(--series-6)}
.stroke-7{stroke:var(--series-7)} .stroke-8{stroke:var(--series-8)}


/* ============================================================================
   1b. INTERACTIVE ACCENT — text on an accent fill
   ----------------------------------------------------------------------------
   The base sheet paints every accent fill's label a literal #ffffff, which is
   only readable when the accent happens to be dark enough (it isn't, in the
   default dark scheme, and it usually isn't after a rebrand). These rules
   re-point the base's text-on-accent components at the AA-safe pair above.
   The base is NOT edited — it stays a clean vendored copy; the layer loads
   after it and wins on source order. Products that vendor agnt-stylesheet.css
   WITHOUT this layer keep the old, failing colours, so load both.

   Non-text accent uses (borders, focus ring, active underlines, progress
   fills, bullet squares) deliberately keep plain --accent: they only need
   3:1, and they carry the brand.
   ========================================================================== */

.btn-primary {
  background: var(--accent-interactive);
  color: var(--on-accent-interactive);
}
.menu-check .box.on {
  background: var(--accent-interactive);
  border-color: var(--accent-interactive);
  color: var(--on-accent-interactive);
}
.stepper .step.done .num,
.stepper-v .vstep.done .num {
  background: var(--accent-interactive);
  color: var(--on-accent-interactive);
}


/* ============================================================================
   2. FIGURE FRAME
   ----------------------------------------------------------------------------
   Every chart is a <figure class="figure">: a titled, sourced container that
   sits on a card. Title/subtitle carry the story; the source line carries
   provenance. Legend rides the top for ≥2 series (never for one).
   ========================================================================== */

.figure {
  display: flex; flex-direction: column; gap: 10px;
  background: var(--chart-surface);
  border: 1px solid var(--line);
  border-radius: var(--r10);
  padding: 16px;
  margin: 0;
}
.figure-head { display: flex; flex-direction: column; gap: 2px; }
.figure-title { font-size: 16px; font-weight: 600; color: var(--text); }
.figure-sub   { font-size: 12px; font-weight: 400; color: var(--text2); }
.figure-source{ font-size: 11px; font-weight: 400; color: var(--text3); margin-top: 2px; }
.figure-plot  { position: relative; width: 100%; }
.figure-plot svg { display: block; width: 100%; height: auto; overflow: visible; }

/* Legend — always for ≥2 series. Identity is the swatch, text is ink. */
.chart-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.legend-key {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--text2);
}
.legend-key .swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.legend-key .swatch.line { height: 2px; border-radius: 2px; width: 14px; }


/* ============================================================================
   3. CHART CHROME — axes, gridlines, labels, tooltip
   ----------------------------------------------------------------------------
   Recessive by design. Grid is a solid hairline (never dashed). Text wears
   text tokens, never the series colour.
   ========================================================================== */

.axis-line   { stroke: var(--chart-axis); stroke-width: 1; }
.grid-line   { stroke: var(--chart-grid); stroke-width: 1; }
.tick-label  { fill: var(--chart-muted); font-size: 11px;
               font-family: var(--font-ui); }
.tick-num    { fill: var(--chart-muted); font-size: 11px;
               font-variant-numeric: tabular-nums; font-family: var(--font-ui); }
.axis-title  { fill: var(--chart-ink-2); font-size: 11px; font-weight: 600;
               font-family: var(--font-ui); }
/* Direct label riding a mark — ink, selective, never one-per-point */
.mark-label  { fill: var(--chart-ink); font-size: 12px; font-weight: 600;
               font-family: var(--font-ui); }
.mark-label-inside { fill: #ffffff; font-size: 11px; font-weight: 600;
               font-family: var(--font-ui); }

/* All marks share the rounded data-end + surface-gap idiom */
.bar-mark, .col-mark { rx: var(--mark-radius); }
.dot-mark { stroke: var(--chart-surface); stroke-width: var(--spacer); }
.line-mark { fill: none; stroke-width: var(--line-weight);
             stroke-linejoin: round; stroke-linecap: round; }
.area-fill { opacity: 0.10; }

/* Tooltip — the one elevated element on a chart (uses agnt's only shadow) */
.chart-tip {
  position: absolute; pointer-events: none; z-index: 5;
  background: var(--bg4); border: 1px solid var(--line2);
  border-radius: var(--r6); box-shadow: var(--shadow-pop);
  padding: 8px 10px; font-size: 12px; color: var(--text);
  min-width: 120px; opacity: 0; transition: opacity 0.15s;
}
.chart-tip.show { opacity: 1; }
.chart-tip .tip-title { font-weight: 600; margin-bottom: 4px; }
.chart-tip .tip-row {
  display: flex; align-items: center; gap: 6px;
  color: var(--text2); line-height: 1.6;
}
.chart-tip .tip-row .swatch { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.chart-tip .tip-row .tip-val {
  margin-left: auto; color: var(--text); font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.crosshair { stroke: var(--chart-axis); stroke-width: 1; }

/* Annotation layer (tools/charts.mjs annotate()) — reference/threshold lines,
   highlight bands, event markers, point callouts. Colour is set inline from a
   tone token; these classes carry structure only. Dashes are the one sanctioned
   dashed-line use — they mark a line as an annotation, not data. */
.annot-band        { opacity: 0.09; }
.annot-band-label  { fill: var(--text3); font-size: 10px; font-family: var(--font-ui); }
.annot-refline     { stroke-width: 1; stroke-dasharray: 4 3; fill: none; }
.annot-marker      { stroke-width: 1; stroke-dasharray: 3 3; }
.annot-tag-bg      { }                  /* fill inline (tone) — structure only */
.annot-tag         { fill: #ffffff; font-size: 10px; font-weight: 600; font-family: var(--font-ui); }
.annot-lead        { stroke-width: 1; }
.annot-dot         { stroke: var(--chart-surface); stroke-width: 1.5; }
.annot-note-bg     { fill: var(--bg4); stroke: var(--line2); stroke-width: 1; }
.annot-note        { fill: var(--text); font-size: 11px; font-weight: 600; font-family: var(--font-ui); }


/* ============================================================================
   4. BAR & COLUMN
   ----------------------------------------------------------------------------
   ≤24px thick, 4px rounded data-end (square at baseline via clip in markup),
   2px surface gap between adjacent bars. Grouped bars pull from the series
   ramp in order; a single-series chart uses --series-1 throughout.
   ========================================================================== */

.col-mark, .bar-mark { transition: opacity 0.15s; }
.col-mark:hover, .bar-mark:hover { opacity: 0.85; }
/* single-series default fill */
.figure-plot .col-mark:not([class*="fill-"]),
.figure-plot .bar-mark:not([class*="fill-"]) { fill: var(--series-1); }


/* ============================================================================
   5. LINE & AREA
   ========================================================================== */

.figure-plot .line-mark:not([class*="stroke-"]) { stroke: var(--series-1); }
.figure-plot .area-fill:not([class*="fill-"])   { fill: var(--series-1); }


/* ============================================================================
   6. DONUT / PART-TO-WHOLE
   ----------------------------------------------------------------------------
   Segments carry the series ramp; a 2px surface-gap ring separates them (via
   stroke in the surface colour in markup). Centre carries the total.
   ========================================================================== */

.donut-seg { stroke: var(--chart-surface); stroke-width: var(--spacer);
             transition: opacity 0.15s; }
.donut-seg:hover { opacity: 0.85; }
.donut-center-value { fill: var(--text); font-size: 22px; font-weight: 600;
             font-family: var(--font-ui); text-anchor: middle; }
.donut-center-label { fill: var(--text2); font-size: 11px;
             font-family: var(--font-ui); text-anchor: middle; }


/* ============================================================================
   7. SPARKLINE — inline, no axes, no chrome
   ========================================================================== */

.sparkline { display: inline-block; vertical-align: middle; height: 1em; }
.sparkline svg { height: 100%; width: auto; overflow: visible; }
.sparkline .line-mark { stroke: var(--text3); stroke-width: 1.5; }
.sparkline .spark-now { fill: var(--series-1); }        /* current-period dot */


/* ============================================================================
   7b. EXPANDED CHART PACK — waterfall, funnel, bullet, slope, dumbbell,
       scatter, heatmap (barChart / stackedColumn reuse §4 col-mark + fill-*)
   ========================================================================== */

/* Waterfall — increases green, decreases red, totals neutral; thin connectors */
.wf-up      { fill: var(--green); }
.wf-down    { fill: var(--red); }
.wf-total   { fill: var(--text3); }
.wf-connect { stroke: var(--line2); stroke-width: 1; }

/* Funnel — HTML component: coloured trapezoid stages (clip-path) with an icon +
   label inside, and Users / % columns with dotted leaders on the right. */
.funnel-chart { display: flex; flex-direction: column; gap: 3px;
  max-width: 620px; margin: 0 auto; }              /* stays balanced in a wide figure */
.funnel-seg { height: 58px; display: flex; align-items: center; justify-content: center;
  print-color-adjust: exact; -webkit-print-color-adjust: exact; }   /* keep colour in PDF */
.funnel-seg-in { display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 1px; line-height: 1.12; text-align: center; }
.funnel-seg-top { display: inline-flex; align-items: center; gap: 7px; }
.funnel-seg i { font-size: 18px; flex: none; }
.funnel-seg .fl { font-size: 13px; font-weight: 600; }
.funnel-seg-val { font-size: 12px; font-weight: 600; opacity: 0.9;
  font-variant-numeric: tabular-nums; }

/* Funnel — "stages" variant: monochromatic, big title + description, chevron notch */
.funnel-stages { display: flex; flex-direction: column; gap: 3px;
  max-width: 520px; margin: 0 auto; }
.funnel-stage { min-height: 96px; display: flex; align-items: center; justify-content: center;
  padding: 18px 24px; text-align: center;
  print-color-adjust: exact; -webkit-print-color-adjust: exact; }
.funnel-stage-in { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.funnel-stage-title { font-size: 17px; font-weight: 600; line-height: 1.15;
  letter-spacing: 0.02em; text-transform: uppercase; }
.funnel-stage-desc { font-size: 14px; line-height: 1.35; opacity: 0.92; }
.funnel-stage-val { font-size: 15px; font-weight: 600; margin-top: 2px;
  font-variant-numeric: tabular-nums; }

/* Slope & dumbbell — connector line + end dots */
.slope-line    { stroke-width: 1.5; fill: none; }
.slope-dot     { stroke: var(--chart-surface); stroke-width: 1.5; }
.slope-label   { fill: var(--text2); font-size: 11px; font-family: var(--font-ui); }
.slope-axis-label { fill: var(--text3); font-size: 11px; font-weight: 600; font-family: var(--font-ui); }
.dumbbell-line { stroke: var(--line2); stroke-width: 2; }

/* Scatter / bubble */
.scatter-dot { stroke: var(--chart-surface); stroke-width: 1; }

/* Heatmap — cells coloured inline from the --seq ramp; labels in text tokens */
.heat-cell  { stroke: var(--chart-surface); stroke-width: 2; }
.heat-val   { font-size: 11px; font-weight: 600; font-family: var(--font-ui); }
.heat-label { fill: var(--text2); font-size: 11px; font-family: var(--font-ui); }


/* ============================================================================
   8. STAT TILES, HERO FIGURE, METER
   ----------------------------------------------------------------------------
   When the form is a number, not a plot. Built on agnt's .card-inset idiom.
   ========================================================================== */

.stat-tile {
  display: flex; flex-direction: column; gap: 4px;
  background: var(--bg3); border-radius: var(--r8); padding: 14px 16px;
}
.stat-tile .stat-label { font-size: 12px; color: var(--text2); }
.stat-tile .stat-value {
  font-size: 24px; font-weight: 600; color: var(--text); line-height: 1.1;
}
.stat-tile .stat-foot { display: flex; align-items: center; gap: 6px; }
.stat-delta { font-size: 12px; font-weight: 600; display: inline-flex;
              align-items: center; gap: 3px; }
.stat-delta.up-good, .stat-delta.down-bad-inv { color: var(--green); }
.stat-delta.down-bad, .stat-delta.up-good-inv { color: var(--red); }
.stat-delta.flat { color: var(--text3); }
.stat-tile .stat-period { font-size: 11px; color: var(--text3); }

/* Hero figure — exactly one per view, ≥48px, system sans */
.hero-figure { font-size: 48px; font-weight: 600; color: var(--text);
               line-height: 1; letter-spacing: -0.01em; }
.hero-figure-label { font-size: 13px; color: var(--text2); margin-top: 4px; }

/* Meter — fill carries severity; track is a lighter step of the same idea */
.meter { height: 8px; border-radius: 20px; background: var(--chart-track);
         overflow: hidden; }
.meter .meter-fill { height: 100%; border-radius: 20px; background: var(--series-1);
         transition: width 0.15s; }
.meter-fill.good{background:var(--stat-good)} .meter-fill.warning{background:var(--stat-warning)}
.meter-fill.serious{background:var(--stat-serious)} .meter-fill.critical{background:var(--stat-critical)}


/* ============================================================================
   9. FINDINGS & NARRATIVE
   ----------------------------------------------------------------------------
   The vocabulary for communicating findings — what agnt-ds has only a generic
   .callout for. Severity-coded, token-built, extends the callout idiom.
   ========================================================================== */

/* Executive summary — the lead block of a report */
.exec-summary {
  border-left: 2px solid var(--accent);
  background: var(--purple-bg);
  border-radius: var(--r8);
  padding: 16px 18px;
  display: flex; flex-direction: column; gap: 8px;
}
.exec-summary .exec-eyebrow {
  font-size: 10px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent2);
}
.exec-summary .exec-lead { font-size: 15px; line-height: 1.5; color: var(--text); }

/* Finding card — a single finding, severity in the left rail + badge */
.finding {
  display: grid; grid-template-columns: auto 1fr; gap: 12px;
  background: var(--bg2); border: 1px solid var(--line);
  border-left: 3px solid var(--text3); border-radius: var(--r8);
  padding: 14px 16px;
}
.finding.sev-good{border-left-color:var(--stat-good)}
.finding.sev-warning{border-left-color:var(--stat-warning)}
.finding.sev-serious{border-left-color:var(--stat-serious)}
.finding.sev-critical{border-left-color:var(--stat-critical)}
.finding .finding-icon { font-size: 18px; color: var(--text3); margin-top: 1px; }
.finding.sev-good .finding-icon{color:var(--stat-good)}
.finding.sev-warning .finding-icon{color:var(--stat-warning)}
.finding.sev-serious .finding-icon{color:var(--stat-serious)}
.finding.sev-critical .finding-icon{color:var(--stat-critical)}
.finding .finding-body { display: flex; flex-direction: column; gap: 4px; }
.finding .finding-title { font-size: 14px; font-weight: 600; color: var(--text); }
.finding .finding-text { font-size: 13px; line-height: 1.5; color: var(--text2); }
.finding .finding-meta { display: flex; gap: 8px; align-items: center;
                         margin-top: 2px; flex-wrap: wrap; }

/* Insight block — a highlighted takeaway pulled out of the flow */
.insight {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--bg3); border-radius: var(--r10); padding: 16px 18px;
}
.insight .insight-mark {
  font-size: 20px; color: var(--accent2); flex: none; margin-top: 1px;
}
.insight .insight-text { font-size: 15px; line-height: 1.5; color: var(--text); }
.insight .insight-text strong { font-weight: 600; }

/* Key takeaway — a big-number statement, number + supporting clause */
.takeaway { display: flex; align-items: baseline; gap: 12px; }
.takeaway .takeaway-num { font-size: 32px; font-weight: 600; color: var(--text);
                          line-height: 1; letter-spacing: -0.01em; }
.takeaway .takeaway-num.good{color:var(--stat-good)}
.takeaway .takeaway-num.bad{color:var(--stat-critical)}
.takeaway .takeaway-text { font-size: 14px; color: var(--text2); line-height: 1.4; }

/* Recommendation list — numbered, actionable */
.reco-list { display: flex; flex-direction: column; gap: 10px;
             counter-reset: reco; list-style: none; padding: 0; margin: 0; }
.reco-list .reco {
  display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start;
}
.reco-list .reco::before {
  counter-increment: reco; content: counter(reco);
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent-interactive); color: var(--on-accent-interactive);
  font-size: 12px; font-weight: 600;
  display: flex; align-items: center; justify-content: center; flex: none;
}
.reco .reco-title { font-size: 14px; font-weight: 600; color: var(--text); }
.reco .reco-text  { font-size: 13px; color: var(--text2); line-height: 1.5; }

/* Comparison / before-after — two panes with a delta */
.compare { display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px;
           align-items: stretch; }
.compare .compare-pane {
  background: var(--bg3); border-radius: var(--r8); padding: 14px 16px;
  display: flex; flex-direction: column; gap: 4px;
}
.compare .compare-label { font-size: 11px; color: var(--text3);
  text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.compare .compare-value { font-size: 22px; font-weight: 600; color: var(--text); }
.compare .compare-arrow { display: flex; align-items: center; color: var(--text3);
                          font-size: 18px; }


/* ============================================================================
   10. PRINT / PDF
   ----------------------------------------------------------------------------
   Communication assets are frequently rendered to PDF. Force the light,
   print-safe surface, avoid page breaks inside figures/findings, keep charts
   as vector (SVG stays crisp).
   ========================================================================== */

@media print {
  body { background: #ffffff; }
  .figure, .finding, .insight, .exec-summary, .stat-tile, .compare, .reco {
    break-inside: avoid;
  }
  .chart-tip, .crosshair { display: none !important; }
  .figure { border: 1px solid rgba(0,0,0,0.12); box-shadow: none; }
}


/* ============================================================================
   11. REPORT / DOCUMENT
   ----------------------------------------------------------------------------
   Long-form client deliverables. A centred reading column with a cover,
   contents, and numbered sections. Sans by default (modern); add .report-serif
   for a formal, printed-paper feel (agnt --font-serif). One section per printed
   page group; charts and findings drop straight in.
   ========================================================================== */

.report { max-width: 820px; margin: 0 auto; padding: 56px 40px 96px;
          color: var(--text); }
.report.report-serif { font-family: var(--font-serif); }
.report.report-serif .report-body p,
.report.report-serif .report-lead { font-family: var(--font-serif); }

/* Cover */
.report-cover { min-height: 78vh; display: flex; flex-direction: column;
                justify-content: space-between; padding-bottom: 40px;
                border-bottom: 1px solid var(--line); margin-bottom: 40px; }
.report-cover .cover-top { display: flex; align-items: center; gap: 10px; }
.report-cover .cover-mark { width: 22px; height: 30px; background: var(--text);
  -webkit-mask: var(--brand-mark) center/contain no-repeat;
  mask: var(--brand-mark) center/contain no-repeat; }
.report-cover .cover-org { font-size: 13px; font-weight: 600; color: var(--text2); }
.report-cover .cover-main { display: flex; flex-direction: column; gap: 14px; }
.report-cover .cover-kicker { font-size: 12px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent2); }
.report-cover .cover-title { font-size: 42px; font-weight: 600; line-height: 1.1;
  letter-spacing: -0.01em; color: var(--text); max-width: 18ch; }
.report-cover .cover-sub { font-size: 17px; color: var(--text2); max-width: 52ch;
  line-height: 1.5; }
.report-cover .cover-meta { display: flex; gap: 24px; flex-wrap: wrap;
  font-size: 13px; color: var(--text3); }
.report-cover .cover-meta b { color: var(--text2); font-weight: 600; }

/* Table of contents */
.report-toc { margin: 0 0 48px; }
.report-toc .toc-title { font-size: 10px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text3); margin-bottom: 12px; }
.report-toc ol { list-style: none; counter-reset: toc; padding: 0; margin: 0; }
.report-toc li { counter-increment: toc; display: flex; align-items: baseline;
  gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.report-toc li::before { content: counter(toc, decimal-leading-zero);
  font-variant-numeric: tabular-nums; color: var(--accent2); font-weight: 600;
  font-size: 12px; flex: none; }
.report-toc .toc-dots { flex: 1; border-bottom: 1px dotted var(--line2);
  transform: translateY(-3px); }
.report-toc .toc-page { color: var(--text3); font-variant-numeric: tabular-nums; }

/* Sections */
.report-section { margin: 48px 0; }
.report-section .section-no { font-size: 12px; font-weight: 600; color: var(--accent2);
  font-variant-numeric: tabular-nums; }
.report-section .section-title { font-size: 24px; font-weight: 600; color: var(--text);
  margin: 4px 0 6px; letter-spacing: -0.01em; }
.report-section .section-rule { height: 1px; background: var(--line); margin: 12px 0 20px; }
.report-body { font-size: 15px; line-height: 1.65; color: var(--text); }
.report-body p { margin: 0 0 16px; }
.report-body .report-lead { font-size: 17px; line-height: 1.6; color: var(--text2); }
.report-body h3 { font-size: 16px; font-weight: 600; margin: 24px 0 8px; color: var(--text); }
.report-figure { margin: 24px 0; }
.report-figure .fig-caption { font-size: 12px; color: var(--text3); margin-top: 8px;
  text-align: center; }


/* ============================================================================
   12. PRESENTATION / DECK
   ----------------------------------------------------------------------------
   16:9 slides that read on screen (a scrolling stack) and print one-per-page to
   PDF. Slides are a fixed 16:9 canvas; content is laid out in px at a ~1120-wide
   reference. Variants: title, section divider, content, chart, quote, closing.
   ========================================================================== */

.deck { display: flex; flex-direction: column; align-items: center; gap: 24px;
        padding: 32px 16px 64px; background: var(--bg); }
.slide {
  position: relative; width: 100%; max-width: 1120px; aspect-ratio: 16 / 9;
  background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r12);
  padding: 56px 64px; overflow: hidden; display: flex; flex-direction: column;
  color: var(--text);
}
.slide .slide-num { position: absolute; bottom: 22px; right: 28px; font-size: 12px;
  color: var(--text3); font-variant-numeric: tabular-nums; }
.slide .slide-mark { position: absolute; bottom: 20px; left: 28px; width: 15px;
  height: 20px; background: var(--text3);
  -webkit-mask: var(--brand-mark) center/contain no-repeat;
  mask: var(--brand-mark) center/contain no-repeat; }
.slide .slide-kicker { font-size: 13px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent2); margin-bottom: 14px; }

/* Title slide */
.slide-title { justify-content: center; background: var(--bg3); }
.slide-title .st-title { font-size: 54px; font-weight: 600; line-height: 1.08;
  letter-spacing: -0.02em; max-width: 20ch; }
.slide-title .st-sub { font-size: 20px; color: var(--text2); margin-top: 18px;
  max-width: 46ch; line-height: 1.5; }
.slide-title .st-meta { margin-top: auto; display: flex; gap: 24px; font-size: 14px;
  color: var(--text3); padding-top: 24px; }

/* Section divider */
/* Full-bleed accent slide: the same AA pair as the buttons, because the whole
   slide is text on an accent fill. The secondary marks were rgba white — which
   inverts wrongly the moment the fill is light — so they are the on-accent ink
   at an opacity that still measures AA (0.8 → 5.3:1; 0.7 fell to 4.3:1). */
.slide-section { justify-content: center; align-items: flex-start;
  background: var(--accent-interactive); color: var(--on-accent-interactive); }
.slide-section .ss-no { font-size: 16px; font-weight: 600; opacity: 0.8; }
.slide-section .ss-title { font-size: 44px; font-weight: 600; line-height: 1.1;
  letter-spacing: -0.01em; max-width: 22ch; margin-top: 8px; }
.slide-section .slide-mark { background: var(--on-accent-interactive); opacity: 0.6; }
.slide-section .slide-num { color: var(--on-accent-interactive); opacity: 0.8; }

/* Content slide */
.slide-head { margin-bottom: 22px; }
.slide-head .sh-title { font-size: 32px; font-weight: 600; letter-spacing: -0.01em;
  line-height: 1.15; }
.slide-body { flex: 1; min-height: 0; display: flex; flex-direction: column;
  gap: 16px; font-size: 18px; line-height: 1.5; color: var(--text); }
/* Grid (not flex:1) for the two-column split — Chrome's print engine reliably
   honours grid tracks but can drop flex-direction:row under @page, which lets a
   chart column blow out to full width. min-width:0 lets the chart shrink to fit. */
.slide-body.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 40px;
  align-items: center; }
.slide-body.two-col > * { min-width: 0; }
.slide-bullets { list-style: none; padding: 0; margin: 0; display: flex;
  flex-direction: column; gap: 14px; }
.slide-bullets li { display: grid; grid-template-columns: auto 1fr; gap: 12px;
  align-items: start; font-size: 18px; color: var(--text); }
.slide-bullets li::before { content: ""; width: 8px; height: 8px; border-radius: 2px;
  background: var(--accent); margin-top: 9px; }

/* Quote / closing */
.slide-quote { justify-content: center; }
.slide-quote .sq-text { font-size: 34px; font-weight: 600; line-height: 1.3;
  letter-spacing: -0.01em; max-width: 24ch; }
.slide-quote .sq-cite { font-size: 15px; color: var(--text2); margin-top: 20px; }


/* ============================================================================
   13. WEB / PUBLIC PAGE SECTIONS
   ----------------------------------------------------------------------------
   Full-bleed sections for public-facing pages and microsites. Rhythm and
   generous scale distinguish these from dense product chrome.
   ========================================================================== */

.web { color: var(--text); }
.web-section { padding: 80px 24px; }
.web-section .web-inner { max-width: 1080px; margin: 0 auto; }
.web-hero { text-align: center; padding: 112px 24px 96px; }
.web-hero .hero-kicker { font-size: 13px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent2); }
.web-hero .hero-title { font-size: 56px; font-weight: 600; line-height: 1.05;
  letter-spacing: -0.02em; margin: 16px auto 0; max-width: 16ch; }
.web-hero .hero-sub { font-size: 20px; color: var(--text2); line-height: 1.5;
  margin: 20px auto 0; max-width: 52ch; }
.web-hero .hero-cta { display: inline-flex; gap: 12px; margin-top: 32px; }
.web-eyebrow { font-size: 12px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text3); text-align: center; }
.web-h2 { font-size: 34px; font-weight: 600; letter-spacing: -0.01em;
  text-align: center; margin: 10px auto 8px; max-width: 22ch; }
.web-lede { font-size: 17px; color: var(--text2); text-align: center; line-height: 1.5;
  margin: 0 auto 40px; max-width: 54ch; }
.feature-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.feature { background: var(--bg2); border: 1px solid var(--line);
  border-radius: var(--r12); padding: 28px; display: flex; flex-direction: column;
  gap: 10px; }
.feature .feature-icon { font-size: 24px; color: var(--accent2); }
.feature .feature-title { font-size: 18px; font-weight: 600; color: var(--text); }
.feature .feature-text { font-size: 15px; color: var(--text2); line-height: 1.55; }
.cta-band { text-align: center; background: var(--bg2); border: 1px solid var(--line);
  border-radius: var(--r12); padding: 56px 24px; }
.cta-band .cta-title { font-size: 30px; font-weight: 600; letter-spacing: -0.01em;
  margin-bottom: 20px; }

@media (max-width: 820px) {
  .feature-grid { grid-template-columns: 1fr; }
  .web-hero .hero-title { font-size: 40px; }
  .web-h2 { font-size: 26px; }
  .slide-body.two-col { flex-direction: column; gap: 16px; }
}


/* ============================================================================
   14. PRINT / PDF — deck & report paging
   ----------------------------------------------------------------------------
   A report prints on the default portrait page and never breaks inside a
   section. A DECK is exported separately: put the deck page in landscape with
   zero margins (Chrome: --no-pdf-header-footer, or set body.deck-print), and
   each 16:9 slide fills one page. Because report @page margins and deck
   full-bleed conflict, decks live on their own page/export.
   ========================================================================== */

@media print {
  .report-section, .report-cover, .report-toc { break-inside: avoid; }
  .report-cover { break-after: page; }
  .slide-section { break-after: page; }

  .deck { gap: 0; padding: 0; background: #ffffff; }
  /* Keep aspect-ratio:16/9 — with a 16:9 @page (13.333in×7.5in) and width:100%,
     the derived height equals the page height, so each slide fills its page.
     Overriding to height:100% here fails: % height has no definite parent in a
     flex column and collapses the slide body. Break only BETWEEN slides. */
  .slide {
    max-width: none; width: 100%;
    border: none; border-radius: 0; break-inside: avoid;
  }
  .slide:not(:last-child) { break-after: page; }
  /* Deck export sets landscape + zero margins via the print command flags
     (headless Chrome: --landscape, no header/footer). The rules above make each
     slide fill the page; nothing more is needed in CSS. */
}
/* Reports print on a comfortable portrait margin. Deck export passes its own
   zero-margin landscape page size on the command line, overriding this. */
@page { margin: 16mm; }


/* ============================================================================
   15. FLOWCHART / JOURNEY (see tools/flow.mjs + the `flowchart` skill)
   ----------------------------------------------------------------------------
   Node + edge marks for customer-journey / lifecycle / process diagrams. Marks
   wear token fills (direct var(), so they track light/dark); text wears text
   tokens. Terminal = start/end (accent), step = a stage (surface), decision =
   a branch (amber). Generated as static SVG — print-perfect, no runtime.
   ========================================================================== */

.flow-figure .flow-plot { overflow-x: auto; text-align: center; }   /* long flows scroll; centre the diagram */
/* Linear flows: natural size, capped to the column — wide shrink to fit, narrow
   (vertical) are not blown up. width:auto overrides §2's width:100%.
   margin-inline:auto centres the diagram in the figure. */
.flow-plot svg { display: block; width: auto; height: auto; max-width: 100%; margin-inline: auto; }
/* Branching graphs: render at natural size and SCROLL if wider than the column —
   shrinking a dense graph to fit makes the nodes illegible. */
.flow-graph-plot svg { max-width: none; }

.flow-step      { fill: var(--bg2);  stroke: var(--line2); stroke-width: 1; }
.flow-terminal  { fill: var(--purple-bg); stroke: var(--accent); stroke-width: 1.5; }
.flow-decision  { fill: var(--amber-bg);  stroke: var(--amber);  stroke-width: 1.5; }

.flow-text        { fill: var(--text); font-size: 14px; font-weight: 600;
                    font-family: var(--font-ui); }
.flow-text-accent { fill: var(--accent2); }

.flow-edge      { stroke: var(--line2); stroke-width: 1.5; fill: none; }
.flow-edge-back { stroke: var(--text3); }   /* loop-back / retry edges read quieter */
.flow-arrowhead { fill: var(--text3); }
.flow-edge-label    { fill: var(--text2); font-size: 12px; font-family: var(--font-ui); }
.flow-edge-label-bg { fill: var(--chart-surface); }     /* clears the line behind the label */

/* Swimlanes — horizontal actor/system bands ("label@Lane" + lanes:[…]) */
.lane-band-alt { fill: var(--bg3); opacity: 0.5; }
.lane-sep      { stroke: var(--line); stroke-width: 1; }
.lane-gutter   { stroke: var(--line2); stroke-width: 1; }
.lane-label    { fill: var(--text2); font-size: 12px; font-weight: 600; font-family: var(--font-ui); }

@media print { .flow-figure .flow-plot { overflow-x: visible; } }


/* ============================================================================
   16. REPORT-GRADE DATA TABLES
   ----------------------------------------------------------------------------
   Tables carry the bulk of a report's evidence. .data-table adds in-cell
   visuals (sparklines, data bars, heat cells, RAG dots, delta chips), totals
   rows and grouped headers. .matrix-table is the comparison / feature / pricing
   grid. Built from tokens; in-cell viz reuses the chart classes and ramps.
   ========================================================================== */

.data-table { width: 100%; border-collapse: collapse; font-size: 13px; color: var(--text); }
.data-table thead th { font-size: 10px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text3); text-align: left;
  padding: 8px 12px; border-bottom: 1px solid var(--line2); white-space: nowrap; }
.data-table tbody td { padding: 9px 12px; border-bottom: 1px solid var(--line);
  vertical-align: middle; }
.data-table tbody tr:hover td { background: var(--bg3); }
.data-table th.num, .data-table td.num { text-align: right;
  font-variant-numeric: tabular-nums; }
.data-table th.center, .data-table td.center { text-align: center; }
/* grouped / spanning header row above the column labels */
.data-table thead tr.group-head th { text-align: center; color: var(--text2);
  border-bottom: 1px solid var(--line); padding-bottom: 4px; }
/* subtotal / total rows */
.data-table tr.subtotal td { font-weight: 600; border-top: 1px solid var(--line2); }
.data-table tr.total td { font-weight: 600; color: var(--text);
  border-top: 2px solid var(--line2); border-bottom: none; }
.data-table tr.muted td { color: var(--text2); }

/* in-cell data bar (proportion within a cell) */
.cell-bar { display: inline-block; width: 72px; height: 8px; border-radius: 20px;
  background: var(--bg4); vertical-align: middle; overflow: hidden; }
.cell-bar-fill { display: block; height: 100%; border-radius: 20px; background: var(--series-1); }
/* heat cell — background set inline from the --seq ramp; label stays legible */
.cell-heat { display: inline-block; min-width: 34px; padding: 2px 8px; border-radius: var(--r4);
  font-variant-numeric: tabular-nums; text-align: center; }
/* RAG status dot + label */
.rag { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.rag::before { content: ""; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--text3); }
.rag-good::before { background: var(--green); }
.rag-warning::before { background: var(--amber); }
.rag-critical::before { background: var(--red); }
/* delta chip inside a cell */
.cell-delta { font-variant-numeric: tabular-nums; font-weight: 600; display: inline-flex; align-items: center; gap: 2px; }
.cell-delta.up { color: var(--green); }
.cell-delta.down { color: var(--red); }
.cell-delta.flat { color: var(--text3); }
/* the in-cell sparkline sits on the table row; keep it small */
.data-table .sparkline { height: 20px; }

/* Comparison / feature-matrix / pricing table */
.matrix-table { width: 100%; border-collapse: collapse; font-size: 13px; color: var(--text); }
.matrix-table thead th { padding: 12px; text-align: center; font-weight: 600;
  border-bottom: 1px solid var(--line2); }
.matrix-table th:first-child, .matrix-table td:first-child { text-align: left;
  color: var(--text2); font-weight: 400; }
.matrix-table tbody td { padding: 11px 12px; text-align: center;
  border-bottom: 1px solid var(--line); }
.matrix-table .mx-price { font-size: 20px; font-weight: 600; }
.matrix-table .mx-price small { font-size: 12px; font-weight: 400; color: var(--text3); }
/* recommended column highlight */
.matrix-table .col-rec { background: var(--purple-bg); }
.matrix-table thead th.col-rec { color: var(--accent2);
  border-top: 2px solid var(--accent); border-radius: var(--r6) var(--r6) 0 0; }
.matrix-table tbody tr:last-child td.col-rec { border-radius: 0 0 var(--r6) var(--r6); }
.mx-yes { color: var(--green); font-size: 16px; }
.mx-no { color: var(--text3); font-size: 16px; }
.mx-partial { color: var(--amber); font-size: 16px; }


/* ============================================================================
   17. FORMAL DOCUMENT LAYER
   ----------------------------------------------------------------------------
   The scaffolding that makes an exported PDF read as a published document:
   admonition/callout blocks, summary lists, pull quotes & testimonials,
   footnotes, auto figure/table numbering, glossary, and paged print chrome
   (running header/footer + confidentiality stamp). Pure CSS (counters + @page +
   position:fixed), so it survives a PDF export.
   ========================================================================== */

/* Admonitions — note / tip / warning / important / caution */
.admonition { display: flex; gap: 12px; border-radius: var(--r8); padding: 14px 16px;
  border-left: 3px solid var(--text3); background: var(--bg3); break-inside: avoid; }
.admonition .adm-icon { font-size: 18px; color: var(--text3); flex: none; margin-top: 1px; }
.admonition .adm-body { display: flex; flex-direction: column; gap: 3px; }
.admonition .adm-title { font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text2); }
.admonition .adm-text { font-size: 14px; line-height: 1.55; color: var(--text); }
.adm-note      { border-left-color: var(--blue);   background: var(--blue-bg); }
.adm-note .adm-icon, .adm-note .adm-title { color: var(--blue); }
.adm-tip       { border-left-color: var(--green);  background: var(--green-bg); }
.adm-tip .adm-icon, .adm-tip .adm-title { color: var(--green); }
.adm-warning   { border-left-color: var(--amber);  background: var(--amber-bg); }
.adm-warning .adm-icon, .adm-warning .adm-title { color: var(--amber); }
.adm-important { border-left-color: var(--accent); background: var(--purple-bg); }
.adm-important .adm-icon, .adm-important .adm-title { color: var(--accent2); }
.adm-caution   { border-left-color: var(--red);    background: var(--red-bg); }
.adm-caution .adm-icon, .adm-caution .adm-title { color: var(--red); }

/* Summary list — key/value "at a glance" facts (GOV.UK style) */
.summary-list { border-top: 1px solid var(--line); }
.summary-list .sl-row { display: grid; grid-template-columns: 180px 1fr; gap: 16px;
  padding: 10px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.summary-list .sl-key { color: var(--text2); }
.summary-list .sl-val { color: var(--text); }

/* Pull quote & testimonial */
.pullquote { border-left: 3px solid var(--accent); padding: 2px 0 2px 20px; margin: 24px 0;
  font-size: 22px; line-height: 1.4; font-weight: 600; color: var(--text); letter-spacing: -0.01em; }
.pullquote cite { display: block; font-size: 13px; font-weight: 400; font-style: normal;
  color: var(--text2); margin-top: 8px; }
.testimonial { background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r12); padding: 24px; break-inside: avoid; }
.testimonial .tq { font-size: 18px; line-height: 1.5; color: var(--text); }
.testimonial .tcite { display: flex; align-items: center; gap: 10px; margin-top: 16px; }
.testimonial .tname { font-weight: 600; font-size: 13px; color: var(--text); }
.testimonial .trole { font-size: 12px; color: var(--text2); }

/* Footnotes — superscript refs auto-numbered, list at the foot */
.report, .doc { counter-reset: figure table footnote; }
.fnref { counter-increment: footnote; font-size: 0.72em; vertical-align: super;
  color: var(--accent2); font-weight: 600; line-height: 0; }
.fnref::before { content: counter(footnote); }
.footnotes { margin-top: 32px; padding-top: 12px; border-top: 1px solid var(--line);
  counter-reset: fnlist; }
.footnotes .fn { counter-increment: fnlist; display: grid; grid-template-columns: 20px 1fr;
  gap: 6px; font-size: 12px; color: var(--text2); line-height: 1.5; margin-bottom: 6px; }
.footnotes .fn::before { content: counter(fnlist); color: var(--accent2); font-weight: 600; }

/* Auto figure/table numbering — captions get "Figure N." / "Table N." */
.report-figure { counter-increment: figure; }
.report-figure .fig-caption::before { content: "Figure " counter(figure) ". ";
  font-weight: 600; color: var(--text2); }
.report-table { counter-increment: table; margin: 24px 0; }
.report-table .fig-caption { font-size: 12px; color: var(--text3); margin-top: 8px; text-align: center; }
.report-table .fig-caption::before { content: "Table " counter(table) ". ";
  font-weight: 600; color: var(--text2); }

/* Glossary / abbreviations & appendix */
.glossary .gl-row { display: grid; grid-template-columns: 170px 1fr; gap: 16px;
  padding: 8px 0; border-bottom: 1px solid var(--line); font-size: 13px; }
.glossary .gl-term { font-weight: 600; color: var(--text); }
.glossary .gl-def { color: var(--text2); line-height: 1.5; }
.appendix { border-top: 2px solid var(--line2); margin-top: 40px; padding-top: 24px; }
.appendix .appendix-label { font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text3); }

/* Paged print chrome.
   A confidentiality watermark (position:fixed) repeats cleanly on every printed
   page in Chrome. Repeating running headers/footers WITH live "Page X of Y" are
   deliberately NOT done in CSS here: Chrome cannot place repeating content in the
   @page margin (it anchors position:fixed to the content area, colliding with the
   body, and ignores @page margin-box at-rules). Produce those via the print
   dialog's own header/footer, headless Chrome's --header-template, or a paged.js /
   Prince build pass — all of which read `.doc-runhead`/`.doc-runfoot` content or
   accept a template. On screen, .doc-runhead/.doc-runfoot render as a document
   masthead/footer band. */
.doc-confidential { display: none; }
.doc-runhead, .doc-runfoot { display: flex; justify-content: space-between;
  font-size: 10px; color: var(--text3); padding: 6px 0; }
.doc-runhead { border-bottom: 1px solid var(--line); margin-bottom: 8px; }
.doc-runfoot { border-top: 1px solid var(--line); margin-top: 8px; }
@media print {
  .doc-confidential { display: block; position: fixed; top: 45%; left: 50%;
    transform: translate(-50%,-50%) rotate(-28deg); font-size: 78px; font-weight: 700;
    color: var(--red); opacity: 0.06; pointer-events: none; letter-spacing: 0.08em;
    white-space: nowrap; }
  .admonition, .testimonial, .pullquote, .summary-list .sl-row { break-inside: avoid; }
}


/* ============================================================================
   18. DIAGRAM PACK — timeline, gantt/roadmap, 2×2 quadrant, org tree
       (see tools/diagrams.mjs). Marks wear tokens; colour set inline by tone/slot.
   ========================================================================== */

/* Timeline */
.tl-line  { stroke: var(--line2); stroke-width: 2; }
.tl-stub  { stroke: var(--line2); stroke-width: 1; }
.tl-dot   { stroke: var(--chart-surface); stroke-width: 2; }
.tl-date  { font-size: 12px; font-weight: 600; font-family: var(--font-ui); }
.tl-title { fill: var(--text); font-size: 12px; font-family: var(--font-ui); }

/* Gantt / roadmap */
.gantt-grid      { stroke: var(--line); stroke-width: 1; }
.gantt-period    { fill: var(--text3); font-size: 11px; font-weight: 600; font-family: var(--font-ui); }
.gantt-label     { fill: var(--text2); font-size: 12px; font-family: var(--font-ui); }
.gantt-bar       { }                       /* fill inline (slot/tone) */
.gantt-milestone { stroke: var(--chart-surface); stroke-width: 2; }

/* 2×2 quadrant matrix */
.quad-box        { fill: none; stroke: var(--line2); stroke-width: 1; }
.quad-cross      { stroke: var(--line2); stroke-width: 1; }
.quad-label      { fill: var(--text3); font-size: 11px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase; font-family: var(--font-ui); }
.quad-axis-label { fill: var(--text2); font-size: 11px; font-weight: 600; font-family: var(--font-ui); }
.quad-point      { stroke: var(--chart-surface); stroke-width: 2; }
.quad-point-label{ fill: var(--text); font-size: 11px; font-weight: 600; font-family: var(--font-ui); }

/* Org / hierarchy tree */
.org-node       { fill: var(--bg2); stroke: var(--line2); stroke-width: 1; }
.org-edge       { fill: none; stroke: var(--line2); stroke-width: 1.5; }
.org-text       { fill: var(--text); font-size: 13px; font-weight: 600; font-family: var(--font-ui); }
.org-text-accent{ fill: var(--accent2); }


/* ============================================================================
   19. STRUCTURE DIAGRAMS — pyramid, layer stack, nested, venn
   ----------------------------------------------------------------------------
   Shapes that carry an argument rather than a measurement (see tools/diagrams.mjs).
   They share one focal convention: the accent TINT — --purple-bg fill plus an
   --accent stroke — never a solid accent fill. That keeps every label on a
   surface colour, so no text lands on an accent and the AA interactive pair is
   not in play. It also matches .flow-terminal and .adm-important, so a focal
   mark reads the same wherever it appears.

   One focal element per diagram. Two erases the signal, which is what the
   builders' complexity budget warns about.
   ========================================================================== */

/* Pyramid / funnel */
.pyr-layer       { fill: var(--bg2); stroke: var(--line2); stroke-width: 1; }
.pyr-layer.focal { fill: var(--purple-bg); stroke: var(--accent); stroke-width: 1.5; }
.pyr-name        { fill: var(--text);  font-size: 14px; font-weight: 600; font-family: var(--font-ui); }
.pyr-sub         { fill: var(--text2); font-size: 11px; font-family: var(--font-ui); }
.pyr-note        { fill: var(--text3); font-size: 11px; font-weight: 600; font-family: var(--font-ui); }

/* Layer stack */
.layer-band       { fill: var(--bg2); stroke: var(--line2); stroke-width: 1; }
.layer-band.focal { fill: var(--purple-bg); stroke: var(--accent); stroke-width: 1.5; }
.layer-sep        { stroke: var(--line); stroke-width: 1; }
.layer-index      { fill: var(--text3); font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
                    text-transform: uppercase; font-family: var(--font-ui); }
.layer-name       { fill: var(--text);  font-size: 15px; font-weight: 600; font-family: var(--font-ui); }
.layer-sub        { fill: var(--text2); font-size: 11px; font-family: var(--font-ui); }
.layer-axis       { fill: var(--text3); font-size: 10px; font-weight: 600; letter-spacing: 0.08em;
                    text-transform: uppercase; font-family: var(--font-ui); }
.layer-axis-line  { stroke: var(--line2); stroke-width: 1; }
.layer-axis-head  { fill: var(--text3); }

/* Nested containment — stroke and fill step up together as scope narrows, so
   depth reads even in greyscale. */
.nest-ring        { fill: var(--bg2); stroke: var(--line); stroke-width: 1; }
.nest-ring.nest-d1{ fill: var(--bg3); }
.nest-ring.nest-d2{ fill: var(--bg4); stroke: var(--line2); }
.nest-ring.nest-d3{ fill: var(--bg4); stroke: var(--line2); }
.nest-ring.nest-d4{ fill: var(--bg4); stroke: var(--line2); }
.nest-ring.focal  { fill: var(--purple-bg); stroke: var(--accent); stroke-width: 1.5; }
.nest-label-bg    { fill: var(--chart-surface); }   /* knocks the ring's border out behind the label */
.nest-label       { fill: var(--text2); font-size: 10px; font-weight: 600; letter-spacing: 0.10em;
                    text-transform: uppercase; font-family: var(--font-ui); }
.nest-label.focal { fill: var(--accent2); }
.nest-sub         { fill: var(--text3); font-size: 11px; font-family: var(--font-ui); }

/* Venn — tints of one ink rather than three hues, so the overlaps darken by
   compounding and no region needs its own computed shape. Colour is not
   carrying identity here; position and label are. */
.venn-circle      { fill: var(--text); fill-opacity: 0.05; stroke: var(--line2); stroke-width: 1; }
.venn-s2          { stroke: var(--text3); }
.venn-s3          { stroke: var(--text2); }
.venn-set-label   { fill: var(--text);  font-size: 13px; font-weight: 600; font-family: var(--font-ui); }
.venn-set-sub     { fill: var(--text3); font-size: 11px; font-family: var(--font-ui); }
.venn-overlap     { fill: var(--text2); font-size: 11px; font-weight: 600; font-family: var(--font-ui); }
.venn-overlap.focal { fill: var(--accent2); font-size: 12px; }
