/* ============================================================================
   FDS MATURITY MAP — PAPER DESIGN SYSTEM (tokens.css)
   The operator's document: warm paper, ink body, bronze accents.
   Build-ready. Import this first; component CSS layers on top.

   Source of truth: canon/FDS-CANON.md v1.3 (brand tokens, motion canon),
   canon/10-DELIVERABLE-FORM-AND-DESIGN-DECISION-CARD.md (D3 surface=paper,
   D4 motion=guided-build). Every value below is locked, not invented.

   Two bronze ROLES max per beat (the §/0.x marker + one emphasis). Mixed WEIGHT
   is the contrast device, never color. Hairline-ruled tables are first-class.
   ============================================================================ */

/* ----------------------------------------------------------------------------
   1. FONT STACKS
   Self-host the three families (woff2) for board-print fidelity and offline
   governance copies. Variable fonts required for Fraunces (opsz + SOFT + wght)
   and Newsreader (opsz). IBM Plex Mono ships static weights.
   Replace url() paths with the build's asset pipeline output.
   ---------------------------------------------------------------------------- */

@font-face {
  font-family: "Fraunces";
  src: url("/fonts/Fraunces-VariableFont.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-stretch: 100%;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Fraunces";
  src: url("/fonts/Fraunces-Italic-VariableFont.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("/fonts/Newsreader-VariableFont.woff2") format("woff2-variations");
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("/fonts/Newsreader-Italic-VariableFont.woff2") format("woff2-variations");
  font-weight: 300 600;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/IBMPlexMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/IBMPlexMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/IBMPlexMono-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* ----------------------------------------------------------------------------
   2. ROOT CUSTOM PROPERTIES
   ---------------------------------------------------------------------------- */

:root {
  /* --- Palette (locked; from FDS-CANON brand tokens) --- */
  --paper:        #F7F4ED;   /* canvas */
  --paper-2:      #EFEAE0;   /* raised surfaces, cards */
  --paper-3:      #E5DECB;   /* deep raised / reference bands */
  --ink:          #1A1816;   /* body reading prose */
  --anchor:       #0A0A0A;   /* assertion, footer, head-rules, benchmark markers */
  --bronze-light: #C49156;   /* ASSIGNED ROLE (finding B1): benchmark reference-zone bands ONLY — non-text accent, a depth-step below --bronze-deep value bar. NEVER used for text. */
  --bronze:       #946834;   /* primary bronze role: §/0.x markers, mono labels (on --paper / --paper-2) */
  --bronze-deep:  #5E4118;   /* second bronze role: single emphasis per beat; ALSO mono labels on --paper-3 (finding M4: --bronze fails AA on the deeper band) */
  --rule:         rgba(10, 10, 10, 0.14);   /* hairline row-rules */
  --rule-strong:  rgba(10, 10, 10, 0.28);   /* head-rules where --anchor is too heavy */

  /* Semantic aliases — components reference these, not raw colors */
  --bg:            var(--paper);
  --bg-raised:     var(--paper-2);
  --bg-band:       var(--paper-3);
  --text:          var(--ink);
  --text-assert:   var(--anchor);
  --label:         var(--bronze);
  --label-on-band: var(--bronze-deep);  /* mono labels on --paper-3 surfaces, e.g. the NYC card (finding M4: ≥AA) */
  --emphasis:      var(--bronze-deep);
  --benchmark-mark: var(--anchor);   /* best-in-class marker on benchmark bullets (at the 0–5 rubric position, finding B1) */
  --value-bar:     var(--bronze-deep);  /* the client's value bar (finding B1: --bronze-deep so it sits a depth-step ABOVE the --bronze-light reference bands) */
  --bench-band:    var(--bronze-light); /* benchmark reference-zone bands — a depth-step below the value bar (finding B1) */
  --bench-capline: var(--bronze-deep);  /* the co-cap vertical line through ≥2 co-capping bars (finding B1) */

  /* Coverage glyphs (role-coverage table). The "absent" glyph is the HEADLINE datum
     and must look CHOSEN, not faded — ≥3:1 on --paper, never --rule-weight (finding M4). */
  --cov-present-formal:   var(--ink);          /* F — chartered role */
  --cov-present-informal: var(--ink);          /* i — performed without mandate */
  --cov-absent:           rgba(10, 10, 10, 0.55);  /* — absent; ≥3:1 on --paper (finding M4) */
  --cov-lapsed:           var(--bronze-deep);   /* i* — lapsed annotation */

  /* Severity (data idiom only — never decorative). Bronze-family + ink, no RYG.
     Severity must survive a two-second scan WITHOUT alarm color — carried by
     ENCLOSURE + rule weight + label step, not by tile color (findings H1 + M3). */
  --sev-critical:  var(--bronze-deep);   /* Critical findings (e.g. NYC) */
  --sev-stressed:  var(--bronze);        /* Stressed / Mismatch-addressable */
  --sev-workable:  var(--ink);           /* Workable / no flag */
  --sev-track:     var(--rule);          /* empty track behind a value bar */
  /* Pod-card enclosure: the single most-severe pod gets a full bounded card +
     heavier left-rule; non-critical pods drop to a top hairline only (findings H1 + M3). */
  --pod-rule-critical: 4px solid var(--bronze-deep);  /* heavier full left-rule, critical pod only */
  --pod-rule-minimal:  1px solid var(--rule);          /* top hairline only, non-critical pods */

  /* --- Type families --- */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-body:    "Newsreader", Georgia, "Times New Roman", serif;
  --font-mono:    "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* --- Type scale (rem; 1rem = 16px). Roles map to the ramp in the spec. --- */
  --t-hero:       clamp(2.75rem, 6vw, 4.25rem);  /* beat 1 structural finding */
  --t-beat-h:     clamp(2rem, 4vw, 2.75rem);     /* beat headline */
  --t-sub-h:      1.5rem;                         /* sub-section assertion */
  --t-lead:       1.375rem;                       /* lead paragraph / aside */
  --t-body:       1.0625rem;                      /* reading prose (17px) */
  --t-small:      0.9375rem;                      /* secondary prose */
  --t-mono-lg:    0.875rem;                        /* mono data, large */
  --t-mono:       0.75rem;                         /* mono labels (12px) */
  --t-mono-sm:    0.6875rem;                        /* table headers (11px) */

  /* --- Line heights --- */
  --lh-tight:     1.05;
  --lh-snug:      1.18;
  --lh-body:      1.62;
  --lh-mono:      1.4;

  /* --- Spacing scale (8px base; beats breathe) --- */
  --s-1:  0.25rem;
  --s-2:  0.5rem;
  --s-3:  0.75rem;
  --s-4:  1rem;
  --s-5:  1.5rem;
  --s-6:  2rem;
  --s-7:  3rem;
  --s-8:  4.5rem;
  --s-9:  7rem;     /* inter-beat rhythm */
  --measure: 38rem;   /* body reading measure (~66ch) — ragged right */

  /* --- Layout --- */
  --spine-w:      13rem;    /* left spine-nav rail width >=1020px */
  --content-max:  46rem;    /* narrative column max */
  --gutter:       clamp(1.25rem, 5vw, 4rem);

  /* --- Motion tokens (locked; FDS-CANON motion canon) --- */
  --ease:         cubic-bezier(0.16, 1, 0.3, 1);
  --d-50:   50ms;
  --d-150:  150ms;
  --d-200:  200ms;
  --d-300:  300ms;   /* the guided-build default */
  --d-400:  400ms;

  /* --- Borders / hairlines --- */
  --hair:    1px solid var(--rule);
  --hair-strong: 1px solid var(--anchor);
}

/* ----------------------------------------------------------------------------
   3. BASE ELEMENT STYLES
   ---------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  font-weight: 400;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  font-variation-settings: "opsz" 18;
}

/* Reading prose is ragged-right, NEVER justified (brand rule) */
p {
  max-width: var(--measure);
  text-align: left;
  text-wrap: pretty;
  margin: 0 0 var(--s-4);
}

/* Display headings — Fraunces. opsz matched to size; SOFT 0 for hard claims.
   wght carries contrast (mixed weight is the device). */
h1, h2, h3 {
  font-family: var(--font-display);
  color: var(--text-assert);
  margin: 0 0 var(--s-4);
  line-height: var(--lh-snug);
  letter-spacing: -0.005em;
  /* protect the loudest lines from a single-word last line (R06 — Jonas);
     balance equalises rag on short declarative headings. */
  text-wrap: balance;
}
h1 {
  font-size: var(--t-beat-h);
  font-weight: 600;
  line-height: var(--lh-tight);
  font-variation-settings: "opsz" 72, "SOFT" 0, "wght" 600;
}
h2 {
  font-size: var(--t-sub-h);
  font-weight: 560;
  font-variation-settings: "opsz" 36, "SOFT" 0, "wght" 560;
}
h3 {
  font-size: var(--t-lead);
  font-weight: 500;
  font-variation-settings: "opsz" 28, "SOFT" 12, "wght" 500;
}

a { color: var(--emphasis); text-decoration-thickness: 1px; text-underline-offset: 2px; }

/* ----------------------------------------------------------------------------
   4. MONO LABEL SYSTEM — §/0.x markers, all numbers, captions
   IBM Plex Mono, uppercase, 0.12–0.14em tracked, bronze.
   ---------------------------------------------------------------------------- */

.mono-label {
  font-family: var(--font-mono);
  font-size: var(--t-mono);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  color: var(--label);
  line-height: var(--lh-mono);
}

.mono-num {                 /* all numbers render in mono, by brand rule */
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  font-feature-settings: "tnum" 1;
}

.section-marker {           /* the §/0.x beat marker — primary bronze role */
  font-family: var(--font-mono);
  font-size: var(--t-mono);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--label);
  display: inline-block;
  margin-bottom: var(--s-3);
}

.caption {                  /* source captions, evidence attribution */
  font-family: var(--font-mono);
  font-size: var(--t-mono-sm);
  letter-spacing: 0.08em;
  color: color-mix(in srgb, var(--ink) 62%, transparent);
  text-transform: none;
}

/* The SOFT 100 italic accent — exactly once per beat (e.g. the hero aside) */
.accent-italic {
  font-family: var(--font-display);
  font-style: italic;
  font-variation-settings: "opsz" 40, "SOFT" 100, "wght" 380;
  color: var(--emphasis);
}

/* ----------------------------------------------------------------------------
   5. HAIRLINE-RULED TABLES — first-class data idiom
   11px mono uppercase headers · --anchor head-rule · --rule row-rules ·
   NO grid lines, NO zebra fill, NO vertical borders. Numbers tabular.
   ---------------------------------------------------------------------------- */

.hairline-table {
  width: 100%;
  border-collapse: collapse;
  margin: var(--s-5) 0;
  font-size: var(--t-small);
}
.hairline-table thead th {
  font-family: var(--font-mono);
  font-size: var(--t-mono-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-assert);
  text-align: left;
  padding: 0 var(--s-4) var(--s-2) 0;
  border-bottom: 1.5px solid var(--anchor);   /* anchor head-rule */
  vertical-align: bottom;
}
.hairline-table tbody td {
  padding: var(--s-3) var(--s-4) var(--s-3) 0;
  border-bottom: var(--hair);                 /* rule row-rules only */
  vertical-align: top;
}
.hairline-table tbody tr:last-child td { border-bottom: none; }
.hairline-table .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; padding-right: 0; }
.hairline-table caption {
  caption-side: top;
  text-align: left;
  font-family: var(--font-mono);
  font-size: var(--t-mono-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--label);
  padding-bottom: var(--s-3);
}

/* ----------------------------------------------------------------------------
   6. GUIDED-BUILD UTILITY — IntersectionObserver .build / .built pattern
   A visual assembles ONCE on first viewport entry because the build teaches
   structure. No re-trigger, no scrub, no pin. The JS observer adds .built once.
   reduced-motion: skip the build, show final (the .built end-state).
   ---------------------------------------------------------------------------- */

/* Default (pre-entry) state of a buildable element — the "unbuilt" pose.
   Components define WHAT builds (bar grows, line draws, cap snaps) by overriding
   these vars; the timing + trigger live here. */
.build {
  --build-dur: var(--d-300);
  --build-ease: var(--ease);
}

/* Bars / fills: scale from 0 to value along the inline axis */
.build .build-grow {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--build-dur) var(--build-ease);
}
.build.built .build-grow { transform: scaleX(1); }

