/* ============================================================
   ICON ROCKLEAR ONTARIO, shared system  ·  V2
   Doc No. ICON-WEB-CSS-002 · loads after tokens.css

   This file is the archetype library. A page is composed from the
   classes in section 5 and nothing else. If a pattern is not here
   and not in _ART/ART-DIRECTION.md, it does not go on the site.

   Build reference for page agents: _ART/COMPONENTS.md
   Verify against: _ART/kitchen-sink.html

   CONTENTS
     1  Reset and base
     2  Type scale
     3  Layout, bands, surfaces, the seam rule
     4  Signature elements
     5  Section archetypes AR-1 to AR-10
     6  Components
     7  Motion
     8  Utilities
     9  Print
   ============================================================ */


/* ============================================================
   1 · RESET AND BASE
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--nav-h) + 16px);
}

body {
  font-family: var(--body);
  font-size: var(--b1-size);
  font-weight: 400;
  line-height: var(--b1-lh);
  color: var(--fg-dim);
  background: var(--surface-0);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video, canvas { display: block; max-width: 100%; }
img, video { height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
table { border-collapse: collapse; width: 100%; }
::selection { background: var(--gold); color: var(--black); }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 300;
  padding: var(--s-3) var(--s-5);
  background: var(--gold);
  color: var(--black);
  font-family: var(--mono);
  font-size: var(--m2-size);
  letter-spacing: var(--m2-ls);
  text-transform: uppercase;
}
.skip-link:focus { left: var(--gutter); top: var(--s-3); }


/* ============================================================
   2 · TYPE SCALE, ART-DIRECTION §E1
   Every role is a class. Use the class, not a bare element, so the
   role travels with the markup. Bare h1 to h4 carry sane defaults
   for content that arrives without classes.
   ============================================================ */

/* ---------- display ---------- */
.d1, .d2, .d3, .d4, .d5 {
  font-family: var(--disp);
  color: var(--fg);
  text-wrap: balance;
  hyphens: none;
}

.d1 {
  font-weight: 700;
  font-size: var(--d1-size);
  line-height: var(--d1-lh);
  letter-spacing: var(--d1-ls);
  text-transform: uppercase;
}
/* §E2: D1 at its 76px maximum is permitted only against a photograph.
   Over a flat field it is capped at 48px. The surface class enforces it. */
.on-black .d1,
.on-paper .d1 { font-size: clamp(2rem, 3.6vw, 3rem); }

.d2 {
  font-weight: 700;
  font-size: var(--d2-size);
  line-height: var(--d2-lh);
  letter-spacing: var(--d2-ls);
  text-transform: uppercase;
}

.d3 {
  font-weight: 700;
  font-size: var(--d3-size);
  line-height: var(--d3-lh);
  letter-spacing: var(--d3-ls);
}

.d4 {
  font-weight: 600;
  font-size: var(--d4-size);
  line-height: var(--d4-lh);
  letter-spacing: var(--d4-ls);
}

.d5 {
  font-weight: 600;
  font-size: var(--d5-size);
  line-height: var(--d5-lh);
  letter-spacing: var(--d5-ls);
  text-transform: uppercase;
}

/* ---------- figures ---------- */
.n1, .n2 {
  font-family: var(--disp);
  font-weight: 700;
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--fg-figure);
  white-space: nowrap;
}
.n1 { font-size: var(--n1-size); line-height: var(--n1-lh); letter-spacing: var(--n1-ls); }
.n2 { font-size: var(--n2-size); line-height: var(--n2-lh); letter-spacing: var(--n2-ls); }
.n1 .unit, .n2 .unit {
  font-family: var(--mono);
  font-size: var(--m1-size);
  font-weight: 400;
  letter-spacing: var(--m1-ls);
  color: var(--fg-muted);
  margin-left: 0.35em;
  text-transform: uppercase;
}

/* ---------- body ---------- */
.b0, .b1, .b2, .b3 {
  font-family: var(--body);
  font-weight: 400;
  text-wrap: pretty;
}
.b0 {
  font-size: var(--b0-size); line-height: var(--b0-lh);
  letter-spacing: var(--b0-ls); color: var(--fg-dim);
  max-width: var(--b0-measure);
}
.b1 {
  font-size: var(--b1-size); line-height: var(--b1-lh);
  letter-spacing: var(--b1-ls); color: var(--fg-dim);
  max-width: var(--b1-measure);
}
.b2 {
  font-size: var(--b2-size); line-height: var(--b2-lh);
  letter-spacing: var(--b2-ls); color: var(--fg-dense);
  max-width: var(--b2-measure);
}
.b3 {
  font-size: var(--b3-size); line-height: var(--b3-lh);
  letter-spacing: var(--b3-ls); color: var(--fg-muted);
  max-width: var(--b2-measure);
}
/* Run-in label, three words or fewer. Never for emphasis mid-sentence. */
.b1 strong, .b2 strong, .runin { font-weight: 600; color: var(--fg); }

/* ---------- mono ---------- */
.m1, .m2, .m3, .m4 {
  font-family: var(--mono);
  text-transform: uppercase;
  font-variant-numeric: lining-nums tabular-nums;
}
.m1 { font-weight: 500; font-size: var(--m1-size); line-height: var(--m1-lh); letter-spacing: var(--m1-ls); color: var(--fg-code); }
.m2 { font-weight: 500; font-size: var(--m2-size); line-height: var(--m2-lh); letter-spacing: var(--m2-ls); color: var(--fg-accent); }
.m3 { font-weight: 400; font-size: var(--m3-size); line-height: var(--m3-lh); letter-spacing: var(--m3-ls); color: var(--fg-muted); }
.m4 { font-weight: 400; font-size: var(--m4-size); line-height: var(--m4-lh); letter-spacing: var(--m4-ls); color: var(--fg-faint); }

/* ---------- unclassed element defaults ---------- */
h1, h2, h3, h4, h5 { font-family: var(--disp); color: var(--fg); text-wrap: balance; }
h1:not([class]) { font-weight: 700; font-size: clamp(2rem, 3.6vw, 3rem); line-height: var(--d2-lh); letter-spacing: var(--d2-ls); text-transform: uppercase; }
h2:not([class]) { font-weight: 700; font-size: var(--d2-size); line-height: var(--d2-lh); letter-spacing: var(--d2-ls); text-transform: uppercase; }
h3:not([class]) { font-weight: 700; font-size: var(--d3-size); line-height: var(--d3-lh); letter-spacing: var(--d3-ls); }
h4:not([class]) { font-weight: 600; font-size: var(--d4-size); line-height: var(--d4-lh); letter-spacing: var(--d4-ls); }
p:not([class]) { font-size: var(--b1-size); line-height: var(--b1-lh); color: var(--fg-dim); max-width: var(--b1-measure); text-wrap: pretty; }

.gold { color: var(--fg-accent); }
.tnum { font-variant-numeric: lining-nums tabular-nums; }


/* ============================================================
   3 · LAYOUT, BANDS, SURFACES, THE SEAM RULE
   ART-DIRECTION §D1, §D2, §D4. This section is the fix for the
   2,000px of void measured on the first pass. Do not add
   padding-block to a section by hand. Use a band modifier.
   ============================================================ */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--tight { max-width: calc(var(--wrap-tight) + 2 * var(--gutter)); }
.wrap--flush { padding-inline: 0; }

/* ---------- the band ----------
   --pad is the band's own padding budget. Every seam rule below
   works off it, so a modifier only has to change one number. */
.band {
  --pad: var(--pad-std);
  position: relative;
  padding-block: var(--pad);
  background: var(--surface);
  color: var(--fg-dim);
}
.band--tight  { --pad: var(--pad-tight); }
.band--anchor { --pad: var(--pad-anchor); }
.band--bleed  { --pad: 0px; }

/* §D2 THE SEAM RULE. Padding is paid once per seam, not twice.
   Two standard desktop bands cost 54px at the join, not 108px.

   EVERY SEAM BONUS BELOW IS CLAMPED TO --seam-max. See the ruling
   at tokens.css §4: §D2's flat 1.5x register bonus produced 120px
   seams against §D3's 96px ceiling, so the bonus is now paid only
   out of the headroom the ceiling leaves. The clamp is what makes
   the void ceiling structural rather than something QC finds after
   the fact, and it holds even if a page overrides --pad.

   The headroom is measured against --pad-std, not against this
   band's own --pad, because the band paying the other half of the
   seam is the one ABOVE and CSS cannot read a previous sibling's
   custom property. --pad-std is the worst case it can be paying.
   Consequence, and the only one: a band that raises its own --pad
   above --pad-std must not sit directly above a register change. No
   band on the site does; the page-level overrides all go downward. */
.band + .band { padding-top: 0; }

/* Register change earns up to 1.5x the standard gap and a gold
   hairline. The previous band already paid 1.0, so this side pays
   0.5, or whatever is left under the ceiling, whichever is less.
   If nothing is left it pays nothing and the hairline alone marks
   the change, which is what §D4 asks for anyway. */
.band.on-paper + .band.on-black,
.band.on-black + .band.on-paper {
  padding-top: clamp(0px, calc(var(--pad) * 0.5), calc(var(--seam-max) - var(--pad-std)));
  border-top: 1px solid var(--gold);
}

/* A full-bleed band pays nothing, so its neighbour restores its own. */
.band--bleed + .band { padding-top: var(--pad); }

/* Except after the hero. AR-1 is the one bleed band that does pay a
   bottom budget, inside .hero-inner, so the band under it was paying
   the seam twice: --pad-tight from the hero and a full --pad from
   itself. This bills only what is left under the ceiling. */
