/* ============================================================================
   CetusEd public site — TYPE (three roles, not one)
   Ledger item P0-2 · Spec: Addendum A Part B "Type v2" + Part A items 2 and 3
   ----------------------------------------------------------------------------
   THE FIX THIS FILE EXISTS FOR. The current site emphasises the second clause of
   every headline by tinting it teal — thirty-four times. Addendum A Part A item 2
   calls the typeface switch "the single most transferable idea in the reference,
   and the exact fix for CetusEd's worst habit": swap the FACE for two or three
   words instead. It is more distinctive, works in monochrome, survives
   colourblindness, and does not require the headline to be split into two clauses
   — which was the structural cause of the em-dash problem (base audit §3.8).

   ⛔ USE THE MONO FACE AS THE HIGHLIGHT, never a handwritten face (wrong register
   for a compliance product). A monospaced fragment inside a display headline reads
   as a citation, a code, a term of art — native to this subject. It carries
   emphasis, tone and information in one move.

   ⛔ THE NO-BOLD RULE (Addendum A Part A item 3). Weights are restricted to 400
   and 500. There is no 700 anywhere on this site. Emphasis comes from SIZE,
   TRACKING and FACE SELECTION. This forces real hierarchy instead of letting
   weight paper over its absence.

   ⛔ SENTENCE CASE THROUGHOUT. Every letterspaced 10px uppercase kicker is
   deleted (base audit Part Seven); kickers become § numbers or mono labels.

   ── TYPEFACE STATUS (ledger A-TYPE, founder-owned) ─────────────────────────
   Shipping the FREE STACK, which Addendum A specifies as a legitimate ship.
   All three are on Google Fonts, which _headers ALREADY allow-lists for the
   marketing paths (style-src + font-src) — so this needs no CSP edit and no
   asset-tracking work (ledger C13, C6).

   ⚠ DISPLAY FACE CHANGED 2026-08-13. Familjen Grotesk shipped first and the
   founder's read was that the site looked generic. That was a fair call: it is a
   competent neutral grotesk with little character, and the base audit's OWN free
   recommendation was Bricolage Grotesque — "variable, has real character".
   Bricolage is an optical-size variable face, so the display sizes get genuinely
   different letterforms rather than one drawing scaled up, which is most of what
   distinguishes a designed page from a templated one.

   SWAPPING TO THE COMMERCIAL STACK IS STILL A TOKEN CHANGE, not a refactor:
   replace the three --f-* values below and the @import. Addendum A's
   recommendation is Beatrice (Sharp Type) display · Inter text · Berkeley Mono
   data, and it calls the licence the highest-impact non-code purchase available.

   ⚠ IF SELF-HOSTING LATER: every font file must be git-tracked or
   lint-published-asset-tracked fails the build (ledger C6). Self-hosting is
   preferred long-term — it removes the last third-party dependency on the
   marketing pages — but it is not a blocker for the build.
   ========================================================================= */

/* ⛔ THE @import THAT WAS HERE IS NOW A <link> IN THE DOCUMENT HEAD.
   A CSS @import inside a LINKED stylesheet is not discovered until that sheet
   has been fetched and parsed, so the font request was two round trips behind
   the HTML instead of one. Every page therefore painted in system-ui first and
   swapped — which is a large part of why the type read as fragmented: the
   display tracking below is set for Bricolage Grotesque and looks wrong on the
   fallback, so the first paint was a different typeface at the wrong spacing.

   shell.js now emits preconnect hints and the stylesheet link in the head, so
   the request starts on the first parse. The CSP already allows both hosts
   (style-src fonts.googleapis.com, font-src fonts.gstatic.com) — this was never
   a permissions problem, only a discovery-order one. */