/* Stroke draw-on (SVG paths): pathLength normalized to 1 */
.build .build-draw {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset var(--build-dur) var(--build-ease);
}
.build.built .build-draw { stroke-dashoffset: 0; }

/* Snap (the composite cap dropping into place): opacity + small translate */
.build .build-snap {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--d-200) var(--build-ease),
              transform var(--d-200) var(--build-ease);
}
.build.built .build-snap { opacity: 1; transform: none; }

/* Fade markers (benchmark marker, reference bands) in after the bar lands */
.build .build-fade {
  opacity: 0;
  transition: opacity var(--d-200) var(--build-ease) var(--d-150);
}
.build.built .build-fade { opacity: 1; }

/* No-JS: the IntersectionObserver never runs, so resolve every buildable to its
   final pose — mirrors the .section-rule / .stat-line no-JS fallbacks. Without
   this a no-JS visitor sees blank figure boxes; draw-on never completes (R04). */
html:not(.js) .build .build-grow { transform: scaleX(1); }
html:not(.js) .build .build-draw { stroke-dashoffset: 0; }
html:not(.js) .build .build-snap,
html:not(.js) .build .build-fade { opacity: 1; transform: none; }

/* True hairlines on HiDPI: a logical 1px maps to 2–3 device px and reads heavier
   than designed; 0.5px renders one device row on 2×+ screens (R04 — Jonas). */
