/* ============================================================================
   SAVOY DRUGSTORE — base.css
   Reset, document defaults, the type roles as real elements and classes, the
   container/grid utilities, the section grounds, and the motion floor.

   Loads AFTER tokens.css and BEFORE components.css.
   No raw colours, no off-lattice space: every value here is a custom property
   from tokens.css (DESIGN_SPEC §10.33 / §10.34).

   ── THIS WHOLE FILE IS `@layer base` ──────────────────────────────────────
   tokens.css declares `@layer base, components, figures;`. Everything below is
   the FLOOR: element defaults and type roles that any component or section is
   entitled to overrule by ordinary specificity. Before the layer existed these
   element selectors outranked every component rule applied to the same element
   (an unlayered declaration beats any layered one), and components.css had to
   carry a hand-maintained `revert-layer` patch list to hand each property back
   one at a time — a list that could only ever be one component behind. The
   layer replaces the list entirely.
   The `!important` reduced-motion guard at the end is unaffected: an important
   declaration in an earlier layer still wins.
   ========================================================================= */

@layer base {

/* ============================================================================
   0.  RESET
   ========================================================================= */

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

/* §5 / §10.4 — border-radius is 0 on every HTML element, without exception.
   Circles exist only as SVG <circle> in authored artwork. Declared at zero
   specificity so it is a floor, not a fight: anything that sets a radius is
   overriding a decree and will be caught in review. */
*,
*::before,
*::after { border-radius: 0; }

/* §10.5 — the only permitted box-shadows are `inset 0 0 0 1px` (a border that
   does not affect layout) and `inset 0 1px 0` (the dark-band top light).
   Any drop shadow is a rejection. There is nothing to reset here; this note
   exists so the rule is visible where authors look for it. */

html,
body { height: auto; }

body,
h1, h2, h3, h4, h5, h6,
p, figure, figcaption, blockquote,
dl, dd, ol, ul,
fieldset, legend { margin: 0; padding: 0; }

ol, ul { list-style: none; }

img, svg, video, canvas, picture { display: block; max-width: 100%; }
img, video { height: auto; }

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

button, input, select, textarea, optgroup {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  margin: 0;
}

button {
  background: none;
  border: 0;
  padding: 0;
  text-align: inherit;
  cursor: pointer;
  -webkit-appearance: none;
          appearance: none;
}

button::-moz-focus-inner { border: 0; padding: 0; }

textarea { resize: vertical; }

table { border-collapse: collapse; border-spacing: 0; }

/* §2.6 — every rule on this site is 1px. */
hr {
  border: 0;
  height: var(--rule-w);
  background: var(--ln-hair);
  margin: 0;
}

abbr[title] { text-decoration: none; }

[hidden] { display: none !important; }


/* ============================================================================
   1.  DOCUMENT DEFAULTS
   ========================================================================= */

html {
  /* §3.6 — tabular lining figures GLOBALLY, so no number ever changes width. */
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;

  -webkit-text-size-adjust: 100%;
          text-size-adjust: 100%;
  scroll-behavior: smooth;

  /* `clip` (not `hidden`) so descendant `position: sticky` keeps working. */
  overflow-x: clip;
}

body {
  background: var(--sf-page);
  color: var(--tx-body);

  /* §3.1 — Pagella is the voice: all display type AND all editorial body.
     Heros (--f-ui) is opted into by form controls and nav, never inherited. */
  font-family: var(--f-display);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  font-weight: 400;

  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* §8.2 — the nav reserves --nav-h; every in-page anchor clears it. */
[id] { scroll-margin-top: calc(var(--nav-h) + var(--s5)); }

/* §2.4 — --royal-tint is the selection wash. Legible over paper AND night. */
::selection {
  background: var(--royal-tint);
  color: var(--ink);
}

/* §6.4 — one focus ring, everywhere. §10.38: no interactive element without it.
   `.is-focus` is the specimen sheet's documentation hook: site/kit.html has to
   PRINT the focus state statically and carries no CSS of its own, so it borrows
   this rule rather than restating the ring. Never ship it in a page. */
:focus-visible,
.is-focus {
  outline: var(--focus-w) solid var(--ac-identity);
  outline-offset: var(--focus-offset);
}
:focus:not(:focus-visible) { outline: none; }


/* ============================================================================
   2.  §3.2  THE TYPE ROLES
   Every role exists twice: as the element default a section gets for free, and
   as a `.t-*` class so any role can be applied to any element (a hero H1 needs
   --t-d1, a minor H2 needs --t-d4, §4.5.4 requires adjacent sections to
   alternate). Size, leading and tracking always travel together.
   ========================================================================= */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--f-display);
  font-weight: 400;
  color: var(--tx-display);
  /* §3.3 — balance every heading of ≤4 lines. */
  text-wrap: balance;
  hyphens: none;
  overflow-wrap: normal;
}

/* Page H1, inner pages. The hero H1 adds .t-d1. */
h1 { font-size: var(--t-d2); line-height: var(--lh-d2); letter-spacing: var(--tr-d2); --roman-fs: var(--t-d2); }
/* Section H2, major. A minor H2 adds .t-d4. */
h2 { font-size: var(--t-d3); line-height: var(--lh-d3); letter-spacing: var(--tr-d3); --roman-fs: var(--t-d3); }
/* Row / step title. */
h3 { font-size: var(--t-h3); line-height: var(--lh-h3); letter-spacing: var(--tr-h3); --roman-fs: var(--t-h3); }
/* Sub-head / card title. */
h4 { font-size: var(--t-h4); line-height: var(--lh-h4); letter-spacing: var(--tr-h4); --roman-fs: var(--t-h4); }
/* No h5/h6 role exists in the scale. They inherit h4's role so a document that
   needs the outline depth stays typographically legal. */
h5, h6 { font-size: var(--t-h4); line-height: var(--lh-h4); letter-spacing: var(--tr-h4); --roman-fs: var(--t-h4); }

/* Every display role publishes --roman-fs, the size an italic voice clause
   must measure itself against (§3.4). See §4 below. */
/* --lh-d1 ships at .88 rather than §3.2's .86 because .86 collides two lines of
   Pagella by construction (tokens.css §3.2). The .02em difference is bought
   back OPTICALLY rather than typographically: a negative block margin of half
   that difference at each end puts the lockup's outer edges exactly where a .86
   setting would have put them, so the block sits on the same lattice as the
   spec's numbers while its lines keep the leading the face can actually hold.
   Only the hero tier carries it — it is the only tier §3.2 leads under .90. */
.t-d1    { font-family: var(--f-display); font-weight: 400; font-size: var(--t-d1);     line-height: var(--lh-d1);     letter-spacing: var(--tr-d1);     color: var(--tx-display); --roman-fs: var(--t-d1); margin-block: -.04em; }
.t-d2    { font-family: var(--f-display); font-weight: 400; font-size: var(--t-d2);     line-height: var(--lh-d2);     letter-spacing: var(--tr-d2);     color: var(--tx-display); --roman-fs: var(--t-d2); }
.t-d3    { font-family: var(--f-display); font-weight: 400; font-size: var(--t-d3);     line-height: var(--lh-d3);     letter-spacing: var(--tr-d3);     color: var(--tx-display); --roman-fs: var(--t-d3); }
.t-d4    { font-family: var(--f-display); font-weight: 400; font-size: var(--t-d4);     line-height: var(--lh-d4);     letter-spacing: var(--tr-d4);     color: var(--tx-display); --roman-fs: var(--t-d4); }
.t-h3    { font-family: var(--f-display); font-weight: 400; font-size: var(--t-h3);     line-height: var(--lh-h3);     letter-spacing: var(--tr-h3);     color: var(--tx-display); --roman-fs: var(--t-h3); }
.t-h3-s  { font-family: var(--f-display); font-weight: 400; font-size: var(--t-h3-s);   line-height: var(--lh-h3-s);   letter-spacing: var(--tr-h3-s);   color: var(--tx-display); --roman-fs: var(--t-h3-s); }
.t-h4    { font-family: var(--f-display); font-weight: 400; font-size: var(--t-h4);     line-height: var(--lh-h4);     letter-spacing: var(--tr-h4);     color: var(--tx-display); --roman-fs: var(--t-h4); }
.t-fig   { font-family: var(--f-display); font-weight: 400; font-size: var(--t-fig);    line-height: var(--lh-fig);    letter-spacing: var(--tr-fig);    color: var(--ac-identity); }
.t-lede  { font-family: var(--f-display); font-weight: 400; font-size: var(--t-lede);   line-height: var(--lh-lede);   letter-spacing: var(--tr-lede);   color: var(--tx-body); }
.t-body  { font-family: var(--f-display); font-weight: 400; font-size: var(--t-body);   line-height: var(--lh-body);   letter-spacing: var(--tr-body);   color: var(--tx-body); }
.t-ui    { font-family: var(--f-ui);      font-weight: 400; font-size: var(--t-ui);     line-height: var(--lh-ui);     letter-spacing: var(--tr-ui);     color: var(--tx-display); }
/* THERE IS NO `.t-body-s`. See tokens.css §3.2: lede / body / body-s / ui were
   four declared tiers inside a 5.8px band, and two of them sat in the 12–16px
   band §3.1 declares empty. The editorial ramp is lede → body → (form) ui, and
   everything that used to reach for body-s now sets body. */