.hero + .band {
  padding-top: min(var(--pad), calc(var(--seam-max) - var(--pad-tight)));
}

/* Any band into the closing plate earns up to 1.25x, same clamp. */
.band + .band.band--cta {
  padding-top: clamp(0px, calc(var(--pad) * 0.25), calc(var(--seam-max) - var(--pad-std)));
}

/* First band on a page that has no hero must clear the fixed nav.
   It bills the tight budget on top of the bar, not the standard one:
   the nav logo is the last ink above it, so a standard budget here
   opens a gap the ceiling cannot carry at 390. */
.band--below-nav { padding-top: calc(var(--nav-h) + var(--pad-tight)); }

/* The footer is not a band, and on every page it sits outside <main>,
   so neither the seam rule nor an adjacent-sibling selector reaches
   it. Without this the last band's bottom budget and the footer's own
   top budget stack, which is the one seam on the site that was still
   being paid twice. Both shapes are covered. */
main > .band:last-child,
.band:has(+ .foot) { padding-bottom: min(var(--pad), var(--pad-tight)); }

/* ---------- surfaces, §D4 ----------
   Four surfaces are in play: black, raised black, paper, photograph.
   No more than two consecutive bands may share one surface value.
   These classes re-declare the context tokens. Every component in
   section 5 and 6 reads those tokens, so nothing is duplicated
   per surface. */
/* The black register. Also the register a steel plate carries,
   which is why .plate and .cta-plate re-apply this same set even
   when the band around them is paper. */
.on-black,
.on-photo {
  --surface: var(--surface-0);
  --surface-well: var(--surface-2);
  --fg: var(--on-black);
  --fg-dim: var(--on-black-dim);
  --fg-dense: var(--on-black-dim);
  --fg-muted: var(--on-black-muted);
  --fg-faint: var(--on-black-faint);
  --fg-accent: var(--gold-rich);
  --fg-figure: var(--gold-rich);
  --fg-code: var(--gold);
  --hair: var(--rule-soft);
  --hair-strong: var(--rule-strong);
  --hair-gold: var(--rule);
  --rule-heavy: var(--gold);
  --focus: var(--gold-rich);
  --tile-field: linear-gradient(158deg, rgba(227, 151, 76, 0.17) 0%, rgba(227, 151, 76, 0.045) 62%), var(--surface-1);
  --tile-edge: rgba(227, 151, 76, 0.34);
  --tile-riser: rgba(227, 151, 76, 0.34);
  color: var(--fg-dim);
}
.on-black.raised { --surface: var(--surface-1); --surface-well: var(--black); }
/* On the raised value the tile field has to climb with the band or it
   stops reading as raised. */
.on-black.raised {
  --tile-field: linear-gradient(158deg, rgba(227, 151, 76, 0.20) 0%, rgba(227, 151, 76, 0.06) 62%), var(--surface-2);
}
.on-photo { --surface: transparent; background: var(--black); }

.on-paper {
  --surface: var(--paper);
  --surface-well: var(--paper-deep);
  --fg: var(--ink);
  --fg-dim: var(--ink);
  /* Dense body on paper sits a touch off pure ink, per PROTO .desc-cell. */
  --fg-dense: var(--ink-soft);
  --fg-muted: var(--grey);
  --fg-faint: var(--grey);
  --fg-accent: var(--ink);
  /* Paper figures are ink. Gold on paper is rules, never a figure. */
  --fg-figure: var(--ink);
  --fg-code: var(--gold-deep);
  --hair: var(--hairline);
  --hair-strong: var(--hairline);
  --hair-gold: rgba(227, 151, 76, 0.5);
  --rule-heavy: var(--ink);
  --focus: var(--gold-deep);
  /* Paper tiles carry a stronger wash, because paper absorbs a tint
     that black amplifies. Ink on this field measures 13.4:1. */
  --tile-field: linear-gradient(158deg, rgba(227, 151, 76, 0.26) 0%, rgba(227, 151, 76, 0.08) 62%), var(--paper);
  --tile-edge: rgba(227, 151, 76, 0.55);
  --tile-riser: rgba(227, 151, 76, 0.55);
  background: var(--paper);
  color: var(--ink);
}


/* ============================================================
   4 · SIGNATURE ELEMENTS, DESIGN-SYSTEM §3
   ============================================================ */

/* ---------- 4.1 I-beam section header ----------
   Thick flange, web row with title and mono ref, thin flange.
   Replaces all kickers and eyebrows.
   BUDGET: maximum four per page, §D5. Never two in a row. */
.ibeam {
  margin-bottom: var(--s-6);
  border-top: var(--flange-thick) solid var(--rule-heavy);
  border-bottom: var(--flange-thin) solid var(--hair);
}
.ibeam-web {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  padding: 8px 0 7px;
}
.ibeam-title {
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d5-size);
  line-height: 1.15;
  letter-spacing: var(--d5-ls);
  text-transform: uppercase;
  color: var(--fg);
}
.ibeam-ref {
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--m1-size);
  letter-spacing: var(--m1-ls);
  text-transform: uppercase;
  color: var(--fg-code);
  white-space: nowrap;
}

/* ---------- 4.2 steel plate ----------
   Black block, 4px gold base rule, chamfered corners.
   PROTO .terms cuts bottom-right and top-left. */
.plate {
  background: var(--surface-1);
  border-top: var(--plate-rule) solid var(--gold);
  padding: var(--s-6);
}
.plate--chamfer {
  clip-path: polygon(
    var(--chamfer) 0, 100% 0,
    100% calc(100% - var(--chamfer)), calc(100% - var(--chamfer)) 100%,
    0 100%, 0 var(--chamfer)
  );
}
.plate--quiet { border-top-color: var(--hair-gold); }
/* A plate always carries the black register, even inside a paper
   band. It re-declares the full context set so nothing from the
   paper band leaks into it. */
.on-paper .plate,
.cta-plate {
  --surface: var(--black);
  --surface-well: var(--surface-2);
  --fg: var(--on-black);
  --fg-dim: var(--on-black-dim);
  --fg-dense: var(--on-black-dim);
  --fg-muted: var(--on-black-muted);
  --fg-faint: var(--on-black-faint);
  --fg-accent: var(--gold-rich);
  --fg-figure: var(--gold-rich);
  --fg-code: var(--gold);
  --hair: var(--rule-soft);
  --hair-strong: var(--rule-strong);
  --hair-gold: var(--rule);
  --rule-heavy: var(--gold);
  --focus: var(--gold-rich);
  --tile-field: linear-gradient(158deg, rgba(227, 151, 76, 0.20) 0%, rgba(227, 151, 76, 0.06) 62%), var(--surface-1);
  --tile-edge: rgba(227, 151, 76, 0.34);
  --tile-riser: rgba(227, 151, 76, 0.34);
  background: var(--black);
  color: var(--on-black-dim);
}

/* ---------- 4.3 plated image frame, §F2 ----------
   Straight edges, 1px border, no rounding, no shadow.
   The frame's aspect-ratio must sit within 15% of the source's own. */
.framed {
  position: relative;
  display: block;
  border: 1px solid var(--hair-gold);
  background: var(--surface-well);
  overflow: hidden;
}
.framed > img,
.framed > video { width: 100%; height: 100%; object-fit: cover; }
.framed--chamfer {
  clip-path: polygon(
    12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px
  );
}
/* §F3: every photograph earns a caption on its own line, 12px gap. */
.cap {
  display: block;
  margin-top: 12px;
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--m3-size);
  line-height: var(--m3-lh);
  letter-spacing: var(--m3-ls);
  text-transform: uppercase;
  color: var(--fg-muted);
}
figure { margin: 0; }

/* ---------- 4.4 certification seal ----------
   Double ring, an object, not a logo. AR-10 requires 150px and
   requires it to overlap the plate edge by ~40% of its diameter. */
.seal {
  position: relative;
  width: var(--seal-size);
  height: var(--seal-size);
  flex: none;
  display: grid;
  place-items: center;
  text-align: center;
  border: 3px solid var(--gold);
  border-radius: 50%;
  background: var(--black);
  font-family: var(--disp);
}
.seal::before {
  content: "";
  position: absolute;
  inset: 7px;
  border-radius: 50%;
  border: 1px solid var(--gold-rich);
}
.seal-1 { font-size: 0.5rem; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--gold-rich); }
.seal-2 { font-size: 1.75rem; font-weight: 700; line-height: 1.05; margin: 3px 0; color: var(--paper); }
.seal-3 { font-size: 0.4375rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--on-black-muted); }
.seal--overlap {
  position: absolute;
  right: var(--s-6);
  top: calc(var(--seal-size) * -0.4);
  z-index: 2;
}

/* ---------- 4.5 engineering title block ----------
   Bordered grid of mono-labelled fields. PROTO .tblock. */
/* Grid lines are made by a 1px gap over a gold backing, not by
   per-cell borders. That removes all the nth-child arithmetic and
   keeps the joins perfectly square at every column count. */
.tblock {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1px;
  background: rgba(227, 151, 76, 0.45);
  border: 1px solid rgba(227, 151, 76, 0.45);
}
.tblock-cell {
  padding: 14px 18px 12px;
  background: var(--black);
}
.tblock-label {
  font-family: var(--mono);
  font-size: 0.5rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.tblock-value {
  font-family: var(--disp);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.25;
  margin-top: 5px;
  color: var(--fg);
}
.tblock-value.gold { color: var(--fg-accent); }

/* ---------- 4.6 blueprint grid ----------
   §3.7 and AR-8: black covers only, never on reading pages.
   On this site it appears in exactly one place, the diagram plate. */
.blueprint { position: relative; isolation: isolate; }
.blueprint::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: var(--grid-cell) var(--grid-cell);
  pointer-events: none;
}