@media (min-resolution: 2dppx) {
  :root { --hair: 0.5px solid var(--rule); }
}

/* ----------------------------------------------------------------------------
   7. REDUCED MOTION — skip the build, resolve to final. BANNED motion stays off.
   ---------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .build .build-grow { transform: scaleX(1); transition: none; }
  .build .build-draw { stroke-dashoffset: 0; transition: none; }
  .build .build-snap { opacity: 1; transform: none; transition: none; }
  .build .build-fade { opacity: 1; transition: none; }
  * { scroll-behavior: auto !important; }
}

/* ----------------------------------------------------------------------------
   8. FOCUS / A11Y BASELINE — real buttons get real focus rings.

   [REVISION — finding M4] Contrast build-decisions encoded in the tokens above:
   - --cov-absent ≥3:1 on --paper (the headline datum looks chosen, not faded);
   - mono labels on --paper-3 use --label-on-band (--bronze-deep), never --bronze;
   - spine-nav inactive links render solid --bronze (≥AA), not a faded variant;
   - --bronze-light is a non-text band accent ONLY (never text).
   Behavior (in component JS, not CSS): the evidence popover returns focus to its
   trigger on click-outside close, mirroring Esc (finding M4).
   ---------------------------------------------------------------------------- */

:focus-visible {
  outline: 2px solid var(--bronze-deep);
  outline-offset: 2px;
  border-radius: 1px;
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Buttons reset to paper-native; component CSS styles affordances */
button {
  font: inherit; color: inherit; background: none; border: none;
  cursor: pointer; padding: 0; text-align: left;
}

/* ----------------------------------------------------------------------------
   9. PRINT / GOVERNANCE VIEW — the board leave-behind.
   Build-states resolve to final; popovers become numbered footnotes (component
   CSS handles the footnote rendering); spine-nav + lens control hidden; clean
   pagination. The LINK is the deliverable; this is the record.
   ---------------------------------------------------------------------------- */

@media print {
  :root { --bg: #FFFFFF; }              /* true white for toner economy */
  body { font-size: 11pt; line-height: 1.5; background: #fff; }
  .spine-nav, .lens-control, .topbar-nav, [data-print="hide"] { display: none !important; }

  /* All build elements resolve to final */
  .build .build-grow { transform: scaleX(1) !important; }
  .build .build-draw { stroke-dashoffset: 0 !important; }
  .build .build-snap, .build .build-fade { opacity: 1 !important; transform: none !important; }

  /* Interactive states resolve to their default/final rendering */
  [data-interactive] { pointer-events: none; }

  .beat { break-inside: avoid-page; }
  h1, h2, h3 { break-after: avoid; }
  .hairline-table { break-inside: avoid; }
  figure, .scorecard, .incident-card { break-inside: avoid; }

  /* Evidence popovers print as numbered footnotes (see component inventory) */
  .evidence-trigger[data-footnote]::after {
    content: " [" attr(data-footnote) "]";
    font-family: var(--font-mono);
    font-size: 0.8em;
    vertical-align: super;
  }
  .evidence-popover { display: none !important; }
  .footnote-ledger { display: block !important; }

  a { color: inherit; text-decoration: none; }
}