/* ============================================================================
   3.  §3.3  EDITORIAL PARAGRAPH RULES
   ========================================================================= */

p {
  font-size: var(--t-body);
  line-height: var(--lh-body);
  color: var(--tx-body);

  /* Measure 46–62ch; hard ceiling 64ch. A section may tighten this by setting
     --measure on an ancestor; it may never exceed --measure-max. */
  max-width: min(var(--measure), var(--measure-max));

  /* §3.3 / §10.22 — the browser may NEVER hyphenate, and a hyphenated compound
     breaks only at a space.
     `hyphens: none` alone does not deliver that: it suppresses the hyphens the
     BROWSER would insert, and says nothing about the break opportunity that
     already exists after a U+002D the author typed. Measured at 390 the guard
     let `--t-` / `xl`, `DATA-` / `REVEAL-STAGGER` and `--` / `E-WIPE` all break,
     with two of the three lines ending on a bare hyphen (§10.21, §10.22).
     `word-break: keep-all` removes that opportunity, which is the outcome the
     rule was written to produce. Real word-spaces are untouched. */
  hyphens: none;
  -webkit-hyphens: none;
  overflow-wrap: normal;
  word-break: keep-all;

  /* §3.3 / §10.23 — pretty resolves most one-word widows and short last lines. */
  text-wrap: pretty;

  /* §3.3 — no justification, ever. Ragged right only. */
  text-align: left;
}

/* The opening editorial paragraph of a section. Also the drop-cap host (§3.7).

   §3.3 IS A CEILING ON THE MEASURE, NOT ON THE FONT SIZE, AND IT HAS TO BE
   ENFORCED BY THE TIER RATHER THAN BY EVERY AUTHOR.
   `.t-lede` is set at ~18.7px in a grid cell that can be 730px wide, which is
   83 characters a line — nineteen over §3.3's hard ceiling of 64 and twenty-one
   over the top of its 46–62 band. Measured across the homepage before this
   rule: hero 83ch, overview drop-cap 83ch, partnerships 81ch, philosophy 77ch,
   services 74ch, assessment 67ch — six rejections from one missing declaration.
   The cap lives on the tier so a lede is 62ch wherever it is placed, and the
   column it sits in keeps whatever surplus it has as a deliberate rag. */
.lede,
.t-lede {
  font-size: var(--t-lede);
  line-height: var(--lh-lede);
  letter-spacing: var(--tr-lede);
  color: var(--tx-body);
  max-width: min(100%, var(--measure));
}
/* The drop-capped opening paragraph reads one notch narrower (see
   --measure-drop): the initial occupies its own first three lines. */
.lede { max-width: min(100%, var(--measure-drop)); }

/* §3.3'S MEASURE FLOOR WINS AT 390, AND SOMETHING HAS TO GIVE FOR IT TO.
   The column a 390 viewport offers is 348px. §3.3 asks every editorial
   paragraph for 46–62 characters per line; §3.1 keeps every editorial tier at
   or above 16px. 46ch in 348px needs 15.9px, so at this width the lede tier and
   the measure rule cannot both be honoured — and the rule that matters to a
   reader is the measure. Below 560px, therefore, the lede IS the body tier: the
   opening paragraph is told apart by its drop cap, its leading and its position
   — which is how a printed page does it — rather than by 1.4px of size that
   costs it ten characters a line. Above 560 the 1.27 step is untouched. */
/* THE TIER MOVES FROM SIZE TO LEADING — IT IS NOT DELETED.
   Merging the lede into --t-body and keeping --lh-lede (1.62) left the opening
   paragraph the same size as body AND set 0.6px tighter than it: five of the
   six ledes on the homepage carry no drop cap, so at 390 they had no
   typographic entry point at all. The measure still wins the size argument
   (above); the tier survives in the axis that is free — leading. */
@media (max-width: 559px) {
  .t-lede,
  .lede {
    font-size: var(--t-body);
    line-height: var(--lh-lede-sm);
  }
}

/* `small` is a semantic de-emphasis, not a size tier: with --t-body-s deleted
   it sets the body size and takes its quietness from colour and context. The
   two places that genuinely need a smaller mark — a ledger's sub-caption, a
   figure's licence line — set the MICRO tiers explicitly (§3.2 m3 / m4), which
   is the jump §3.1 calls the hierarchy. */
small,
.t-small {
  font-size: var(--t-body);
  line-height: var(--lh-body);
}

/* ── THE ANNOTATION NOTE ────────────────────────────────────────────────────
   §3.5 built the micro tiers for LABELS of a few words. Tracked uppercase at
   10.5px / .15em / 1.3 is unreadable as running prose, and a five- to
   eight-line block of it reads as console output pasted into the layout — the
   one place on a sheet where nothing looks composed.
   So the system owns a composed long-annotation form, and the rule is
   mechanical: a micro-label runs to TWO LINES; anything longer is a `.note` —
   Pagella at the small editorial size, micro colour, a 46ch measure. Same
   information, set as type rather than as a caps string. */
.note {
  /* §3.3's ceiling, not its floor. A note is an ANNOTATION, and 46ch was the
     right measure for one standing in a 30ch margin — but the same class also
     annotates a figure inside a 733px grid cell and a section head inside a
     663px column, and there it left 200–400px of blank paper to its right on
     every row it appeared in, which stacked into the vertical channels §4.6
     measures. `min(100%, 64ch)` keeps the narrow case exactly as it was (the
     column is the cap) and lets the wide case fill to the hard ceiling §3.3
     sets for any paragraph on this site. */
  max-width: min(100%, var(--measure-max)); /* 64ch, §3.3's hard ceiling */
  font-family: var(--f-display);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  letter-spacing: var(--tr-body);
  color: var(--tx-micro);
  text-wrap: pretty;
  hyphens: none;
  -webkit-hyphens: none;
  overflow-wrap: normal;
  word-break: keep-all;
}
* + .note { margin-top: var(--s3); }
.note + .note { margin-top: var(--s2); }

/* §3.3 — emphasis is Pagella italic at one shade darker than the body. */
em,
i,
cite {
  font-style: italic;
  color: var(--tx-display);
}

/* §3.3 — BOLD BODY TEXT IS BANNED. Pagella bold appears nowhere in running
   copy, so a stray <strong>/<b> inside a paragraph is coerced to the legal
   emphasis form rather than silently breaking the type system. */
p strong, p b,
li strong, li b,
dd strong, dd b {
  font-weight: 400;
  font-style: italic;
  color: var(--tx-display);
}

/* §3.3 — the no-break span. Known compounds: in-house, end-to-end, clinic-only,
   professional-use, Follow-Up, B2B, 18–35, MOHAP, No. 61109. */
.nb { white-space: nowrap; }

/* §8.4 — inline text links: royal, no rest underline, 1px underline wipes in
   from the left on hover. On dark grounds --ac-identity is already --beam. */