/* ---------- 4.7 beamline ----------
   Mono caption left and right with a beam rule spanning between. */
.beamline {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  font-family: var(--mono);
  font-size: var(--m4-size);
  letter-spacing: var(--m4-ls);
  text-transform: uppercase;
  color: var(--fg-faint);
}
/* The beam sits between the two captions as its own element,
   exactly as PROTO .foot .beamline does. */
.beamline .beam {
  flex: 1 1 40px;
  height: 5px;
  border-top: 2px solid var(--rule-heavy);
  border-bottom: 1px solid var(--hair);
}
.beamline b { color: var(--fg-accent); font-weight: 500; }


/* ============================================================
   5 · SECTION ARCHETYPES
   Ten patterns. A page is assembled from these and nothing else.
   ============================================================ */

/* ------------------------------------------------------------
   AR-1 · PLATE HERO
   Full-bleed image statement, viewport anchored. One per page,
   always first. Never 100svh: 88svh leaves a sliver of the next
   band visible, which is what doubles scroll rate.
   ------------------------------------------------------------ */
.hero {
  position: relative;
  display: grid;
  align-items: end;
  min-height: 560px;
  height: min(84svh, 620px);
  overflow: hidden;
  isolation: isolate;
}
.hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* §AR-1: crop so the subject sits in the outer 55% and the type
     sits in the inner 45%. Set per page with --hero-pos. */
  object-position: var(--hero-pos, 68% 50%);
  z-index: -2;
}
/* Directional scrim tuned to a left-set headline, plus a bottom fade
   that hands off to the next band. Never filter: brightness(). */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to top, var(--black) 0%, transparent 18%),
    linear-gradient(100deg,
      rgba(11, 10, 9, 0.90) 0%,
      rgba(11, 10, 9, 0.72) 34%,
      rgba(11, 10, 9, 0.18) 62%,
      rgba(11, 10, 9, 0.05) 100%);
}
.hero--right { --hero-pos: 28% 50%; }
.hero--right::before {
  background:
    linear-gradient(to top, var(--black) 0%, transparent 18%),
    linear-gradient(260deg,
      rgba(11, 10, 9, 0.90) 0%,
      rgba(11, 10, 9, 0.72) 34%,
      rgba(11, 10, 9, 0.18) 62%,
      rgba(11, 10, 9, 0.05) 100%);
}
.hero-inner {
  padding-block: var(--pad-std) var(--pad-tight);
  display: grid;
  gap: var(--s-4);
  justify-items: start;
}
.hero--right .hero-inner { justify-items: end; text-align: right; margin-left: auto; }
.hero-inner .b0 { max-width: 44ch; }
.hero .btn-row { margin-top: var(--s-2); }
/* A gold hairline closes every full-bleed band, §F2. */
.hero::after,
.statement::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--gold);
  z-index: 1;
}

/* ------------------------------------------------------------
   AR-2 · SPEC LEDGER
   Dense bordered rows with gold mono ref codes. The workhorse.
   Replaces every tile grid, card grid and stat chip.
   4 rows minimum, 8 maximum. A 5 row ledger lands at 340 to 400px.
   ------------------------------------------------------------ */
.ledger { width: 100%; border-top: 2px solid var(--rule-heavy); }
.ledger-row {
  display: grid;
  grid-template-columns: 76px minmax(180px, 1.1fr) minmax(0, 2fr) auto;
  align-items: baseline;
  column-gap: var(--s-5);
  row-gap: var(--s-2);
  padding-block: 20px;
  border-bottom: 1px solid var(--hair);
}
.ledger-row:last-child { border-bottom: none; }
.ledger-ref {
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--m1-size);
  letter-spacing: var(--m1-ls);
  text-transform: uppercase;
  color: var(--fg-code);
}
.ledger-label {
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d4-size);
  line-height: var(--d4-lh);
  letter-spacing: var(--d4-ls);
  color: var(--fg);
}
.ledger-note {
  font-size: var(--b2-size);
  line-height: var(--b2-lh);
  letter-spacing: var(--b2-ls);
  color: var(--fg-dense);
  max-width: 52ch;
}
.ledger-value {
  font-family: var(--disp);
  font-weight: 700;
  font-variant-numeric: lining-nums tabular-nums;
  font-size: var(--n1-size);
  line-height: var(--n1-lh);
  letter-spacing: var(--n1-ls);
  color: var(--fg-figure);
  white-space: nowrap;
  justify-self: end;
  text-align: right;
}
.ledger-value .unit {
  display: block;
  font-family: var(--mono);
  font-size: var(--m1-size);
  font-weight: 400;
  letter-spacing: var(--m1-ls);
  color: var(--fg-muted);
  margin-top: 4px;
}
/* The ledger closes with a 2px rule and an M4 foot line. */
.ledger-foot {
  border-top: 2px solid var(--rule-heavy);
  padding-top: 10px;
  font-family: var(--mono);
  font-size: var(--m4-size);
  line-height: var(--m4-lh);
  letter-spacing: var(--m4-ls);
  text-transform: uppercase;
  color: var(--fg-faint);
}
/* Compact variant for lists of short rows, AR-9 city rows and the
   "what we look for" ledger. No note column, no figure. */
.ledger--compact .ledger-row {
  grid-template-columns: 76px 1fr auto;
  padding-block: 12px;
}

/* AR-2 says a set over eight rows splits into two ledgers under one
   I-beam. That is a property of the archetype, not of a page, so the
   grouping lives here. The Coating lane and the Partners lane both
   built a version of it locally.
     .ledger-group  one ledger plus its own small head
     .ledger-head   a D5 or M1 head over a ledger inside a group
     .ledger--nofig a ledger that carries findings rather than
                    figures: the value column is dropped and the note
                    takes the width back. */
/* Two ledgers under one I-beam are one object, so the gap between
   them is a paragraph break, not a seam. --s-6 read as a void inside
   the band at tablet width and tripped the ceiling. */
.ledger-group + .ledger-group { margin-top: var(--s-5); }
.ledger-head {
  margin-bottom: var(--s-3);
  color: var(--fg-muted);
}
.ledger--nofig .ledger-row {
  grid-template-columns: 76px minmax(180px, 1.1fr) minmax(0, 2.4fr);
}
.ledger--nofig .ledger-note { max-width: 62ch; }

/* ------------------------------------------------------------
   AR-2b · TILES
   DESIGN-SYSTEM §3b, standing ruling, Alex, Aug 18 2026.

   THE RULING, IN ONE LINE
   Default to tiles. Fall back to a ledger only when the content is
   genuinely tabular: a value column the reader compares downward,
   row by row technical data, test results. Everything else, three
   to six parallel items each carrying a headline and a line of
   support, is a tile set. The ledger used for that material "looks
   like an accounting document and boring" and spends far too much
   page on what it says.

   WHAT MAKES A TILE CORRECT
   1. The chamfered corner cut, --tile-chamfer, which is --chamfer,
      which is the same token the buttons and the plates cut with.
      One geometry language across the whole site.
   2. Colour, not flat black. A gold washed field, a gold edge and a
      gold flange. A low opacity photograph behind it is sanctioned
      and is the --image variant.
   3. It sits slightly proud of the page: a hard gold riser under the
      chamfered silhouette, and a subtle lift on hover.
   4. Never a white card, never a rounded corner, never a soft drop
      shadow. Never the retired "tile grid" dialect either: that ban
      was about generic three across icon cards with no substance.
      These carry real content in the house geometry.

   DENSITY IS THE POINT. Measured in _ART/kitchen-sink.html, which
   carries the same five specification items twice, once as a ledger
   and once as a 3-up figure tile set:

       width   ledger   tiles   saved
       1280      517     357     31%
        768      500     329     34%
        390      688     589     14%

   (object only; add 28px of ledger foot to either.) A tile set that
   is taller than the ledger it replaces has failed its only brief,
   so re-measure when you change the padding or the grid.

   TWO IMPLEMENTATION NOTES, BOTH LOAD BEARING
   - clip-path clips box-shadow and outline away, so the riser is
     drawn with filter: drop-shadow at zero blur, which is applied
     after the clip and therefore follows the chamfer. Zero blur
     makes it a base rule under a plate, DESIGN-SYSTEM §3.3, not a
     soft drop shadow. For the same reason a linked tile focuses
     with outline-offset: -3px, inside its own edge.
   - Every colour reads a context token, so one component works on
     black and on paper. Do not write a per surface copy.
   ------------------------------------------------------------ */

.tilegrid {
  display: grid;
  gap: clamp(10px, 1.4vw, 16px);
  /* The riser hangs below the last row and the lift raises the first,
     so the grid reserves its own room rather than eating the seam. */
  padding-bottom: var(--tile-riser-y);
}
/* 390 is one column for 2-up and 3-up. A 4-up set is figures, which
   are short, so it pairs rather than stacking to four screens. */
.tilegrid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Five across in one row. Client, Aug 20 2026: a five item set is short
   enough that stacking it wastes the horizontal space we have. Two up on a
   phone with the fifth running full width, three up on a tablet, then all
   five in a single row from 1100 where each column still clears 180px. */