:root {
  --f-display: 'Bricolage Grotesque', 'Familjen Grotesk', 'Schibsted Grotesk', system-ui, sans-serif;
  --f-text:    'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --f-data:    'JetBrains Mono', 'Commit Mono', 'Martian Mono', ui-monospace, 'Cascadia Mono', monospace;

  /* ── DISPLAY SCALE — five steps, fluid, clamp()-based ────────────────────
     ⛔ NEVER scale root font-size by vw. There is a widely-copied
     `html { font-size: 1.1vw }` snippet for 4K; it breaks user zoom and is a
     WCAG failure (Addendum A Part E). clamp() with rem minimums instead. */
  --d1: clamp(2.5rem,  5vw,    5.5rem);   /* hero / threshold statement */
  --d2: clamp(2rem,    3.6vw,  3.5rem);   /* page opener */
  --d3: clamp(1.6rem,  2.4vw,  2.25rem);  /* section head */
  --d4: clamp(1.3rem,  1.7vw,  1.6rem);   /* sub-section */
  --d5: clamp(1.1rem,  1.3vw,  1.25rem);  /* smallest display use */

  /* ── TEXT SCALE — three steps ───────────────────────────────────────────── */
  --t-lead: clamp(1.06rem, 1.15vw, 1.22rem);  /* lead paragraph, max 3 lines */
  --t-body: 1rem;
  --t-small: 0.875rem;

  /* ── DATA SCALE — mono ───────────────────────────────────────────────────── */
  --m-body:  0.9375rem;
  --m-small: 0.8125rem;
  --m-tick:  0.6875rem;   /* plate coordinate ticks, axis labels */
}

/* ── BASE ─────────────────────────────────────────────────────────────────── */
body {
  font-family: var(--f-text);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ── DISPLAY ──────────────────────────────────────────────────────────────
   Large sizes, sparingly. No colour changes inside a headline — that is the
   habit being replaced. Tracking tightens as size grows. */
.d1, .d2, .d3, .d4, .d5 {
  font-family: var(--f-display);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.02em;
  text-wrap: balance;
  margin: 0;
}
/* ⛔ OPENED UP. -0.038em at hero size closes the counters — the enclosed
   space inside a, e, o — and a headline whose letters are touching reads as
   one dense mass rather than as words, which is the fragmentation complaint
   at the largest size on the page. The optical-size axis is already doing the
   tightening that a display face needs; the manual tracking was doubling it.
   Roughly halved at every step, keeping the same voice. */
.d1 { font-size: var(--d1); letter-spacing: -0.020em; line-height: 1.00; font-variation-settings: 'opsz' 96; }
.d2 { font-size: var(--d2); letter-spacing: -0.016em; font-variation-settings: 'opsz' 64; }
.d3 { font-size: var(--d3); letter-spacing: -0.012em; font-variation-settings: 'opsz' 40; }
.d4 { font-size: var(--d4); letter-spacing: -0.016em; line-height: 1.2; font-variation-settings: 'opsz' 24; }
.d5 { font-size: var(--d5); letter-spacing: -0.012em; line-height: 1.3; font-variation-settings: 'opsz' 18; }

/* ⛔ THE EMPHASIS MECHANISM — WEIGHT, NOT FACE.

   THIS RULE USED TO SWITCH TO THE MONO FACE, and it was on the h1 of all ten
   deck pages — every headline on the site. Rendered, "the paperwork around it
   does not" put JetBrains Mono at 55px inside Bricolage at 64px. JetBrains Mono
   is a CODE face; in a marketing headline it does not read as emphasis, it
   reads as a terminal fragment spliced into a sentence. That is the most
   literal possible instance of "the font choices render fragmented", at the
   largest size on the page, ten times over.

   ⛔ It is also the thing a numeric check cannot see. The mono census I ran
   during the type pass counted .tick / .cite / .cue / .label and reported 1–3
   fragments per page. .hl was not in it, so the biggest member of the class was
   invisible to the instrument measuring the class. It took a screenshot.

   Emphasis now comes from WEIGHT in the same face — 500 against 400 — which
   keeps one typographic voice per headline. ⛔ NOT COLOUR: tinting the second
   clause of every headline is the exact habit this design system was built to
   replace (see the semantic-accent block in cetus-site.css), and an accent here
   would also collide with the meaning those accents carry.

   <h1 class="d1">One record, from a first-grade teacher's concern to a
     <span class="hl">transition plan</span>.</h1>                            */
.hl {
  font-weight: 500;
}

/* ── TEXT ─────────────────────────────────────────────────────────────────── */
.lead { font-size: var(--t-lead); line-height: 1.5; max-width: 58ch; }
p     { max-width: var(--w-reading); }
.small { font-size: var(--t-small); }

/* ── DATA / MONO ──────────────────────────────────────────────────────────
   ⛔ TABULAR FIGURES ARE MANDATORY. Every WAC/RCW/IDEA citation, every date,
   every day count, every ID, every status, every axis label and every table
   figure is set in this face with tnum on. Addendum A Part B: this alone will
   read as authored-by-someone-who-does-this-work.

   The reason it is not merely cosmetic: a deadline table whose digits do not
   align cannot be scanned down a column, and scanning down the column is the
   entire reason the table exists. */
.mono, .cite, .figure, code, th, td.num {
  font-family: var(--f-data);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: 'tnum' 1, 'lnum' 1;
  font-weight: 400;
}
.mono  { font-size: var(--m-body); }
.cite  { font-size: var(--m-small); letter-spacing: -0.01em; }
.tick  { font-family: var(--f-data); font-size: var(--m-tick);
         font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }

/* ── § SECTION NUMBERS — the spine (Addendum A Part A item 4) ──────────────
   Chapter numbering is the structural mechanism that lets a dense site feel
   navigable rather than long. Replaces every letterspaced uppercase kicker. */
.sec-n {
  font-family: var(--f-data);
  font-size: var(--m-small);
  font-variant-numeric: tabular-nums;
  color: var(--star-dim);
  letter-spacing: 0.04em;
}
/* ⛔ --text-ink-lo MEASURED 3.32:1 HERE, UNDER THE 4.5 AA FLOOR.
   .sec-n is a figcaption class and a figcaption is the NAME of a plate — the
   one line telling a reader what they are looking at — so a dim treatment is
   wrong on the merits as well as on the number. It went unnoticed because the
   a11y gate's contrast selector listed p / li / dd / dt / td / th / h1-h3 and
   never included figcaption; widening that selector found this on its first
   run, on a plate that had been shipping for weeks. */
.g-chart .sec-n, .g-chart-soft .sec-n { color: color-mix(in srgb, var(--text-ink) 78%, transparent); }

/* ── WEIGHT GUARD ─────────────────────────────────────────────────────────
   The no-bold rule made mechanical. <strong> and <b> are semantic and must stay
   semantic — they get the 500 step, never 700. If a design needs more emphasis
   than this gives, the answer is size or the mono switch, not weight. */
strong, b, th { font-weight: 500; }

/* ── LINKS ────────────────────────────────────────────────────────────────
   Underline is the affordance. Accent colour is NOT available here: every accent
   in tokens.css means exactly one thing, and "this is a link" is not one of them
   (ledger C-semantic rule). Links carry a --star underline that brightens. */
a { color: inherit; text-decoration-line: underline; text-decoration-thickness: 1px;
    text-underline-offset: 0.22em; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); }