p a,
li a,
dd a,
.link {
  color: var(--ac-identity);
  background-image: linear-gradient(var(--ac-identity), var(--ac-identity));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0 var(--rule-w);
  text-underline-offset: .18em;
  transition: background-size var(--t-m) var(--e-wipe);
}
p a:hover, p a:focus-visible,
li a:hover, li a:focus-visible,
dd a:hover, dd a:focus-visible,
.link:hover, .link:focus-visible,
.link.is-hover { background-size: 100% var(--rule-w); }   /* kit hook, see §1 */

blockquote {
  font-family: var(--f-display);
  color: var(--tx-display);
}


/* ============================================================================
   4.  §3.4  THE ITALIC VOICE CLAUSE — the signature device.
   A subordinate clause of a heading, Pagella italic in royal, stepped right
   from the roman line above it.

   THE RATIO IS ENFORCED BY THE SYSTEM, NOT BY THE AUTHOR.
   §3.4 fixes a RELATIONSHIP — `voice ≤ 0.46 × roman` — and calls any larger
   ratio "the 'two serifs in one headline' defect … a rejection". An absolute
   size token cannot hold a relationship: the published clamp measured 0.46
   against a d1 roman and 0.72 / 0.93 against a d3 / d4 one, so every heading
   tier below the hero rendered a clause the same size as the line it modifies.

   So: every display role in §2 above publishes `--roman-fs`, and the clause
   multiplies it by `--ratio-voice`. Two authoring forms, both automatic:

     (a) SIBLING — the clause follows its heading inside one block:
           <div class="head">
             <h2>Licensing &amp; Compliance</h2>
             <span class="voice">Built on Trust &amp; Regulatory Excellence</span>
           </div>
         The `:has()` rules below publish the heading's size onto that block,
         so the clause inherits it. A block may hold one display line.

     (b) NESTED — the clause is inside the heading:
           <h1 class="t-d1">Regulatory Excellence<span class="voice">…</span></h1>
         Nothing extra is needed: the heading sets --roman-fs on itself.

   If a `.voice` is authored with no display line to read, it falls back to
   --roman-fs's :root value (the major H2) rather than to an arbitrary size.
   Resolved sizes at 1440: d1 → 53.0 · d2 → 40.5 · d3 → 32.4 · d4 → 25.0.

   Still the author's to police: at most ONCE per section, FOUR times per
   page (§10.31).
   ========================================================================= */

/* (a) — a block that contains one display line publishes that line's size.
   Direct-child only, so the section element never claims it and two nested
   blocks cannot fight. Class rules come after element rules deliberately:
   `<h2 class="t-d4">` must publish d4, not d3. */
:has(> h1)      { --roman-fs: var(--t-d2); }
:has(> h2)      { --roman-fs: var(--t-d3); }
:has(> h3)      { --roman-fs: var(--t-h3); }
:has(> h4)      { --roman-fs: var(--t-h4); }
:has(> .t-d1)   { --roman-fs: var(--t-d1); }
:has(> .t-d2)   { --roman-fs: var(--t-d2); }
:has(> .t-d3)   { --roman-fs: var(--t-d3); }
:has(> .t-d4)   { --roman-fs: var(--t-d4); }
:has(> .t-h3)   { --roman-fs: var(--t-h3); }
:has(> .t-h3-s) { --roman-fs: var(--t-h3-s); }
:has(> .t-h4)   { --roman-fs: var(--t-h4); }

.voice {
  display: block;
  font-family: var(--f-display);
  font-style: italic;
  font-weight: 400;
  /* §3.4's hard ceiling, applied as the size itself. */
  font-size: calc(var(--roman-fs) * var(--ratio-voice));
  line-height: var(--lh-voice);
  /* The clause is subordinate: its line box may never run past the roman line
     it modifies. At 1440 in the A6 band the clause was 778px wide against a
     714px roman, overhanging it by 150px — a subordinate clause cannot be the
     widest thing in the headline. */
  max-width: 100%;
  /* §3.4 — +0.004em on top of the roman's tracking, to compensate for the
     italic's tighter fit. */
  letter-spacing: calc(var(--tr-voice) + var(--tr-voice-delta));
  color: var(--ac-voice);
  /* §3.4 — starts at the roman line's optical right-third. */
  padding-left: var(--voice-indent);
  text-wrap: balance;
}

/* The hero's deeper step. */
.voice--hero { padding-left: var(--voice-indent-hero); }

/* ── §9 ROW 7 · THE PULL QUOTE — "the page's one large italic serif block" ───
   NOT a `.voice`. A voice clause is a SUBORDINATE clause of a roman display
   line and sizes itself at ≤0.46 × that line (§3.4); the philosophy pull quote
   modifies no heading, so as a `.voice` it either fell back to :root's
   --roman-fs (18px at 390 — a 1.13× step over body, not a display block at
   all) or had to fake a roman size with an inline `style=`, which put it at
   0.57 × the roman that actually precedes it. It is a display block in its own
   right and takes its own tier: --t-h3, the row/step title size, which is the
   one display step no H2 on the homepage uses. */
.pull {
  font-family: var(--f-display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--t-h3);
  line-height: var(--lh-h3);
  letter-spacing: var(--tr-voice);
  color: var(--ac-voice);
  max-width: min(100%, var(--measure));
  text-wrap: balance;
}


/* ============================================================================
   5.  §3.5  THE MICRO-LABEL ROLE
   Three tracking tiers plus the FIG. caption tier. Never invent a fourth
   value: .15 / .20 / .26 / .28em are the only legal trackings (§10.35).
   Colour on paper is --ink-mute (--champagne-ink for indices and FIG.);
   never --ink-ghost, never --champagne (§3.5).
   ========================================================================= */

.t-m1, .t-m2, .t-m3, .t-m4 {
  font-family: var(--f-micro);
  text-transform: uppercase;
  color: var(--tx-micro);
  /* A LABEL IS NOT A PARAGRAPH. §3.3's 62ch measure is an EDITORIAL measure,
     and 62ch of 10px condensed capitals is 310px — so a micro-label set on a
     <p> was being wrapped at a third of its column, which is how a §8.12
     caption specimen came to break as `FIG. 02 — AUTHORITY PATHWAYS` /
     `— SPECIMEN`, opening its second line on a separator (§10.21 read left to
     right). Micro-labels are capped at two lines by §3.5 instead: anything
     longer is a `.note`, which does take the editorial measure. */
  max-width: none;
  /* Tracked uppercase is never balanced, never hyphenated, and never broken
     at a typed hyphen — a caps string ending a line on a bare `-` is §10.21. */
  hyphens: none;
  overflow-wrap: normal;
  word-break: keep-all;
}

/* L1 — eyebrow. The top of the ramp on THREE axes at once: 12px against m2's
   11, HerosC 700 against m2's 400, and champagne-ink against ink-mute. Hue is
   declared on the ROLE rather than only on the `.eyebrow` alias, which is what
   stops a `.t-m1` block rendering as an m2 (the specimen sheet printed exactly
   that). §2.5 already assigns "eyebrow labels" to --champagne-ink. */
.t-m1 { font-size: var(--t-m1); line-height: var(--lh-m1); letter-spacing: var(--tr-m1); font-weight: var(--fw-m1); color: var(--ac-metal-text); }
/* L2 — ledger keys, button labels, column headings. */
.t-m2 { font-size: var(--t-m2); line-height: var(--lh-m2); letter-spacing: var(--tr-m2); font-weight: var(--fw-m2); }
/* L3 — tags, axis ticks, chart units. */
.t-m3 { font-size: var(--t-m3); line-height: var(--lh-m3); letter-spacing: var(--tr-m3); font-weight: var(--fw-m3); }
/* L4 — FIG. captions only. Champagne-ink by role (§8.12). */
.t-m4 { font-size: var(--t-m4); line-height: var(--lh-m4); letter-spacing: var(--tr-m4); font-weight: var(--fw-m4); color: var(--ac-metal-text); }