.tilegrid--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tilegrid--5 > :last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (min-width: 560px) {
  .tilegrid--2,
  .tilegrid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* 3-up arrives at 768, not 1024. Held back to 1024 a 3-up set spends
   three tablet rows on five items and measures taller than the ledger
   it replaces, which fails its only brief. */
@media (min-width: 768px) {
  .tilegrid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .tilegrid--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Back to normal flow: at 3-up the fifth tile is the second item of the
     second row, not a stranded odd one. */
  .tilegrid--5 > :last-child:nth-child(odd) { grid-column: auto; }
}
@media (min-width: 1024px) {
  .tilegrid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 1100px) {
  .tilegrid--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

.tile {
  position: relative;
  isolation: isolate;
  display: grid;
  align-content: start;
  gap: 6px;
  padding: 16px 18px 18px;
  background: var(--tile-field);
  border: 1px solid var(--tile-edge);
  border-top: var(--flange-thick) solid var(--gold);
  color: var(--fg-dense);
  clip-path: polygon(
    var(--tile-chamfer) 0, 100% 0,
    100% calc(100% - var(--tile-chamfer)), calc(100% - var(--tile-chamfer)) 100%,
    0 100%, 0 var(--tile-chamfer)
  );
  filter: drop-shadow(0 var(--tile-riser-y) 0 var(--tile-riser));
  transition:
    transform var(--dur-hover) var(--ease-out),
    filter var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out);
}
/* Softer flange, for a set that sits beside something louder. */
.tile--quiet { border-top-color: var(--hair-gold); }

/* The lift. Hover only where hover is real, so a phone does not hold
   a hover state after a tap. */
@media (hover: hover) and (pointer: fine) {
  .tile:hover {
    transform: translateY(calc(var(--tile-lift) * -1));
    filter: drop-shadow(0 calc(var(--tile-riser-y) + var(--tile-lift)) 0 var(--tile-riser));
    border-color: var(--gold);
  }
}
/* A tile may be a link. Keyboard gets the same lift and a visible
   ring, drawn inside the edge because clip-path would cut an
   outset outline away. */
a.tile:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -3px;
  transform: translateY(calc(var(--tile-lift) * -1));
  filter: drop-shadow(0 calc(var(--tile-riser-y) + var(--tile-lift)) 0 var(--tile-riser));
  border-color: var(--gold);
}

/* ---------- tile contents ---------- */
.tile-ref {
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--m1-size);
  line-height: var(--m1-lh);
  letter-spacing: var(--m1-ls);
  text-transform: uppercase;
  color: var(--fg-code);
}
.tile-figure {
  font-family: var(--disp);
  font-weight: 700;
  font-variant-numeric: lining-nums tabular-nums;
  font-size: clamp(2rem, 3.4vw, 2.75rem);
  line-height: 1;
  letter-spacing: var(--n1-ls);
  color: var(--fg-figure);
  white-space: nowrap;
}
/* Inline, not stacked. A stacked unit is the ledger's habit and it
   costs a whole line of height per tile. */
.tile-figure .unit {
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--m1-size);
  letter-spacing: var(--m1-ls);
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-left: 0.35em;
}
.tile-label {
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d4-size);
  line-height: var(--d4-lh);
  letter-spacing: var(--d4-ls);
  color: var(--fg);
}
.tile-head {
  font-family: var(--disp);
  font-weight: 700;
  font-size: clamp(1.125rem, 1.7vw, 1.375rem);
  line-height: 1.1;
  letter-spacing: var(--d3-ls);
  color: var(--fg);
  text-wrap: balance;
}
.tile-note {
  font-size: var(--b3-size);
  line-height: var(--b3-lh);
  letter-spacing: var(--b3-ls);
  color: var(--fg-dense);
  max-width: 38ch;
  text-wrap: pretty;
}
.tile-cap {
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--m3-size);
  line-height: var(--m3-lh);
  letter-spacing: var(--m3-ls);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.tile .link-arrow { margin-top: 4px; justify-self: start; }

/* ---------- variant: figure ----------
   The replacement for a spec ledger used on parallel items. Big
   number, label, one line of support. Ref code optional. */
.tile--figure { gap: 4px; }
.tile--figure .tile-ref { margin-bottom: 2px; }
.tile--figure .tile-label { margin-top: 2px; }

/* Below 560 a stacked figure tile is taller than the ledger row it
   replaces, so the figure moves beside the text instead of above it.
   Same markup, same four elements, no page has to know. */
@media (max-width: 559px) {
  .tile { padding: 13px 15px 15px; }
  .tile--figure {
    grid-template-columns: minmax(76px, auto) minmax(0, 1fr);
    column-gap: 15px;
    row-gap: 3px;
  }
  .tile--figure .tile-ref    { grid-column: 1 / -1; grid-row: 1; margin-bottom: 0; }
  .tile--figure .tile-figure { grid-column: 1; grid-row: 2 / span 2; align-self: start; }
  .tile--figure .tile-label  { grid-column: 2; grid-row: 2; margin-top: 0; }
  .tile--figure .tile-note   { grid-column: 2; grid-row: 3; }
  /* A 4-up set of bare figures keeps the stacked reading, there is no
     note to sit beside. */
  .tilegrid--4 .tile--figure { grid-template-columns: minmax(0, 1fr); }
  .tilegrid--4 .tile--figure .tile-figure { grid-column: 1; grid-row: auto; }
  .tilegrid--4 .tile--figure .tile-label { grid-column: 1; grid-row: auto; }
}

/* ---------- variant: statement ----------
   Headline and support. Three to six per set. */
.tile--statement { gap: 8px; padding-block: 18px 20px; }
.tile--statement .tile-note { max-width: 44ch; }

/* ---------- variant: image ----------
   A photograph behind the tile at low strength, text over it.
   The tile carries the BLACK register whatever band it sits in,
   because ink on a photograph is not legible, exactly as .plate
   does. It re-declares the context set rather than being copied
   per surface.

   ART-DIRECTION §F5.6 bans an image under 40% opacity used as a
   texture behind body copy. DESIGN-SYSTEM §3b, which is newer and
   is the law, sanctions a low opacity image behind a tile. Both
   hold at 0.45 plus a directional scrim, which is what ships. */
.tile--image {
  --fg: var(--on-black);
  --fg-dim: var(--on-black-dim);
  --fg-dense: var(--on-black-dim);
  --fg-muted: var(--on-black-muted);
  --fg-faint: var(--on-black-faint);
  --fg-accent: var(--gold-rich);
  --fg-figure: var(--gold-rich);
  --fg-code: var(--gold);
  --focus: var(--gold-rich);
  --tile-img-opacity: 0.45;
  background: var(--black);
  color: var(--on-black-dim);
  min-height: 200px;
  align-content: end;
  padding: 20px;
}
.tile-img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--tile-img-pos, 50% 50%);
  opacity: var(--tile-img-opacity);
}
/* Directional scrim, tuned to type set at the foot of the tile.
   Never filter: brightness(), it flattens the gloss. */
.tile--image::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to top,
    rgba(11, 10, 9, 0.92) 0%,
    rgba(11, 10, 9, 0.66) 46%,
    rgba(11, 10, 9, 0.30) 100%);
}
.tile--image .tile-cap { color: var(--on-black-muted); }

/* ------------------------------------------------------------
   AR-3 · FULL-BLEED STATEMENT BAND
   A photograph and one line of display type. The page's
   punctuation. Deliberately short. No paragraph, no button.
   Maximum two per page, never adjacent.
   ------------------------------------------------------------ */
.statement {
  position: relative;
  display: grid;
  align-items: center;
  height: clamp(300px, 44vh, 460px);
  overflow: hidden;
  isolation: isolate;
  border-top: 1px solid var(--gold);
}
.statement-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--statement-pos, 50% 50%);
  z-index: -2;
}
.statement::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg,
    rgba(11, 10, 9, 0.82) 0%,
    rgba(11, 10, 9, 0.55) 40%,
    rgba(11, 10, 9, 0.10) 78%,
    rgba(11, 10, 9, 0.02) 100%);
}
.statement-inner { display: grid; gap: var(--s-4); align-content: center; }
.statement-inner .d2 { max-width: 20ch; }
.statement-cap {
  position: absolute;
  left: var(--gutter);
  bottom: var(--s-5);
  font-family: var(--mono);
  font-size: var(--m3-size);
  letter-spacing: var(--m3-ls);
  text-transform: uppercase;
  color: var(--on-black-muted);
  z-index: 1;
}

/* ------------------------------------------------------------
   AR-4 · SPLIT EDITORIAL
   Two columns: argument and evidence. The default reading section.
   align-items: start, never center. Centre alignment is what
   produced the 200px voids under short columns on the first pass.
   Never twice in a row with the same column order.
   ------------------------------------------------------------ */
.split {
  display: grid;
  gap: var(--s-6);
  align-items: start;
}
.split-text { display: grid; gap: var(--s-4); align-content: start; justify-items: start; }
.split-media { display: grid; align-content: start; }
.split--flip .split-media { order: -1; }

/* justify-items: start on .split-text and .cta-left shrink-wraps every
   child to its own content width, which is right for type and wrong for
   anything that is structurally a full-width object. Three page lanes
   hit this separately (an accordion, a form, a title block), so the
   objects that always want the column are named here once. Anything
   else takes the .stretch utility. */
.split-text > .acc,
.split-text > .ledger,
.split-text > .tilegrid,
.split-text > .form,
.split-text > form,
.split-text > table,
.split-text > .notice,
.split-text > .tabs,
.cta-left > .acc,
.cta-left > .ledger,
.cta-left > .tilegrid,
.cta-left > .form,
.cta-left > form,
.cta-left > table,
.cta-left > .notice,
.cta-left > .tabs,
.stretch {
  justify-self: stretch;
  width: 100%;
}

/* Three column variant, paper only, hairline between columns.
   The only sanctioned way to put three things side by side.
   Columns with rules between them, not cards. */