a:hover { text-decoration-color: currentColor; }

/* ══ WIDOWS AND ORPHANS ═══════════════════════════════════════════════════
   Founder 2026-08-16: "some of the text isn't wrapping correctly, like the
   clocks where it says 'screen says district policy' pushed the word district
   and policy each on their own row."

   Measured across 11 pages at three viewports: 59 text elements whose LAST
   rendered line held 4-16% of the widest line — one or two words alone on a
   row. Measured with Range.getClientRects(), which is the only way to see
   where the browser actually broke a line rather than where the markup does.

   ⭐ text-wrap DOES apply here even though split.js rewrites these elements.
   The splitter groups words by offsetTop — it READS the browser's line breaks
   rather than deciding them — so improving the break improves what it reads.
   Had it computed its own breaks this rule would have been inert, which is
   worth checking before reaching for it in another codebase.

   `pretty` for prose: the browser reflows the last few lines to avoid a
   single-word final row. `balance` for headings: evens all lines, which is
   what a two- or three-line display line wants and is capped at ~6 lines by
   the spec, so it is wrong for body copy.
   ⚠ Both degrade to normal wrapping where unsupported — no fallback needed
   and none pretended. */
h1, h2, h3, .d0, .d1, .d2, .d3, .d4, .hero-h, .prov-h, .shot-hd {
  text-wrap: balance;
}
p, li, dd, dt, figcaption, .lead, .lede, .small, .fig-l, .chain-title, .v-text,
.cap-what, .prov-what, .doc-d {
  text-wrap: pretty;
}