/* Semantic aliases so section markup reads as prose, not as a scale. */
/* §2.5 names "eyebrow labels" among the four permitted --champagne-ink forms.
   Hue is the third of the three axes that separate m1 from m2 — size (12 v 11),
   weight (700 v 400) and hue (5.55:1 champagne-ink v 5.29:1 ink-mute) — and it
   also states what an eyebrow IS: the section's index entry, the same register
   as its FIG. captions and its row indices. Tracking is NOT one of the three:
   .26 against .20em is a 6% difference in sidebearing on a 40px word, and the
   ramp used to ask it to carry a whole tier on its own. On dark the alias
   follows §3.5 to --champagne-lit; on royal it steps to --on-night (§2.5.5). */
.eyebrow  { font-family: var(--f-micro); font-size: var(--t-m1); line-height: var(--lh-m1); letter-spacing: var(--tr-m1); font-weight: var(--fw-m1); text-transform: uppercase; color: var(--ac-metal-text); }

/* THE EYEBROW SPENDS NO CHAMPAGNE ON A DARK GROUND (§2.5.1, §3.5).
   §3.5's colour clause reads "on dark: --on-night-52, or --champagne-lit for
   INDICES" — the eyebrow is a label, not an index — and §2.5.1 caps a section
   at three champagne groups. A dark band already owes three to the marks §2.5.2
   names first: the italic register in metal (voice clause + licence numeral),
   the MOHAP strand with its legend, and the FIG. caption with its rule. Making
   the eyebrow universal (see .sec-head) would have made it the fourth in every
   dark section on the site, so the tier steps to --tx-micro there instead. On
   paper the eyebrow keeps its champagne-ink; the device is the section opener
   either way, and on a dark ground the tracking and the weight already carry
   it. Indices (.index-no) and FIG. captions (.t-m4) are untouched — they are
   the two roles §3.5 names for --champagne-lit. */
[data-ground="night"] :is(.eyebrow, .t-m1),
[data-ground="royal"] :is(.eyebrow, .t-m1),
.ground--night :is(.eyebrow, .t-m1),
.ground--royal :is(.eyebrow, .t-m1),
.on-night :is(.eyebrow, .t-m1) { color: var(--tx-micro); }
.index-no { font-family: var(--f-micro); font-size: var(--t-m2); line-height: var(--lh-m2); letter-spacing: var(--tr-m2); font-weight: var(--fw-m2); text-transform: uppercase; color: var(--ac-metal-text); }

/* Tracked uppercase adds a trailing sidebearing equal to the tracking. Strip it
   when the label is right-aligned or is the last thing on an optical edge. */
   The cancellation is PER TIER — one hard-coded -.26em cancelled m1's tracking
   correctly and over-cancelled m3's by .11em, so a "flush" tag row hung 1.1px
   past the axis it was flush to. */
.t-m1.is-flush, .eyebrow.is-flush  { margin-right: calc(var(--tr-m1) * -1); }
.t-m2.is-flush, .index-no.is-flush { margin-right: calc(var(--tr-m2) * -1); }
.t-m3.is-flush                     { margin-right: calc(var(--tr-m3) * -1); }
.t-m4.is-flush                     { margin-right: calc(var(--tr-m4) * -1); }

/* §3.5 — two micro-labels are never stacked in one margin column. If a section
   needs both a name and a reference they are ONE string: `REF / 03 — SERVICES`. */


/* ============================================================================
   6.  §3.7  THE DROP CAP (decreed fix — reproduced literally)
   Once per page maximum, on the opening editorial paragraph of the primary
   overview section.

   Acceptance test at 390 / 768 / 1440 / 1920: the wrap indent must cover
   exactly N lines (3 desktop, 2 mobile); no empty pocket taller than 8px under
   the cap; the cap's right sidebearing optically matches the paragraph's
   word-space ±2px.

   NOTE: the float fallback's 5.80em is derived in the spec against a 1.66
   leading (--lh-body). --lh-lede is 1.70, so the fallback path runs ~2% tall.
   The spec's numbers are decreed and reproduced unchanged; every engine we
   target supports `initial-letter`, so the fallback is a safety net, not the
   render path.
   ========================================================================= */

.lede::first-letter {
  initial-letter: 3 3;
  color: var(--ac-identity);
  font-weight: 400;
  /* §3.7's acceptance test, not §3.7's literal .06em — see --cap-gap in
     tokens.css. An em on ::first-letter resolves against the PARAGRAPH's font
     size, so .06em was 1.2px and the measured ink gap was 3–5px against a
     7–8px word space. The token lands it at 7–9px, inside the ±2px tolerance
     the clause actually decrees. */
  padding-right: var(--cap-gap);
}

@supports not (initial-letter: 3) {
  .lede::first-letter {
    float: left;
    font-size: 5.80em;   /* = ((3-1) × 1.66 + 0.692) / 0.692 · Pagella cap-height 0.692 at lh 1.66 */
    line-height: .69;
    margin: .02em .10em -.06em 0;
  }
}

/* §3.7 — THE SHORT-PARAGRAPH CAP.
   A three-line cap needs a paragraph with enough lines left under it to close
   naturally. On a lede that sets to four lines in a narrow column the third
   line ends early and the fourth returns to the full measure, and the rag reads
   as a hole rather than a wrap — the exact "pocket under the initial" §3.7 was
   written to outlaw. Two lines fixes it: the indent ends where the paragraph
   still has body left to square it off.

   Round caps (O, C, G, Q) also carry their own optical sidebearing, so they
   take less added padding than a flat-sided letter to hit the same measured
   gap against the paragraph's word space. */
.lede--cap-2::first-letter {
  initial-letter: 2 2;
  padding-right: var(--cap-gap-sm);
}

@supports not (initial-letter: 2) {
  .lede--cap-2::first-letter { font-size: 3.40em; }
}

.lede--cap-round::first-letter { padding-right: calc(var(--cap-gap-sm) * 0.6); }

@media (max-width: 559px) {
  /* THE CORRECTION SCALES INVERSELY WITH THE CAP, NOT WITH IT.
     This branch used to scale the padding DOWN by the cap's own .586 ratio,
     which is backwards and failed §3.7's mandatory 390 measurement: the gap the
     reader sees is the cap's natural right sidebearing PLUS this padding, the
     sidebearing shrinks with the two-line cap, and the target — the paragraph's
     word space — is a constant in paragraph ems. So a smaller cap needs MORE
     padding, not less. Measured at 390 the shipped .14em left a 4px gap against
     a 7–8px word space (3.5px outside the ±2px tolerance, with the E's lower
     arm kissing the following r); the value below lands it inside tolerance at
     390 while 1440 keeps its own measured value. */
  .lede::first-letter { initial-letter: 2 2; padding-right: var(--cap-gap-sm); }
  @supports not (initial-letter: 2) {
    .lede::first-letter { font-size: 3.40em; }
  }
}


/* ============================================================================
   7.  FIGURES AND CAPTIONS  (§8.12)
   Every discrete authored figure carries, 12px below its optical bottom-left
   edge, a 24px champagne-ink rule and then
   `FIG. 0N — NAME — SPECIMEN` in --t-m4.
   A caption may not assert anything not stated verbatim in CONTENT_BRIEF.md.
   ========================================================================= */

figure { margin: 0; }

/* THE RULE SITS ON THE CAPTION'S OWN LINE, NOT ABOVE IT.
   Stacked, the 24px rule was a champagne block at the figure's left margin at
   exactly the pitch, x-origin, width and weight of the legend swatches above
   it — at 390 the Fig. II legend read as four entries, the fourth unlabelled,
   which is a phantom datum on the page's primary information graphic. Set
   inline at 16px it belongs to the caption's line, can never align to a legend
   column, and §8.12's "a 24px rule then FIG. 0N …" still reads left to right. */
figcaption {
  display: flex;
  align-items: center;
  gap: var(--s3);          /* 12px */
  font-family: var(--f-micro);
  font-size: var(--t-m4);
  line-height: var(--lh-m4);
  letter-spacing: var(--tr-m4);
  font-weight: var(--fw-m4);
  text-transform: uppercase;
  color: var(--ac-metal-text);
  margin-top: var(--s4);   /* 16px */
}

figcaption::before {
  content: "";
  flex: 0 0 var(--s4);     /* 16px */
  height: var(--rule-w);
  background: currentColor;
}