.cols-3 { display: grid; gap: 0; }
.cols-3 > * {
  padding-block: var(--s-5) 0;
  border-top: 1px solid var(--hair);
  display: grid;
  gap: var(--s-3);
  align-content: start;
}

/* ------------------------------------------------------------
   AR-5 · COMPARISON TABLE
   Paper register only. A comparison is a document and a document
   is paper. No tick and cross iconography, numbers and short noun
   phrases only. Densest object on the site.

   Mobile does not scroll and does not collapse to cards. Supply
   .compare-stack alongside .compare-table: one shows, one hides.
   ------------------------------------------------------------ */
/* REVISION, Aug 20 2026. Client on the first pass: "now this makes
   sense to be a chart, but it's boring again, how can we spruce this
   up a bit but still keep it a side by side comparison?"

   Side by side is kept, because the comparison IS the point. What
   changed, per DESIGN-SYSTEM §3b's closing paragraph:
     - the ICON column is the SUBJECT, not one grey column of four.
       It gets a 2px gold rule left and right running the whole table
       height, a 13% wash instead of 7%, a gold flange across the top
       of its header cell, and a 3px gold rule closing it at the foot.
     - the header plate now separates the subject from the field: the
       ICON head is gold-rich in Chakra 700, the rivals sit at the
       muted value.
     - row rhythm: the attribute column is set in the display face so
       it reads as a label rail rather than more body copy, alternate
       rows carry a paper-deep wash so the eye tracks across a five
       column row, and the row height drops from 14px to 11px.
     - a row lights up on hover where hover is real. */
.compare-table { width: 100%; border-collapse: collapse; }
.compare-table thead th {
  background: var(--black);
  color: var(--on-black-muted);
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d5-size);
  line-height: 1.2;
  letter-spacing: var(--d5-ls);
  text-transform: uppercase;
  text-align: left;
  padding: 15px 13px 13px;
  vertical-align: bottom;
  border-bottom: var(--plate-rule) solid var(--gold);
}
/* The first head is the rail's own label, quieter still. */
.compare-table thead th:first-child {
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--m1-size);
  letter-spacing: var(--m1-ls);
  color: var(--on-black-faint);
}
.compare-table tbody th {
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d4-size);
  line-height: 1.3;
  letter-spacing: var(--d4-ls);
  text-align: left;
  color: var(--fg);
  padding: 11px 13px;
  vertical-align: top;
}
.compare-table tbody td {
  font-size: var(--b2-size);
  line-height: var(--b2-lh);
  color: var(--fg-dense);
  padding: 11px 13px;
  vertical-align: top;
}
.compare-table tbody tr { border-bottom: 1px solid var(--hair); }
/* Row rhythm. A five column row is a long way for the eye to travel,
   so alternate rows carry a wash. The ICON cell paints its own
   background over this, which is the intended stacking. */
.compare-table tbody tr:nth-child(even) { background: var(--paper-deep); }
.compare-table tbody tr:last-child { border-bottom: 2px solid var(--rule-heavy); }
@media (hover: hover) and (pointer: fine) {
  .compare-table tbody tr { transition: background var(--dur-hover) var(--ease-out); }
  .compare-table tbody tr:hover { background: rgba(227, 151, 76, 0.09); }
}
/* The ICON column is the subject: 2px gold rules the full table
   height, a 13% wash, figures in the display face. Every other
   column is plain, which is what makes this one read. */
.compare-table .is-icon {
  background: var(--tint-gold-2);
  border-left: 2px solid var(--gold);
  border-right: 2px solid var(--gold);
  color: var(--ink);
  font-variant-numeric: lining-nums tabular-nums;
}
/* The header cell of the subject column is a gold-capped plate. */
.compare-table thead .is-icon {
  background: var(--black);
  color: var(--gold-rich);
  font-weight: 700;
  box-shadow: inset 0 var(--plate-rule) 0 var(--gold);
  padding-top: 19px;
}
/* The subject's values are set in the display face at every width.
   The SIZE only steps up at 1024, because between 768 and 1023 five
   columns share about 700px and a page is entitled to tighten the
   cell there (the-coating does). A hard size here would override
   that tightening on the one column that can least afford it. */
.compare-table tbody .is-icon {
  font-family: var(--disp);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: var(--d4-ls);
}
@media (min-width: 1024px) {
  .compare-table tbody .is-icon { font-size: var(--d4-size); }
}
/* The subject column closes on its own rule, heavier than the table's. */
.compare-table tbody tr:last-child .is-icon {
  box-shadow: inset 0 -3px 0 var(--gold);
}
.compare-foot {
  margin-top: 10px;
  font-family: var(--mono);
  font-size: var(--m4-size);
  letter-spacing: var(--m4-ls);
  text-transform: uppercase;
  color: var(--fg-faint);
}
/* Mobile reformat: one ledger per comparand, ICON first. */
.compare-stack { display: grid; gap: var(--s-6); }
.compare-stack-head {
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d5-size);
  letter-spacing: var(--d5-ls);
  text-transform: uppercase;
  color: var(--fg);
  padding-bottom: 8px;
  border-bottom: 2px solid var(--rule-heavy);
}
.compare-stack-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s-4);
  padding-block: 11px;
  border-bottom: 1px solid var(--hair);
  font-size: var(--b2-size);
}
.compare-stack-row dt { color: var(--fg-muted); }
.compare-stack-row dd { color: var(--fg); font-weight: 600; text-align: right; }
/* On mobile the subject block gets the tile treatment, so the same
   emphasis survives the reformat: gold field, gold flange, the house
   chamfer and the riser. It is the one block a phone reader is meant
   to stop on. */
.compare-stack > .is-icon .compare-stack-head { border-bottom-color: var(--gold); }
.compare-stack > .is-icon {
  background: var(--tile-field);
  border: 1px solid var(--tile-edge);
  border-top: var(--flange-thick) solid var(--gold);
  padding: 14px 16px 16px;
  clip-path: polygon(
    var(--tile-chamfer) 0, 100% 0,
    100% calc(100% - var(--tile-chamfer)), calc(100% - var(--tile-chamfer)) 100%,
    0 100%, 0 var(--tile-chamfer)
  );
  filter: drop-shadow(0 var(--tile-riser-y) 0 var(--tile-riser));
}
.compare-stack > .is-icon .compare-stack-row:last-child { border-bottom: none; }

/* ------------------------------------------------------------
   AR-6 · PROOF WALL
   Press, testimonials and installs. Dense by design.
   Rules between, never boxes around. Never a card grid.
   ------------------------------------------------------------ */
.pressrow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(24px, 5vw, 72px);
  padding-block: 28px;
  border-top: 1px solid var(--hair-gold);
  border-bottom: 1px solid var(--hair-gold);
}
.pressrow .m2 { flex: none; }
.pressrow img {
  height: 32px;
  width: auto;
  opacity: 0.72;
  filter: grayscale(1) brightness(1.6);
}
.on-paper .pressrow img { filter: grayscale(1) brightness(0.35); opacity: 0.8; }
.pressrow-mark {
  font-family: var(--disp);
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-muted);
}

/* Testimonial wall: two column masonry separated by hairlines,
   every third slot may hold a plated install photograph. */
.quotewall { columns: 1; column-gap: var(--s-7); }
.quote {
  break-inside: avoid;
  padding-block: var(--s-5);
  border-bottom: 1px solid var(--hair);
  display: grid;
  gap: var(--s-3);
}
.quote:first-child { padding-top: 0; }
.quote-body {
  font-family: var(--disp);
  font-weight: 700;
  font-size: var(--d3-size);
  line-height: var(--d3-lh);
  letter-spacing: var(--d3-ls);
  color: var(--fg);
  max-width: 34ch;
  text-wrap: balance;
}
.quote-attr {
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--m2-size);
  letter-spacing: var(--m2-ls);
  text-transform: uppercase;
  color: var(--fg-accent);
}

/* ------------------------------------------------------------
   AR-7 · FILM PLATE
   Video framed like a document exhibit. 980px maximum, centred,
   never full width. The native control bar must not be visible
   in the resting state.
   ------------------------------------------------------------ */
.filmplate {
  max-width: 980px;
  margin-inline: auto;
  padding: 10px;
  border: 1px solid var(--hair-gold);
  background: var(--surface-well);
}
.filmframe {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--black);
  overflow: hidden;
}
.filmframe > video,
.filmframe > img { width: 100%; height: 100%; object-fit: cover; }
.filmplay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(11, 10, 9, 0.28);
  cursor: pointer;
  transition: background var(--dur-hover) var(--ease-out);
}
.filmplay::after {
  content: "";
  width: 32px;
  height: 34px;
  background: var(--gold);
  clip-path: polygon(0 0, 100% 50%, 0 100%);
  transition: transform var(--dur-hover) var(--ease-out);
}
.filmplate.is-playing .filmplay { display: none; }
.filmframe .m3 {
  position: absolute;
  left: 14px;
  bottom: 12px;
  color: var(--on-black-muted);
  z-index: 2;
}

/* ------------------------------------------------------------
   AR-8 · DIAGRAM PLATE
   Drawn, not photographed. The 63 micron argument. Black with the
   blueprint grid, the only place on the site the grid appears.
   A raster infographic here is banned. SVG or the section does
   not ship.
   ------------------------------------------------------------ */
.diagram {
  display: grid;
  gap: var(--s-6);
  align-items: center;
}
.diagram-svg { width: 100%; height: auto; }
.diagram-svg .leader { stroke: var(--gold); stroke-width: 1; fill: none; }
/* Sizes are SVG user units, so they scale with the viewBox. Keep the
   viewBox tight to the drawing or the band inherits dead space. */