/* §10.21 — THE CAPTION NEVER SOFT-WRAPS. `FIG. 0N — NAME — SPECIMEN` is one
   string 41 characters long; in a 253px art cell at 768 it broke after the
   second em dash and printed a separator as the last glyph of line 1 (and a
   leading one on line 2 at 390). The `— SPECIMEN` qualifier is therefore its
   own element: on one line it carries the separator, and where the cell is too
   narrow it is set on the line below WITHOUT one, so neither line can ever open
   or close on a dash. The break is declared, never discovered. */
figcaption > .fig-cap__tail::before { content: "\2014\00a0"; }
figcaption > .fig-cap__name { white-space: nowrap; }
/* (The breakpoint that acts on this lives in figures.css: the art layer is a
   later cascade layer than `base`, and the caption's separator is declared in
   `components`.) */

/* Ambient underlays are not discrete figures and carry no caption (§7.2.5). */
figcaption.is-bare::before { display: none; }


/* ============================================================================
   8.  §4.2  CONTAINERS
   All text lives inside --shell. Above 1680px the shell stays at 1420px.
   ========================================================================= */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Single-topic sections: FAQ, philosophy, legal. */
.shell--narrow { max-width: var(--shell-narrow); }

/* §1 COMPOSED — A NARROW SHELL HANGS ON THE PAGE'S OWN LEFT EDGE.
   `margin-inline: auto` centres a 1080px shell inside a 1420px page, which
   moves that section's measure origin 170px right of every other section's and
   then snaps back on the next one: a visible hiccup in the page's spine, read
   as a mistake rather than as an offset. Hung, the narrow shell starts exactly
   where the wide one does and simply ends sooner — which is what a single-topic
   section is: the same page, a shorter measure. */
.shell--hang { margin-inline: max(0px, calc(50% - var(--shell) / 2)) auto; }

/* Long-form measure blocks. */
.shell--text   { max-width: var(--shell-text); }

/* §4.2 / §7.2 — the art-bleed layer. Wider than the shell, but its outermost
   geometry must still terminate --bleed-inset (40px) inside the viewport edge,
   and it never receives pointer events or reading text. */
.bleed {
  width: 100%;
  max-width: var(--bleed);
  margin-inline: auto;
  pointer-events: none;
}


/* ============================================================================
   9.  §4.3  GRID
   12 / 8 / 4 columns. Breakpoints are 390 / 560 / 768 / 900 / 1080 / 1360 /
   1680 and no others.
   ========================================================================= */

.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
}