.diagram-svg .layer-label {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  fill: var(--gold);
}
.diagram-svg .layer-note {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  fill: var(--on-black-muted);
}
/* An SVG scaled into a 350px column renders its labels at half size,
   which is illegible. Supply two drawings, the same way AR-5 supplies
   a table and a stack: a wide one with labels in the right margin and
   a stacked one with labels under the drawing. */
.diagram-svg--wide { display: none; }
@media (min-width: 768px) {
  .diagram-svg--wide { display: block; }
  .diagram-svg--stack { display: none; }
}
.diagram-note {
  font-family: var(--mono);
  font-size: var(--m4-size);
  letter-spacing: var(--m4-ls);
  text-transform: uppercase;
  color: var(--fg-faint);
}

/* ------------------------------------------------------------
   AR-9 · NETWORK LEDGER
   Locations. Paper: a directory is a document. Map plate left,
   indexed city ledger right. Never a bullet list of place names.
   ------------------------------------------------------------ */
.network { display: grid; gap: var(--s-6); align-items: start; }
.network-map { display: grid; align-content: start; }
.city-row {
  display: grid;
  grid-template-columns: 76px 1fr auto;
  align-items: baseline;
  gap: var(--s-4);
  padding-block: 12px;
  border-bottom: 1px solid var(--hair);
}
.city-row:first-child { border-top: 2px solid var(--rule-heavy); }
.city-index {
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--m1-size);
  letter-spacing: var(--m1-ls);
  text-transform: uppercase;
  color: var(--fg-code);
}
.city-name {
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d4-size);
  letter-spacing: var(--d4-ls);
  color: var(--fg);
  transition: color var(--dur-hover) var(--ease-out);
}
a.city-name { border-bottom: 1px solid transparent; }
.city-status {
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--m1-size);
  letter-spacing: var(--m1-ls);
  text-transform: uppercase;
  color: var(--fg-muted);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.city-status::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--gold);
}
/* Coming soon: grey row, hollow marker. */
.city-row.is-soon .city-name { color: var(--fg-muted); }
.city-row.is-soon .city-status::before { background: none; border: 1px solid var(--fg-muted); }

/* ------------------------------------------------------------
   AR-10 · TITLE-BLOCK CTA
   The closing plate, straight from the PROTO cover. One per page.
   One primary button, not two. The seal must overlap the edge.
   ------------------------------------------------------------ */
.cta-plate {
  position: relative;
  background: var(--black);
  /* The plate sits on a black band, so it needs a real edge or it
     dissolves into the field and its internal padding reads as void. */
  border: 1px solid var(--rule);
  border-top: var(--plate-rule) solid var(--gold);
  padding: var(--s-7) var(--s-6) var(--s-6);
  clip-path: polygon(
    var(--chamfer) 0, 100% 0,
    100% calc(100% - var(--chamfer)), calc(100% - var(--chamfer)) 100%,
    0 100%, 0 var(--chamfer)
  );
  display: grid;
  gap: var(--s-6);
  /* Register tokens are set in the shared plate rule in section 4.2. */
}
/* The seal breaks the edge. clip-path on the parent would cut it,
   so the overlap wrapper sits outside the clipped plate. */
.cta-wrap { position: relative; }
.cta-wrap .seal--overlap { top: calc(var(--seal-size) * -0.4); }
.cta-left { display: grid; gap: var(--s-4); justify-items: start; align-content: start; }
/* The plate's second column. Usually the title block on its own; on a
   page whose left column is a form it also carries the direct route
   and the next steps, so the plate does not open a hole under the
   block. The Partners lane and the Support lane both built this. */
.cta-side { display: grid; gap: var(--s-5); align-content: start; }
.cta-price {
  font-family: var(--disp);
  font-weight: 700;
  font-variant-numeric: lining-nums tabular-nums;
  font-size: var(--n2-size);
  color: var(--gold-rich);
  line-height: 1;
}
.cta-price small {
  display: block;
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--m4-size);
  letter-spacing: var(--m4-ls);
  text-transform: uppercase;
  color: var(--on-black-muted);
  margin-top: 6px;
}


/* ============================================================
   6 · COMPONENTS
   ============================================================ */

/* ---------- 6.1 buttons ----------
   Gold fill, black text, chamfered. One primary per section. */
.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.875rem 1.625rem;
  font-family: var(--disp);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.09em;
  line-height: 1.1;
  text-transform: uppercase;
  border: 1px solid transparent;
  clip-path: polygon(
    0 0, 100% 0,
    100% calc(100% - var(--chamfer-sm)), calc(100% - var(--chamfer-sm)) 100%,
    0 100%
  );
  transition:
    background var(--dur-hover) var(--ease-out),
    color var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out),
    transform var(--dur-press) var(--ease-out);
}
.btn:active { transform: scale(0.975); }
.btn-primary { background: var(--gold); color: var(--black); }
.btn-primary:hover { background: var(--gold-rich); color: var(--black); }
.btn-ghost { border-color: var(--hair-strong); color: var(--fg); }
.btn-ghost:hover { border-color: var(--fg-code); color: var(--fg-code); }
.btn-sm { padding: 0.625rem 1.125rem; font-size: 0.6875rem; }

/* ---------- 6.2 link arrow ---------- */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--m2-size);
  letter-spacing: var(--m2-ls);
  text-transform: uppercase;
  color: var(--fg-code);
  padding-bottom: 3px;
  border-bottom: 1px solid var(--hair-gold);
  transition:
    border-color var(--dur-hover) var(--ease-out),
    color var(--dur-hover) var(--ease-out);
}
.link-arrow::after {
  content: "";
  width: 7px; height: 8px;
  background: currentColor;
  clip-path: polygon(0 0, 100% 50%, 0 100%);
  transition: transform var(--dur-hover) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .link-arrow:hover { color: var(--fg-accent); border-bottom-color: var(--gold); }
  .link-arrow:hover::after { transform: translateX(3px); }
  a.city-name:hover { color: var(--fg-accent); border-bottom-color: var(--hair-gold); }
  .filmplay:hover { background: rgba(11, 10, 9, 0.16); }
  .filmplay:hover::after { transform: scale(1.06); }
}
/* Inline text link inside body copy. */
.tlink {
  color: var(--fg);
  border-bottom: 1px solid var(--hair-gold);
  transition: border-color var(--dur-hover) var(--ease-out);
}
.tlink:hover { border-bottom-color: var(--gold); }

/* ---------- 6.3 nav ---------- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 200;
  min-height: var(--nav-h);
  padding: var(--s-3) var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  border-bottom: 1px solid transparent;
  transition:
    background var(--dur-nav) var(--ease-out),
    border-color var(--dur-nav) var(--ease-out);
}
.nav.scrolled {
  background: rgba(11, 10, 9, 0.92);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--rule);
}
.nav-logo img { height: 26px; width: auto; }
.nav-links { display: flex; align-items: center; gap: var(--s-6); }
.nav-links a {
  font-family: var(--body);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--on-black-dim);
  transition: color var(--dur-hover) var(--ease-out);
}
.nav-links a:hover,
.nav-links a[aria-current="page"] { color: var(--on-black); }
.nav-links .btn { color: var(--black); }
.nav-toggle { display: none; padding: 8px; }
.nav-toggle span {
  display: block;
  width: 22px; height: 2px;
  background: var(--on-black);
  margin: 4px 0;
}

/* ---------- 6.4 footer, beamline register ---------- */
.foot {
  border-top: 2px solid var(--gold);
  background: var(--surface-0);
  padding-block: var(--pad-tight);
  --fg: var(--on-black);
  --fg-dim: var(--on-black-dim);
  --fg-muted: var(--on-black-muted);
  --fg-faint: var(--on-black-faint);
  --fg-code: var(--gold);
  --hair: var(--rule-soft);
  --rule-heavy: var(--gold);
  color: var(--on-black-dim);
}
/* REVISION, Aug 20 2026. The footer ran four columns in a 1.4fr 1fr
   1fr grid, so "Owner support" fell to a second row on its own and
   the footer grew a whole extra band of height for one link list.
   All three link columns now sit on one row beside the logo block,
   which is what the width was always there for, and the logo block
   carries the phone and the email under the blurb. */
.foot-grid {
  display: grid;
  gap: var(--s-5);
  padding-bottom: var(--s-5);
}
.foot-logo img { height: 28px; width: auto; margin-bottom: var(--s-3); }
.foot-blurb { font-size: var(--b3-size); color: var(--fg-muted); max-width: 32ch; }
/* Phone and email. Rendered through the marker system from
   data/site.json, never typed into a page: the address may change
   and twenty files is how a site ends up printing a dead one. */
.foot-contact {
  display: grid;
  justify-items: start;
  gap: 5px;
  margin-top: 12px;
}
.foot-contact a {
  font-family: var(--mono);
  font-size: var(--m3-size);
  line-height: 1.5;
  /* Tracked below the M3 value on purpose. The email is 29 characters
     and it has to survive the narrowest logo track, which is 768. */
  letter-spacing: 0.03em;
  color: var(--fg-dim);
  border-bottom: 1px solid transparent;
  transition:
    color var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out);
  overflow-wrap: anywhere;
}
.foot-contact a:hover { color: var(--gold-rich); border-bottom-color: var(--hair-gold); }
.foot-col h4 {
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--m1-size);
  letter-spacing: var(--m1-ls);
  text-transform: uppercase;
  color: var(--fg-code);
  margin-bottom: var(--s-3);
  white-space: nowrap;
}
.foot-col li { margin-bottom: 9px; }
.foot-col li:last-child { margin-bottom: 0; }
.foot-col a {
  font-size: var(--b3-size);
  color: var(--fg-dim);
  transition: color var(--dur-hover) var(--ease-out);
}
.foot-col a:hover { color: var(--gold-rich); }
.foot-beam { border-top: 1px solid var(--hair); padding-top: var(--s-4); }