@media (max-width: 1079px) {
  .grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
  .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* minmax(0,1fr) everywhere above means a grid child can shrink below its
   content; this guards the one case it cannot — a long unbroken string. */
.grid > * { min-width: 0; }

/* ── COLUMN SPANS ───────────────────────────────────────────────────────────
   The handful of spans §4.4's archetypes actually name — the A1 cover's
   display block and art band, the A5 specimen's figure and prose columns —
   as classes, so a section never writes `grid-column` with raw numbers and
   never re-derives the collapse. All of them become full width below 768,
   where the grid is four columns and a split is a squeeze. */
.c-1-7  { grid-column: 1 / 8; }
.c-1-9  { grid-column: 1 / 10; }
.c-1-5  { grid-column: 1 / 6; }
.c-1-6  { grid-column: 1 / 7; }
.c-6-12 { grid-column: 6 / 13; }
.c-7-12 { grid-column: 7 / 13; }
.c-8-12 { grid-column: 8 / 13; }
/* The three-part row: a tall plate, a second plate, and a column of record.
   §4.6 needs a third cell wherever two fill only two thirds of the shell. */
.c-6-9   { grid-column: 6 / 10; }
.c-10-12 { grid-column: 10 / 13; }
.c-full { grid-column: 1 / -1; }

@media (max-width: 1079px) {
  /* Eight columns: the twelfths above would overflow, so each span is re-cut
     to the nearest eighth that preserves the composition's proportion. */
  .c-1-7  { grid-column: 1 / 6; }
  .c-1-9  { grid-column: 1 / 7; }
  .c-1-5  { grid-column: 1 / 5; }
  .c-1-6  { grid-column: 1 / 5; }
  .c-6-12 { grid-column: 5 / 9; }
  .c-7-12 { grid-column: 5 / 9; }
  .c-8-12 { grid-column: 6 / 9; }
  .c-6-9  { grid-column: 5 / 7; }
  .c-10-12{ grid-column: 7 / 9; }
}
@media (max-width: 767px) {
  .c-1-7, .c-1-9, .c-1-5, .c-1-6, .c-6-12, .c-7-12, .c-8-12,
  .c-6-9, .c-10-12 { grid-column: 1 / -1; }
}

/* ── §4.4  THE ARCHETYPE COLUMN TEMPLATES ───────────────────────────────────
   tokens.css already carries the five templates §4.4 decrees; this is the one
   place they become layout, so no section re-derives a template or invents a
   collapse threshold. A2/A6/A7 collapse at 900 (their two halves are prose and
   a plate); A4 collapses at 820, the threshold §8.5/§8.11 already use for the
   chart's own stacking, so the rail and the Gantt never disagree about it. */
.arch        { display: grid; gap: var(--grid-gap); align-items: start; }
.arch--a2    { grid-template-columns: var(--g-ledger); }        /* 1.6fr / 1fr  */
/* A4's left column must STRETCH — it holds the sticky head plus the full-height
   rail drawing that keeps it from emptying (§8.13). */
.arch--a4    { grid-template-columns: var(--g-chart); align-items: stretch; }
.arch--a6    { grid-template-columns: var(--g-band); }          /* 5fr / 7fr    */
.arch--a7    { grid-template-columns: var(--g-declaration); }   /* 7.6fr / 4fr  */
.arch > *    { min-width: 0; }

@media (max-width: 899px) {
  .arch--a2, .arch--a6, .arch--a7 { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 819px) {
  .arch--a4 { grid-template-columns: minmax(0, 1fr); }
}

/* ── §4.5.3  THE H2 COLUMN ROTATION ─────────────────────────────────────────
   "No two adjacent sections may start their H2 at the same grid column. Rotate
    through col 1, col 2, col 3."

   Declared on the SECTION, exactly like its archetype and its ground, so the
   rule stays machine-checkable and a page's rhythm can be read off its markup:

       <section class="sec" data-archetype="A3" data-ground="paper" data-h2-col="2">

   The head block (`.sec-head`: eyebrow + H2 + any voice clause and lede that
   belong to it) steps right by that many grid columns. Below 768 the step is
   removed — four columns cannot carry an indent and a measure. */
/* THE SECTION HEAD IS A MEASURE WITH A MARGIN.
   The display block runs in column 1 on its own measure; column 2 is the
   margin, and it carries the section's declaration — archetype, ground, H2
   column, H2 size token (§11 wants those machine-checkable, and a reader of
   the printed page can then check them too). A head with nothing in its margin
   leaves the right half of the sheet empty for the height of the headline,
   which §4.6 does not accept however good the reason. */
/* THE MEASURE AND ITS MARGIN, SIZED TO WHAT THEY HOLD (§4.6).
   The head used to be `1fr / 30ch`, and that is the shape that manufactured the
   sheet's worst void. Both columns hold text with a HARD measure — a lede is
   capped at 62ch, an annotation at 46–64ch — so a 1fr track 995px wide carried
   a 620px paragraph and a 30ch margin 270px wide was pushed to the shell's
   right edge. Everything between them was blank paper: measured 330 × 380 in
   §2, 470 × 460 in §3, 330 × 350 in §5, against §4.6's 240 × 200 ceiling. Four
   consecutive sections, because it was the MOLECULE that was wrong, not four
   authors.

   Re-cut so neither track can be wider than the copy it holds:
     · 1.35fr / 1fr, so the margin grows with the sheet instead of staying at
       30ch while the measure column inherits every surplus pixel;
     · the margin's annotation fills its track (up to §3.3's 64ch ceiling)
       rather than sitting at 46ch inside it;
     · a 1px hairline runs the head's full height between them, so the two
       columns read as one register rather than as two things that happen to
       share a row — and no gap on the sheet is ever unmarked.
   Measured after the re-cut at 1440: the largest unmarked rectangle in any head
   is 121 × 137 (§2), inside the ceiling on both axes. */
/* ── THE SECTION-HEAD MOLECULE (one component, every section, every page) ────
   THERE WAS NO HEAD COMPONENT — THERE WERE SEVEN ASSEMBLIES.
   Measured on the specimen sheet before this rewrite: only three of nine heads
   carried the champagne eyebrow at all, so six sections opened with nothing in
   the register that says "a section begins here"; and where both labels existed
   their cap-lines disagreed by +10px (§2), 0 (§5) and −31px (§8.11) — a 41px
   spread on the one horizontal a reader uses to find the top of a section.
   `align-items: center` was the cause of the spread, and an optional eyebrow
   was the cause of the absence. Both are removed here, in the molecule, so no
   page can reintroduce either.

   THE MOLECULE IS TWO ROWS, NOT TWO COLUMNS.

     row 1   .sec-head__eyebrow          .sec-head__meta        ← ONE cap-line
     row 2   .sec-head__main             .sec-head__ref
             (H2 · voice · lede)         (annotation)

   Row 1 is the DECLARATION LINE: the section's eyebrow hangs on the left, its
   machine-readable declaration (archetype · ground · H2 column · size token)
   hangs in the right margin, and the two are locked to one another by
   `align-self: baseline`. Baseline alignment inside a grid row is exact by
   construction — not a padding that has to be re-tuned per tier — so the two
   labels share a baseline at 0px delta at every width, on every ground, and
   whatever tier either one is set in. At m1 (12px) against m3 (10px) their cap
   tops then differ by 0.7px, which is the optical answer as well as the
   geometric one: a shared BASELINE is how two different sizes are set on one
   line in print, and a shared cap-line would sit the smaller label visibly
   high.

   Row 2 hangs from the same two columns and is `start`-aligned: an H2 and a
   46ch annotation have nothing to align on but their tops.

   The eyebrow is REQUIRED. A head without one still composes (the grid row
   simply collapses), but §4.5.5's molecule count is the only thing that ever
   argued for dropping it, and that clause caps the eyebrow → H2 → PARAGRAPH
   molecule, not the eyebrow. The declaration line is the section's index entry
   and every section has one.

   THE TWO COLUMNS MUST END WITHIN 240px OF EACH OTHER (§4.6). Whichever runs
   shorter leaves an empty rectangle the width of a whole column, so the void
   rule is a LENGTH contract on the head's copy, not something CSS can absorb:
   the annotation belongs in the margin only while the margin does not outrun
   the measure, and the surplus goes into the measure column under the lede
   (`.sec-head__main` takes a `.note` as happily as the margin does). Measured
   across the nine heads on the specimen sheet after balancing: −195 to +179px,
   inside the ceiling on every one; before, three heads ran 269 / 345 / 482px
   of empty paper beside a margin full of text.

   THE MEASURE AND ITS MARGIN, SIZED TO WHAT THEY HOLD (§4.6): 1.35fr / 1fr, so
   the margin grows with the sheet instead of staying at 30ch while the measure
   column inherits every surplus pixel, and a 1px hairline runs the head's full
   height between them so the two columns read as one register. The divider
   cannot be a border on a baseline-aligned box, so the head paints it: a 1px
   background rule at the exact column boundary — main track + half the gap,
   where the main track is 1.35/2.35 of the head minus the gap. One expression,
   exact at every width. */
.sec-head {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  column-gap: var(--grid-gap);
  align-items: start;
  padding-left: 0;
  margin-bottom: var(--s7);

  background-image: linear-gradient(var(--ln-soft), var(--ln-soft));
  background-repeat: no-repeat;
  background-size: var(--rule-w) 100%;
  background-position: calc((100% - var(--grid-gap)) * (1.35 / 2.35)
                            + var(--grid-gap) / 2) 0;
}

/* Row 1 — the declaration line. Both cells opt into baseline alignment; grid
   groups baseline-aligned items by row, so this pair and only this pair. */
.sec-head__eyebrow {
  grid-column: 1;
  grid-row: 1;
  align-self: baseline;
  min-width: 0;
}
.sec-head__meta {
  grid-column: 2;
  grid-row: 1;
  align-self: baseline;
  min-width: 0;
  padding-left: var(--grid-gap);
}

/* Row 2 — the measure and its margin. */
.sec-head__main {
  grid-column: 1;
  grid-row: 2;
  min-width: 0;
  /* §4.5 — the declaration line's distance to the display line is a DECISION,
     one per section, taken from the lattice. It was one number for every head
     on the sheet (24px, ten times), and a constant that never varies stops
     being a decision and starts being a template. */
  margin-top: var(--head-gap, var(--s5));
}
.sec-head__main > * + * { margin-top: var(--s4); }

.sec-head__ref {
  grid-column: 2;
  grid-row: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  min-width: 0;
  margin-top: var(--head-gap, var(--s5));
  padding-left: var(--grid-gap);
}
.sec-head__ref > * + * { margin-top: var(--s3); }
/* Both children fill the margin track: an annotation set at 46ch inside a
   500px column is the same void one level down. --measure-max is §3.3's hard
   ceiling, so the note can never exceed it however wide the sheet gets. */
.sec-head__ref > .note,
.sec-head__ref > p { max-width: min(100%, var(--measure-max)); }

/* A head that has not been given its declaration line still holds its shape:
   row 1 collapses to zero and row 2's top margin comes off with it. */
.sec-head:not(:has(.sec-head__eyebrow, .sec-head__meta)) :is(.sec-head__main, .sec-head__ref) {
  margin-top: 0;
}

@media (max-width: 899px) {
  .sec-head {
    grid-template-columns: minmax(0, 1fr);
    /* One column: there is no boundary to paint, and the margin becomes a block
       under the measure, opened by a rule instead of divided by one. */
    background-image: none;
  }
  /* Source order is eyebrow · meta · main · ref; stacked, the reading order is
     eyebrow · main · meta · ref, so the two right-column cells travel together
     under the measure they annotate. */
  .sec-head__eyebrow { grid-column: 1; grid-row: 1; padding-left: 0; }
  .sec-head__main    { grid-column: 1; grid-row: 2; }
  .sec-head__meta    { grid-column: 1; grid-row: 3; padding-left: 0;
                       margin-top: var(--s5);
                       border-top: var(--rule-w) solid var(--ln-soft);
                       padding-top: var(--s4); }
  .sec-head__ref     { grid-column: 1; grid-row: 4;
                       margin-top: var(--s3);
                       padding-left: 0; }
}

/* ── THE OPEN HEAD — the second construction, and the reason the first one
   stops reading as a template ────────────────────────────────────────────────
   §4.5.5 caps the molecule *eyebrow → H2 → annotation paragraph* at three per
   page and §10.30 fails it in three consecutive sections. The measured sheet
   ran it TEN times: ten heads, ten eyebrows at one cap-line, ten annotations in
   the right margin at the same dy, so a reader scrolling saw one layout stamped
   down the page whatever the section was about.
   The cap is only satisfiable if the system owns a second way to open a
   section, so here it is: ONE column, no margin, no painted boundary — the
   display line and whatever belongs to its own measure, opening full-bleed on
   the H2. A page then alternates two constructions instead of repeating one,
   and the two-column head is spent where a section genuinely has a marginal
   record to print (§9's dossier plates: the overview, the dark band, the
   contact register). */
.sec-head--open {
  grid-template-columns: minmax(0, 1fr);
  background-image: none;             /* no boundary: there is no second column */
}
.sec-head--open > .sec-head__main,
.sec-head--open > .sec-head__eyebrow,
.sec-head--open > .sec-head__ref { grid-column: 1; padding-left: 0; }
.sec-head--open > .sec-head__ref { grid-row: 3; margin-top: var(--s5); }

/* §4.5 — the eyebrow → display gap, one decision per section, from the lattice. */
.sec-head--gap-s3 { --head-gap: var(--s3); }
.sec-head--gap-s6 { --head-gap: var(--s6); }
.sec-head--gap-s7 { --head-gap: var(--s7); }

/* §4.5 — THE STEPPED DISPLAY BLOCK, off A1's own construction. A two-line H2
   whose second line hangs in from the first: one head on the page is composed
   line by line rather than set as a paragraph of display type. Not an
   alternating indent (§4.5.8 governs LIST rows); a stepped display block is the
   cover's device, used once. */
.h2--step > .rv:nth-child(2) { padding-left: var(--s9); }
@media (max-width: 767px) {
  .h2--step > .rv:nth-child(2) { padding-left: var(--s5); }
}

[data-h2-col="2"] .sec-head { padding-left: var(--col-step); }
[data-h2-col="3"] .sec-head { padding-left: calc(var(--col-step) * 2); }

@media (max-width: 1079px) {
  /* A media query cannot read --grid-cols, so the eight-column step is stated. */
  .sec-head { --col-step: calc((100% - 7 * var(--grid-gap)) / 8 + var(--grid-gap)); }
}
/* THE COLUMN OFFSET DIES WITH THE COLUMNS. §4.5.3's rotation exists so
   adjacent sections start their display line on a different GRID COLUMN; once
   every two-column archetype has collapsed (899px) there are no columns to
   start on, and a 179px indent inside a single 700px measure stops reading as
   an offset and starts reading as a centred heading — checklist #6, arrived at
   without a single `text-align: center`. Below 900 every head opens on the
   page's one left origin. */
@media (max-width: 899px) {
  [data-h2-col="2"] .sec-head,
  [data-h2-col="3"] .sec-head { padding-left: 0; }
}


/* ============================================================================
   10. §4.3 / §5  SECTION SHELL AND GROUND UTILITIES
   Every section is `<section class="sec sec--<name>" data-archetype="A3"
   data-ground="paper">` (§11), so the rhythm rules in §4.5 stay
   machine-checkable and the ground is declarative.

   The five depth mechanisms and NO OTHERS:
     E0 flat paper · E1 hairline · E2 ground step · E3 dark band · E4 frost
   ========================================================================= */

.sec {
  position: relative;
  padding-block: var(--sec-pad);
  /* E0 — flat paper. No shadow. Ever. */
  background: var(--sf-page);
  color: var(--tx-body);
}

/* A "breath" section (A10 MARGIN, the assessment CTA). §4.3 declares three
   vertical regimes and a page must exercise more than one: a sheet where every
   section is `sec--breath` has one section height from nav to footer, which is
   the uniform rhythm PROJECT_BRIEF §2 bans. The standard regime is the default
   above; `--breath` is for the low-height A10; a dark band takes the tall one
   automatically further down. */
.sec--breath { padding-block: var(--sec-pad-breath); }

/* ── THE CAESURA IS A DECISION PER EDGE, NOT ONE NUMBER PER PAGE ─────────────
   §4.3 declares three vertical regimes; a page that spends the middle one on
   every section pays 144px above and 144px below every rule on the sheet, and
   the measured result is a 288px caesura between almost every pair — one tempo
   from nav to footer, which is PROJECT_BRIEF §2's "every section the same" in
   another axis. The three regimes are therefore addressable PER EDGE, so a
   section can close tight and the next one open wide (or the reverse) and the
   page breathes unevenly, the way a set page does. No new values: every one of
   these is one of §4.3's own three. */
.sec--close-top    { padding-top: var(--sec-pad-breath); }
.sec--close-bottom { padding-bottom: var(--sec-pad-breath); }
.sec--open-top     { padding-top: var(--sec-pad-dark); }
.sec--open-bottom  { padding-bottom: var(--sec-pad-dark); }

/* THE STACK — vertical rhythm inside a composed column.
   A grid cell holding several blocks (a hero's display column, a band's left
   half, a specimen cell) needs one spacing decision, not one per child. Three
   steps, all on the lattice; nothing else. */
.stack > * + *        { margin-top: var(--s5); }
.stack--tight > * + * { margin-top: var(--s3); }
.stack--wide > * + *  { margin-top: var(--s7); }

/* THE BLOCK RHYTHM INSIDE A SECTION.
   Successive blocks in a section's shell stand 48px apart. Adjacent margins
   collapse, so a block that declares its own spacing (the 48px under
   `.sec-head`, a component's own margin) keeps it rather than adding to it.
   Scoped to a section's shell: the nav's shell is a flex bar and the footer
   sets its own. */
.sec > .shell > * + * { margin-top: var(--s7); }

/* §8.2 — the nav is FIXED and reserves --nav-h, so the first section on a page
   has to clear it or its opening line renders under the frost. At 390 the
   section pad is 80px against an 88px nav and the eyebrow collides; every page
   would otherwise solve this privately in its hero file. The reservation is
   added to whatever vertical rhythm the section already declares, so a breath
   hero and a full-pad hero both stay on the lattice. */
main > .sec:first-child,
.sec--first { padding-top: calc(var(--sec-pad) + var(--nav-h)); }
main > .sec--breath:first-child,
.sec--breath.sec--first { padding-top: calc(var(--sec-pad-breath) + var(--nav-h)); }

/* ── E0/E2 · the paper ramp ─────────────────────────────────────────────────
   Adjacent sections change exactly one step. The transition between steps is a
   hard edge or a 1px --rule-soft line — never a gradient fade. */
/* --sf-page follows the ground, not just the body. Anything that has to paint
   ITS OWN GROUND — a sticky axis header, a label knocking a rule out behind
   itself, an E0 island asserting the page surface — reads the alias, and if the
   alias stayed at --paper inside a paper-warm section every one of them painted
   a visibly cooler patch. Two adjacent steps of the ramp are 6 luminance points
   apart: invisible in a swatch, obvious as a band behind a tag row. */
[data-ground="paper"]      { background: var(--paper);      --sf-page: var(--paper); }
[data-ground="paper-warm"] { background: var(--paper-warm); --sf-page: var(--paper-warm); }
[data-ground="paper-deep"] { background: var(--paper-deep); --sf-page: var(--paper-deep); }

/* ── E3 · the dark band ─────────────────────────────────────────────────────
   A single top-centre light source. No vignette from more than one direction.
   The inset 0 1px 0 is one of the only two legal box-shadows on the site. */
[data-ground="night"],
.ground--night {
  background:
    radial-gradient(120% 80% at 50% -12%, var(--night-3) 0%, var(--night-3-fade) 62%),
    linear-gradient(180deg, var(--night-2) 0%, var(--night) 100%),
    /* The background COLOUR, not a third decoration. The `background`
       shorthand resets background-color to transparent, so without this a dark
       band paints as bare paper anywhere the gradients do not (print, an
       image-blocked context) — carrying --on-night text, i.e. invisible — and
       every automated contrast audit reads the band as paper and reports a
       false failure for every line in it. The royal field below has always had
       its colour as a final layer; this brings the two into line. */
    var(--night);
  box-shadow: inset 0 1px 0 var(--rule-night);
}

/* ── the royal field ────────────────────────────────────────────────────────
   §4.5.7 — maximum ONE per page. §2.4.3 — never a gradient into any hue other
   than --royal-deep. */
[data-ground="royal"],
.ground--royal {
  background:
    radial-gradient(80% 120% at 14% 0%, var(--royal-wash), var(--royal-wash-0) 60%),
    linear-gradient(160deg, var(--royal-deep-0) 30%, var(--royal-deep) 100%),
    var(--royal);
}

/* A dark band's vertical padding is taller than a paper section's (§4.3). */
[data-ground="night"],
[data-ground="royal"] { padding-block: var(--sec-pad-dark); }

/* ── inverted alias layer ───────────────────────────────────────────────────
   Re-pointing the §2.7 aliases is what makes a section written against the
   aliases invert correctly. It also makes §10.37 structurally impossible:
   --ac-identity becomes --beam here, so --royal can never land as text on a
   dark ground, and --ac-metal-text becomes --champagne-lit.
   `.on-night` applies the same inversion to a non-section island (the footer,
   the mobile menu panel) without repainting a background. */
[data-ground="night"],
[data-ground="royal"],
.ground--night,
.ground--royal,
.on-night {
  --tx-display:    var(--on-night);
  --tx-body:       var(--on-night-70);
  --tx-micro:      var(--on-night-52);
  --tx-inverse:    var(--ink);

  --ln-hair:       var(--rule-night);
  --ln-soft:       var(--rule-night-soft);
  --ln-structural: var(--on-night);
  /* §10.42 — the interactive boundary on a dark ground. --rule-night-strong is
     .42 on night (3.74:1) and base.css lifts it to .70 on royal (4.24:1). */
  --ln-control:    var(--rule-night-strong);

  --ac-identity:   var(--beam);
  --ac-metal-text: var(--champagne-lit);
  /* §3.4 — on dark grounds the voice clause is champagne, not blue. */
  --ac-voice:      var(--champagne-lit);
  /* §3.6 — and so is the licence numeral. These two are the SAME inversion
     rule; before --ac-figure existed the clause turned gold and the numeral
     three rows below it stayed blue, and no reader could infer the system. */
  --ac-figure:     var(--champagne-lit);

  --sf-page:       var(--night);
  --sf-raised:     var(--night-2);
  --sf-sunken:     var(--night);
  --sf-field:      var(--night-3);

  color: var(--tx-body);
}

/* The §2.3 / §2.5 alphas are calibrated against --night (L* 7). The royal
   field is far lighter (--royal is L* 33), and measured against it:
     --on-night-70   4.25:1     --on-night-52   3.01:1
     --champagne-lit 4.49:1     --on-night      7.03:1
   Only the last clears the §10.42 floor of 4.5:1 for small text, and micro
   labels (11px / 10.5px) are exactly the sizes that floor exists for. So on
   royal — and only on royal — every text alias resolves to --on-night, and
   hierarchy is carried by family, case and size rather than by three greys.
   Champagne is untouched as a STROKE (--ac-metal): 4.49:1 clears the 3:1
   graphical floor, so the seal, the hairlines and the brandmark rule keep
   their gold. Nothing changes on night, where the decreed alphas are correct. */
[data-ground="royal"],
.ground--royal {
  --tx-body:       var(--on-night);
  --tx-micro:      var(--on-night);
  --ac-metal-text: var(--on-night);

  /* §2.5.5 — CHAMPAGNE DOES NOT LAND ON ROYAL AT ALL, as a line either.
     Measured on this ground a champagne-lit hairline is 2.45:1 and a --champagne
     one is worse; both are under the 3:1 graphical floor §10.42 sets for a UI
     boundary, and the footer's licence seal — the page's single most important
     trust artefact — was drawn in it at 2.2:1, i.e. invisible. The metal alias
     therefore steps to --on-night here (7.03:1) exactly as the text alias does.
     Gold is a paper-and-night material; the royal field is not its ground. */
  --ac-metal:      var(--on-night);

  /* §3.6's numeral follows the same reasoning: champagne-lit is 4.49:1 here. */
  --ac-figure:     var(--on-night);

  /* §8.3's ghost-inverse edge (rgba 242,241,236,.42) measures 3.74:1 on night —
     legal — and 2.45:1 on royal. Every hairline that bounds an INTERACTIVE
     control steps up one rung on this ground, to 4.24:1. */
  --rule-night-strong: var(--on-night-70);
}

/* ── E4 · frost. The nav, plus one dark variant for the mobile menu. The only
   blur filters on the site. ───────────────────────────────────────────────── */
.frost {
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  background: var(--frost-light);
  /* See components.css §5 E4: an in-flow frost island must isolate, or the
     backdrop texture it forces the compositor to build spans the whole
     document and long pages lose bands of paint. */
  isolation: isolate;
}
.frost--dark { background: var(--frost-dark); }


/* ============================================================================
   11. §4.6  THE VOID RULE GUARD
   "Any rectangular empty region inside a content column exceeding 240px tall ×
   200px wide at 1440 (measured on a FULL-PAGE STATIC EXPORT, not a live sticky
   viewport) must be resolved."

   CSS cannot measure emptiness, so this section is two things:
   (a) the affordances that make the rule easy to satisfy, always on;
   (b) an opt-in diagnostic that paints the obvious offenders during review.
   ========================================================================= */

/* (a) The §8.13 fix: a sticky rail must be PAIRED with a non-sticky drawing
   that spans the column's full height, so the left column never empties in the
   static export. `.sticky-rail` is the sticky part; `.fill-col` is its
   mandatory sibling. Both live on a grid child, which is why they can claim
   100% height honestly. */
/* THE RUNNING HEAD TRAVELS OVER THE DRAWING, SO IT CARRIES ITS OWN GROUND.
   The rail head is sticky and the plate under it is not, which means that
   through the middle of the section the counter — and, per §4.4 A4, the H2
   above it — slides across the plate's leaders and nodes. Line art passing
   through live text is checklist #15 whichever of the two is moving, so the
   head paints the section's own ground behind itself and lifts off the plate.
   `--sf-page` is the ground token the section already publishes, so the head is
   opaque on paper, on paper-warm and on night without knowing which it is. */
.sticky-rail {
  position: sticky;
  top: calc(var(--nav-h) + var(--s5));
  align-self: start;
  z-index: 1;
  background: var(--sf-page);
  padding-bottom: var(--s5);
}

.fill-col {
  min-height: 100%;
  height: 100%;
}

/* A grid column that hosts a sticky rail must stretch, or `height: 100%` on the
   companion drawing resolves against nothing. Two rows, explicitly: the rail
   head takes what it needs and the drawing takes ALL the rest — which is what
   makes "the rail spans the column's full height" true rather than aspirational.
   With `align-content: start` alone both rows were auto-sized, the drawing
   resolved its height against nothing and rendered as a ~190px stub in a column
   whose caption promised the opposite. */
.has-sticky-rail {
  display: grid;
  grid-template-rows: auto minmax(var(--s12), 1fr);
  min-height: 100%;
}

/* Below 820 the A4 archetype is one column: nothing is sticky, so there is no
   column to keep from emptying, and the companion drawing becomes exactly what
   it exists to prevent — a 350 × 200 band of blank paper between the counter
   and the chart. The pair is dismissed together, at the width the archetype
   itself collapses (see figures.css §4 for the matching rail rule). */
@media (max-width: 819px) {
  .sticky-rail { position: static; }
  .has-sticky-rail { display: block; min-height: 0; }
  .has-sticky-rail > .fill-col { display: none; }
}

/* (b) Review diagnostic. Add `data-void-guard` to <html> (or toggle it from the
   console) and every empty flow child of a content column is painted with the
   240×200 minimum it is failing. Never enabled in production markup. */
[data-void-guard] :is(.grid, .shell, .sec) > :empty:not(svg, img, canvas, picture, video, iframe, input, textarea, select, br, hr, [aria-hidden="true"]) {
  min-height: 240px;
  min-width: 200px;
  outline: var(--rule-w) dashed var(--ac-metal);
  outline-offset: calc(var(--s1) * -1);
  position: relative;
}

[data-void-guard] :is(.grid, .shell, .sec) > :empty:not(svg, img, canvas, picture, video, iframe, input, textarea, select, br, hr, [aria-hidden="true"])::after {
  content: "VOID · §4.6";
  position: absolute;
  inset: auto auto var(--s2) var(--s2);
  font-family: var(--f-micro);
  font-size: var(--t-m4);
  letter-spacing: var(--tr-m4);
  color: var(--ac-metal-text);
}


/* ============================================================================
   12. §6.5  REDUCED MOTION — the base floor.
   Reproduced from the spec verbatim. The reveal primitives (.rv / .rise /
   .draw) are defined in components.css; this block is their guard and loads
   first deliberately — `!important` wins regardless of order.

   NOT covered here, and owned by the JS layer (§6.5): under reduced motion the
   Gantt bars render at full scale, the process rail renders fully drawn with
   the stage counter fixed at 06 / 06, counters render their final value, the
   scroll-indicator sweep is removed, and magnetic-hover and parallax listeners
   are NEVER ATTACHED — feature-detect, do not merely override in CSS (§10.40).
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .rv > * { clip-path: none !important; transform: none !important; transition: none !important; }
  .rise   { opacity: 1 !important; transform: none !important; transition: none !important; }
  .draw * { stroke-dasharray: none !important; stroke-dashoffset: 0 !important; transition: none !important; }

  * {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

} /* ── end @layer base ─────────────────────────────────────────────────────── */