/* ---------- 6.5 forms ----------
   Fields sit on wells, 1px hairline, gold on focus, chamfered submit. */
.form { display: grid; gap: var(--s-4); }
.form-grid { display: grid; gap: var(--s-4); }
.field { display: grid; gap: 7px; }
.field-label {
  font-family: var(--mono);
  font-weight: 500;
  font-size: var(--m1-size);
  letter-spacing: var(--m1-ls);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.field-label .req { color: var(--fg-code); }
.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 13px 14px;
  font-family: var(--body);
  font-size: var(--b1-size);
  line-height: 1.4;
  color: var(--fg);
  background: var(--surface-well);
  border: 1px solid var(--hair);
  border-radius: 0;
  appearance: none;
  transition:
    border-color var(--dur-hover) var(--ease-out),
    background var(--dur-hover) var(--ease-out);
}
.field textarea { min-height: 118px; resize: vertical; }
.field select {
  background-image: linear-gradient(45deg, transparent 50%, var(--gold) 50%),
                    linear-gradient(135deg, var(--gold) 50%, transparent 50%);
  background-position: calc(100% - 19px) center, calc(100% - 13px) center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 40px;
}
.field input::placeholder,
.field textarea::placeholder { color: var(--fg-faint); }
.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--gold);
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}
.field-note {
  font-family: var(--mono);
  font-size: var(--m4-size);
  letter-spacing: var(--m4-ls);
  text-transform: uppercase;
  color: var(--fg-faint);
}
/* Checkbox and radio, square, gold fill when on. */
.check { display: grid; grid-template-columns: auto 1fr; gap: 11px; align-items: start; }
.check input[type="checkbox"],
.check input[type="radio"] {
  width: 17px; height: 17px;
  margin-top: 2px;
  appearance: none;
  background: var(--surface-well);
  border: 1px solid var(--hair);
  border-radius: 0;
  display: grid;
  place-items: center;
  cursor: pointer;
}
.check input:checked { background: var(--gold); border-color: var(--gold); }
.check input:checked::after {
  content: "";
  width: 9px; height: 9px;
  background: var(--black);
  clip-path: polygon(14% 47%, 0 61%, 39% 100%, 100% 22%, 86% 8%, 39% 71%);
}
.check input[type="radio"] { border-radius: 50%; }
.check input[type="radio"]:checked::after { clip-path: circle(50%); width: 7px; height: 7px; }
.check label { font-size: var(--b2-size); color: var(--fg-dense); }

/* Form status panel. Every form on the site can land without an
   endpoint configured, and when it does it must not pretend to have
   submitted: it prints the direct route instead. Hidden until the
   script fills it, so it never renders empty and never occupies
   space with JS off. The Partners lane and the Support lane both
   invented this, identically. */
.form-status {
  display: none;
  margin-top: var(--s-4);
  padding: var(--s-4);
  border: 1px solid var(--hair-gold);
  background: var(--surface-well);
  font-size: var(--b2-size);
  line-height: var(--b2-lh);
  color: var(--fg-dense);
}
.form-status.show { display: block; }
.form-status strong {
  display: block;
  margin-bottom: 6px;
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d4-size);
  letter-spacing: var(--d4-ls);
  color: var(--fg);
}
.form-status a { color: var(--fg-accent); border-bottom: 1px solid var(--hair-gold); }

/* ---------- 6.6 data table, generic ----------
   For warranty schedules and spec lists. AR-5 has its own class. */
.dtable th, .dtable td {
  text-align: left;
  padding: 12px 14px 12px 0;
  border-bottom: 1px solid var(--hair);
  font-size: var(--b2-size);
  line-height: var(--b2-lh);
  color: var(--fg-dense);
  vertical-align: top;
}
.dtable thead th {
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d5-size);
  letter-spacing: var(--d5-ls);
  text-transform: uppercase;
  color: var(--fg);
  border-bottom: 2px solid var(--rule-heavy);
  padding-bottom: 10px;
}
.dtable tbody tr:last-child th,
.dtable tbody tr:last-child td { border-bottom: none; }
.dtable .num { text-align: right; font-variant-numeric: lining-nums tabular-nums; padding-right: 0; }

/* ---------- 6.7 accordion ----------
   Native details and summary. No JS. The FAQ deck is built on this. */
.acc { border-top: 2px solid var(--rule-heavy); }
.acc-item { border-bottom: 1px solid var(--hair); }
.acc-q {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--s-4);
  padding-block: 16px;
  cursor: pointer;
  list-style: none;
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d4-size);
  line-height: var(--d4-lh);
  letter-spacing: var(--d4-ls);
  color: var(--fg);
  transition: color var(--dur-hover) var(--ease-out);
}
.acc-q::-webkit-details-marker { display: none; }
.acc-q:hover { color: var(--fg-accent); }
.acc-q::after {
  content: "";
  width: 11px; height: 11px;
  background:
    linear-gradient(var(--fg-code), var(--fg-code)) center / 11px 1px no-repeat,
    linear-gradient(var(--fg-code), var(--fg-code)) center / 1px 11px no-repeat;
}
.acc-item[open] .acc-q::after {
  background: linear-gradient(var(--fg-code), var(--fg-code)) center / 11px 1px no-repeat;
}
.acc-a { padding-bottom: 18px; display: grid; gap: var(--s-3); }
.acc-a > * { max-width: 66ch; }

/* ---------- 6.8 tabs, CSS only ----------
   Radio inputs plus labels. No script, so it renders in headless
   and works with JS off. Panels follow the inputs in source order.
   Supports up to six tabs. */
.tabs { display: grid; }
.tabs > input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
.tablist {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  border-bottom: 1px solid var(--hair);
  margin-bottom: var(--s-5);
}
.tablist label {
  padding: 11px 18px;
  font-family: var(--disp);
  font-weight: 600;
  font-size: var(--d5-size);
  letter-spacing: var(--d5-ls);
  text-transform: uppercase;
  color: var(--fg-muted);
  cursor: pointer;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  transition: color var(--dur-hover) var(--ease-out),
              border-color var(--dur-hover) var(--ease-out);
}
.tablist label:first-child { padding-left: 0; }
.tablist label:hover { color: var(--fg); }
.tabpanel { display: none; }
.tabs > input:nth-of-type(1):checked ~ .tabpanels > .tabpanel:nth-child(1),
.tabs > input:nth-of-type(2):checked ~ .tabpanels > .tabpanel:nth-child(2),
.tabs > input:nth-of-type(3):checked ~ .tabpanels > .tabpanel:nth-child(3),
.tabs > input:nth-of-type(4):checked ~ .tabpanels > .tabpanel:nth-child(4),
.tabs > input:nth-of-type(5):checked ~ .tabpanels > .tabpanel:nth-child(5),
.tabs > input:nth-of-type(6):checked ~ .tabpanels > .tabpanel:nth-child(6) { display: grid; gap: var(--s-4); }
.tabs > input:nth-of-type(1):checked ~ .tablist label:nth-child(1),
.tabs > input:nth-of-type(2):checked ~ .tablist label:nth-child(2),
.tabs > input:nth-of-type(3):checked ~ .tablist label:nth-child(3),
.tabs > input:nth-of-type(4):checked ~ .tablist label:nth-child(4),
.tabs > input:nth-of-type(5):checked ~ .tablist label:nth-child(5),
.tabs > input:nth-of-type(6):checked ~ .tablist label:nth-child(6) {
  color: var(--fg);
  border-bottom-color: var(--gold);
}
.tabs > input:focus-visible ~ .tablist label { outline: none; }
.tabs > input:nth-of-type(1):focus-visible ~ .tablist label:nth-child(1),
.tabs > input:nth-of-type(2):focus-visible ~ .tablist label:nth-child(2),
.tabs > input:nth-of-type(3):focus-visible ~ .tablist label:nth-child(3),
.tabs > input:nth-of-type(4):focus-visible ~ .tablist label:nth-child(4),
.tabs > input:nth-of-type(5):focus-visible ~ .tablist label:nth-child(5),
.tabs > input:nth-of-type(6):focus-visible ~ .tablist label:nth-child(6) {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

/* ---------- 6.9 notice strip ----------
   One line of mono on a hairline pair. For status and legal notes.
   Not a callout box, and never a side-stripe. */
.notice {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-5);
  align-items: baseline;
  padding-block: 13px;
  border-top: 1px solid var(--hair-gold);
  border-bottom: 1px solid var(--hair-gold);
}


/* ============================================================
   7 · MOTION, ART-DIRECTION §G
   Restrained, ease-out, nothing over 700ms.
   ============================================================ */

/* TWO GATES, AND THEY ARE NOT THE SAME GATE.

   .js       set by main.js on every page, as its first statement.
             Gates the scroll reveal. Safe to set late, because
             main.js resolves every reveal that is already on screen
             in the same synchronous block, so the page cannot paint
             a section, hide it, and bring it back.

   .js-early set only when a page carries the one line head script
             <script>document.documentElement.classList.add('js')</script>.
             Gates the hero entrance, which is the one animation that
             genuinely has to be armed before first paint. Without it
             the hero simply renders composed, which is correct and
             is never a flicker.

   Content is visible with JS off, in a headless render and on a
   hidden tab. Nothing on this site carries opacity: 0. */

/* Section reveal. The default state is VISIBLE. The class only
   enhances an already rendered section, so nothing ships blank in
   a headless render or on a hidden tab. This is deliberate and it
   is the fix for the first pass, which gated visibility on JS. */
.reveal { transition: opacity var(--dur-reveal) var(--ease-out),
                      transform var(--dur-reveal) var(--ease-out); }
.js .reveal { opacity: 0.001; transform: translateY(16px); }
.js .reveal.in { opacity: 1; transform: none; }

/* Ledger rows stagger within one ledger only, never across sections. */
.js .reveal .ledger-row { transition: opacity var(--dur-reveal) var(--ease-out),
                                      transform var(--dur-reveal) var(--ease-out); }
.js .reveal:not(.in) .ledger-row { opacity: 0.001; transform: translateY(8px); }
.reveal.in .ledger-row:nth-child(1) { transition-delay: 0ms; }
.reveal.in .ledger-row:nth-child(2) { transition-delay: 40ms; }
.reveal.in .ledger-row:nth-child(3) { transition-delay: 80ms; }
.reveal.in .ledger-row:nth-child(4) { transition-delay: 120ms; }
.reveal.in .ledger-row:nth-child(5) { transition-delay: 160ms; }
.reveal.in .ledger-row:nth-child(6) { transition-delay: 200ms; }
.reveal.in .ledger-row:nth-child(7) { transition-delay: 240ms; }
.reveal.in .ledger-row:nth-child(8) { transition-delay: 280ms; }

/* Hero sequence, runs once on load, whole thing under 700ms.
   Keyed on .js-early, not .js: armed after first paint it would
   hide type the reader has already seen. */
.js-early .hero-inner > * { animation: rise 520ms var(--ease-out) both; }
.js-early .hero-inner > *:nth-child(1) { animation-delay: 60ms; }
.js-early .hero-inner > *:nth-child(2) { animation-delay: 150ms; }
.js-early .hero-inner > *:nth-child(3) { animation-delay: 240ms; }
.js-early .hero-inner > *:nth-child(4) { animation-delay: 330ms; }
@keyframes rise { from { opacity: 0.001; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* AR-8 leader lines draw in. The one piece of expressive motion. */
.diagram-svg .leader { stroke-dasharray: var(--len, 260); stroke-dashoffset: 0; }
.js .reveal:not(.in) .diagram-svg .leader { stroke-dashoffset: var(--len, 260); }
.diagram-svg .leader { transition: stroke-dashoffset var(--dur-draw) var(--ease-out); }
.reveal.in .diagram-svg .leader:nth-of-type(2) { transition-delay: 60ms; }
.reveal.in .diagram-svg .leader:nth-of-type(3) { transition-delay: 120ms; }
.reveal.in .diagram-svg .leader:nth-of-type(4) { transition-delay: 180ms; }
.reveal.in .diagram-svg .leader:nth-of-type(5) { transition-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .js .reveal:not(.in) .ledger-row { opacity: 1; transform: none; }
  .js .reveal:not(.in) .diagram-svg .leader { stroke-dashoffset: 0; }
  .js-early .hero-inner > * { animation: none; }
  .btn:active { transform: none; }
  /* AR-2b: the tile keeps its riser and its edge change, loses the
     movement. The gold border still reports the hover state, so
     nothing is signalled by motion alone. */
  .tile:hover,
  a.tile:focus-visible {
    transform: none;
    filter: drop-shadow(0 var(--tile-riser-y) 0 var(--tile-riser));
  }
  /* Opacity crossfades are allowed to keep a short duration. */
  .filmplay, .nav { transition-duration: 120ms !important; }
}


/* ============================================================
   8 · UTILITIES
   ============================================================ */
.flow > * + * { margin-top: var(--flow, var(--s-4)); }
.flow--tight { --flow: var(--s-3); }
.flow--loose { --flow: var(--s-5); }
.measure-44 { max-width: 44ch; }
.measure-52 { max-width: 52ch; }
.measure-58 { max-width: 58ch; }
.measure-66 { max-width: 66ch; }
.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;
}
.hairline-top { border-top: 1px solid var(--hair); }
.gold-top { border-top: 1px solid var(--gold); }


/* ============================================================
   9 · RESPONSIVE
   Mobile first. The rules above are the 390 state. Everything
   below is an enhancement at 768 and 1024.
   ============================================================ */

@media (min-width: 560px) {
  .form-grid--2 { grid-template-columns: 1fr 1fr; }
  .foot-grid { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 768px) {
  .hero { height: min(86svh, 700px); }
  .quotewall { columns: 2; }
  .compare-stack { display: none; }
  .cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--s-6); }
  .cols-3 > * + * { padding-left: var(--s-6); border-left: 1px solid var(--hair); }
  /* Logo block plus all three link columns, one row. The logo track
     carries the email address, so it is the widest. */
  .foot-grid { grid-template-columns: 1.75fr repeat(3, minmax(0, 1fr)); gap: var(--s-5); }
  .beamline { font-size: var(--m3-size); letter-spacing: var(--m3-ls); }
}

@media (max-width: 767px) {
  /* AR-2 mobile: ref and label on one line, note under, value right. */
  .ledger-row {
    grid-template-columns: 60px 1fr auto;
    padding-block: 16px;
  }
  .ledger-note { grid-column: 2 / -1; }
  .ledger-value { grid-row: 1; grid-column: 3; font-size: 1.625rem; }
  .ledger--compact .ledger-row { padding-block: 11px; }
  .ledger--nofig .ledger-row { grid-template-columns: 60px 1fr; }
  /* AR-5 mobile: the table is replaced by per-comparand ledgers. */
  .compare-table { display: none; }
  /* AR-4 three column variant stacks with rules kept. */
  .split-media { order: 2; }
  .split--flip .split-media { order: 2; }
  /* B2 may hyphenate in narrow columns, §E3. */
  .b2, .ledger-note { hyphens: auto; }
  .cta-plate { padding: var(--s-6) var(--s-5) var(--s-5); }
  .seal { --seal-size: 108px; }
  .seal--overlap { right: var(--s-5); }
  .statement-inner .d2 { max-width: 14ch; }
}

@media (min-width: 1024px) {
  .hero { height: min(88svh, 780px); min-height: 620px; }
  .hero-inner > * { max-width: 45%; }
  .hero-inner .d1 { max-width: 13ch; }
  .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 64px; }
  .split--wide-text { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
  .network { grid-template-columns: 1.15fr 1fr; gap: 56px; }
  .diagram { grid-template-columns: 1.35fr 1fr; gap: var(--s-7); }
  .cta-plate { grid-template-columns: 1fr auto; align-items: start; gap: var(--s-8); padding: var(--s-8) var(--s-7) var(--s-7); }
  /* The seal hangs 40% of its diameter above the plate, so the rest of
     it lands 60% inside. Drop the title block clear of it, but only
     when a seal is actually present. */
  .cta-wrap:has(.seal--overlap) .cta-plate .tblock {
    margin-top: calc(var(--seal-size) * 0.6 - var(--s-8) + 6px);
  }
  .cta-side { max-width: 460px; }
  .tblock { grid-template-columns: repeat(3, minmax(0, 1fr)); min-width: 440px; }
  .ledger-row { column-gap: var(--s-6); }
  .quotewall { column-gap: var(--s-8); }
  .foot-grid { grid-template-columns: 1.5fr repeat(3, minmax(0, 1fr)); column-gap: var(--s-7); }
}

@media (max-width: 900px) {
  .nav-links { display: none; }
  .nav-toggle { display: block; }
  .nav-links.open {
    display: flex;
    position: absolute;
    top: 100%;
    right: var(--gutter);
    left: var(--gutter);
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-4);
    padding: var(--s-5);
    background: var(--surface-1);
    border: 1px solid var(--rule);
    border-top: var(--plate-rule) solid var(--gold);
  }
  .nav-links.open a { font-size: 1rem; }
}

/* Title block: one column on phone, two on tablet, three on desktop. */
@media (min-width: 560px) and (max-width: 1023px) {
  .tblock { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ============================================================
   11 · TRANSITIONAL SHIM, DELETE WHEN THE SWARM LANDS
   about.html, shops.html and the-coating.html still carry the V1
   class names and are not in a page lane yet. These four rules keep
   them legible until they are rebuilt on the archetype library.
   Do not use any of them in new work.
   ============================================================ */
.section { padding-block: var(--pad-std); }
.section + .section { padding-top: 0; }
.meta {
  font-family: var(--mono); font-weight: 500;
  font-size: var(--m2-size); line-height: var(--m2-lh);
  letter-spacing: var(--m2-ls); text-transform: uppercase;
  color: var(--fg-code);
}
.meta-dim { color: var(--fg-muted); }
.lede {
  font-size: var(--b0-size); line-height: var(--b0-lh);
  letter-spacing: var(--b0-ls); color: var(--fg-dim);
  max-width: var(--b0-measure);
}
.framed-caption {
  display: block; margin-top: 12px;
  font-family: var(--mono); font-size: var(--m3-size);
  letter-spacing: var(--m3-ls); text-transform: uppercase;
  color: var(--fg-muted);
}


/* ============================================================
   10 · PRINT
   ============================================================ */
@media print {
  .nav, .filmplay, .btn, .skip-link { display: none !important; }
  body, .band, .on-black, .on-photo { background: #fff !important; color: #000 !important; }
  .band { padding-block: 18pt !important; }
  /* The riser is a screen device. On paper the chamfer and the flange
     carry the tile on their own. */
  .tile { filter: none !important; background: #fff !important; border-color: #000 !important; }
  .tile, .tile * { color: #000 !important; }
  .tile-img, .tile--image::before { display: none !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 8pt; }
}
