/* ═══ LATVERA — 150BC TECHNICAL DOSSIER ═══
   Per Website - Design System (locked): pale cast-stone page, graphite
   structure, ONE signal in the logo red, cedar for material notes.
   The dark assembly hero is the jewel; the page is the daylight —
   flipped at a zero-width boundary trigger, readable mid-transition.
   Type: Archivo Variable (wdth 62–125) display · Geist body · Geist Mono data. */

@font-face { font-family: "Archivo VF"; src: url("../fonts/archivo-vf.woff2") format("woff2-variations"); font-weight: 100 900; font-stretch: 62% 125%; font-display: swap; }
@font-face { font-family: "Geist"; src: url("../fonts/geist-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Geist"; src: url("../fonts/geist-500.woff2") format("woff2"); font-weight: 500; font-display: swap; }
@font-face { font-family: "Geist Mono"; src: url("../fonts/geist-mono-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Geist Mono"; src: url("../fonts/geist-mono-500.woff2") format("woff2"); font-weight: 500; font-display: swap; }

:root {
  /* Latvera palette — every value from Website - Design System.md */
  --stone: oklch(94% 0.004 120);
  --stone-2: oklch(90% 0.005 120);
  --graphite: oklch(19% 0.006 80);
  --ink-2: oklch(47% 0.006 80);
  --brand:      oklch(59.5% 0.230 21);  /* the logo red, exact — marks only */
  --brand-lift: oklch(62.5% 0.230 21);  /* +3% L, the smallest lift that clears 4.5:1 */
  --lime: var(--brand);                 /* legacy alias: the 33 existing var(--lime) uses */
  /* Was L=56%: 4.04:1 on --stone, under the 4.5 floor for the 11px mono kickers.
     Measured in-browser, the light page is not flat — .grid paints a fixed 5%
     graphite lattice over it, so a glyph crossing a grid line sits on
     rgb(224,224,222), not rgb(235,235,233). L=53% clears the flat page (4.55)
     but still fails the grid (4.11) and the --paper plates (4.02). L=50% clears
     every backing that actually occurs: page 5.20, grid 4.70, plate 4.60 — and
     is the value four other rules here already settled on for this same fix. */
  --cedar: oklch(50% 0.10 55);

  /* live theme channels — dark studio first, flipped at the boundary */
  --bg: oklch(16% 0.006 80);
  --bg-2: oklch(21% 0.006 80);
  --ink: var(--stone);
  --ink-ghost: oklch(94% 0.004 120 / 0.14);
  --dim: oklch(72% 0.006 100);
  --hair: oklch(94% 0.004 120 / 0.15);
  --gridline: oklch(94% 0.004 120 / 0.045);
  --accent-text: var(--brand-lift); /* lifted brand red as text: dark zone only */

  --paper: var(--stone-2);   /* was NEVER defined — var(--paper) silently resolved to transparent */
  --pad: clamp(20px, 4vw, 60px);
  --nav-h: 76px;
  --mono: "Geist Mono", ui-monospace, monospace;
  --body: "Geist", system-ui, sans-serif;
  --display: "Archivo VF", "Archivo", "Helvetica Neue", sans-serif;

  --ease-magic:    cubic-bezier(.33, 0, 0, 1);
  --ease-out-expo: cubic-bezier(.19, 1, .22, 1);
  --ease-quart:    cubic-bezier(.41, .35, .2, 1);
}
html.light {
  --bg: var(--stone);
  --bg-2: var(--stone-2);
  --ink: var(--graphite);
  --ink-ghost: oklch(19% 0.006 80 / 0.14);
  --dim: var(--ink-2);
  --hair: oklch(19% 0.006 80 / 0.16);
  --gridline: oklch(19% 0.006 80 / 0.05);
  --accent-text: var(--cedar);      /* the brand red is a mark on light, never text */
}

#top, #work, #range, #flagship, #specs, #contact, #asas, #pergolas,
#pd-spec, #pd-colour, #pd-doors,
#f1, #f2, #f3, #f4, #f5, #f6 {
  scroll-margin-top: calc(var(--nav-h) + 14px);
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { overflow-x: clip; }
body {
  background: var(--bg); color: var(--ink);
  font-family: var(--body); font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
  transition: background-color .5s ease, color .5s ease;
}

.skip {
  position: fixed; top: -60px; left: var(--pad); z-index: 60;
  display: inline-flex; align-items: center; min-height: 44px;
  background: var(--graphite); color: var(--stone); padding: 0 18px;
  font-family: var(--mono); font-size: 12px; letter-spacing: .1em; text-decoration: none;
  transition: top .2s;
}
.skip:focus-visible { top: 12px; }
@media (prefers-reduced-motion: reduce) { .skip { transition: none; } }
:focus-visible { outline: 2px solid var(--lime); outline-offset: 3px; }
:focus:not(:focus-visible) { outline: none; }

/* drafting grid */
.grid {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--gridline) 1px, transparent 1px),
    linear-gradient(90deg, var(--gridline) 1px, transparent 1px);
  background-size: 72px 72px;
  transition: opacity .5s;
}

/* doc header */
.doc {
  position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  /* 8 + 8 + 44(CTA min-target) + 8 + 8 = 76px occupied: under the 80px nav cap
     while still reading as detached from the top edge. */
  padding: 8px var(--pad);
  font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
  background: none; border: 0;            /* the shell paints nothing now */
  transform: translate3d(0,0,0);
  transition: transform .42s var(--ease-magic);
}
.doc__panel {
  position: relative;
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 20px;
  margin-inline: -20px;                    /* content keeps sitting on the page grid */
  color: var(--ink);
}
/* the floating surface: a separate painted layer so only opacity animates */
.doc__panel::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: color-mix(in oklch, var(--bg) 88%, transparent);
  border: 1px solid var(--hair);
  /* A drop shadow tinted with the PAGE background (2026-08-13: it was
     color-mix(var(--bg) 70%)) is invisible on the light page it was tuned for,
     and becomes a bright halo the moment the band floats over a dark chapter —
     §03 and the pergola experience both. A neutral dark shadow is correct on
     both grounds: a real shadow on light, and nothing to glow on dark. */
  box-shadow: 0 10px 30px oklch(12% 0.004 80 / 0.16);
  opacity: 0;
  transition: opacity .42s var(--ease-magic);
}
html.nav-blur .doc__panel::before { backdrop-filter: blur(10px) saturate(1.4); -webkit-backdrop-filter: blur(10px) saturate(1.4); }
.doc.is-float .doc__panel::before { opacity: 1; }

/* stone text at the top is ONLY valid over the dark hero film on index */
.page--hero .doc:not(.is-float) .doc__panel { color: var(--stone); }
.page--hero .doc:not(.is-float) .doc__cta   { color: var(--stone); border-color: oklch(94% 0.004 120 / 0.34); }
.page--hero .doc:not(.is-float) .gdrop > summary { color: var(--stone); border-color: oklch(94% 0.004 120 / 0.34); }
.page--hero .doc:not(.is-float) .doc__no    { color: oklch(94% 0.004 120 / 0.72); }
.page--hero .doc:not(.is-float) .doc__sections { color: oklch(94% 0.004 120 / 0.72); }
.doc__scrim {
  display: none;
  position: fixed; top: 0; left: 0; right: 0; height: 132px; z-index: 39;
  pointer-events: none;
  background: linear-gradient(to bottom, oklch(16% 0.006 80 / 0.55), transparent);
  opacity: 1; transition: opacity .42s var(--ease-magic);
}
.page--hero .doc__scrim { display: block; }
html.nav-floating .doc__scrim { opacity: 0; }

/* auto-hide while reading downward; returns instantly on scroll up */
.doc.is-hidden { transform: translate3d(0,calc(-100% - 14px),0); will-change: transform; }
.doc:focus-within { transform: none !important; transition: none; }

/* scroll progress: bottom hairline of the panel, transform only */
.doc__prog {
  position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--lime); transform: scaleX(0); transform-origin: 0 50%;
  opacity: 0; transition: opacity .42s var(--ease-magic);
}
.doc.is-float .doc__prog { opacity: .85; }

/* The brand mark: the Latvera logo, and the way back to the top from anywhere.
   NOTE: the glyph below is still the mark inherited from the previous brand. The
   wordmark rebranded to Latvera on 2026-08-16; drawing a Latvera mark is its own
   design job, and it drops in here when it exists.
   The logo is inline SVG so its ink can be currentColor — that makes it correct over the
   dark hero, over the light zone once the nav floats, and inside the dark chapter, with
   one asset and no swapping. The red stays the brand red via var(--brand). */
.doc__brand {
  color: inherit; text-decoration: none;
  display: inline-flex; align-items: center; min-height: 44px;   /* touch target */
}
a.doc__brand:focus-visible { outline: 2px solid var(--brand); outline-offset: 4px; }
/* The MARK alone, not the full lockup. At nav size the lockup's letterspaced "METAL"
   line renders about 4px tall — illegible, and it reads as dirt rather than type. The
   mark is crisp at any size and carries the brand on its own. */
.brandlogo__mark { display: block; width: auto; height: clamp(26px, 2.6vw, 32px); }
.doc__no { color: var(--dim); }
.doc__sections { color: var(--dim); min-width: 0; }
.doc__section-list { display: flex; align-items: center; gap: clamp(12px, 1.6vw, 24px); }
.doc__section {
  position: relative; color: inherit; text-decoration: none; white-space: nowrap;
  transition: color .25s ease;
}
.doc__section::after {
  content: ""; position: absolute; left: 0; right: .14em; bottom: -8px; height: 2px;
  background: var(--lime); transform: scaleX(0); transform-origin: 100% 50%;
  transition: transform .3s var(--ease-magic);
}
.doc__section:hover, .doc__section:focus-visible { color: var(--ink); }
.page--hero .doc:not(.is-float) .doc__section:hover,
.page--hero .doc:not(.is-float) .doc__section:focus-visible { color: var(--stone); }
.doc__section.is-current::after { transform: scaleX(1); transform-origin: 0 50%; }
.doc__section-current { display: none; white-space: nowrap; overflow: hidden; }
.doc__cta {
  color: var(--ink); text-decoration: none; border: 1px solid var(--hair);
  padding: 9px 14px; font-size: 10px; letter-spacing: .18em;
  transition: border-color .3s, color .3s, background .3s;
  min-height: 44px; display: inline-flex; align-items: center;
}
.doc__cta:hover { border-color: currentColor; }
.doc__nav { display: flex; gap: 10px; }
@media (max-width: 820px) {
  .doc__no, .doc__section-list { display: none; }
  .doc__section-current { display: block; max-width: 14ch; text-overflow: clip; }
}
/* Panel edge inset = var(--pad) + margin-inline; content stays on the page grid because
   padding-inline cancels the negative margin. At 390px --pad is 20px, so -8px leaves a
   12px inset: enough to read as floating instead of a full-width bar. */
@media (max-width: 560px) {
  :root { --nav-h: 84px; }   /* catalog measured 80px at 390 */
  .doc__panel { padding: 8px; margin-inline: -8px; column-gap: 10px; }
  /* Three pills at desktop metrics measure 289px inside a 351px panel at 375,
     so the readout flex-shrank to 20px and rendered the brand name hard-clipped
     against the GALLERY pill — it read as a broken logo, not a label. Buy the
     label its width back from the pills (tighter padding, tracking and gaps)
     and let it truncate with an ellipsis. The readout cannot simply hide at
     this width: on sub pages it is the only thing naming the page once
     .doc__section-list is gone at 820px (see js/nav.js). Touch targets are
     untouched — only the inline padding moves, min-height stays 44px. */
  /* 2026-08-15 — that first pass was not enough. Measured at 390px the three
     pills still took 250px of the 350px panel and the readout got 54px, so
     EVERY label came out as five characters plus an ellipsis: the brand name on the
     hero (it reads as a broken logo), "02 PE…", "03 WO…". The longest label
     ("02 PERGOLAS") needs ~119px at the inherited 11px/.14em.
     Buy it back from both sides: the pills lose a little more padding and
     tracking, and the readout drops to its own smaller, tighter setting — it is
     a status label, not a control, so it does not owe the pills type parity.
     Budget at 390: brand 26 + readout ~75 + pills ~205 + gaps = 350.
     SIZE THE READOUT FOR 375, NOT 390. 390 has ~22px of slack and hides the
     real constraint; 375 (SE 2/3, 12/13 mini) is the tight case and two labels
     land right on the line there — index "02 PERGOLAS" needs 82px in an 82px
     box, and the gallery pages' "ZIP SCREENS · GALLERY" needs 142.8px in 138.7
     and clipped. At 9.5px/.05em (the pills' own size, so no new type value
     enters the bar) the long one comes to ~130px and both carry real headroom
     instead of squeaking past. Verified on gallery-zip, the worst label on the
     site, at 320/375/390. */
  .doc__nav { gap: 5px; flex: 0 0 auto; }
  .doc__cta, .gdrop > summary { padding-inline: 8px; letter-spacing: .06em; font-size: 9.5px; }
  .gdrop > summary { gap: 5px; }
  .doc__sections { flex: 1 1 auto; }
  .doc__section-current {
    max-width: none; text-overflow: ellipsis;
    font-size: 9.5px; letter-spacing: .05em;
  }
}
/* 320px (SE-class). Even at the tightened metrics the three pills need ~207px
   of a 280px content row, which left the readout 27px — the label rendered as
   an empty gap, not a truncation. Nothing is worth deleting from the bar, so
   below 360 the readout takes a row of its own under the pills. --nav-h grows
   with it: scroll-margin-top, the gallery sheet, .wk-rail and --pd-cluster-top
   are all measured off that token, so it has to stay ahead of the real bar. */
@media (max-width: 360px) {
  :root { --nav-h: 96px; }
  .doc__panel { flex-wrap: wrap; row-gap: 1px; }
  .doc__brand { order: 1; }
  .doc__nav { order: 2; margin-left: auto; }
  .doc__sections { order: 3; flex: 1 0 100%; }
}

@media (prefers-reduced-transparency: reduce) {
  .doc__panel::before { background: var(--bg); backdrop-filter: none; -webkit-backdrop-filter: none; }
}
@media (prefers-reduced-motion: reduce) {
  .doc, .doc__panel::before, .doc__prog, .doc__scrim { transition: none; }
  .doc.is-hidden { transform: none; }   /* never hide the nav under reduced motion */
}
html.static .doc { transform: none; }
html.static .doc__panel { color: var(--ink) !important; }
html.static .doc__cta   { color: var(--ink) !important; border-color: var(--hair) !important; }
html.static .doc__no    { color: var(--dim) !important; }
html.static .doc__sections { color: var(--dim) !important; }
html.static .doc__scrim { display: none; }
html.static .doc__panel::before, html.static .doc__prog { opacity: 1; }

/* ══ warm film hero ══ (self-contained: stone text over footage, any theme) */
.hero {
  position: relative; z-index: 1;
  min-height: 100vh; min-height: 100svh;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 14vh var(--pad) 26px;
  color: var(--stone);
}
.hero__media { position: absolute; inset: 0; overflow: clip; }
.hero__poster, .hero__film {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.hero__film { opacity: 0; transition: opacity .8s ease; }
.hero.is-filming .hero__film { opacity: 1; }
.hero__grade {
  position: absolute; inset: 0;
  background:
    linear-gradient(92deg, oklch(14% 0.02 60 / 0.55), oklch(14% 0.02 60 / 0.22) 46%, oklch(14% 0.02 60 / 0) 68%),
    linear-gradient(180deg, oklch(15% 0.02 60 / 0.38), oklch(15% 0.02 60 / 0.05) 34%, oklch(15% 0.02 60 / 0.12) 62%, oklch(13% 0.02 60 / 0.7));
}
.hero__content { position: relative; z-index: 2; max-width: 1400px; }
.hero__kicker { font-family: var(--mono); font-size: 11px; letter-spacing: .3em; color: oklch(94% 0.004 120 / 0.8); margin-bottom: 26px; }
.hero__h1 {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(46px, 8.6vw, 132px);
  line-height: 0.94; letter-spacing: -0.035em;
  font-variation-settings: "wdth" 70;
  text-shadow: 0 2px 30px oklch(10% 0.02 60 / 0.35);
}
.hero__line { display: block; white-space: nowrap; }
.hero__deck {
  margin-top: 24px; font-size: clamp(15px, 1.7vw, 19px); line-height: 1.6;
  max-width: 52ch; color: oklch(94% 0.004 120 / 0.92);
}
.hero__ctas { display: flex; gap: 14px; margin-top: 34px; flex-wrap: wrap; }
.btn--call { background: var(--brand-lift); color: var(--graphite); }
.btn--call:hover { background: var(--stone); color: var(--graphite); }
.btn--big { font-size: 14px; padding: 20px 40px; }
.hero .btn--ghost { background: transparent; color: var(--stone); box-shadow: inset 0 0 0 1px oklch(94% 0.004 120 / 0.4); }
.hero .btn--ghost:hover { box-shadow: inset 0 0 0 1px var(--stone); background: transparent; }
.mq--hero { position: relative; z-index: 2; margin-top: clamp(30px, 6vh, 60px); }
.mq--hero .mq__label { color: oklch(94% 0.004 120 / 0.75); }
.mq--hero .mq__fig img { border-color: oklch(94% 0.004 120 / 0.25); }
html.static .hero__film { display: none; }

/* statement kicker + contact */
.statement__k {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .26em; color: var(--dim);
  margin-bottom: 26px;
}
.contact {
  position: relative; z-index: 1; border-top: 1px solid var(--hair);
  padding: clamp(80px, 16vh, 180px) var(--pad);
}
.contact__k { font-family: var(--mono); font-size: 11px; letter-spacing: .3em; color: var(--accent-text); margin-bottom: 24px; }
.contact__t {
  font-family: var(--display); font-weight: 500; font-variation-settings: "wdth" 96;
  font-size: clamp(44px, 7.4vw, 116px); letter-spacing: -0.03em; line-height: 0.96;
  margin-bottom: 22px;
}
.contact__x { font-size: 17px; line-height: 1.6; color: var(--dim); max-width: 50ch; margin-bottom: 40px; }
.contact__ctas { display: flex; gap: 14px; flex-wrap: wrap; }
.cform { margin: 40px 0 34px; max-width: 720px; }
.cform__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px 18px; }
.cform__field--wide { grid-column: 1 / -1; }
.cform__label {
  display: block; margin-bottom: 8px;
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--dim);
}
.cform__opt { text-transform: none; letter-spacing: .06em; opacity: .7; }
.cform__input {
  width: 100%; min-height: 48px; padding: 12px 14px;
  background: transparent; color: var(--ink);
  border: 1px solid var(--hair); border-radius: 0;
  font-family: var(--body); font-size: 15px; line-height: 1.5;
  transition: border-color .25s;
}
.cform__textarea { min-height: 132px; resize: vertical; }
.cform__input:hover { border-color: color-mix(in oklch, var(--ink) 45%, transparent); }
.cform__input:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; border-color: var(--ink); }
/* --cedar measured 4.04:1 on the contact background: under the 4.5:1 AA floor for the
   10px error text. This deeper brick measures 6.42:1 while staying in the same family. */
.cform__input[aria-invalid="true"] { border-color: oklch(46% 0.15 35); }
.cform__err { margin: 7px 0 0; font-family: var(--mono); font-size: 10px; letter-spacing: .1em; color: oklch(46% 0.15 35); }
.cform__foot { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin-top: 26px; }
.cform__foot .btn { margin-top: 0; }
.cform__status { margin: 0; font-family: var(--mono); font-size: 11px; letter-spacing: .1em; color: var(--dim); max-width: 44ch; }
.cform__status--err { color: var(--cedar); }
.contact__ctas .btn { margin-top: 0; }
@media (max-width: 700px) { .cform__grid { grid-template-columns: 1fr; } }

/* cover (dark zone) */
.cover {
  position: relative; z-index: 1;
  min-height: 92vh; display: flex; flex-direction: column; justify-content: center;
  padding: 18vh var(--pad) 8vh;
}
.cover__scramble { font-family: var(--mono); font-size: 12px; letter-spacing: .22em; color: var(--accent-text); margin-bottom: 30px; min-height: 1.2em; }
.cover__h1 {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(54px, 11vw, 168px);
  line-height: 0.92; letter-spacing: -0.035em;
  font-variation-settings: "wdth" 66;  /* narrow; opens to 100 as the section is scrubbed */
}
.cover__line { display: block; white-space: nowrap; } /* stretch never rewraps the lines */
.cover__slash { color: var(--accent-text); padding: 0 .06em; font-weight: 400; }
.cover__meta {
  display: flex; gap: clamp(18px, 4vw, 54px); flex-wrap: wrap;
  margin-top: 44px; font-family: var(--mono); font-size: 12px; letter-spacing: .16em; color: var(--dim);
}
.cover__meta span { border-top: 1px solid var(--hair); padding-top: 12px; font-variant-numeric: tabular-nums; }
/* the sliding bar — a continuous marquee of range renders under the title */
.mq { margin-top: clamp(30px, 6vh, 56px); }
.mq__label {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--mono); font-size: 10px; letter-spacing: .26em; color: var(--dim);
  margin-bottom: 14px;
}
.tag--record { background: var(--cedar); color: var(--stone); font-size: 8px; letter-spacing: .22em; padding: 3px 7px; font-weight: 500; }
.mq__clip { overflow: clip; margin: 0 calc(-1 * var(--pad)); }
.mq__track {
  display: flex; width: max-content;
  animation: mq-slide 52s linear infinite;
  will-change: transform;
}
/* No hover-pause. Pausing a composited CSS animation restarts it in WebKit, which is
   the marquee "reset on hover" the owner hit — first on the partners strip, then on the
   hero. Reduced-motion still stops the marquee outright, so the a11y need is covered by
   the media query, not by a mouse-only affordance that was never keyboard-reachable. */
.mq__dup { display: contents; }
.mq__fig { flex: 0 0 auto; height: clamp(110px, 17vh, 168px); margin-right: 10px; overflow: clip; position: relative; }
.mq__fig img {
  height: 100%; width: auto; display: block;
  border: 1px solid oklch(94% 0.004 120 / 0.14);
  /* moodier baseline: deeper, more saturated — the strip should smolder, not glare */
  filter: brightness(0.78) saturate(1.3) contrast(1.06);
  transition: filter .45s ease, opacity .55s var(--ease-magic);
}
.mq--hero.mq--loadfx .mq__fig img:not(.is-loaded) { opacity: 0; }
.mq__fig:hover img { filter: brightness(1) saturate(1.15) contrast(1.03); }
@keyframes mq-slide { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.mq--paused .mq__track { animation-play-state: paused; }        /* hero off-screen: zero cost */
@media (prefers-reduced-motion: reduce) { .mq__track { animation: none; } }
html.static .mq__track { animation: none; }

/* ═══ partners strip ═══════════════════════════════════════════════════════ */
/* No background pin — the strip follows the page theme, and the ink layer flips with it
   (see .mq__ink below). Pinning it stone would fight that: on the dark theme the logos
   would invert to near-white and then sit on a stone band. */
.mq--partners { margin-top: 0; padding: clamp(30px, 5vh, 52px) 0 clamp(30px, 5vh, 52px);
  border-top: 0; }
.mq--partners .mq__label { padding: 0 var(--pad); margin-bottom: clamp(20px, 3.4vh, 32px); }
.mq--partners .mq__label::after { content: none; }
.mq--partners .mq__fig { height: 56px; margin-right: clamp(38px, 5.2vw, 76px);
  display: flex; align-items: center; position: relative; }
.mq--partners .mq__fig img { height: 100%; width: auto; display: block; border: 0; filter: none; }
.mq--partners .mq__ink { opacity: .58; transition: opacity .3s ease; }
/* Theme-aware ink. The logos are baked in --graphite (#151411); inverting that gives
   #eaebee, which is within 5/255 of --stone (#ebebe9) — so the dark theme gets a correct
   light-ink logo set with no third asset set and no extra bytes. Measured 16.28:1 on the
   dark background. The colour-on-hover layer is never inverted: brand colours are brand
   colours in both themes. */
html:not(.light) .mq--partners .mq__ink { filter: invert(1); }
.mq--partners .mq__col { position: absolute; top: 0; left: 0; height: 100%; width: auto;
  opacity: 0; transition: opacity .3s ease; }
.mq--partners .mq__fig:hover .mq__ink { opacity: 0; }
.mq--partners .mq__fig:hover .mq__col { opacity: 1; }
.mq--partners .mq__track { animation-duration: 64s; animation-direction: reverse; }
@media (max-width: 860px) {
  .mq--partners .mq__fig { height: 34px; margin-right: clamp(28px, 8vw, 46px); }
}
@media (prefers-reduced-motion: reduce) {
  .mq--partners .mq__track { animation: none; }
  .mq--partners .mq__ink, .mq--partners .mq__col { transition: none; }
}

.cover__hint { margin-top: 9vh; font-family: var(--mono); font-size: 10px; letter-spacing: .3em; color: var(--accent-text); animation: pulse 2.4s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: .35 } 50% { opacity: 1 } }
@media (prefers-reduced-motion: reduce) { .cover__hint { animation: none; } }

/* assembly scrub (dark zone — the jewel) */
.asm { position: relative; z-index: 1; height: 520vh; }
.asm__pin { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: clip; background: oklch(11% 0.005 80); }
.asm__poster, .asm__cv { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.asm__cv { opacity: 0; background: #141310; }
.asm--contain .asm__poster,
.asm--contain .asm__cv { object-fit: contain; background: #141310; }
.asm.is-live .asm__cv { opacity: 1; }

.tick { position: absolute; width: 22px; height: 22px; z-index: 3; }
.tick--tl { top: 84px; left: var(--pad); border-top: 1px solid oklch(72% 0.006 100); border-left: 1px solid oklch(72% 0.006 100); }
.tick--tr { top: 84px; right: var(--pad); border-top: 1px solid oklch(72% 0.006 100); border-right: 1px solid oklch(72% 0.006 100); }
.tick--bl { bottom: 30px; left: var(--pad); border-bottom: 1px solid oklch(72% 0.006 100); border-left: 1px solid oklch(72% 0.006 100); }
.tick--br { bottom: 30px; right: var(--pad); border-bottom: 1px solid oklch(72% 0.006 100); border-right: 1px solid oklch(72% 0.006 100); }
.rtag {
  position: absolute; top: 88px; right: calc(var(--pad) + 34px); z-index: 3;
  font-family: var(--mono); font-size: 9px; letter-spacing: .26em;
  color: var(--cedar);
}

.asm__dims { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; }
.dim { stroke: var(--lime); stroke-width: 1.2; }
.dimtxt { fill: var(--stone); font-family: var(--mono); font-size: 13px; letter-spacing: .14em; }

.asm__hud { position: absolute; left: var(--pad); bottom: 64px; z-index: 3; display: grid; gap: 14px; }
.asm__sec { font-family: var(--display); font-variation-settings: "wdth" 100; font-weight: 500; font-size: 22px; letter-spacing: .04em; color: var(--stone); }
.asm__secno { color: var(--brand-lift); margin-right: 10px; }
.asm__read { display: grid; grid-template-columns: auto auto; gap: 6px 18px; font-family: var(--mono); font-size: 12px; letter-spacing: .12em; color: var(--stone); }
.asm__k { color: oklch(72% 0.006 100); }
.asm__v { font-weight: 500; font-variant-numeric: tabular-nums; }
.asm__note {
  position: absolute; right: var(--pad); bottom: 64px; z-index: 3;
  max-width: 30ch; font-family: var(--mono); font-size: 12px; line-height: 1.7;
  color: oklch(72% 0.006 100); text-align: right;
}
@media (max-width: 760px) { .asm__note { display: none; } }

/* statement — the light zone opens with a line that draws itself in ink
   (scrub-driven fill: one CSS var on one element per frame) */
.statement { position: relative; z-index: 1; padding: clamp(70px, 15vh, 170px) var(--pad) clamp(30px, 6vh, 70px); }
.statement__t {
  font-family: var(--display); font-weight: 500; font-variation-settings: "wdth" 96;
  font-size: clamp(40px, 7vw, 110px); line-height: 0.96; letter-spacing: -0.03em;
  color: transparent;
  background: linear-gradient(100deg,
    var(--ink) var(--fill, 0%),
    var(--ink-ghost) var(--fill, 0%));
  -webkit-background-clip: text;
  background-clip: text;
}
.st-mask { display: block; overflow: clip; }
.statement__t.is-revealed .st-mask { overflow: visible; }
.st-line { display: block; white-space: nowrap; }

/* Descender clearance for the hero headline.
   .hero__h1 runs line-height .94, which puts the baseline ~11px above the bottom of the
   clip box at 124px type, while a descender needs ~22px — so the tail of g/p/y/j/q was
   sliced off ("is the building." / "The envelope"). The old headline had no descenders,
   which is why this only surfaced now.
   Padding opens the clip box downward (overflow clips at the PADDING edge); the equal
   negative margin gives the space straight back, so line spacing is untouched.
   Scoped to the hero on purpose: .st-mask also wraps .statement__t, whose lines reveal
   with yPercent 108 and therefore need their mask to keep clipping tightly. */
.hero__h1 .st-mask,
.hero__h1 .ch { padding-bottom: .15em; margin-bottom: -.15em; }
/* flow-root so the LAST mask's negative margin is not collapsed out of the h1 — without
   it the heading grew by the padding and pushed the deck 18px down. */
.hero__h1 { display: flow-root; }
.statement__s { margin-top: 26px; font-family: var(--mono); font-size: 12px; letter-spacing: .16em; color: var(--dim); }
.statement__link { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--hair); padding-bottom: 1px; transition: color .25s, border-color .25s; }
.statement__link:hover, .statement__link:focus-visible { color: var(--graphite); border-color: var(--graphite); }

/* the seam draw (batch 09, order 5) — JS hands each chapter's top hairline
   to a scrubbed line that draws in from the left; the CSS border stays the
   complete no-JS/static truth and goes transparent only per armed section */
.has-seam { position: relative; border-top-color: transparent !important; }
.seamline {
  position: absolute; top: -1px; left: 0; right: 0; height: 1px;
  background: var(--hair); transform: scaleX(0); transform-origin: left;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .statement__t { color: var(--ink); background: none; -webkit-background-clip: initial; background-clip: initial; }
  .st-line { transform: none !important; }
}
html.static .statement__t { color: var(--ink); background: none; -webkit-background-clip: initial; background-clip: initial; }
@media (max-width: 860px) {
  .statement { padding-top: clamp(44px, 7vh, 76px); }
  .statement__t {
    color: var(--ink); background: none;
    -webkit-background-clip: initial; background-clip: initial;
  }
}

/* numbered sheets (light zone) */
.secs { position: relative; z-index: 1; }
.sec { padding: clamp(60px, 13vh, 150px) var(--pad); border-top: 1px solid var(--hair); }
.sec__head { display: flex; align-items: baseline; gap: 20px; margin-bottom: clamp(30px, 6vh, 70px); flex-wrap: wrap; }
.sec__no {
  font-family: var(--mono); font-size: 13px; letter-spacing: .18em; font-weight: 500;
  background: var(--brand-lift); color: var(--graphite); padding: 4px 9px;
}
.sec__t {
  font-family: var(--display); font-weight: 500; font-variation-settings: "wdth" 96;
  font-size: clamp(38px, 6vw, 92px); letter-spacing: -0.02em; line-height: 0.92;
}
.sec__sub { font-family: var(--mono); font-size: 12px; letter-spacing: .18em; color: var(--dim); margin-left: auto; }
.sec__body { display: grid; grid-template-columns: minmax(320px, 560px) 1fr; gap: clamp(28px, 5vw, 90px); align-items: center; max-width: 1400px; }
.sec__body--flip { grid-template-columns: 1fr minmax(320px, 560px); }
.sec__body--flip .sec__fig { order: 2; }
.sec__body--single { grid-template-columns: 1fr; max-width: 900px; }
@media (max-width: 860px) { .sec__body, .sec__body--flip { grid-template-columns: 1fr; } .sec__body--flip .sec__fig { order: 0; } .sec__sub { margin-left: 0; } }
@media (max-width: 860px) {
  /* header composes as ONE block: kicker row (badge + rule), title, caption */
  .range .sec__head {
    display: grid; grid-template-columns: auto 1fr; align-items: center;
    /* matches the phone .sec__head rule — this override was still reserving
       up to 40px and left §01 with a 39px hole under the title */
    gap: 0; margin-bottom: clamp(16px, 2.4vh, 26px);
  }
  .range .sec__head .sec__no { grid-column: 1; grid-row: 1; }
  .range .sec__head::after {
    content: ""; grid-column: 2; grid-row: 1;
    height: 1px; background: var(--hair); margin-left: 14px;
  }
  .range .sec__head .sec__t {
    grid-column: 1 / -1; grid-row: 2; margin-top: 16px;
    font-size: clamp(30px, 8.2vw, 38px); text-wrap: balance;
  }
  .range .sec__head .sec__sub {
    grid-column: 1 / -1; grid-row: 3; margin-top: 10px; margin-left: 0;
  }
  /* the vertical drum pins full-bleed; the section keeps its own padding */
  .range .vdrum { margin-inline: calc(-1 * var(--pad)); }
}
/* specimen plates: every sheet figure lives in a 3D tilt frame */
.sec__fig { perspective: 1100px; }
.sec__fig .plate3d {
  position: relative; transform-style: preserve-3d;
  transition: transform .5s cubic-bezier(.2,.8,.2,1), box-shadow .5s ease;
  will-change: transform;
}
.sec__fig:hover .plate3d { box-shadow: 0 30px 70px -30px oklch(19% 0.006 80 / 0.45); }
.sec__fig .plate3d.is-live { transition: box-shadow .5s ease; } /* cursor drives transform directly */
.sec__fig img { width: 100%; height: auto; display: block; border: 1px solid var(--hair); }
.plate3d__glare {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(600px circle at var(--gx, 50%) var(--gy, 50%), oklch(98% 0.01 100 / 0.22), transparent 55%);
  opacity: 0; transition: opacity .4s ease;
}
.sec__fig:hover .plate3d__glare { opacity: 1; }
.plate3d__ticks { position: absolute; inset: 0; pointer-events: none; }
.plate3d__ticks::before, .plate3d__ticks::after {
  content: ""; position: absolute; width: 18px; height: 18px;
}
.plate3d__ticks::before { top: -7px; left: -7px; border-top: 1.5px solid var(--accent-text); border-left: 1.5px solid var(--accent-text); }
.plate3d__ticks::after { bottom: -7px; right: -7px; border-bottom: 1.5px solid var(--accent-text); border-right: 1.5px solid var(--accent-text); }
.sec__fig figcaption { margin-top: 12px; font-family: var(--mono); font-size: 11px; letter-spacing: .16em; color: var(--cedar); }
@media (prefers-reduced-motion: reduce) { .sec__fig .plate3d { transition: none; } }
.sec__data p { font-size: 17px; line-height: 1.65; max-width: 58ch; color: var(--ink); }

.kv { display: grid; grid-template-columns: repeat(2, minmax(140px, 1fr)); gap: 26px 40px; margin-top: 42px; font-family: var(--mono); }
.kv--wide { grid-template-columns: repeat(4, minmax(130px, 1fr)); }
@media (max-width: 860px) { .kv--wide { grid-template-columns: repeat(2, 1fr); } }
.kv div { border-top: 1px solid var(--hair); padding-top: 12px; }
.kv dt { font-size: 10px; letter-spacing: .24em; color: var(--dim); }
.kv dd { font-size: clamp(19px, 2.3vw, 32px); font-weight: 500; margin-top: 10px; font-variant-numeric: tabular-nums; }
.kv--wide dd { font-size: clamp(15px, 1.5vw, 22px); } /* specs table keeps its density */

/* technical-data drawers — the engineering lives one click deep */
.tech { margin-top: 34px; border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); }
.tech summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 12px;
  padding: 16px 2px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .22em; color: var(--dim);
  transition: color .25s;
  min-height: 44px;
}
.tech summary::-webkit-details-marker { display: none; }
.tech summary:hover, .tech[open] summary { color: var(--ink); }
.tech summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.tech__plus { position: relative; width: 12px; height: 12px; flex: 0 0 auto; }
.tech__plus::before, .tech__plus::after {
  content: ""; position: absolute; background: currentColor;
  transition: transform .3s ease;
}
.tech__plus::before { left: 0; right: 0; top: 5px; height: 1.5px; }
.tech__plus::after { top: 0; bottom: 0; left: 5px; width: 1.5px; }
.tech[open] .tech__plus::after { transform: scaleY(0); }
/* animated open: grid-rows 0fr→1fr */
.tech__wrap { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .4s ease; }
.tech[open] .tech__wrap { grid-template-rows: 1fr; }
.tech__in { overflow: hidden; }
.tech__table { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12px; letter-spacing: .06em; margin: 4px 0 18px; }
.tech__table th, .tech__table td { text-align: left; padding: 11px 16px 11px 0; border-top: 1px solid var(--hair); vertical-align: top; }
.tech__table th { color: var(--dim); width: 190px; font-weight: 400; font-size: 10px; letter-spacing: .18em; padding-top: 13px; white-space: nowrap; }
.tech__codes { font-family: var(--mono); font-size: 11px; letter-spacing: .16em; color: var(--dim); line-height: 1.9; margin: 0 0 18px; }
@media (prefers-reduced-motion: reduce) { .tech__wrap, .tech__plus::before, .tech__plus::after { transition: none; } }
@media (max-width: 640px) { .tech__table th { width: 130px; white-space: normal; } }

/* 04 · anchorage — pinned chapter: the detail draws itself in six components */
.anchor__intro { font-size: 18px; line-height: 1.65; max-width: 54ch; color: var(--ink); margin-bottom: 0; }
.anchor__introrow { margin-bottom: clamp(24px, 5vh, 54px); }
.anchor { height: 320vh; }
.anchor__pin {
  position: sticky; top: 0; height: 100vh; height: 100svh;
  display: grid; grid-template-columns: minmax(300px, 520px) 1fr;
  gap: clamp(28px, 5vw, 90px); align-items: center;
  max-width: 1400px;
}
.anchor__list { list-style: none; }
.aitem {
  display: grid; grid-template-columns: 44px 1fr; gap: 14px; align-items: baseline;
  padding: 15px 0; border-top: 1px solid var(--hair);
  opacity: 0.34; transition: opacity .35s ease;
}
.anchor__list .aitem:last-child { border-bottom: 1px solid var(--hair); }
.aitem.is-on { opacity: 1; }
.aitem__no {
  font-family: var(--mono); font-size: 12px; letter-spacing: .14em;
  padding: 3px 8px; justify-self: start;
  transition: background .3s, color .3s;
}
.aitem.is-now .aitem__no { background: var(--brand-lift); color: var(--graphite); }
.aitem__t strong { display: block; font-family: var(--display); font-variation-settings: "wdth" 96; font-weight: 500; font-size: clamp(19px, 2.1vw, 27px); letter-spacing: -0.01em; }
.aitem__s { display: block; margin-top: 5px; font-family: var(--mono); font-size: 11px; letter-spacing: .1em; color: var(--dim); }
.anchor__stage { position: relative; height: min(74vh, 660px); }
.anchor__svg { width: 100%; height: 100%; display: block; }
.acomp path {
  fill: none; stroke: var(--ink); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
}
.acomp .acomp__light { stroke-width: 1; opacity: .45; }
.anchor__read {
  position: absolute; left: 0; bottom: 0;
  display: flex; align-items: center; gap: 14px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .16em;
}
.anchor__k { color: var(--dim); }
.anchor__v { font-variant-numeric: tabular-nums; font-weight: 500; }
.anchor__bar { width: 130px; height: 2px; background: var(--hair); overflow: hidden; }
.anchor__fill { display: block; height: 100%; width: 100%; background: var(--lime); transform: scaleX(0); transform-origin: left; }
.fnd__codes { margin-top: clamp(24px, 4vh, 40px); font-family: var(--mono); font-size: 11px; letter-spacing: .16em; color: var(--dim); line-height: 1.9; }

@media (max-width: 860px) {
  /* batch 09: the phone gets the same pinned instrument as desktop. The old
     mobile collapse scrubbed the steps through a flow layout mostly below
     the fold AND neutralized .aitem lighting with an opacity:1 override —
     the two reasons the steps never visibly played on a phone. Sticky pin,
     short runway (~253px of scroll per step), compact rows so the stage,
     all six items and the HUD share one viewport. */
  .anchor { height: 250vh; }
  .anchor__pin { grid-template-columns: 1fr; gap: 8px; align-items: start; align-content: center; }
  /* 09c (owner): the centered block left ~131px of dead paper under the list —
     the drawing takes that space instead (33→42svh) and the rows breathe */
  .anchor__stage { height: 42svh; order: -1; }
  .aitem { padding: 10px 0; gap: 10px; grid-template-columns: 34px 1fr; }
  .aitem__no { font-size: 10px; padding: 2px 6px; }
  .aitem__t strong { font-size: 17px; }
  .aitem__s { font-size: 10.5px; margin-top: 2px; }
  /* the HUD keeps its absolute footing inside the stage; the drawing cedes
     it a line so nothing overlaps the list below */
  .anchor__svg { height: calc(100% - 30px); }
  .anchor__read { bottom: 2px; }

  /* ── 10a · THE LIVE INSTRUMENT: no reserved paper ────────────────────────
     Measured at 393x852 before this rule: 44.6% of the screen was blank on
     step 01 and 42% on step 05 (the owner's screenshot). Two causes stacked.

     (1) `.anchor__stage` reserved a fixed 42svh = 328px box, aspect 1.08,
         while the camera frame is a WIDE band for five of the six steps
         (3.08 -> 2.21). `xMidYMid meet` fits such a frame by width, so the
         ink drew a 115-137px ribbon and the remaining ~200px was letterbox,
         split above and below. The box now follows the camera: js/main.js
         writes the exact height the live frame needs at the current width,
         so `meet` has nothing left to letterbox.
     (2) `align-content: center` centred a 684.8px block in an 852px pin and
         split the 167px remainder into two dead margins — 84px under the nav
         and the 84px band under row 6 the owner arrowed. The pin is a real
         grid now: the stage takes what it needs, the list takes the rest.

     NOTE the `html.js-motion` gate. It is exactly "the pin is live": main.js
     returns before adding that class under prefers-reduced-motion and ?static
     (js/main.js:22-28), so the camera never runs there and those baselines —
     plus the no-JS one — keep the flow layout below, untouched. */
  html.js-motion .anchor__pin {
    grid-template-rows: auto 1fr;          /* stage(+HUD) · list */
    gap: 10px;
    align-items: stretch; align-content: stretch;
    /* the 84px that used to clear the nav was an ACCIDENT of centring. Say it
       out loud instead — the nav is fixed and 76px tall, so without this the
       drawing slides underneath it. */
    padding-block: calc(var(--nav-h) + 8px) max(16px, env(safe-area-inset-bottom));
  }
  /* the HUD stops being an absolute overlay the drawing had to cede 30px to
     (the old `calc(100% - 30px)`) and becomes a row that costs its own 14px */
  html.js-motion .anchor__stage {
    height: auto; display: grid; grid-template-rows: 1fr auto; gap: 8px; min-height: 0;
    /* the drawing takes the gutter too. With `meet` fitting a wide frame BY
       WIDTH, width is the only thing that makes the ink bigger — killing the
       letterbox alone left the band at exactly its old 115-137px. The extra
       40px of width is +11% on the drawing at every width-bound step, and the
       phone drum next door already bleeds this way (line 584), so the ground
       line running the full width of the screen is this site's own grammar. */
    margin-inline: calc(-1 * var(--pad));
  }
  html.js-motion .anchor__svg { height: var(--asvg-h, 40svh); min-height: 0; }
  /* the HUD is a row now, not an overlay — and it keeps the page gutter the
     bled stage above it gave up, so it still lines up with the list below */
  html.js-motion .anchor__read {
    position: static; bottom: auto; padding-inline: var(--pad);
  }
  /* the six rows share whatever the drawing does not need: they breathe wide
     open while the frame is a short band and tighten as the column arrives,
     so there is no band under row 6 at any step */
  html.js-motion .anchor__list {
    display: grid; grid-template-rows: repeat(6, 1fr); align-content: stretch;
  }
  html.js-motion .aitem { align-content: center; }
}
@media (max-width: 860px) and (prefers-reduced-motion: reduce) {
  .anchor { height: auto; }
  .anchor__pin { position: static; height: auto; }
  .anchor__stage { height: 52vh; }
  .anchor .aitem { opacity: 1 !important; transform: none !important; transition: none !important; }
  .anchor .acomp path,
  .anchor .dim { stroke-dashoffset: 0 !important; transition: none !important; }
}
html.static .anchor { height: auto; }
html.static .anchor__pin { position: static; height: auto; grid-template-columns: 1fr; }
html.static .anchor__stage { height: 52vh; }
html.static .acomp path { stroke-dasharray: none !important; stroke-dashoffset: 0 !important; }
html.static .aitem { opacity: 1; }

/* spec table */
.specs { position: relative; z-index: 1; padding: clamp(60px, 13vh, 150px) var(--pad) 10vh; border-top: 1px solid var(--hair); max-width: 1200px; }
.specs__t {
  font-family: var(--display); font-weight: 500; font-variation-settings: "wdth" 96;
  font-size: clamp(34px, 5vw, 72px); margin-bottom: 44px; letter-spacing: -0.02em;
}
.spectable { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 13px; letter-spacing: .08em; }
.spectable th, .spectable td { text-align: left; padding: 16px 18px 16px 0; border-bottom: 1px solid var(--hair); vertical-align: top; }
.spectable th { color: var(--dim); font-weight: 400; width: 180px; letter-spacing: .2em; font-size: 11px; }
.td--accent { color: var(--accent-text); }
.btn {
  display: inline-flex; align-items: center; margin-top: 46px; padding: 16px 30px; min-height: 44px;
  background: var(--graphite); color: var(--stone); text-decoration: none;
  font-family: var(--mono); font-size: 12px; letter-spacing: .18em; font-weight: 500;
  transition: background .3s, color .3s;
}
.btn:hover { background: var(--brand-lift); color: var(--graphite); }
.range__ctas { display: flex; gap: 14px; flex-wrap: wrap; }
.range__ctas .btn { margin-top: 0; }
.btn--quiet { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--hair); }
.btn--quiet:hover { background: transparent; box-shadow: inset 0 0 0 1px var(--ink); color: var(--ink); }

/* 05 · the range — catalog teaser on the dossier */
.range { position: relative; z-index: 1; padding: clamp(60px, 13vh, 150px) var(--pad) clamp(60px, 11vh, 120px); border-top: 1px solid var(--hair); max-width: 1400px; margin-inline: auto; }

/* the wheel — six families on a scroll-spun 3D ring (desktop, motion on) */
.wheel { display: none; }
@media (min-width: 861px) {
  html.js-motion .wheel { display: block; height: 300vh; margin: 0 calc(-1 * var(--pad)); }
  html.js-motion .range.is-systems-ready .range__mobilepack { display: none; }
}
.wheel__pin {
  position: sticky; top: 0; height: 100vh; overflow: clip;
  display: flex; align-items: center; justify-content: center;
  perspective: 1700px; perspective-origin: 50% 50%;
  /* one shared card unit keeps ring geometry consistent across the six families */
  --wcard-w: clamp(340px, 30vw, 460px);
}
/* The stage holds the family ring. When the code drum opens the ring steps back,
   shrinks and slides left, driven by custom props so its rotateX tilt survives. */
.wheel__stage {
  transform-style: preserve-3d;
  transform: translateX(var(--stx, 0%)) translateY(var(--sty, calc(var(--wcard-w) * -0.134))) translateZ(var(--stz, 0px)) scale(var(--sts, 1)) rotateX(var(--strx, -8deg));
  display: grid; place-items: center;
  /* duration and ease deliberately match the open timeline's power3.out in
     wheels.js — the shrink and the second wheel's emergence are one move */
  transition: transform .9s cubic-bezier(0.215, 0.61, 0.355, 1);
}
/* Shift and scale are sized so the ring's SIDE cards clear the second wheel, not just
   its front card: at 60° a side card still reaches ~0.72 * ring-radius to the right, and
   the pin's containing block is only as wide as .range's 1400px max-width — so -20%/0.76
   left a measured 100px overlap. Verified clear at 1600 and at 900. */
.wheel.is-open .wheel__stage {
  /* protractor redesign 2026-08-05: the card becomes the fan's hub plate —
     small, bottom-left, the fan arcs over it. Still never translateZ-buried. */
  --stx: -44%; --sty: -2%; --stz: 0px; --sts: 0.88; --strx: -3deg;
}
/* Narrower desktops: the second wheel's column is a % of the viewport but the ring's
   card width has a 340px floor, so the two converge — measured 4px of clearance at
   900px wide. The ring gives up more ground there. */
@media (max-width: 1200px) {
  .wheel.is-open .wheel__stage { --stx: -46%; --sty: -2%; --sts: 0.84; --strx: -3deg; }
}
.wheel__ring { grid-area: 1 / 1; justify-self: center; align-self: center; }
.wheel__ring {
  position: relative; width: var(--wcard-w); aspect-ratio: 1100 / 943;
  transform-style: preserve-3d; will-change: transform;
  --wz: calc(var(--wcard-w) * 1.02);           /* ring radius: hexagon + breathing gap */
}
.wcard {
  position: absolute; inset: 0; display: block; text-decoration: none;
  transform: rotateY(calc(var(--i) * 60deg)) translateZ(var(--wz)) scale(var(--cs, 1));
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  border: 1px solid var(--hair); background: var(--paper); overflow: clip; cursor: pointer;
}
.wcard--noimg {
  background:
    linear-gradient(var(--hair) 1px, transparent 1px),
    linear-gradient(90deg, var(--hair) 1px, transparent 1px),
    var(--graphite);
  background-size: 44px 44px;
}
.wcard img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wcard__veil {
  position: absolute; inset: 0; pointer-events: none;
  background: oklch(19% 0.006 80 / 0.55); backdrop-filter: none;
  opacity: 1; transition: opacity .45s ease;
}
.wcard.is-front .wcard__veil { opacity: 0; }
.wcard__no {
  position: absolute; top: 14px; left: 16px; font-family: var(--mono);
  font-size: 11px; letter-spacing: .16em; color: oklch(94% 0.004 120 / 0.9);
}
.wcard__name {
  position: absolute; left: 16px; bottom: 34px; font-family: var(--display);
  font-weight: 500; font-variation-settings: "wdth" 88;
  font-size: clamp(20px, 1.9vw, 30px); letter-spacing: -0.01em; color: oklch(96% 0.004 120);
  text-shadow: 0 1px 18px oklch(19% 0.006 80 / 0.6);
}
.wcard__d {
  position: absolute; left: 16px; bottom: 14px; font-family: var(--mono);
  font-size: 10px; letter-spacing: .1em; color: oklch(94% 0.004 120 / 0.72);
}
.wcard__cta {
  position: absolute; top: 14px; right: 16px; z-index: 3;
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 9px; letter-spacing: .16em;
  color: oklch(94% 0.004 120 / 0.85);
  text-shadow: 0 1px 12px oklch(19% 0.006 80 / 0.55);
  opacity: 0; transform: translateY(4px);
  transition: opacity .3s var(--ease-magic), transform .3s var(--ease-magic);
}
.wcard__cta-tick {
  width: 11px; height: 1px; background: var(--lime);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .3s var(--ease-magic) .06s;
}
.wcard.is-front .wcard__cta,
.wcard:hover .wcard__cta,
.wcard:focus-visible .wcard__cta { opacity: 1; transform: none; }
.wcard.is-front .wcard__cta-tick,
.wcard:hover .wcard__cta-tick,
.wcard:focus-visible .wcard__cta-tick { transform: scaleX(1); }
.wcard.is-front:hover { --cs: 1.02; }
.wheel.is-open .wcard__cta { opacity: 0; }
.wcard .tag { position: absolute; top: 12px; right: 12px; }
.wcard.is-front .wcard__no { color: var(--brand-lift); }
.wcard::after {                                  /* ink gradient so the name always reads */
  content: ""; position: absolute; inset: auto 0 0 0; height: 42%;
  background: linear-gradient(to top, oklch(19% 0.006 80 / 0.72), transparent);
  pointer-events: none;
}
.wcard__veil { z-index: 2; } .wcard__no, .wcard__name, .wcard__d, .wcard .tag { z-index: 3; }
.wheel__hud {
  position: absolute; left: var(--pad); right: var(--pad); bottom: 26px;
  display: flex; align-items: baseline; gap: 26px;
  font-family: var(--mono); letter-spacing: .16em;
}
.wheel__count { font-size: 12px; color: var(--ink); }
.wheel__count #wheelNo { color: var(--accent-text); }
.wheel__name { font-size: 12px; color: var(--dim); }
.wheel__hint { margin-left: auto; font-size: 10px; color: var(--dim); }
@media (prefers-reduced-motion: reduce) { .wheel { display: none !important; } .range__mobilepack { display: block !important; } }
/* the strip is a horizontal track that slides past as you scroll (scrubbed) */
.range__strip {
  display: flex; gap: clamp(14px, 2vw, 28px);
  width: 126%;
  margin-bottom: clamp(36px, 6vh, 64px);
  will-change: transform;
}
.range__fig { flex: 0 0 calc((100% - 2 * clamp(14px, 2vw, 28px)) / 3); }
@media (max-width: 760px) {
  .range__strip { display: grid; grid-template-columns: 1fr; width: 100%; will-change: auto; }
  .range__fig { flex: none; }
}
.range__fig img { width: 100%; height: auto; display: block; border: 1px solid var(--hair); }
.range__fig figcaption { margin-top: 10px; font-family: var(--mono); font-size: 10px; letter-spacing: .12em; color: var(--dim); line-height: 1.7; }
.tag { display: inline-block; font-size: 8px; letter-spacing: .22em; font-weight: 500; padding: 3px 6px; margin-right: 8px; vertical-align: 1px; }
.tag--photo { background: var(--brand-lift); color: var(--graphite); }
.range__index { display: block; margin-bottom: 40px; }
.system-family {
  border-top: 1px solid var(--hair);
}
.system-family:last-child { border-bottom: 1px solid var(--hair); }
.system-family__summary {
  min-height: 64px; padding: 14px 6px;
  display: grid; grid-template-columns: 44px minmax(220px, 340px) 1fr 18px;
  gap: 18px; align-items: center; cursor: pointer; list-style: none;
}
.system-family__summary::-webkit-details-marker,
.product__trigger::-webkit-details-marker { display: none; }
.system-family__no,
.system-family__partial {
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
}
.system-family__no { color: var(--accent-text); }
.system-family__name {
  font-family: var(--display); font-variation-settings: "wdth" 94; font-weight: 500;
  font-size: clamp(18px, 2vw, 25px); letter-spacing: -.015em;
}
.system-family__lede {
  font-family: var(--mono); font-size: 10px; line-height: 1.6;
  letter-spacing: .1em; color: var(--dim); text-align: right;
}
.system-family__mark,
.product__mark {
  position: relative; display: block; width: 13px; height: 13px;
  transition: transform .3s var(--ease-magic);
}
.system-family__mark::before,
.system-family__mark::after,
.product__mark::before,
.product__mark::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 13px; height: 1px; background: currentColor;
  transform: translate(-50%, -50%);
}
.system-family__mark::after,
.product__mark::after { transform: translate(-50%, -50%) rotate(90deg); }
.system-family[open] > .system-family__summary .system-family__mark,
.system-product[open] > .product__trigger .product__mark,
.product__trigger.is-active .product__mark { transform: rotate(45deg); }
.system-family__desc {
  max-width: 52ch; margin: 12px 6px 28px 68px;
  font-size: 15px; line-height: 1.7; color: var(--dim);
}
.system-products { margin-left: 68px; }
.system-product { break-inside: avoid; border-top: 1px solid var(--hair); }
.system-family__partial {
  margin: 20px 6px 30px 68px; color: var(--dim);
}
@media (min-width: 1101px) {
  .system-products { column-count: 2; column-gap: clamp(28px, 4vw, 72px); }
}
@media (max-width: 760px) {
  .system-family__summary {
    grid-template-columns: 34px 1fr 18px; gap: 12px; align-items: center;
  }
  .system-family__lede { display: none; }
  .system-family__desc,
  .system-products,
  .system-family__partial { margin-left: 46px; }
}
.range .btn { margin-top: 6px; }

.foot { position: relative; z-index: 1; padding: 26px var(--pad) 32px; border-top: 1px solid var(--hair); }
.foot p { font-family: var(--mono); font-size: 11px; letter-spacing: .1em; color: var(--dim); max-width: 80ch; line-height: 1.7; }

/* ═══ SKIPPED CHAPTERS — off-screen style/layout containment ═════════════════
   .asm, .anchor and .wheel are the only sections whose box is sized by CSS alone
   (520vh / 320vh / 300vh) instead of by their contents. That is what makes
   content-visibility safe here and nowhere else on this page: the skipped box and
   the rendered box are identical, so no contain-intrinsic-size estimate is involved
   and neither the document height nor any ScrollTrigger start/end can move.
   Verified identical at 1280/1440/1680 — 99 triggers, same scrollHeight.

   Do NOT extend this to the content-sized sections (.work, .range, .secs, .specs,
   .contact). Those need a contain-intrinsic-size guess, and .work alone swings
   5656 → 7021px between 1280 and 1680. ScrollTrigger resolves positions once at
   load while the page is still at scroll 0 (autoRefreshEvents deliberately excludes
   load), so a wrong guess desyncs every trigger below it for the whole session.
   Measured: that variant lost 1,138px of document height and ran 27% SLOWER.

   Gated on .js-motion because html.static rewrites .asm/.anchor back to height:auto,
   and on 861px because .anchor collapses to height:auto below that. Both gates are
   load-bearing: verified that .anchor drops to content-visibility:visible at 860px
   and that .asm/.anchor do in static and reduced-motion.
   Measured 2026-08-05, 1440×900 @2dpr, 4× CPU throttle, median of 11 cold loads:
   render total 2,658 → 2,170 ms (−18%), paint 616 → 357 (−42%), PrePaint 312 → 261.
   CLS across a full scroll 0.014 → 0.0005. */
html.js-motion .asm { content-visibility: auto; }
@media (min-width: 861px) {
  html.js-motion .anchor,
  html.js-motion .wheel { content-visibility: auto; }
}
/* The mobile vertical drum qualifies under the same law: wheels.js sizes
   .vdrum to a fixed svh runway (inline style), so the skipped box and the
   rendered box are identical. The sticky pin is unaffected (sticky resolves
   against the scrollport, not the containment box). The RM flat column is
   content-sized and therefore excluded. */
@media (max-width: 860px) {
  html.js-motion .vdrum:not(.vdrum--flat) { content-visibility: auto; }
}

/* static mode */
html.static .asm { height: auto; }
html.static .asm__pin { position: relative; height: auto; display: grid; }
html.static .asm__poster { position: relative; height: auto; }
html.static .asm__cv, html.static .asm__dims { display: none; }
html.static .asm__exploded-static { display: block; }
.asm__exploded-static { display: none; }
html.static .asm__exploded-static img { width: 100%; height: auto; }
html.static .asm__hud, html.static .asm__note { position: relative; inset: auto; padding: 18px var(--pad); }

/* ═══ §02 — COAXIAL CODE DRUM + TECHNICAL BLOCK ══════════════════════════════
   The ring and drum retain their 3D contexts. Only their leaves are faded;
   grouping properties never touch the 3D parents, so rear faces stay hidden. */

.wcard { transition: transform .55s var(--ease-out-expo); }
.wcard:focus-visible { outline: 2px solid var(--lime); outline-offset: 5px; }
/* Open state, per client 2026-08-05: the family ring STAYS as shrunken context at
   left while the drum pops up at right and takes focus. Opacity lives on the CARDS
   (leaves), never on .wheel__ring — the ring must keep its 3D context (css:589).
   The old collision is gone because the drum no longer overlaps the receded ring. */
.wcard { transition: transform .55s var(--ease-out-expo), opacity .45s var(--ease-magic); }
/* Open: only the CHOSEN category card stays — the side cards of the hexagon project
   ~130px past the front card at ±60° and were physically overlapping the drum
   (a parent rect ignores 3D-projected children, which is how the "gap" lied).
   Cards are leaves; opacity here is safe. Ring returns fully on close/switch. */
.wheel.is-open .wcard { opacity: 0; pointer-events: none; }
.wheel.is-open .wcard.is-front { opacity: 1; }

/* ── drafting plate (2026-08-05): when the fan opens, the front card trades its
   photograph for a white specimen plate — the selected system's cutaway large,
   a title block along the base. The instrument stands on a drawing, not a photo. */
.wcard__plate {
  position: absolute; inset: 0; z-index: 4; display: grid;
  grid-template-rows: 1fr auto; background: oklch(97.5% 0.003 110);
  opacity: 0; pointer-events: none; transition: opacity .45s var(--ease-magic);
}
.wheel.is-open .wcard.is-front .wcard__plate { opacity: 1; }
.plate__specimen { position: relative; margin: 0; overflow: clip; background: #fff; }
.wcard__plate .plate__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; padding: 0; opacity: 0;
  transition: opacity .32s var(--ease-magic);
}
.wcard__plate .plate__img.is-shown { opacity: 1; }
.plate__tb {
  display: flex; align-items: baseline; gap: 14px;
  padding: 10px 14px; border-top: 1px solid oklch(19% 0.006 80 / 0.22);
  font-family: var(--mono); letter-spacing: .16em; color: oklch(32% 0.008 90);
}
/* brand red at the lightness the old green had, so contrast on stone is unchanged
   (measured: old green 6.11:1, this 6.05:1 — the 4.5 floor is for text like this) */
.plate__no { font-size: 10px; color: oklch(48% 0.19 21); }
.plate__name { font-size: 11px; font-weight: 600; }
.plate__count { margin-left: auto; font-size: 9px; color: oklch(52% 0.008 95); }

/* ── vernier caliper (2026-08-05): fixed jaw over a sliding code scale ── */
.cal__dock {
  position: absolute; z-index: 6; transform: translateX(-50%);
  visibility: hidden; pointer-events: none;
}
.wheel.is-open .cal__dock { visibility: visible; pointer-events: auto; }
.cal__beam {
  position: absolute; left: 0; right: 0; bottom: 0; height: 12px;
  border-top: 1.6px solid oklch(30% 0.006 90 / .55);
  border-bottom: 1px solid var(--hair);
  background: repeating-linear-gradient(90deg,
    transparent 0 22px, oklch(30% 0.006 90 / .35) 22px 23px);
}
.cal__window { position: absolute; inset: -46px 0 0 0; overflow: clip; }
.cal__scale {
  position: absolute; left: 0; right: 0; bottom: 8px; height: 56px;
  will-change: transform;
}
.cal__stop {
  position: absolute; bottom: 0; left: calc(50% + (var(--j) * var(--cal-pitch, 92px)));
  min-width: 44px; min-height: 44px; padding: 0;
  display: flex; flex-direction: column-reverse; align-items: center; justify-content: flex-start;
  transform: translateX(-50%); background: none; border: 0; cursor: pointer;
  font-family: var(--mono); transition: opacity .3s var(--ease-magic);
}
.cal__tick {
  display: block; width: 1.4px; height: 14px; background: var(--ink);
  transition: height .3s var(--ease-magic);
}
.cal__stop.is-front .cal__tick { height: 20px; background: var(--lime); }
.cal__code {
  display: block; margin-bottom: 6px; font-size: 11px; letter-spacing: .14em;
  color: var(--dim);
  transition: color .3s var(--ease-magic);
}
.cal__stop:hover .cal__tick,
.cal__stop:focus-visible .cal__tick { height: 20px; }
.cal__stop:hover .cal__code,
.cal__stop:focus-visible .cal__code { color: var(--ink, oklch(20% 0.008 90)); }
.cal__stop.is-front .cal__code {
  color: var(--ink, oklch(20% 0.008 90)); font-weight: 600;
}
.cal__stop:focus-visible { outline: 2px solid var(--lime); outline-offset: 4px; }
.cal__jaw {
  position: absolute; left: 50%; bottom: 34px; transform: translateX(-50%);
  min-width: 88px; padding: 7px 14px; text-align: center;
  background: oklch(93% 0.004 110); border: 1px solid oklch(30% 0.006 90 / .4);
}
.cal__readout {
  display: block; font: 600 15px/1 var(--mono); letter-spacing: .1em;
}
.cal__readout.is-swap { animation: calswap .18s var(--ease-magic); }
@keyframes calswap { from { opacity: 0; transform: translateY(5px); } }
.cal__prong {
  position: absolute; left: 50%; bottom: calc(-1 * var(--prong, 44px));
  width: 2px; height: var(--prong, 44px); background: var(--lime);
  transform: translateX(-50%); pointer-events: none;
}
.cal__prong::after {
  content: ""; position: absolute; left: 50%; bottom: -3.5px;
  width: 7px; height: 7px; background: var(--lime);
  transform: translateX(-50%) rotate(45deg);
}
.drum__partial {
  position: absolute; left: 0; top: calc(100% + 18px); margin: 0;
  font-family: var(--mono); font-size: 9px; letter-spacing: .16em; color: var(--dim);
}

.wheel__technical {
  position: absolute; z-index: 7; top: 50%; right: clamp(18px, 3.5vw, 76px);
  width: min(29vw, 424px); max-height: min(calc(100vh - 160px), 860px); padding: 0 0 10px 22px;
  overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;
  border-left: 1px solid var(--hair); background: var(--paper);
  transform: translateY(-50%) translateX(22px);
  visibility: hidden; pointer-events: none; opacity: 0;
  transition: transform .55s var(--ease-out-expo), opacity .35s var(--ease-magic), visibility 0s .55s;
}
.wheel.is-open .wheel__technical {
  transform: translateY(-50%) translateX(0);
  visibility: visible; pointer-events: auto; opacity: 1;
  transition-delay: 0s;
}
.wheel__tech-head {
  position: sticky; top: 0; z-index: 2;
  margin: 0 0 0 -22px; width: calc(100% + 22px);
  background: var(--paper); border-bottom: 1px solid var(--hair);
}
.wheel__close {
  width: 100%; min-height: 44px; padding: 8px 10px;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  background: var(--paper); border: 0; color: var(--ink); cursor: pointer;
  font-family: var(--mono); font-size: 9px; letter-spacing: .16em;
}
.wheel__close-tick {
  width: 11px; height: 1px; background: var(--lime);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .3s var(--ease-magic);
}
.wheel__close:hover .wheel__close-tick,
.wheel__close:focus-visible .wheel__close-tick { transform: scaleX(1); }
.wheel__technical .product-tech { margin-top: 8px; padding-top: 8px; }
@media (max-height: 800px) {
  .wheel__technical .product-tech__fig { height: clamp(112px, 17vh, 170px); }
}
.wheel__close:focus-visible { outline: 2px solid var(--lime); outline-offset: -3px; }
.product-tech__action:focus-visible { outline: 2px solid var(--lime); outline-offset: 3px; }

/* The disclosure styles below belong to the always-readable mobile/JS-off pack. */
.products { column-count: 2; column-gap: clamp(22px, 3vw, 50px); }
.product { break-inside: avoid; border-top: 1px solid var(--hair); }
.product__trigger {
  position: relative; width: 100%; min-height: 50px; padding: 11px 25px 11px 20px;
  display: grid; grid-template-columns: minmax(76px, auto) 1fr 14px;
  gap: 12px; align-items: center; list-style: none;
  appearance: none; border: 0; background: transparent; color: var(--ink);
  text-align: left; cursor: pointer; opacity: 1;
  transition: opacity .3s var(--ease-magic);
}
.product__tick {
  position: absolute; left: 0; top: 50%; width: 11px; height: 1px;
  background: var(--lime); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .3s var(--ease-magic);
}
.product__code {
  font-family: var(--mono); font-size: clamp(14px, 1.25vw, 18px); line-height: 1.65;
  letter-spacing: .13em; transform: translateX(0);
  transition: transform .3s var(--ease-magic);
}
.product__name {
  font-size: 11px; line-height: 1.45; color: var(--dim); text-align: right;
}
.product__trigger:hover .product__tick,
.product__trigger:focus-visible .product__tick,
.product__trigger.is-active .product__tick { transform: scaleX(1); }
.product__trigger:hover .product__code,
.product__trigger:focus-visible .product__code,
.product__trigger.is-active .product__code { transform: translateX(.4em); }
.products:has(.product__trigger:hover) .product__trigger:not(:hover),
.products:has(.product__trigger:focus-visible) .product__trigger:not(:focus-visible),
.system-products:has(.product__trigger:hover) .product__trigger:not(:hover),
.system-products:has(.product__trigger:focus-visible) .product__trigger:not(:focus-visible) {
  opacity: .45;
}
.system-family__partial { color: var(--dim); }

.product-tech {
  margin-top: 18px; padding: 16px 0 2px; border-top: 1px solid var(--hair);
}
.product-tech__eyebrow,
.product-tech__capability,
.product-tech__status {
  font-family: var(--mono); font-size: 9px; letter-spacing: .16em;
}
.product-tech__eyebrow { color: var(--dim); }
.product-tech__code {
  margin-top: 7px; font-family: var(--mono); font-size: clamp(34px, 4.4vw, 66px);
  font-weight: 400; line-height: 1.08; letter-spacing: .1em;
}
.wheel__technical .product-tech__code { font-size: clamp(24px, 2.5vw, 40px); }
.product-tech__name { margin-top: 5px; font-size: 12px; color: var(--dim); }
.product-tech__desc {
  max-width: 52ch; margin-top: 12px; font-size: 12.5px; line-height: 1.6;
}
.product-tech__capability { margin-top: 13px; color: var(--dim); }
.product-tech__meta { margin-top: 12px; display: flex; align-items: center; gap: 12px; }
.product-tech__action {
  min-height: 44px; padding: 10px 13px; display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--hair); color: var(--ink); text-decoration: none;
  font-family: var(--mono); font-size: 9px; letter-spacing: .14em;
}
.product-tech__action-tick {
  width: 11px; height: 1px; background: var(--lime);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .3s var(--ease-magic);
}
.product-tech__action:hover .product-tech__action-tick,
.product-tech__action:focus-visible .product-tech__action-tick { transform: scaleX(1); }
.product-tech__action[data-state="pending"] { opacity: .55; cursor: not-allowed; }
.product-tech__status { color: var(--dim); }
/* ── product sheet (2026-08-05): every hero is a white-ground technical plate
   showing the profile internals — contain, never crop, so the drum scroll
   flips through matching plates ── */
.product-tech__fig {
  position: relative; margin: 0 0 14px; height: clamp(126px, 20vh, 200px);
  background: #fff; border: 1px solid var(--hair); overflow: clip;
}
.product-tech__fig > img {
  width: 100%; height: 100%; object-fit: contain; display: block; padding: 0;
}
.product-tech__specs { margin: 16px 0 0; }
.product-tech__row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 5px 0; border-top: 1px solid var(--hair);
}
.product-tech__row dt {
  font-family: var(--mono); font-size: 9px; letter-spacing: .16em; color: var(--dim);
  text-transform: uppercase; white-space: nowrap;
}
.product-tech__row dd {
  margin: 0; font-family: var(--mono); font-size: 11px; letter-spacing: .08em;
  text-align: right; font-variant-numeric: tabular-nums;
}
.product-tech__apps {
  margin-top: 11px; font-family: var(--mono); font-size: 9px; line-height: 1.7;
  letter-spacing: .14em; color: var(--dim); text-transform: uppercase;
}
.product-tech__colors {
  margin-top: 9px; font-family: var(--mono); font-size: 9px; letter-spacing: .16em;
  color: var(--dim);
}
.product-tech--fallback { margin: 0 0 18px 20px; padding-right: 8px; }
.product-tech--fallback .product-tech__code { font-size: clamp(28px, 5vw, 48px); }

@media (max-width: 1100px) {
  .wheel__technical { right: 18px; width: min(32vw, 360px); }
  .products { column-count: 1; }
}
@media (max-width: 520px) {
  .product__trigger { grid-template-columns: minmax(72px, auto) 1fr 14px; }
  .product__name { font-size: 10px; }
  .product-tech--fallback { margin-left: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .system-family__mark,
  .product__mark,
  .product__trigger,
  .product__tick,
  .product__code,
  .wcard__cta,
  .wcard__cta-tick,
  .wheel__close-tick,
  .product-tech__action-tick,
  .cal__tick,
  .cal__code { transition: none; }
}

/* ═══ §03 — SELECTED WORK: THE DRAWER ════════════════════════════════════════
   Ten drawing sheets pulled past a live index rail, closed by a system schedule.

   Replaces the sun-path wall (batch 10, 2026-08-13). The old form scattered
   plates either side of a decorative centre rule with 252px hairline figures in
   the margins; measured at 1440 and 1280 those figures hung off the viewport on
   6 of 10 entries, the hover scope panel landed on the project title on entries
   5-9, and every entry left ~600px of dead black on its empty side. All three
   defects were structural, not tunable, so the structure went.

   THE LAWS THIS BLOCK KEEPS
   · Nothing is hover-gated. Title, location, scope and systems are ALWAYS in the
     document and always visible, so touch, keyboard, no-JS, ?static and
     reduced-motion all carry the complete claim with zero extra rules. That is
     what retired ~200 lines of reveal-safety machinery.
   · No text sits on a photograph. Identity lives in the title block on graphite,
     which is why every label clears 4.5:1 by construction rather than by luck.
   · Hidden entrance states are gated on .wk-armed, which work.js adds only once
     its observer is live. Ship-guard law: default state is visible.
   · The red is a hairline and a tick. Never a text colour on this ground.
   ════════════════════════════════════════════════════════════════════════════ */
.work {
  position: relative; z-index: 1;
  padding: clamp(82px, 10vw, 150px) var(--pad) clamp(96px, 12vw, 168px);
  border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair);
  background: var(--graphite); color: var(--stone); overflow: clip;
  /* Self-contained dark surface: the section owns its hairline channel (ERA
     pattern). Without this, --hair resolves from html.light at this scroll
     position and every rule in the register disappears. */
  --hair: oklch(94% 0.004 120 / 0.15);
  --hair-2: oklch(94% 0.004 120 / 0.30);
  /* Text ramp. Ground is graphite oklch(19%); anything at or above oklch(62%)
     clears 4.5:1 on it, so the quietest ink here is 66% with margin to spare. */
  --wk-ink: var(--stone);
  --wk-ink-2: oklch(78% 0.004 120);
  --wk-ink-3: oklch(66% 0.004 120);
}

/* ── head: the sheet key ── */
.work__head {
  display: grid; grid-template-columns: minmax(44px, .35fr) minmax(0, 1.2fr) minmax(240px, 1fr);
  align-items: baseline; gap: clamp(14px, 2vw, 34px) clamp(16px, 2.4vw, 42px);
  padding-bottom: clamp(28px, 4vw, 52px); border-bottom: 1px solid var(--hair);
}
.work__sect,
.work__sub {
  font-family: var(--mono); font-size: clamp(9px, .72vw, 11px); line-height: 1.45;
  letter-spacing: .16em; text-transform: uppercase;
}
.work__sect { color: var(--brand-lift); }
.work__heading {
  font-family: var(--display); font-size: clamp(34px, 5.4vw, 86px); font-weight: 500;
  font-variation-settings: "wdth" 90; line-height: .92; letter-spacing: -.045em;
}
.work__sub { color: var(--wk-ink-2); grid-column: 3; grid-row: 1; }
/* derived in the generator from work-data.js — never typed, so it cannot drift */
.work__key {
  grid-column: 3; grid-row: 2; list-style: none;
  display: flex; flex-wrap: wrap; gap: 4px 0;
  font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--wk-ink-3);
}
.work__key li + li { margin-left: 14px; padding-left: 14px; border-left: 1px solid var(--hair-2); }

/* ── the drawer: index rail + sheets ── */
.wk-drawer {
  width: min(100%, 1480px); margin-inline: auto;
  display: grid; grid-template-columns: clamp(196px, 17vw, 248px) minmax(0, 1fr);
  gap: clamp(30px, 4.4vw, 76px);
  padding-block-start: clamp(44px, 5.6vw, 84px);
}

.wk-rail { position: sticky; top: calc(var(--nav-h) + 22px); align-self: start; }
.wk-rail__t {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .26em;
  color: var(--wk-ink-3); padding-bottom: 9px;
}
.wk-index { list-style: none; border-top: 1px solid var(--hair-2); }
.wk-idx { border-bottom: 1px solid var(--hair); }
.wk-idx__a {
  position: relative; display: grid; grid-template-columns: 26px minmax(0, 1fr);
  align-items: baseline; column-gap: 4px; row-gap: 2px;
  padding: 9px 0 9px 10px; text-decoration: none; color: inherit;
  transition: background-color .3s var(--ease-quart);
}
.wk-idx__a i {
  grid-row: 1; font-style: normal; font-family: var(--mono); font-size: 9.5px;
  letter-spacing: .12em; color: var(--wk-ink-3); transition: color .3s;
}
.wk-idx__a b {
  grid-row: 1; grid-column: 2; font-weight: 400; font-size: 12.5px; line-height: 1.25;
  color: var(--wk-ink-2); transition: color .3s;
}
.wk-idx__a em {
  grid-row: 2; grid-column: 2; font-style: normal; font-family: var(--mono);
  font-size: 9px; letter-spacing: .1em; text-transform: uppercase; color: var(--wk-ink-3);
}
/* the tick: the only red in the rail, and it is a mark, not a text colour */
.wk-idx__a::before {
  content: ""; position: absolute; left: 0; top: 11px; bottom: 11px; width: 2px;
  background: var(--brand); transform: scaleY(0); transform-origin: 50% 0;
  transition: transform .34s var(--ease-magic);
}
.wk-idx.is-on .wk-idx__a::before { transform: scaleY(1); }
.wk-idx.is-on .wk-idx__a b { color: var(--wk-ink); }
.wk-idx.is-on .wk-idx__a i { color: var(--wk-ink-2); }
.wk-idx__a:hover b, .wk-idx__a:focus-visible b { color: var(--wk-ink); }
.wk-idx__a:hover, .wk-idx__a:focus-visible { background: oklch(94% 0.004 120 / 0.045); }
.wk-idx__a:focus-visible { outline: 2px solid var(--lime); outline-offset: -2px; }

/* ── the sheets ── */
.wk-sheets { display: grid; gap: clamp(72px, 8.4vw, 128px); min-width: 0; }
.wk-sheet {
  position: relative; min-width: 0;
  scroll-margin-top: calc(var(--nav-h) + 30px);
}
/* the pointed-at sheet answers the rail */
.wk-sheet.is-cued .wk-plate { border-color: var(--hair-2); }

/* --span narrows the WHOLE sheet, never just the plate: the title block is the
   sheet's bottom edge and has to end where the plate ends, or the two read as a
   misalignment instead of a smaller drawing. */
.wk-sheet--wide { width: var(--span, 100%); }
.wk-plate {
  position: relative; display: block; margin: 0; overflow: clip;
  width: 100%; aspect-ratio: var(--ar, 16 / 9);
  border: 1px solid var(--hair); background: oklch(15% 0.006 80);
  transition: border-color .35s var(--ease-quart);
  clip-path: inset(0 0 0 0);
}
.wk-plate__shift { position: absolute; inset: -7% 0; display: block; }
.wk-plate__shift img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  /* Rest state only. work.js used to scrub --wpar through this var(); it now
     animates yPercent and writes the transform directly, because an unregistered
     custom property forces a style recalc every frame and cannot composite.
     This declaration remains as the no-JS / reduced-motion / <861px baseline,
     where --wpar is never set and it resolves to a 0% offset. */
  transform: translate3d(0, var(--wpar, 0%), 0);
}
/* seats the photograph against graphite; opens as the sheet reaches the band.
   Paint only, and it never covers a word — nothing is set over the image. */
.wk-plate__grade {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(128% 100% at 50% 44%, transparent 52%, oklch(10% 0.004 80 / .40) 100%);
  opacity: 1; transition: opacity .9s var(--ease-magic);
}
.wk-sheet.is-lit .wk-plate__grade { opacity: .38; }
.wk-plate--empty { display: grid; place-items: center; }
.wk-plate__await {
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
  color: var(--wk-ink-3); text-transform: uppercase;
}

/* ── the title block: the thing in the corner of every real drawing ── */
.wk-block { border-top: 1px solid var(--hair-2); margin-top: 0; }
/* the block reads as a real title block: an identity row over a two-cell foot.
   LOCATION is max-content so its dividing rule hugs the text instead of leaving
   200px of empty cell, and SYSTEMS fills the half of the foot that a single
   82ch scope paragraph would otherwise leave black. */
.wk-hd {
  display: grid; grid-template-columns: 92px minmax(0, 1fr) minmax(140px, max-content);
  border-bottom: 1px solid var(--hair);
}
.wk-ft { display: grid; grid-template-columns: minmax(0, 1fr) minmax(190px, .42fr); }
.wk-ft .wk-c + .wk-c { border-left: 1px solid var(--hair); padding-left: clamp(14px, 1.6vw, 26px); }
.wk-c { display: block; padding: 11px 0 13px; min-width: 0; }
.wk-hd .wk-c + .wk-c { border-left: 1px solid var(--hair); padding-left: clamp(14px, 1.6vw, 26px); }
.wk-c > b {
  display: block; font-family: var(--mono); font-size: 9px; font-weight: 400;
  letter-spacing: .22em; color: var(--wk-ink-3); margin-bottom: 7px;
}
.wk-c > span, .wk-c > p {
  font-family: var(--mono); font-size: 11px; line-height: 1.55;
  letter-spacing: .06em; color: var(--wk-ink-2);
}
.wk-c--lo > span { text-transform: uppercase; letter-spacing: .1em; font-size: 10px; }
.wk-title {
  font-family: var(--display) !important; font-weight: 500;
  font-variation-settings: "wdth" 88;
  font-size: clamp(24px, 2.9vw, 46px) !important; line-height: 1 !important;
  letter-spacing: -.032em !important; color: var(--wk-ink) !important;
  display: block; overflow-wrap: anywhere;
}
.wk-ft { border-bottom: 1px solid var(--hair); }
.wk-c--sc > p { max-width: 74ch; color: var(--wk-ink-2); }
.wk-sys {
  list-style: none; display: grid; gap: 4px;
  font-family: var(--mono); font-size: 9px; letter-spacing: .18em;
  color: var(--wk-ink-3);
}
.wk-sys li { position: relative; padding-left: 13px; line-height: 1.5; }
/* a tick, not a bullet: this is a schedule of delivered systems, not prose */
.wk-sys li::before {
  content: ""; position: absolute; left: 0; top: .58em; width: 6px; height: 1px;
  background: var(--brand);
}

/* beside: every third sheet turns sideways. Purely compositional cadence —
   ten entries must not read as ten identical beats. */
.wk-sheet--beside {
  display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(210px, .82fr);
  gap: clamp(20px, 2.6vw, 40px); align-items: start;
}
.wk-sheet--beside .wk-hd { grid-template-columns: minmax(0, 1fr); border-bottom: 0; }
.wk-sheet--beside .wk-hd .wk-c + .wk-c {
  border-left: 0; padding-left: 0; border-top: 1px solid var(--hair);
}
.wk-sheet--beside .wk-title { font-size: clamp(22px, 2.1vw, 32px) !important; }
.wk-sheet--beside .wk-ft { grid-template-columns: minmax(0, 1fr); border-top: 1px solid var(--hair); }
.wk-sheet--beside .wk-ft .wk-c + .wk-c {
  border-left: 0; padding-left: 0; border-top: 1px solid var(--hair);
}
.wk-sheet--beside .wk-strip { grid-column: 1 / -1; }

/* ── additional frames: only where the entry actually has them ── */
.wk-strip { margin-top: clamp(18px, 2vw, 28px); }
.wk-strip__t {
  font-family: var(--mono); font-size: 9px; letter-spacing: .22em;
  color: var(--wk-ink-3); margin-bottom: 10px;
}
.wk-strip__list { list-style: none; display: flex; flex-wrap: wrap; gap: 14px; }
/* the frames grow to use the sheet's width rather than leaving 400px of black
   to the right of three small thumbs, and hold their size at any count */
.wk-fr { flex: 1 1 156px; max-width: 288px; }
.wk-fr__img {
  display: block; position: relative; overflow: clip;
  aspect-ratio: 3 / 2; border: 1px solid var(--hair); background: oklch(15% 0.006 80);
}
.wk-fr__img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.wk-fr__cap {
  display: block; margin-top: 7px; font-family: var(--mono); font-size: 8.5px;
  letter-spacing: .16em; color: var(--wk-ink-3); text-transform: uppercase;
}

/* ── the schedule: what the ten sheets add up to ────────────────────────────
   Counts, families and cross-references are all computed by the generator from
   the same `systems` arrays the sheets print, so the schedule cannot disagree
   with the register above it. Grouped into families rather than run as 14 ruled
   rows: a hairline under every row of a long list is the worst available layout,
   and the grouping is also the actual argument — this is a glass-and-skin firm. */
.wk-sched {
  width: min(100%, 1480px); margin: clamp(88px, 11vw, 168px) auto 0;
  padding-top: clamp(30px, 3.6vw, 52px); border-top: 1px solid var(--hair-2);
}
.wk-sched__hd {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, .8fr);
  gap: clamp(14px, 2vw, 40px); align-items: baseline;
  padding-bottom: clamp(26px, 3.2vw, 46px);
}
.wk-sched__t {
  font-family: var(--display); font-weight: 500; font-variation-settings: "wdth" 84;
  font-size: clamp(22px, 2.6vw, 40px); line-height: .96; letter-spacing: -.03em;
  color: var(--wk-ink);
}
.wk-sched__s {
  font-family: var(--mono); font-size: 10px; line-height: 1.7; letter-spacing: .06em;
  color: var(--wk-ink-2); max-width: 46ch;
}
/* widths track the family sizes, which are ordered longest-first in the data:
   glass (7 rows) · shade & structure (4) · cladding (2) · whole building (1) */
.wk-sched__grid {
  display: grid; grid-template-columns: 1.5fr 1.15fr 1.05fr .8fr;
  gap: clamp(20px, 2.6vw, 44px);
}
.wk-fam { min-width: 0; border-top: 1px solid var(--hair); padding-top: 12px; }
.wk-fam__t {
  font-family: var(--mono); font-size: 9px; font-weight: 400; letter-spacing: .22em;
  color: var(--brand-lift); margin-bottom: 12px;
}
.wk-fam__list { list-style: none; }
.wk-srow {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline; column-gap: 10px; padding: 7px 0;
}
.wk-srow__n {
  display: flex; align-items: baseline; gap: 9px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em; line-height: 1.5;
  color: var(--wk-ink-2);
}
/* the index leader that carries the eye from the system to its count. A real
   schedule device, and the reason the count can sit at the column edge without
   floating free of its own row. */
.wk-srow__n::after {
  content: ""; flex: 1 1 auto; height: 0; align-self: center;
  border-bottom: 1px dotted var(--hair-2);
}
.wk-srow__c {
  font-family: var(--mono); font-size: 13px; font-weight: 500; letter-spacing: .04em;
  color: var(--wk-ink); font-variant-numeric: tabular-nums;
}
.wk-srow__r { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
.wk-srow__r a {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; min-height: 24px;      /* WCAG 2.2 AA target size (2.5.8) */
  font-family: var(--mono); font-size: 9px; letter-spacing: .1em;
  color: var(--wk-ink-3); text-decoration: none;
  border: 1px solid var(--hair); border-radius: 0;
  transition: color .25s, border-color .25s;
}
.wk-srow__r a:hover, .wk-srow__r a:focus-visible { color: var(--wk-ink); border-color: var(--hair-2); }

/* ── entrance: gated on .wk-armed, which work.js adds only once its observer
   is live. Nothing below can hide content on a no-JS, ?static or failed load. ── */
.work.wk-armed .wk-sheet:not(.is-in) .wk-plate { clip-path: inset(0 100% 0 0); }
/* only .wk-c and .wk-strip carry the fade — .wk-sys lives INSIDE .wk-c--sy now,
   and animating both would double the opacity ramp on the same pixels */
.work.wk-armed .wk-sheet:not(.is-in) .wk-c,
.work.wk-armed .wk-sheet:not(.is-in) .wk-strip { opacity: 0; transform: translateY(9px); }
.work.wk-armed .wk-sheet .wk-plate { transition: clip-path .92s var(--ease-out-expo), border-color .35s var(--ease-quart); }
.work.wk-armed .wk-sheet .wk-c,
.work.wk-armed .wk-sheet .wk-strip {
  transition: opacity .6s var(--ease-quart), transform .6s var(--ease-quart);
}
.work.wk-armed .wk-sheet .wk-hd .wk-c:nth-child(1) { transition-delay: .26s; }
.work.wk-armed .wk-sheet .wk-hd .wk-c:nth-child(2) { transition-delay: .32s; }
.work.wk-armed .wk-sheet .wk-hd .wk-c:nth-child(3) { transition-delay: .38s; }
.work.wk-armed .wk-sheet .wk-c--sc { transition-delay: .44s; }
.work.wk-armed .wk-sheet .wk-c--sy { transition-delay: .50s; }
.work.wk-armed .wk-sheet .wk-strip { transition-delay: .56s; }
.work.wk-armed .wk-sched:not(.is-in) .wk-fam { opacity: 0; transform: translateY(10px); }
.work.wk-armed .wk-sched .wk-fam { transition: opacity .6s var(--ease-quart), transform .6s var(--ease-quart); }
.work.wk-armed .wk-sched .wk-fam:nth-child(1) { transition-delay: .04s; }
.work.wk-armed .wk-sched .wk-fam:nth-child(2) { transition-delay: .12s; }
.work.wk-armed .wk-sched .wk-fam:nth-child(3) { transition-delay: .20s; }
.work.wk-armed .wk-sched .wk-fam:nth-child(4) { transition-delay: .28s; }

/* ── tiers: reduced motion, ?static and no-hover keep every pixel of content,
   and simply stop moving. work.js never arms in these contexts, so these rules
   are belt-and-braces for a mid-session preference change. ── */
@media (prefers-reduced-motion: reduce) {
  .work .wk-plate { clip-path: none !important; transition: none !important; }
  .work .wk-plate__shift img { transform: none !important; }
  .work .wk-plate__grade { opacity: .5 !important; transition: none !important; }
  .work .wk-c, .work .wk-sys, .work .wk-strip, .work .wk-fam {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .work .wk-idx__a::before { transition: none; }
}
html.static .work .wk-plate { clip-path: none !important; transition: none !important; }
html.static .work .wk-plate__shift img { transform: none !important; }
html.static .work .wk-plate__grade { opacity: .5 !important; }
html.static .work .wk-c,
html.static .work .wk-sys,
html.static .work .wk-strip,
html.static .work .wk-fam { opacity: 1 !important; transform: none !important; transition: none !important; }

/* ── narrow desktop: the rail cannot afford a column, so it lays flat above the
   sheets and stops being sticky. Same content, different arrangement. ── */
@media (max-width: 1080px) {
  .wk-drawer { grid-template-columns: minmax(0, 1fr); gap: clamp(30px, 5vw, 48px); }
  .wk-rail { position: static; }
  .wk-index {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    border-top: 1px solid var(--hair-2);
  }
  .wk-idx__a { padding-right: 12px; }
  .wk-sched__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .work { padding-block: clamp(72px, 12vw, 112px); }
  .work__head { grid-template-columns: 44px 1fr; align-items: start; }
  .work__sub { grid-column: 2; grid-row: auto; max-width: 38ch; }
  .work__key { grid-column: 2; grid-row: auto; margin-top: 0; }
  .wk-drawer { padding-block-start: clamp(34px, 7vw, 54px); }
  .wk-sheets { gap: clamp(58px, 12vw, 96px); }
  .wk-index { grid-template-columns: minmax(0, 1fr); }
  /* the sheet reflows to one column: plate, then the block beneath it, always */
  .wk-sheet--beside { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .wk-sheet--beside .wk-hd { border-bottom: 0; }
  .wk-sheet--wide, .wk-plate { width: 100% !important; }
  .wk-plate { aspect-ratio: 16 / 10; }
  .wk-hd { grid-template-columns: minmax(0, 1fr); }
  .wk-hd .wk-c + .wk-c { border-left: 0; padding-left: 0; border-top: 1px solid var(--hair); }
  .wk-title,
  .wk-sheet--beside .wk-title { font-size: clamp(26px, 7.4vw, 42px) !important; }
  .wk-sched__hd { grid-template-columns: minmax(0, 1fr); }
  .wk-sched__grid { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .wk-srow__r a { min-width: 44px; min-height: 44px; }   /* thumb target */
  .wk-fr { width: clamp(124px, 40vw, 168px); }
}

/* below ~680 the two-cell foot squeezes SCOPE into a ~160px column and the
   paragraph goes to seven cramped lines — measured at 390. It stacks instead. */
@media (max-width: 680px) {
  .wk-ft { grid-template-columns: minmax(0, 1fr); }
  .wk-ft .wk-c + .wk-c { border-left: 0; padding-left: 0; border-top: 1px solid var(--hair); }
}

@media (max-width: 560px) {
  .work__head { grid-template-columns: 1fr; }
  .work__sub, .work__key { grid-column: 1; }
}

@media (max-width: 860px) {
  .range { padding-bottom: clamp(40px, 6vh, 64px); }
  /* ── THE COLUMN — §01's vertical drum ─────────────────────────────────────
     The page's own scroll is the gesture: the stage pins and ONE ring node
     turns on X (wheels.js writes only that transform). All geometry is CSS:
     card size keeps the family hero's full 1100×943 aspect (no crop), seats
     sit 60° apart, and the radius leaves a hairline gap between segments. */
  /* one centered instrument cluster — HUD, drum, hint — the pergola phone
     grammar: equal breathing space above and below at every seat.
     STICKY is the pin: compositor-held, never leaves flow (wheels.js sizes
     the .vdrum runway; the ScrollTrigger only scrubs the ring). */
  .vdrum__pin {
    position: sticky; top: 0;
    height: 100svh; overflow: clip;
    display: flex; flex-direction: column; justify-content: center;
    gap: clamp(12px, 2.2svh, 22px);
    padding: calc(var(--nav-h, 52px) + clamp(10px, 2.4svh, 26px)) var(--pad)
      max(14px, env(safe-area-inset-bottom));
  }
  .vdrum__hud {
    color: var(--ink); font-family: var(--mono);
    font-size: 12px; letter-spacing: .1em;
  }
  .vdrum__no { color: var(--accent-text); }
  .vdrum__name { margin-left: 12px; }
  .vdrum__stage {
    /* geometry tokens: card keeps the hero's full 1100×943 aspect; seats sit
       48° apart (--vstep must match stepM in wheels.js); the radius clears
       plane intersection at 48° with a small gap: (H/2)/tan(24°)·1.06 ≈ 1.19H */
    --vw: min(92vw, 500px);
    --vh: calc(var(--vw) / 1.1665);
    --vstep: 48deg;
    --vr: calc(var(--vh) * 1.19);
    /* the APERTURE — the column turns behind a hairline window (the desktop
       caliper's grammar). Clipping lives HERE, never on the 3D elements.

       It GROWS into whatever the pin has left (2026-08-15). The old fixed cap
       of `min(--vh * 1.62, 58svh)` = 469px sat inside a 731px box, and
       `justify-content: center` split the 263px remainder into two dead bands.
       `flex: 1 1 auto` hands that remainder to the window instead, so the
       drum shows more of its own mechanism — the seats turning away above and
       below the front card — and centring has nothing left to distribute. The
       min keeps the old aperture as a floor; the max stops a pathologically
       tall screen from opening the window past the ring itself. */
    flex: 1 1 auto;
    height: auto;
    min-height: min(calc(var(--vh) * 1.62), 58svh);
    max-height: calc(var(--vh) * 2.4);
    /* the card is WIDTH-bound (it holds the hero's 1100x943 with no crop), so
       width is the only thing that makes it bigger: the window takes half the
       page gutter back, which lets the card go 86vw -> 92vw without clipping */
    margin-inline: calc(-1 * var(--pad) / 2);
    position: relative; overflow: clip;
    border-block: 1px solid var(--hair);
    perspective: 1100px; perspective-origin: 50% 50%;
  }
  /* the axis sits BEHIND the front card by one radius, so the front family
     renders at its natural, unmagnified size on the z=0 plane */
  .vdrum__axis {
    position: absolute; inset: 0;
    transform: translateZ(calc(-1 * var(--vr)));
    transform-style: preserve-3d;
  }
  .vdrum__ring {
    position: absolute; inset: 0;
    transform-style: preserve-3d;
  }
  .vcard {
    position: absolute; left: 50%; top: 50%;
    width: var(--vw); height: var(--vh);
    margin: calc(var(--vh) / -2) 0 0 calc(var(--vw) / -2);
    transform: rotateX(calc(var(--i) * -1 * var(--vstep))) translateZ(var(--vr));
    backface-visibility: hidden;
    border: 1px solid var(--hair); overflow: clip; background: var(--paper);
    padding: 0; color: inherit; cursor: pointer;
  }
  .vcard img { display: block; width: 100%; height: 100%; object-fit: cover; }
  .vcard__veil {
    position: absolute; inset: 0; z-index: 2; pointer-events: none;
    background: oklch(19% 0.006 80 / .42);
  }
  .vcard__no {
    position: absolute; z-index: 3; top: 14px; left: 16px;
    color: oklch(94% 0.004 120 / .9); font-family: var(--mono);
    font-size: 11px; letter-spacing: .16em;
  }
  .vcard.is-front .vcard__no { color: var(--brand-lift); }
  .vcard__text {
    position: absolute; left: 16px; right: 16px; bottom: 14px; z-index: 3;
    display: flex; flex-direction: column; gap: 5px;
  }
  .vcard__name {
    color: oklch(96% 0.004 120); font-family: var(--display); font-weight: 500;
    font-variation-settings: "wdth" 88; font-size: clamp(19px, 5.4vw, 26px);
    letter-spacing: -.01em; text-align: left;
    text-shadow: 0 1px 18px oklch(19% 0.006 80 / .6);
  }
  .vcard__d {
    color: oklch(94% 0.004 120 / .72); font-family: var(--mono);
    font-size: 10px; line-height: 1.45; letter-spacing: .1em; text-align: left;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  .vcard__cta {
    position: absolute; z-index: 3; top: 14px; right: 16px;
    display: inline-flex; align-items: center; gap: 7px;
    color: oklch(94% 0.004 120 / .85); font-family: var(--mono);
    font-size: 9px; letter-spacing: .16em;
    text-shadow: 0 1px 12px oklch(19% 0.006 80 / 0.55);
  }
  .vcard__cta-tick {
    width: 11px; height: 1px; background: var(--lime);
    transform-origin: 0 50%;
  }
  .vcard::after {
    content: ""; position: absolute; inset: auto 0 0; height: 42%;
    background: linear-gradient(to top, oklch(19% 0.006 80 / .72), transparent);
    pointer-events: none;
  }
  .vcard:focus-visible { outline: 2px solid var(--lime); outline-offset: 3px; }
  .vdrum__hint {
    color: var(--dim); font-family: var(--mono);
    font-size: 9px; letter-spacing: .16em;
  }
  /* reveal: opacity only — transforms belong to the ring and the seats */
  .vdrum.is-armed .vdrum__pin > * { opacity: 0; }
  .vdrum.is-rev .vdrum__pin > * {
    opacity: 1; transition: opacity .6s var(--ease-magic);
  }
  /* reduced motion: the same cards as a static column — no pin, no turn */
  .vdrum--flat .vdrum__pin { position: static; height: auto; overflow: visible; display: block; }
  /* Flat mode is a LIST, not an aperture, so it has to hand back the fixed
     height, the cap and the clip. It never did: wheels.js:54 returns early for
     ?static but NOT for reduced motion on a phone, so this path is live, and
     measured at 430x932 it stacked 2,106px of cards inside an 814px
     `overflow: clip` box — three of the six families were unreachable. */
  .vdrum--flat .vdrum__stage {
    perspective: none;
    height: auto; min-height: 0; max-height: none; overflow: visible;
    margin-inline: 0;
  }
  .vdrum--flat .vdrum__axis { position: static; transform: none; }
  .vdrum--flat .vdrum__ring {
    position: static; display: flex; flex-direction: column;
    gap: 14px; align-items: center; transform: none !important;
  }
  .vdrum--flat .vcard {
    position: relative; left: auto; top: auto; margin: 0;
    transform: none; aspect-ratio: 1100 / 943; height: auto;
  }
  .vdrum--flat .vdrum__hud { margin-bottom: 12px; }
  .vdrum--flat .vdrum__hint { margin-top: 12px; }
  /* armed mobile: the wheel + sheet ARE the interface; the generated accordion
     stays in the markup as the no-JS / static / rescue baseline (the class is
     removed by the safety timer and the teardown, restoring it) */
  .range.is-mobile-systems-ready .system-family { display: none; }

  /* ── THE FAMILY SHEET — the wheel's second level, a bottom-sheet dialog ── */
  .msheet { position: fixed; inset: 0; z-index: 70; }
  .msheet__scrim { position: absolute; inset: 0; background: oklch(16% 0.006 80 / .52); opacity: 0; transition: opacity .3s; }
  .msheet.is-in .msheet__scrim { opacity: 1; }
  .msheet__panel {
    position: absolute; left: 0; right: 0; bottom: 0; top: max(52px, 7svh);
    background: var(--bg); border-top: 1px solid var(--graphite);
    /* overflow-x HIDDEN, explicitly: with only overflow-y set, the x-axis
       computes to auto and iOS lets the whole sheet drift sideways by the
       few px any subpixel rounding leaves over (the owner's cut-off labels) */
    overflow-y: auto; overflow-x: hidden;
    overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
    transform: translateY(103%); transition: transform .38s var(--ease-magic);
    padding: 0 0 30px; outline: none;
  }
  .msheet.is-in .msheet__panel { transform: translateY(0); }
  .msheet__close {
    position: sticky; top: 0; z-index: 5; width: 100%; min-height: 48px;
    display: flex; align-items: center; justify-content: center; gap: 8px;
    background: var(--bg); border: 0; border-bottom: 1px solid var(--hair);
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .2em;
    font-weight: 500; color: var(--ink); cursor: pointer;
  }
  .msheet__close:focus-visible { outline: 2px solid var(--lime); outline-offset: -3px; }
  .msheet__close-tick { width: 11px; height: 1px; background: var(--lime); }
  .msheet__body { padding: 18px var(--pad) 0; overflow-x: clip; }
  .msheet__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; }
  .msheet__fno { font-family: var(--mono); font-size: 10px; letter-spacing: .18em; color: var(--accent-text); }
  .msheet__fname { font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 88; font-size: clamp(17px, 4.8vw, 22px); letter-spacing: -.01em; color: var(--ink); }
  .msheet__rail {
    display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none;
    /* no negative-margin full-bleed: the calc left a subpixel of horizontal
       overflow on real iOS, which let the whole panel be nudged sideways */
    margin: 0; padding: 2px 0 12px;
    border-bottom: 1px solid var(--hair);
  }
  .msheet__rail::-webkit-scrollbar { display: none; }
  .msheet__rail button {
    flex: 0 0 auto; min-height: 44px; padding: 0 14px;
    background: var(--bg); border: 1px solid var(--hair); cursor: pointer;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; color: var(--ink);
  }
  .msheet__rail button.is-sel { background: var(--graphite); border-color: var(--graphite); color: var(--stone); }
  .msheet__rail button:focus-visible { outline: 2px solid var(--lime); outline-offset: 2px; }
  .msheet__plate { margin: 14px 0 0; background: #fff; border: 1px solid var(--hair); display: grid; place-items: center; min-height: 180px; }
  .msheet__plate img { display: block; width: 100%; height: auto; max-height: 34svh; object-fit: contain; opacity: 0; transition: opacity .3s; }
  .msheet__plate img.is-set { opacity: 1; }
  .msheet__id { display: flex; align-items: baseline; gap: 12px; margin-top: 14px; }
  .msheet__code { font-family: var(--mono); font-size: 13px; letter-spacing: .14em; color: var(--ink); font-weight: 500; }
  .msheet__pname { font-family: var(--body); font-size: 13px; color: var(--ink-2); }
  .msheet__blurb { font-family: var(--body); font-size: 13px; line-height: 1.55; color: var(--ink); margin-top: 8px; }
  .msheet__spec { margin: 12px 0 0; border-top: 1px solid var(--graphite); }
  .msheet__spec div {
    display: grid; grid-template-columns: minmax(132px, 48%) 1fr;
    gap: 12px; align-items: start; padding: 10px 0;
    border-bottom: 1px solid var(--hair);
    font-family: var(--mono); font-size: 11px; letter-spacing: .04em; line-height: 1.5;
  }
  /* min-width: 0 — grid items default to min-width auto, and one unbreakable
     value blows the 1fr column out past the panel (the drifting-sheet class) */
  .msheet__spec dt { color: var(--ink-2); min-width: 0; }
  .msheet__spec dd { color: var(--ink); margin: 0; min-width: 0; overflow-wrap: anywhere; }
  .msheet__apps { font-family: var(--mono); font-size: 10px; letter-spacing: .08em; line-height: 1.7; color: var(--ink-2); margin-top: 12px; }
  .msheet__meta { margin-top: 14px; }
  .msheet__pdf { display: inline-flex; align-items: center; min-height: 44px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em; font-weight: 500; color: var(--graphite); text-decoration: none; border-bottom: 1px solid var(--graphite); }
  a.msheet__pdf::after { content: " →"; }
  .msheet__pdf--none { color: var(--ink-2); border-bottom-color: var(--hair); }
  .msheet__cap { font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; color: var(--ink-2); margin-top: 16px; }
  html.msheet-open { overflow: hidden; }
  /* main.js maps reduced-motion onto html.static — the sheet then cuts, never slides */
  html.static .msheet__scrim, html.static .msheet__panel, html.static .msheet__plate img { transition: none; }
}

/* Hero motion is progressive enhancement. Every hidden/closed start state is gated
   by classes hero.js adds only after the split DOM and entrance timeline are live. */
.hero__kicker { overflow: clip; }
.hero__kicker-i,
.ch,
.ch__i,
.w,
.w__i { display: inline-block; }
.ch,
.w { overflow: clip; vertical-align: bottom; }

/* entrance-hold: pre-split stand-in for the states below, gated on the
   self-releasing html class the head inline script adds (4.5s guard).
   hero.js lifts it only after the split DOM + motion-ready state are live. */
html.entrance-hold .hero__kicker,
html.entrance-hold .hero__line,
html.entrance-hold .hero__deck,
html.entrance-hold .hero__ctas > * { opacity: 0; }
html.entrance-hold .hero .mq__track > .mq__fig img { clip-path: inset(0 0 100%); }

.hero.hero--motion-ready .hero__kicker-i {
  opacity: 0;
  transform: translateY(1em);
}
.hero.hero--motion-ready .ch__i {
  opacity: 0;
  transform: translateX(1em);
}
.hero.hero--motion-ready .w__i {
  opacity: 0;
  transform: translateY(1em);
}
.hero.hero--motion-ready .hero__ctas > * {
  opacity: 0;
  transform: translateY(24px);
}
.hero.hero--motion-ready .mq__track > .mq__fig img {
  clip-path: inset(0 0 100%);
  transform: scale(1.1) translateY(-5%);
}

.hero.hero--motion-ready.hero--motion-running .hero__kicker-i {
  opacity: 1;
  transform: none;
  transition: transform 1.4s var(--ease-magic), opacity 1.4s var(--ease-magic);
}
.hero.hero--motion-ready.hero--motion-running .w__i {
  opacity: 1;
  transform: none;
  transition: transform 1.4s var(--ease-magic), opacity 1.4s var(--ease-magic);
  transition-delay: calc(var(--i) * 75ms);
}
.hero.hero--motion-ready.hero--motion-running .hero__ctas > * {
  opacity: 1;
  transform: none;
  transition: transform .9s var(--ease-out-expo), opacity .9s var(--ease-out-expo);
  transition-delay: calc(var(--i) * .075s);
}
.hero.hero--motion-ready.hero--motion-running .mq__track > .mq__fig img {
  clip-path: inset(0);
  transform: none;
  transition: clip-path 1.2s var(--ease-quart) calc(var(--i) * .2s),
              transform 1.2s var(--ease-quart) calc(var(--i) * .2s),
              opacity .55s var(--ease-magic) 0s;
}

/* Full-bleed contents rule: section wayfinding, not a second document nav. */
.hero__index {
  position: relative; z-index: 2;
  width: calc(100% + var(--pad) + var(--pad));
  margin: 34px calc(-1 * var(--pad)) 0;
  padding-inline: var(--pad);
  border-top: 1px solid var(--hair);
  display: flex; align-items: stretch; justify-content: space-between; gap: 18px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .16em;
}
.hero__index-link {
  min-height: 44px;
  display: inline-flex; align-items: center; gap: .5em;
  color: var(--stone); text-decoration: none; white-space: nowrap;
}
.hero__index-link::before {
  content: "";
  width: .625em; height: .625em; flex: 0 0 .625em;
  border-radius: 50%; background: var(--lime);
  transform: scale(0); transform-origin: center;
  transition: transform .3s var(--ease-magic);
}
.hero__index-link > span {
  display: inline-block;
  transform: translateX(-1.125em);
  transition: transform .3s var(--ease-magic);
}
.hero__index-link:hover::before,
.hero__index-link:focus-visible::before { transform: scale(1); }
.hero__index-link:hover > span,
.hero__index-link:focus-visible > span { transform: translateX(0); }

@media (max-width: 700px) {
  .hero__index { flex-wrap: wrap; gap: 0 18px; }
  .hero__index-link { flex: 1 1 calc(50% - 18px); }
}

@media (prefers-reduced-motion: reduce) {
  .hero__kicker-i,
  .ch__i,
  .w__i,
  .hero__ctas > *,
  .mq--hero .mq__track > .mq__fig img {
    opacity: 1 !important;
    clip-path: none !important;
    transform: none !important;
    transition: none !important;
  }
  .mq--hero .mq__fig img { opacity: 1 !important; transition: none !important; }
}
html.static .hero__kicker-i,
html.static .ch__i,
html.static .w__i,
html.static .hero__ctas > *,
html.static .mq--hero .mq__track > .mq__fig img {
  opacity: 1 !important;
  clip-path: none !important;
  transform: none !important;
  transition: none !important;
}
html.static .mq--hero .mq__fig img { opacity: 1 !important; transition: none !important; }

@media print {
  .mq--hero .mq__fig img { opacity: 1 !important; transition: none !important; }
}

/* ═══ THE CROSSING — chrome figure at the dark → light handover ═══════════════ */
/* no-JS: the crossing is ornament — without the motion runtime it must not exist.
   Same js-motion pattern as .wheel (main.js adds the class only when motion boots). */
html:not(.js-motion) .surfer { display: none; }
.surfer {
  position: relative;
  z-index: 3;
  height: 125vh;
  margin-bottom: -125vh;
  overflow: clip;
  pointer-events: none;
}
.surfer__rig {
  position: sticky;
  top: 46vh;
  height: clamp(180px, 34vh, 380px);
  aspect-ratio: 572 / 560;
  margin-inline: auto;
  opacity: 0;
  transform-origin: center;
}
.surfer__cv {
  display: block;
  width: 100%;
  height: 100%;
}
.surfer__cv--mirror {
  position: absolute;
  top: 100%;
  left: 0;
  opacity: .1;
  -webkit-mask-image: linear-gradient(to bottom, rgb(0 0 0 / .55), transparent 62%);
  mask-image: linear-gradient(to bottom, rgb(0 0 0 / .55), transparent 62%);
}

#s01 .sec__head { position: relative; z-index: 4; }

@media (max-width: 860px), (prefers-reduced-motion: reduce) {
  .surfer { display: none; }
}
html.static .surfer { display: none; }

.wheel__technical .drum__partial {
  margin-top: 14px; font-family: var(--mono); font-size: 10px;
  letter-spacing: .18em; color: var(--dim);
}

/* ═══ catalog page ═══ */
.catalog-page .doc__brand {
  color: var(--ink); text-decoration: none; min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center;
}

.ccover {
  position: relative; z-index: 1; min-height: min(82vh, 880px);
  padding: max(17vh, 150px) var(--pad) clamp(64px, 10vh, 110px);
  display: flex; flex-direction: column; justify-content: center;
}
.ccover__kicker {
  margin-bottom: 28px; color: oklch(50% 0.10 55);
  font-family: var(--mono); font-size: 12px; letter-spacing: .22em;
}
.ccover .cover__h1 { max-width: 1400px; }
.ccover .cover__meta a {
  color: inherit; text-decoration: none; min-height: 44px;
  display: inline-flex; align-items: center;
}
.ccover .cover__meta a:hover { color: var(--ink); }

.fam {
  position: relative; z-index: 1;
  padding: clamp(64px, 11vh, 130px) var(--pad);
  border-top: 1px solid var(--hair);
}
.fam__body {
  display: grid; grid-template-columns: minmax(280px, 520px) minmax(0, 1fr);
  gap: clamp(34px, 5vw, 86px); align-items: start; max-width: 1440px;
}
.fam__body--flip { grid-template-columns: minmax(0, 1fr) minmax(280px, 520px); }
.fam__body--flip .fam__fig { order: 2; }
.fam__fig { overflow: clip; will-change: transform; }
.fam__fig img {
  display: block; width: 100%; height: auto; border: 1px solid var(--hair);
}
.fam__content { min-width: 0; }
.fam__description {
  max-width: 68ch; color: var(--dim); font-size: clamp(16px, 1.5vw, 18px);
  line-height: 1.65;
}
.fam__capability {
  margin: 24px 0 30px; color: oklch(50% 0.10 55);
  font-family: var(--mono); font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase;
}
.fam__products { list-style: none; border-top: 1px solid var(--hair); }
.fam__product { padding: 22px 0 24px; border-bottom: 1px solid var(--hair); }
.fam__product-top {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: start; gap: 18px;
}
.fam__identity { min-width: 0; }
.fam__code {
  margin-bottom: 5px; color: oklch(50% 0.10 55);
  font-family: var(--mono); font-size: 11px; letter-spacing: .18em;
}
.fam__name {
  font-family: var(--display); font-size: clamp(20px, 2vw, 28px);
  font-variation-settings: "wdth" 96; font-weight: 500; letter-spacing: -.01em;
  line-height: 1.12;
}
.fam__blurb { margin-top: 11px; max-width: 70ch; color: var(--dim); font-size: 14px; line-height: 1.55; }
.fam__specs {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 clamp(24px, 4vw, 58px); margin-top: 18px;
}
.fam__specs div {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 14px;
  padding: 8px 0; border-top: 1px solid var(--hair);
  font-family: var(--mono); font-size: 10px; line-height: 1.45;
}
.fam__specs dt { color: var(--dim); letter-spacing: .08em; }
.fam__specs dd { color: var(--ink); text-align: right; overflow-wrap: anywhere; }
.fam__action {
  min-width: 52px; min-height: 44px; padding: 0 13px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--graphite); border: 1px solid var(--hair); text-decoration: none;
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  transition: background .25s, border-color .25s;
}
a.fam__action:hover { background: var(--lime); border-color: var(--lime); }
.fam__action--pending { min-width: 108px; color: var(--dim); }

.asas {
  position: relative; z-index: 1;
  padding: clamp(72px, 12vh, 150px) var(--pad);
  border-top: 1px solid var(--hair);
}
.asas__head { max-width: 1440px; }
.asas__kicker {
  display: flex; align-items: center; gap: 18px; margin-bottom: 24px;
  color: oklch(50% 0.10 55); font-family: var(--mono); font-size: 11px;
  letter-spacing: .22em;
}
.asas__kicker i { height: 1px; flex: 1; background: var(--hair); }
.asas__head h2 {
  font-family: var(--display); font-size: clamp(46px, 8vw, 118px);
  font-variation-settings: "wdth" 88; font-weight: 500;
  letter-spacing: -.03em; line-height: .92;
}
.asas__attribution {
  max-width: 76ch; margin-top: clamp(30px, 5vh, 54px);
  color: var(--dim); font-size: 16px; line-height: 1.65;
}
.asas__attribution strong { color: var(--ink); font-weight: 500; }
.asas__group { max-width: 1440px; margin-top: clamp(66px, 10vh, 112px); }
.asas__group-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 20px;
  padding-bottom: 18px;
}
.asas__group-head h3 {
  font-family: var(--display); font-size: clamp(28px, 4vw, 52px);
  font-variation-settings: "wdth" 94; font-weight: 500; letter-spacing: -.02em;
}
.asas__group-head span {
  color: var(--dim); font-family: var(--mono); font-size: 12px;
  letter-spacing: .16em; font-variant-numeric: tabular-nums;
}
.asas__columns,
.asas__row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) 90px 100px minmax(108px, 132px);
  gap: 16px; align-items: center;
}
.asas__columns {
  min-height: 36px; color: var(--dim); border-top: 1px solid var(--hair);
  font-family: var(--mono); font-size: 9px; letter-spacing: .16em;
}
.asas__list { list-style: none; }
.asas__row {
  min-height: 56px; padding: 10px 0; border-top: 1px solid var(--hair);
}
.asas__row:last-child { border-bottom: 1px solid var(--hair); }
.asas__index,
.asas__pages,
.asas__size {
  color: var(--dim); font-family: var(--mono); font-size: 10px;
  letter-spacing: .08em; font-variant-numeric: tabular-nums;
}
.asas__entry-title { min-width: 0; font-size: 14px; line-height: 1.35; }
.asas__note,
.asas__duplicate {
  display: block; margin-top: 5px; color: var(--dim);
  font-family: var(--mono); font-size: 9px; letter-spacing: .04em;
  line-height: 1.45; overflow-wrap: anywhere;
}
.asas__duplicate { letter-spacing: .08em; }
.asas__meta { display: contents; }
.asas__dot { display: none; }
.asas__action-cell { justify-self: end; }
.asas__action {
  min-height: 44px; min-width: 52px; padding: 0 12px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--graphite); border: 1px solid var(--hair); text-decoration: none;
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  transition: background .25s, border-color .25s;
}
a.asas__action:hover { background: var(--lime); border-color: var(--lime); }
.asas__action--missing {
  min-width: 108px; padding-inline: 8px; color: var(--dim);
  border-color: transparent; font-size: 9px; letter-spacing: .1em;
}
.asas__row--missing { color: var(--dim); }

@media (max-width: 900px) {
  .fam__body,
  .fam__body--flip { grid-template-columns: 1fr; }
  .fam__body--flip .fam__fig { order: 0; }
  .fam__fig { max-width: 600px; }
}

@media (max-width: 860px) {
  .ccover { min-height: 72svh; }
  .ccover .cover__line { white-space: normal; }
  .fam__specs { grid-template-columns: 1fr; }
  .asas__columns { display: none; }
  .asas__row {
    grid-template-columns: 34px minmax(0, 1fr) auto;
    grid-template-rows: auto auto; gap: 5px 12px;
    min-height: 64px; padding: 11px 0; align-items: start;
  }
  .asas__index { grid-column: 1; grid-row: 1 / span 2; padding-top: 3px; }
  .asas__entry-title { grid-column: 2; grid-row: 1; }
  .asas__meta {
    grid-column: 2; grid-row: 2; display: flex; align-items: center;
    gap: 7px; min-width: 0;
  }
  .asas__dot { display: inline; color: var(--dim); }
  .asas__action-cell {
    grid-column: 3; grid-row: 1 / span 2; align-self: center; justify-self: end;
  }
}

@media (max-width: 520px) {
  .catalog-page .doc { padding-block: 10px; }
  .catalog-page .doc__nav { gap: 6px; }
  .catalog-page .doc__cta { padding-inline: 10px; }
  .ccover { padding-top: 128px; }
  .fam__product-top { gap: 10px; }
  .fam__action--pending { min-width: 96px; padding-inline: 8px; font-size: 9px; letter-spacing: .1em; }
  .fam__specs div { grid-template-columns: minmax(0, 1fr) minmax(90px, auto); }
  .asas__group-head { align-items: flex-end; }
  .asas__group-head h3 { max-width: 85%; line-height: 1; }
  .asas__action--missing { min-width: 96px; font-size: 8px; }
}

/* ═══ 02 · PERGOLAS — THE DIAMOND (batch 08b·R3 · tasks/085) ═══
   CLEAN LAW: three grammars only — the diamond stage, the specification table,
   the doors. Static tier complete by default; .pd-armed (JS, no ?static, no RM)
   layers the pinned instrument. Chip fills are colour DATA — never themed. */

.pd {
  position: relative; z-index: 1;
  padding: clamp(82px, 10vw, 150px) var(--pad) clamp(96px, 12vw, 170px);
  border-top: 1px solid var(--hair);
}
/* ── the stage: static tier = four framed plates stacked ── */
.pd-state { margin-bottom: clamp(40px, 5vw, 64px); }
.pd-state__fig { margin: 0; position: relative; border: 1px solid var(--hair); overflow: clip; background: oklch(14% 0.005 80); }
.pd-state__fig img, .pd-state__fig video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 8.4; object-fit: cover; }
.pd-state__fig::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, oklch(14% 0.005 80 / .48), transparent 24%, transparent 66%, oklch(14% 0.005 80 / .60)); pointer-events: none; }
/* living loops arrive over their own anchor frame — the fade hides the slight
   AI relight between poster and clip */
.pd-state__fig .pd-loop { animation: pdloopin .45s ease-out; }
@keyframes pdloopin { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .pd-state__fig .pd-loop { animation: none; } }
.pd-tick { position: absolute; width: 20px; height: 20px; border: 0 solid oklch(94% 0.004 120 / .55); z-index: 2; }
.pd-tick--tl { top: 14px; left: 14px; border-top-width: 1px; border-left-width: 1px; }
.pd-tick--tr { top: 14px; right: 14px; border-top-width: 1px; border-right-width: 1px; }
.pd-tick--bl { bottom: 14px; left: 14px; border-bottom-width: 1px; border-left-width: 1px; }
.pd-tick--br { bottom: 14px; right: 14px; border-bottom-width: 1px; border-right-width: 1px; }
.pd-callout { position: absolute; top: 20px; left: 0; right: 0; z-index: 2; display: flex; justify-content: center; }
.pd-callout span { font-family: var(--mono); font-size: 10.5px; letter-spacing: .2em; color: var(--stone); padding: 5px 14px; position: relative; background: oklch(16% 0.006 80 / .84); }
.pd-callout span::before, .pd-callout span::after { content: ""; position: absolute; top: 50%; width: min(160px, 11vw); height: 1px; background: oklch(59.5% 0.23 21); }
.pd-callout span::before { right: 100%; } .pd-callout span::after { left: 100%; }
.pd-read {
  position: absolute; left: clamp(18px, 2.6vw, 40px); bottom: clamp(16px, 2.8vw, 36px);
  z-index: 2; font-family: var(--mono); color: var(--stone);
  background: oklch(16% 0.006 80 / .74);
  padding: 12px 18px 13px; border-left: 2px solid oklch(59.5% 0.23 21);
}
.pd-read b { display: block; font-size: 10.5px; letter-spacing: .2em; font-weight: 500; color: oklch(87% 0.015 60); margin-bottom: 6px; }
.pd-read strong { display: block; font-family: var(--display); font-weight: 700; font-variation-settings: "wdth" 72; font-size: clamp(34px, 3.8vw, 62px); line-height: .9; letter-spacing: .01em; }
.pd-read em { display: block; font-style: normal; font-size: 10px; letter-spacing: .16em; color: oklch(84% 0.005 100); margin-top: 8px; }
.pd-state__facts { display: flex; flex-wrap: wrap; gap: 0 clamp(24px, 3vw, 48px); border-bottom: 1px solid var(--hair); }
.pd-state__facts div { display: flex; gap: 12px; padding: 10px 0; font-family: var(--mono); font-size: 11px; letter-spacing: .06em; }
.pd-state__facts dt { color: var(--ink-2); }
.pd-state__facts dd { color: var(--ink); }

/* ── the diamond instrument (armed only) ── */
.pd-dia { position: relative; width: min(300px, 100%); aspect-ratio: 1; margin: 44px auto; transform: translateZ(0); }
.pd-dia__apex { position: absolute; left: 50%; top: -32px; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 5px; }
.pd-dia__apex i { width: 1px; height: 15px; background: oklch(59.5% 0.23 21); display: block; }
.pd-dia__apex span { font-family: var(--mono); font-size: 8px; letter-spacing: .26em; color: var(--ink-2); }
.pd-dia__rot { position: absolute; inset: 0; transition: transform .7s var(--ease-magic); will-change: transform; }
.pd-dia__sq { position: absolute; inset: 13%; transform: rotate(45deg); border: 1px solid var(--graphite); background: oklch(94% 0.004 120 / .55); }
.pd-dia__sq::after { content: ""; position: absolute; inset: 9px; border: 1px solid var(--hair); }
.pd-dia__c { position: absolute; left: 50%; top: 50%; width: 106px; height: 106px; margin: -53px 0 0 -53px; display: grid; place-items: center; }
.pd-dia__c[data-i="0"] { transform: translateY(-128%); }
.pd-dia__c[data-i="1"] { transform: translateX(128%); }
.pd-dia__c[data-i="2"] { transform: translateY(128%); }
.pd-dia__c[data-i="3"] { transform: translateX(-128%); }
.pd-dia__c button {
  transition: transform .7s var(--ease-magic), background .3s, color .3s, border-color .3s;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: var(--bg); border: 1px solid var(--hair); padding: 10px 12px; cursor: pointer;
  font-family: var(--mono); min-height: 44px;
}
.pd-dia__c button b { font-size: 9px; letter-spacing: .18em; font-weight: 500; color: var(--cedar); }
.pd-dia__c button span { font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 86; font-size: 13.5px; letter-spacing: .02em; color: var(--ink); }
.pd-dia__c button.is-top { background: var(--graphite); border-color: var(--graphite); }
.pd-dia__c button.is-top b { color: var(--brand-lift); }
.pd-dia__c button.is-top span { color: var(--stone); }
.pd-dia__mid { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); text-align: center; font-family: var(--mono); pointer-events: none; }
.pd-dia__mid b { display: block; font-size: 13px; letter-spacing: .14em; color: var(--ink); font-weight: 500; }
.pd-dia__mid span { font-size: 8.5px; letter-spacing: .24em; color: var(--ink-2); }
/* fixed-height mirror: the facts list must never resize, or the centered
   diamond above it drifts between states (owner: centered + locked) */
.pd-mirror { border-top: 1px solid var(--hair); margin-top: 8px; min-height: 104px; align-content: start; }
.pd-mirror div { display: grid; grid-template-columns: minmax(96px, 42%) 1fr; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--hair); font-family: var(--mono); font-size: 10.5px; letter-spacing: .05em; }
.pd-mirror dt { color: var(--ink-2); }
.pd-mirror dd { color: var(--ink); }
.pd-study {
  display: inline-flex; align-items: center; min-height: 44px; margin-top: 16px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em; font-weight: 500;
  color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--hair); padding-bottom: 2px;
}
.pd-study:hover, .pd-study:focus-visible { color: var(--graphite); border-color: var(--graphite); }

/* armed: THE TAKEOVER (batch 08e) — the plate approaches framed on the paper,
   then expands to the full viewport as the pin engages: the visitor steps INTO
   the terrace. The instrument arrives as a floating drawing-glass panel once
   the room is entered. JS drives .pd-view scale + the --take custom property;
   everything below only *reads* --take. Static tier: untouched stacked plates. */
html:not(.static) .pd.pd-armed .pd-stage { margin-inline: calc(-1 * var(--pad)); }
html:not(.static) .pd.pd-armed .pd-stage__pin { height: 100svh; position: sticky; top: 0; overflow: clip; }
html:not(.static) .pd.pd-armed .pd-inst {
  position: absolute; z-index: 4; left: clamp(20px, 3.2vw, 56px); top: 50%;
  transform: translateY(-50%); width: 390px;
  padding: clamp(14px, 1.5vw, 24px) 16px;
  background: oklch(97.5% 0.003 100 / .8);
  -webkit-backdrop-filter: blur(18px) saturate(1.15);
  backdrop-filter: blur(18px) saturate(1.15);
  border: 1px solid oklch(100% 0 0 / .55);
  box-shadow: 0 24px 70px oklch(20% 0.01 80 / .22);
}
/* the dial is a physical instrument: the plane tilts toward the viewer, the
   chips ride above it, the plate casts a shadow onto the glass. JS only writes
   rotate() on the rotor and the buttons — every 3D term lives here in CSS.
   Margins reserve the corner-chip throw SYMMETRICALLY (the chips reach ~38px
   past the dial box; asymmetric margins left the top chip flush and the
   bottom one hanging out of the panel). */
html:not(.static) .pd.pd-armed .pd-inst { perspective: 900px; }
html:not(.static) .pd.pd-armed .pd-dia {
  width: min(264px, 100%); margin: 44px auto 44px;
  transform: rotateX(16deg); transform-style: preserve-3d;
}
html:not(.static) .pd.pd-armed .pd-dia::after {
  content: ""; position: absolute; inset: 6% 2% 0 2%; z-index: -1;
  background: radial-gradient(ellipse at 50% 62%, oklch(20% 0.01 80 / .24), transparent 66%);
  transform: translateZ(-22px); pointer-events: none;
}
html:not(.static) .pd.pd-armed .pd-dia__rot { transform-style: preserve-3d; }
html:not(.static) .pd.pd-armed .pd-dia__sq {
  background: linear-gradient(160deg, oklch(97.5% 0.003 100), oklch(89% 0.004 100) 48%, oklch(95% 0.003 100));
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / .8), inset 0 -1px 0 oklch(60% 0.008 90 / .35), 0 2px 6px oklch(20% 0.01 80 / .14);
}
html:not(.static) .pd.pd-armed .pd-dia__mid { transform: translate(-50%, -50%) translateZ(24px); }
/* the corner chips must live INSIDE the glass panel: slightly smaller cells,
   slightly shorter throw than the open-layout defaults — lifted off the plate */
html:not(.static) .pd.pd-armed .pd-dia__c { width: 98px; height: 98px; margin: -49px 0 0 -49px; }
html:not(.static) .pd.pd-armed .pd-dia__c[data-i="0"] { transform: translateY(-124%) translateZ(14px); }
html:not(.static) .pd.pd-armed .pd-dia__c[data-i="1"] { transform: translateX(124%) translateZ(14px); }
html:not(.static) .pd.pd-armed .pd-dia__c[data-i="2"] { transform: translateY(124%) translateZ(14px); }
html:not(.static) .pd.pd-armed .pd-dia__c[data-i="3"] { transform: translateX(-124%) translateZ(14px); }
html:not(.static) .pd.pd-armed .pd-dia__c button { box-shadow: 0 5px 12px oklch(20% 0.01 80 / .16), inset 0 1px 0 oklch(100% 0 0 / .7); }
html:not(.static) .pd.pd-armed .pd-dia__c button.is-top { box-shadow: 0 9px 20px oklch(20% 0.01 80 / .32), inset 0 1px 0 oklch(100% 0 0 / .14); }
html:not(.static) .pd.pd-armed .pd-dia[hidden],
html:not(.static) .pd.pd-armed .pd-mirror[hidden],
html:not(.static) .pd.pd-armed .pd-study[hidden] { display: block; }
html:not(.static) .pd.pd-armed .pd-study[hidden] { display: inline-flex; }
html:not(.static) .pd.pd-armed .pd-view {
  position: absolute; inset: 0;
  transform-origin: 50% 50%; will-change: transform;
}
html:not(.static) .pd.pd-armed .pd-state { position: absolute; inset: 0; margin: 0; opacity: 0; visibility: hidden; transition: opacity .5s linear, visibility 0s .5s; }
html:not(.static) .pd.pd-armed .pd-state.is-on { opacity: 1; visibility: visible; transition: opacity .5s linear; }
html:not(.static) .pd.pd-armed .pd-state__fig { position: absolute; inset: 0; }
html:not(.static) .pd.pd-armed .pd-state__facts { display: none; }
html:not(.static) .pd.pd-armed .pd-state__fig img,
html:not(.static) .pd.pd-armed .pd-state__fig video { position: absolute; inset: 0; height: 100%; aspect-ratio: auto; }
/* the room is full-bleed, so the callout must clear the floating nav */
html:not(.static) .pd.pd-armed .pd-callout { top: calc(var(--nav-h) + 18px); }
/* on-plate chrome belongs to the room, not the framed drawing — it fades in
   over the last stretch of the takeover (opacity self-clamps to 0..1) and is
   visibility-gated by JS (.pd-chrome), so nothing invisible stays focusable */
html:not(.static) .pd.pd-armed .pd-callout,
html:not(.static) .pd.pd-armed .pd-read,
html:not(.static) .pd.pd-armed .pd-state__open {
  opacity: calc((var(--take, 1) - .82) / .18);
  visibility: hidden;
}
html:not(.static) .pd.pd-armed .pd-view.pd-chrome .pd-callout,
html:not(.static) .pd.pd-armed .pd-view.pd-chrome .pd-read,
html:not(.static) .pd.pd-armed .pd-view.pd-chrome .pd-state__open { visibility: visible; }

/* ── the specification table — the SPECS grammar ── */
.pd-spec { margin-top: clamp(70px, 9vw, 130px); }
.pd-spec__t {
  font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 92;
  font-size: clamp(26px, 2.8vw, 42px); letter-spacing: -0.01em; margin-bottom: clamp(20px, 2.5vw, 34px);
}
.pd-row {
  display: grid; grid-template-columns: minmax(170px, 250px) 1fr; gap: 16px;
  align-items: center; padding: 11px 0; border-bottom: 1px solid var(--hair);
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .05em; text-align: left;
}
.pd-row > span:first-child { color: var(--ink-2); }
.pd-row > span:last-child { color: var(--ink); line-height: 1.7; }
.pd-row a { color: oklch(49% 0.1 55); text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 1px; }
.pd-row a:hover, .pd-row a:focus-visible { color: var(--ink); }
.pd-row--g { border-top: 1px solid var(--graphite); border-bottom: 1px solid var(--hair); margin-top: clamp(26px, 3vw, 40px); padding: 13px 0; }
.pd-row--g > span:first-child { color: var(--graphite); font-weight: 500; letter-spacing: .18em; }
.pd-row--g > span:last-child { color: var(--ink-2); letter-spacing: .14em; }
.pd-spec > .pd-row--g:first-of-type { margin-top: 0; }
.pd-row--fig { grid-template-columns: minmax(170px, 250px) 1fr minmax(120px, 220px); }
.pd-row--fig img { width: 100%; height: auto; border: 1px solid var(--hair); display: block; }
.pd-row--thumb { grid-template-columns: minmax(170px, 250px) 1fr minmax(90px, 130px); }
.pd-row--thumb img { width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border: 1px solid var(--hair); display: block; }
.pd-row--note { border-bottom: 1px solid var(--hair); }
.pd-row--note > span:last-child { color: var(--ink-2); font-size: 10px; }
.pd-strip { display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; padding: 16px 0; border-bottom: 1px solid var(--hair); }
.pd-strip > span { min-width: 0; }
.pd-strip img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border: 1px solid var(--hair); }
.pd-strip b { display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .14em; font-weight: 500; color: var(--ink); margin-top: 7px; }
.pd-strip em { display: block; font-style: normal; font-family: var(--mono); font-size: 8.5px; letter-spacing: .06em; color: var(--ink-2); margin-top: 2px; }

/* colour: paint band + walls */
.pd-paint { margin: clamp(20px, 2.5vw, 32px) 0 0; position: relative; isolation: isolate; border: 1px solid var(--hair); overflow: clip; }
.pd-paint__coat { position: absolute; inset: 0; background: var(--paint, #373C41); z-index: 0; }
.pd-paint__base { display: block; position: relative; width: 100%; height: auto; mix-blend-mode: luminosity; z-index: 1; }
.pd-paint::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; background: var(--paint, #373C41); mix-blend-mode: multiply; opacity: var(--shade, 0); }
.pd-paint__tag { position: absolute; right: 10px; top: 10px; z-index: 3; font-family: var(--mono); font-size: 9px; letter-spacing: .14em; background: var(--graphite); color: var(--stone); padding: 4px 8px; }
.pd-paint__cap { display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px 20px; border: 1px solid var(--hair); border-top: 0; padding: 12px clamp(12px, 1.8vw, 20px); font-family: var(--mono); margin-bottom: clamp(20px, 2.5vw, 32px); }
.pd-paint__cap span:nth-child(1) { font-size: 13px; letter-spacing: .12em; font-weight: 500; color: var(--ink); }
.pd-paint__cap span:nth-child(2) { font-family: var(--display); font-weight: 600; font-variation-settings: "wdth" 96; font-size: clamp(17px, 1.8vw, 24px); color: var(--ink); }
.pd-paint__cap span:nth-child(3) { font-size: 9.5px; letter-spacing: .18em; color: var(--ink-2); }
.pd-paint__cap span:nth-child(4) { font-size: 9.5px; letter-spacing: .18em; color: var(--ink-2); margin-left: auto; }
/* unarmed: the button is an inert header row and the walls sit open below it —
   the 88 chips are never gated behind JS (the 066 lesson). Armed: it becomes the
   opener and the walls start closed. */
button.pd-row--open { width: 100%; background: none; border-left: 0; border-right: 0; min-height: 44px; cursor: default; }
button.pd-row--open:disabled { color: inherit; opacity: 1; }
html:not(.static) .pd.pd-armed button.pd-row--open:not(:disabled) { cursor: pointer; }
html:not(.static) .pd.pd-armed button.pd-row--open > span:last-child::after { content: " · OPEN THE WALL"; color: var(--ink-2); }
html:not(.static) .pd.pd-armed button.pd-row--open[aria-expanded="true"] > span:last-child::after { content: " · CLOSE"; color: var(--graphite); }
button.pd-row--open:hover > span:first-child, button.pd-row--open:focus-visible > span:first-child { color: var(--graphite); }
html:not(.static) .pd.pd-armed .pd-wall { display: none; }
html:not(.static) .pd.pd-armed .pd-wall.is-open { display: block; }
.pd-wall { border-bottom: 1px solid var(--hair); padding: 6px 0 22px; }
.pd-wall__sub { font-family: var(--mono); font-size: 10px; letter-spacing: .08em; color: var(--ink-2); max-width: 72ch; line-height: 1.7; margin: 14px 0 4px; }
.pd-wall .px-fam { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--ink-2); margin: 22px 0 10px; }
.pd-wall .px-chips { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 10px; padding: 0; }
.pd-wall .pxchip { min-width: 0; cursor: pointer; }
.pd-wall .pxchip__s { display: block; aspect-ratio: 4 / 3; background: var(--c); border: 1px solid var(--hair); }
.pd-wall .pxchip.is-sel .pxchip__s { outline: 2px solid var(--brand); outline-offset: 2px; }
.pd-wall .pxchip__c { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .08em; margin-top: 7px; color: var(--ink); }
.pd-wall .pxchip__n { display: block; font-family: var(--body); font-size: 11px; color: var(--ink-2); line-height: 1.35; }
.pd-wall .px-range__foot { font-family: var(--mono); font-size: 10px; letter-spacing: .06em; line-height: 1.7; color: var(--ink-2); max-width: 78ch; margin-top: 20px; }

/* ── the doors — work-timeline quiet ── */
.pd-doors { margin-top: clamp(70px, 9vw, 130px); }
.pd-door { position: relative; display: block; overflow: clip; background: oklch(16% 0.006 80); border: 1px solid var(--hair); text-decoration: none; }
.pd-door + .pd-door { margin-top: 14px; }
.pd-door img { display: block; width: 100%; height: auto; aspect-ratio: 21 / 6.6; object-fit: cover; opacity: .85; transition: opacity .4s; }
.pd-door:hover img, .pd-door:focus-visible img { opacity: 1; }
.pd-door__id { position: absolute; left: clamp(18px, 2.6vw, 40px); bottom: clamp(14px, 2.2vw, 30px); font-family: var(--mono); color: var(--stone); }
.pd-door__id b { display: block; font-size: 9.5px; letter-spacing: .2em; font-weight: 500; color: oklch(78% 0.005 100); margin-bottom: 5px; }
.pd-door__id strong { font-family: var(--display); font-weight: 700; font-variation-settings: "wdth" 74; font-size: clamp(26px, 2.6vw, 42px); line-height: .9; }
.pd-door__go { position: absolute; right: clamp(18px, 2.6vw, 40px); bottom: clamp(14px, 2.2vw, 30px); font-family: var(--mono); font-size: 10.5px; letter-spacing: .2em; color: var(--stone); border-bottom: 1px solid currentColor; padding-bottom: 3px; }
.pd-door__go::after { content: " →"; }
.pd-door__prov { position: absolute; right: 10px; top: 10px; pointer-events: none; font-family: var(--mono); font-size: 9px; letter-spacing: .14em; background: oklch(16% 0.006 80 / 0.72); color: var(--stone); padding: 4px 8px; }
.pd-close { margin-top: clamp(40px, 5vw, 64px); text-align: center; }

/* ── responsive ── */
@media (max-width: 1060px) {
  /* takeover, phone grammar: full-bleed room; the instrument docks as a compact
     glass strip under the nav; facts mirror + study link yield to the per-state
     OPEN button (bottom-right of the plate) */
  html:not(.static) .pd.pd-armed .pd-inst {
    left: 50%; transform: translateX(-50%);
    /* breathing room below the nav (owner: "too much at the top" on phone) —
       the panel floats in the sky zone, clear of both nav and readout */
    top: var(--pd-cluster-top);
    /* wide enough that the translated corner cells stay INSIDE the glass
       (84px cells at ±124% span ~292px — transforms don't grow the box) */
    width: 308px; padding: 6px 8px 2px;
  }
  /* symmetric chip-throw reserve: 84px cells reach ~54px past the dial box */
  html:not(.static) .pd.pd-armed .pd-dia { width: min(184px, 50vw); margin: 60px auto 60px; }
  html:not(.static) .pd.pd-armed .pd-dia__c { width: 84px; height: 84px; margin: -42px 0 0 -42px; }
  html:not(.static) .pd.pd-armed .pd-dia__c button { padding: 7px 9px; gap: 2px; }
  html:not(.static) .pd.pd-armed .pd-dia__c button span { font-size: 11.5px; }
  html:not(.static) .pd.pd-armed .pd-dia__apex { display: none; }
  html:not(.static) .pd.pd-armed .pd-callout { display: none; }
  html:not(.static) .pd.pd-armed .pd-mirror, html:not(.static) .pd.pd-armed .pd-study { display: none !important; }
  /* phone cluster (owner order): dial glass → readout → OPEN, one centered
     instrument stack with EQUAL 10px gaps. The readout height is LOCKED
     (min-height fits the longest mechanism line) so the OPEN seat never
     drifts between states — the mirror's fixed-height law, applied again. */
  html:not(.static) .pd.pd-armed .pd-stage__pin {
    --pd-panel-h: calc(128px + min(184px, 50vw));
    --pd-read-h: 112px;
    /* the cluster is dial + readout + OPEN with 10px gaps; centre THAT block
       in the stage, and never let it climb under the nav on a short screen */
    --pd-cluster-h: calc(var(--pd-panel-h) + 10px + var(--pd-read-h) + 10px + 40px);
    --pd-cluster-top: max(calc(var(--nav-h) + 14px), calc((100svh - var(--pd-cluster-h)) / 2));
  }
  html:not(.static) .pd.pd-armed .pd-read {
    left: 50%; right: auto; transform: translateX(-50%);
    width: 308px; box-sizing: border-box; min-height: var(--pd-read-h);
    top: calc(var(--pd-cluster-top) + var(--pd-panel-h) + 10px);
    bottom: auto;
  }
  html:not(.static) .pd.pd-armed .pd-state__open {
    left: 50%; right: auto; bottom: auto;
    top: calc(var(--pd-cluster-top) + var(--pd-panel-h) + 10px + var(--pd-read-h) + 10px);
    transform: translateX(-50%);
    padding: 0 14px; font-size: 10px; min-height: 40px;
  }
}
@media (max-width: 860px) {
  .pd-strip { grid-template-columns: repeat(3, 1fr); }
  .pd-row, .pd-row--fig, .pd-row--thumb { grid-template-columns: minmax(110px, 150px) 1fr; }
  .pd-row--fig img, .pd-row--thumb img { grid-column: 2; }
  .pd-callout span::before, .pd-callout span::after { width: 24px; }
  /* unarmed small plates: the readout leaves the image and becomes a caption
     band below it — chips over a ~180px-tall plate obscure the render
     (Sol 094 §3). Armed full-bleed re-absolutes it (rule below at 1060). */
  .pd-callout { display: none; }
  .pd-read { position: static; display: block; padding: 12px 14px; }
  html:not(.static) .pd.pd-armed .pd-callout { display: none; }
  html:not(.static) .pd.pd-armed .pd-read { position: absolute; }
}
@media (prefers-reduced-transparency: reduce) {
  html:not(.static) .pd.pd-armed .pd-inst {
    background: oklch(97.5% 0.003 100);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .pd-callout span, .pd-read { background: oklch(16% 0.006 80); }
}
@media (prefers-reduced-motion: reduce) {
  .pd-dia__rot, .pd-dia__c button, .pd-state, .pd-door img { transition: none !important; }
}

.pd-close__line { font-family: var(--mono); font-size: 10.5px; letter-spacing: .22em; color: var(--ink-2); margin-bottom: 8px; }
/* 085 fix 3 — roving keyboard access for the chip walls */
.pd-wall:focus-visible { outline: 2px solid var(--lime); outline-offset: 4px; }
.pd-wall .pxchip.is-kb .pxchip__s { outline: 2px dashed var(--graphite); outline-offset: 2px; }

/* 08c · per-state page links (the homepage is a portal now) */
.pd-state__open {
  display: inline-flex; align-items: center; min-height: 44px; margin-top: 14px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .18em; font-weight: 500;
  color: var(--graphite); text-decoration: none; border-bottom: 1px solid var(--graphite);
  padding-bottom: 2px; align-self: flex-start;
}
.pd-state__open::after { content: " →"; }
.pd-state__open:hover, .pd-state__open:focus-visible { color: oklch(49% 0.1 55); border-color: currentColor; }
html:not(.static) .pd.pd-armed .pd-state__open {
  position: absolute; right: clamp(18px, 2.6vw, 40px); bottom: clamp(16px, 2.8vw, 36px);
  z-index: 3; background: var(--stone); color: var(--graphite); border-bottom: 0;
  padding: 0 18px; margin: 0;
}
html:not(.static) .pd.pd-armed .pd-state__open:hover,
html:not(.static) .pd.pd-armed .pd-state__open:focus-visible { background: var(--brand-lift); color: var(--graphite); }
@media (max-width: 1060px) {
  html:not(.static) .pd.pd-armed .pd-state__open { right: 12px; bottom: 12px; padding: 0 12px; font-size: 10px; }
}

/* ═══ MOBILE SECTION RHYTHM (round 08e-R7) ═══════════════════════════════════
   Measured at 390: seams stacked to 131–219px of blank paper (prev padBot +
   next padTop). One consistent beat instead — every major seam lands between
   ~50 and ~110px. Last block in the file on purpose: it must win the earlier
   mobile paddings at equal specificity. */
@media (max-width: 860px) {
  .range { padding-top: clamp(48px, 9vw, 64px); }
  .pd { padding-top: clamp(48px, 9vw, 64px); padding-bottom: clamp(52px, 10vw, 72px); }
  .work { padding-block: clamp(52px, 10vw, 72px); }
  .statement { padding-top: clamp(40px, 8vw, 56px); padding-bottom: clamp(28px, 6vw, 44px); }
  .sec { padding-block: clamp(52px, 10vw, 72px); }
  .specs { padding-block: clamp(52px, 10vw, 72px) clamp(48px, 9vw, 64px); }
  .contact { padding-block: clamp(64px, 13vw, 88px); }
  .mq--partners { padding-block: clamp(24px, 5vw, 36px); }
}

/* ═══ GALLERY — the header disclosure (batch 09f) ══════════════════════════
   Shared by BOTH headers: the index panel (.doc) and the pergola pages'
   document bar (.pg-doc). Built on native <details>/<summary>, so the
   ship-guard path is the element itself — it opens, closes, takes Enter and
   Space and announces its expanded state with zero JavaScript. The tiny
   js/gallery-nav.js only adds Escape-to-close, outside-click and
   one-open-at-a-time. Colour comes from --bg/--ink, so the same component is
   legible over the dark hero, on the light paper and inside the pergola bar. */
.gdrop { position: relative; }
.gdrop > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 9px;
  min-height: 44px; padding: 9px 14px;
  border: 1px solid var(--hair); color: inherit; white-space: nowrap;
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
  transition: border-color .3s, color .3s;
}
.gdrop > summary::-webkit-details-marker { display: none; }
.gdrop > summary::marker { content: ""; }
/* the caret: a rotated corner, so it inherits currentColor on every surface */
.gdrop__caret {
  width: 6px; height: 6px; margin-top: -3px; flex: none;
  border-right: 1px solid currentColor; border-bottom: 1px solid currentColor;
  transform: rotate(45deg); transition: transform .3s var(--ease-magic);
}
.gdrop[open] .gdrop__caret { transform: rotate(-135deg); margin-top: 2px; }
.gdrop > summary:hover, .gdrop > summary:focus-visible { border-color: currentColor; }
.gdrop[open] > summary { border-color: currentColor; }

.gdrop__p {
  position: absolute; right: 0; top: calc(100% + 9px); z-index: 60;
  width: min(286px, calc(100vw - 28px)); padding: 5px;
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--hair);
  box-shadow: 0 18px 44px oklch(16% 0.006 80 / .30);
}
.gdrop__h {
  display: block; padding: 9px 11px 8px; margin-bottom: 4px;
  border-bottom: 1px solid var(--hair);
  font-family: var(--mono); font-size: 9px; letter-spacing: .2em; color: var(--dim);
}
.gdrop__p a, .gdrop__soon {
  display: flex; align-items: center; gap: 11px;
  min-height: 44px; padding: 9px 11px;
  font-family: var(--mono); text-decoration: none; color: var(--ink);
  border-left: 2px solid transparent;
  transition: background .25s, border-color .25s;
}
.gdrop__p a:hover, .gdrop__p a:focus-visible {
  background: var(--bg-2); border-left-color: var(--brand);
}
.gdrop__p a[aria-current="page"] { border-left-color: var(--brand); background: var(--bg-2); }
.gdrop__no { font-size: 9px; letter-spacing: .16em; color: var(--dim); flex: none; width: 18px; }
.gdrop__n {
  font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 88;
  font-size: 15px; letter-spacing: .01em; line-height: 1;
}
.gdrop__c { margin-left: auto; font-size: 9px; letter-spacing: .14em; color: var(--dim); }
.gdrop__soon { color: var(--dim); cursor: default; }
.gdrop__soon .gdrop__n { color: var(--dim); }
@media (prefers-reduced-motion: reduce) {
  .gdrop__caret, .gdrop__p a { transition: none; }
}
/* phones: the trigger sits mid-bar on the index header, so a right-anchored
   panel would run off the left edge — below 560 the panel becomes a fixed
   sheet under the header instead, on every page */
@media (max-width: 560px) {
  .gdrop__p { position: fixed; left: 14px; right: 14px; top: calc(var(--nav-h) + 2px); width: auto; }
  /* The phone-nav sizing for this pill has to live HERE, not up in the header
     block at ~224. `.gdrop > summary` is authored below that block with the same
     specificity, and a media query adds none — so its `padding: 9px 14px;
     font-size: 10px; letter-spacing: .18em` won on source order and the GALLERY
     pill never shrank at all (measured: still 99.6px while the two CTAs beside
     it had already gone 69 → 62). Same cascade trap that threw the pergola dial
     off centre. Restated after the base rule, it takes. */
  .gdrop > summary { padding: 9px 8px; font-size: 9.5px; letter-spacing: .06em; gap: 5px; }
}
/* ?static and no-JS both leave the disclosure fully operable — nothing to undo. */
/* the auto-hiding index header must not slide away with an open menu on it */
html.gdrop-open .doc { transform: none !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   BATCH 09b · L11 — THE CROSSING: real transitions on every seam from 2→3 down
   ═══════════════════════════════════════════════════════════════════════════
   The standard is the 01→02 seam: the pergola TAKEOVER, where the plate
   expands to full viewport and the reader steps into the terrace. Every seam
   after it had only the batch-09 hairline draw — a rule, not a transition.

   THE FAMILY (one grammar, distinct per seam):
     · the hairline still draws (kept, untouched)
     · a CROSSING REGISTER rides the seam — `FROM ── ● ── TO` — scrubbed, so
       the outgoing chapter dims and the incoming one lights as you pass through
     · a lime tick TRAVELS the rule left-to-right (or right-to-left on alternate
       seams, which is where the per-seam distinctness lives)
     · the incoming section's first block rises through a SHUTTER (clip-path)

   Everything here is scroll-scrubbed: deterministic, reversible, no stuck
   states, and — critically — NO `pin:`. A single pin-spacer once broke every
   trigger below §02 (batch 09, order 9). Sticky + runway + scrub only.

   The register inherits `currentColor` from the section it is prepended into,
   so it stays legible across the light→dark→light chapter flips without a
   parallel palette.
   ═══════════════════════════════════════════════════════════════════════════ */
.xing {
  position: absolute; top: 0; left: var(--pad); right: var(--pad); z-index: 3;
  display: flex; align-items: center; gap: clamp(10px, 1.4vw, 20px);
  font-family: var(--mono); font-size: clamp(8.5px, .68vw, 10px); letter-spacing: .22em;
  pointer-events: none; opacity: 0;
  /* Sits just INSIDE the incoming chapter, never straddling the boundary.
     Straddling looked more elegant and was wrong: the top half landed on the
     OUTGOING section's background, and since the register inherits the
     incoming section's colour, that half was light-on-light (measured at the
     02->03 seam, where WORK is graphite and the outro above it is paper). */
  top: clamp(16px, 2.2vh, 30px);
}
.xing__from, .xing__to { white-space: nowrap; color: currentColor; }
.xing__from { opacity: .38; }
.xing__to { opacity: .38; }
.xing__rule {
  position: relative; flex: 1 1 auto; height: 1px; min-width: 40px;
  background: currentColor; opacity: .18;
}
.xing__tick {
  position: absolute; top: 50%; left: 0; width: 11px; height: 1px; margin-top: -.5px;
  background: var(--lime); transform: translateX(0);
}
/* the incoming chapter rises through a shutter */
.xshut { clip-path: inset(0 0 0 0); }

@media (max-width: 860px) {
  /* phone keeps the hairline and the shutter; the register would crowd the
     head at 390px, and mobile is shipped and tuned — it does not change */
  .xing { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .xing { display: none; }
  .xshut { clip-path: none !important; }
}

/* Batch 09b’s “SECTION 3 READS AS FILM” rules lived here. Retired 2026-08-13
   with the sun-path wall itself — the two ideas worth keeping (the image drifts
   inside its frame, the grade lifts as a plate reaches the band) moved into the
   §03 THE DRAWER block above, where they now apply to .wk-plate. */

/* ═══════════════════════════════════════════════════════════════════════════
   BATCH 09b · L12 + L13 + L14 — THE SIGNATURE MOVE, REBUILT AS AN INSTRUMENT
   ═══════════════════════════════════════════════════════════════════════════
   The diamond kept its concept and lost its craft: four bordered white boxes,
   a count, a spec list and two competing links all stacked in one panel — it
   read as a pile of text rather than the site's signature control.

   Everything below is scoped `(hover: hover) and (min-width: 861px)`. The
   phone cluster (dial glass → readout → OPEN, equal 10px gaps, locked readout
   height) is shipped and tuned and does NOT change — L13 is desktop-only by
   the owner's instruction, and the rest keeps it company so the phone stack
   cannot drift. The one mobile line at the end re-tunes only the locked
   readout height, because L14 shortened the copy it was sized for.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (hover: hover) and (min-width: 861px) {

  /* ── L14 · the readout is type on film now, not a chip ── */
  .pd-read {
    background: none; border-left: 0; padding: 0;
    left: clamp(26px, 4.2vw, 72px); bottom: clamp(30px, 5.4vw, 78px);
    max-width: min(22ch, 54vw);
    text-shadow: 0 2px 34px oklch(8% 0.004 80 / .92), 0 1px 4px oklch(8% 0.004 80 / .8);
  }
  .pd-read b {
    font-size: 10px; letter-spacing: .34em; color: var(--brand-lift);
    margin-bottom: clamp(12px, 1.2vw, 18px);
  }
  .pd-read strong {
    font-size: clamp(58px, 8.8vw, 148px); font-variation-settings: "wdth" 66;
    line-height: .82; letter-spacing: -.018em;
  }
  .pd-read em {
    font-size: clamp(10.5px, .82vw, 12.5px); letter-spacing: .3em;
    margin-top: clamp(14px, 1.5vw, 22px); color: oklch(92% 0.004 100);
  }
  /* the plate's own scrim carries the type — deepened at the foot so the
     readout clears 4.5:1 on the brightest of the four anchors */
  html:not(.static) .pd.pd-armed .pd-state__fig::after {
    background: linear-gradient(180deg,
      oklch(14% 0.005 80 / .46), transparent 20%,
      transparent 40%, oklch(8% 0.004 80 / .86));
  }

  /* ── L12 · the dial: drawn, not boxed ──────────────────────────────────── */
  /* chips become type with a seat, so three of four read as quiet labels and
     the active one is unmistakably seated at the apex */
  .pd-dia__c button {
    background: none; border: 0; padding: 9px 11px; gap: 4px;
    transition: transform .7s var(--ease-magic), background .34s var(--ease-magic),
                color .34s, opacity .34s;
    opacity: .62;
  }
  .pd-dia__c button b { font-size: 8.5px; letter-spacing: .26em; color: var(--dim); }
  .pd-dia__c button span {
    font-size: 12.5px; letter-spacing: .06em; font-variation-settings: "wdth" 90;
    color: var(--ink-2);
  }
  .pd-dia__c button:hover, .pd-dia__c button:focus-visible { opacity: 1; }
  .pd-dia__c button:hover span, .pd-dia__c button:focus-visible span { color: var(--ink); }
  .pd-dia__c button.is-top {
    background: var(--graphite); border: 0; padding: 11px 17px; opacity: 1;
    box-shadow: 0 10px 26px oklch(20% 0.01 80 / .28);
  }
  .pd-dia__c button.is-top b { color: var(--brand-lift); }
  .pd-dia__c button.is-top span { color: var(--stone); letter-spacing: .09em; }

  /* the ring: two hairline diamonds, no fill — a drawn dial face */
  .pd-dia__sq {
    background: none;
    border-color: color-mix(in oklch, var(--ink) 30%, transparent);
  }
  .pd-dia__sq::after {
    inset: 15px;
    border-color: color-mix(in oklch, var(--ink) 13%, transparent);
  }

  /* the apex pointer picks up the caliper language used elsewhere on the page:
     lime prong + diamond foot, instead of a bare 1px tick */
  .pd-dia__apex { top: -40px; gap: 7px; }
  .pd-dia__apex span { font-size: 8px; letter-spacing: .3em; color: var(--dim); }
  .pd-dia__apex i { height: 19px; background: var(--brand); position: relative; }
  .pd-dia__apex i::after {
    content: ""; position: absolute; left: 50%; bottom: -4px;
    width: 7px; height: 7px; background: var(--brand);
    transform: translateX(-50%) rotate(45deg);
  }

  /* the centre becomes a readout, with its own rule */
  .pd-dia__mid b {
    font-size: 21px; letter-spacing: .1em; font-weight: 500;
    padding-bottom: 7px; position: relative;
  }
  .pd-dia__mid b::after {
    content: ""; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
    width: 34px; height: 1px; background: color-mix(in oklch, var(--ink) 24%, transparent);
  }
  .pd-dia__mid span { font-size: 8px; letter-spacing: .3em; margin-top: 7px; display: block; }

  /* ── L13 · ONE call to action, and it is unmissable ────────────────────── */
  /* the panel's quiet duplicate link is absorbed — two links for one action was
     the actual problem, so the pair becomes a single primary CTA */
  html:not(.static) .pd.pd-armed .pd-study { display: none; }

  html:not(.static) .pd.pd-armed .pd-state__open {
    background: var(--brand); color: var(--stone);
    font-size: 12.5px; letter-spacing: .2em; font-weight: 600;
    min-height: 58px; padding: 0 clamp(26px, 2.4vw, 38px);
    right: clamp(26px, 4.2vw, 72px); bottom: clamp(30px, 5.4vw, 78px);
    box-shadow: 0 20px 50px oklch(8% 0.004 80 / .5);
    transition: background .3s var(--ease-magic), color .3s, box-shadow .3s, transform .3s var(--ease-magic);
  }
  html:not(.static) .pd.pd-armed .pd-state__open::after {
    content: " →"; display: inline-block; margin-left: 10px;
    transition: transform .32s var(--ease-magic);
  }
  html:not(.static) .pd.pd-armed .pd-state__open:hover,
  html:not(.static) .pd.pd-armed .pd-state__open:focus-visible {
    background: var(--stone); color: var(--graphite);
    transform: translateY(-2px);
    box-shadow: 0 26px 60px oklch(8% 0.004 80 / .6);
  }
  html:not(.static) .pd.pd-armed .pd-state__open:hover::after,
  html:not(.static) .pd.pd-armed .pd-state__open:focus-visible::after { transform: translateX(6px); }
  html:not(.static) .pd.pd-armed .pd-state__open:focus-visible { outline: 2px solid var(--stone); outline-offset: 4px; }
}

/* L14 shortened the mechanism line, so the phone's LOCKED readout height (set
   to fit the longest old string) now reserves dead space above the OPEN seat.
   Re-tuned to the new longest line — the lock itself is kept, because it is
   what stops the OPEN button drifting between states. */
@media (max-width: 860px) {
  html:not(.static) .pd.pd-armed .pd-stage__pin { --pd-read-h: 96px; }
}

/* ── 09b corrections, measured against the served page ──────────────────────
   Two collisions with the batch-08e armed rules, which win on specificity
   (`html:not(.static) .pd.pd-armed …` = 0,4,1). Both fixes are re-stated at
   that same weight rather than reached for with !important.

   1. THE READOUT OVERLAPPED THE INSTRUMENT. L14's type is ~2.4x its old size,
      and the floating glass panel is 390px wide at the left edge — measured at
      1440, "HARD TOP" ran underneath it. The readout now starts clear of the
      panel's right edge, which also gives the frame a proper film-title
      layout: title bottom-left-of-centre, one CTA bottom-right.
   2. THE QUIET CHIPS WERE STILL RAISED. Making them borderless was not enough —
      the armed rule also gives every chip a drop shadow + inset highlight, so
      three of four still read as pressed metal buttons. The lift now belongs
      to the ACTIVE chip alone, which is the whole point of the dial. ── */
@media (hover: hover) and (min-width: 861px) {
  html:not(.static) .pd.pd-armed .pd-read {
    left: calc(clamp(20px, 3.2vw, 56px) + 390px + clamp(28px, 3vw, 56px));
    max-width: min(20ch, 42vw);
  }
  html:not(.static) .pd.pd-armed .pd-dia__c button { box-shadow: none; }
  html:not(.static) .pd.pd-armed .pd-dia__c button.is-top {
    box-shadow: 0 10px 26px oklch(20% 0.01 80 / .3);
  }
}
/* below 1180 the panel + a 148px title cannot share the width — the title
   steps down before it can ever collide */
@media (hover: hover) and (min-width: 861px) and (max-width: 1180px) {
  html:not(.static) .pd.pd-armed .pd-read strong { font-size: clamp(44px, 5.4vw, 72px); }
  html:not(.static) .pd.pd-armed .pd-read { max-width: min(16ch, 38vw); }
}

/* ── 09b · the readout has to survive a BRIGHT anchor ───────────────────────
   The four takeover plates are first-light scenes: the type sits over pale
   travertine and a lit sky, not over graphite. Two consequences, both already
   written down in this project's own notes:

   1. The kicker was brand red. Batch 08e recorded that a small red mono line
      cannot reach 4.5:1 on ANY translucent backing — red's luminance sits too
      close to everything — and that red belongs on borders and hairlines while
      data lines go light. It is light now, with the red kept as the rule.
   2. The plate's foot gradient alone is not enough under 148px type. The
      readout carries its OWN soft grade — a wide feathered pool, not a box, so
      it reads as film grading rather than a caption plate. ── */
@media (hover: hover) and (min-width: 861px) {
  html:not(.static) .pd.pd-armed .pd-read { isolation: isolate; }
  html:not(.static) .pd.pd-armed .pd-read::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    left: -14%; right: -34%; top: -34%; bottom: -52%;
    background: radial-gradient(58% 66% at 24% 58%, oklch(6% 0.004 80 / .78), transparent 74%);
  }
  html:not(.static) .pd.pd-armed .pd-read b {
    color: oklch(96% 0.004 100); display: flex; align-items: center; gap: 11px;
  }
  html:not(.static) .pd.pd-armed .pd-read b::before {
    content: ""; width: 22px; height: 1px; background: var(--brand); flex: none;
  }
  html:not(.static) .pd.pd-armed .pd-read em { color: oklch(95% 0.004 100); }
  html:not(.static) .pd.pd-armed .pd-state__fig::after {
    background: linear-gradient(180deg,
      oklch(14% 0.005 80 / .46), transparent 18%,
      transparent 34%, oklch(6% 0.004 80 / .90));
  }
}

/* ── 09b · the grade pool must actually sit under the glyphs ────────────────
   Measured: median backdrop was fine (8–11:1) but the WORST-case pixel under
   the title was 2.49:1 and under the kicker 3.43:1. Cause: `.pd-read` was
   192px wide while its 148px title overflows to ~530px, so the feathered pool
   — sized to the box — covered almost none of the painted type. The box now
   takes its content's width, so the grade travels with the type. ── */
@media (hover: hover) and (min-width: 861px) {
  html:not(.static) .pd.pd-armed .pd-read {
    width: max-content; max-width: min(48vw, 640px);
  }
  html:not(.static) .pd.pd-armed .pd-read::before {
    left: -12%; right: -12%; top: -26%; bottom: -34%;
    background: radial-gradient(80% 84% at 42% 56%, oklch(4% 0.004 80 / .95), oklch(4% 0.004 80 / .74) 52%, transparent 84%);
  }
}

/* ── a11y fixes found by Lighthouse during 09b verification ────────────────
   Both pre-date this batch; both are cheap, so they are fixed rather than
   noted. (1) `.vh` is the visually-hidden copy the hero deck now carries,
   because every split word inside it is aria-hidden and `aria-label` is
   prohibited on a bare <p>. (2) The §01 wheel counter painted --cedar at
   L=0.56, measured 4.04:1 on the paper — under the 4.5 floor. L=0.48 measures
   5.68:1 and is visually indistinguishable at 12px. */
.vh {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.wheel__count #wheelNo { color: oklch(0.48 0.1 55); }

/* ═══ THE SELECTION WHEEL — CINEMATIC (2026-08-14, order 01) ════════════════
   Was: the dial floated inside a white "drawing-glass" panel pinned to the left
   edge, with two fact rows (POST / BEAM, LAMELLA) stacked under it. Against the
   full-bleed terrace imagery that panel read as a UI card dropped on a
   photograph — the brightest object on a cinematic stage, and off-axis.

   Now: no panel at all. The dial floats in the scene on the centre line, the
   fact rows are gone, and the only things left are the big product name and the
   diamond itself. Legibility comes from a vignette pooled behind the dial
   rather than from a plate — the imagery keeps reading, the instrument keeps
   its 3D tilt, and the composition is symmetrical about one axis.
   ═══════════════════════════════════════════════════════════════════════════ */
html:not(.static) .pd.pd-armed .pd-inst {
  /* stays on the LEFT on desktop (owner call) — only the panel, the two fact
     rows and the pale plate were the problem, not the position */
  left: clamp(20px, 3.2vw, 56px); right: auto;
  transform: translateY(-50%);
  width: min(430px, 34vw);
  padding: 0;
  background: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border: 0;
  box-shadow: none;
  text-align: center;
}
/* the pooled light that seats the dial on the photograph */
html:not(.static) .pd.pd-armed .pd-inst::before {
  content: ""; position: absolute; z-index: -1;
  inset: -22% -28%;
  background: radial-gradient(closest-side, oklch(10% 0.006 80 / .62), oklch(10% 0.006 80 / .28) 58%, transparent 78%);
  pointer-events: none;
}
/* the two small details under the dial are withdrawn (order 01) */
html:not(.static) .pd.pd-armed .pd-mirror { display: none !important; }
/* on dark, the apex marker and the centre readout invert */
html:not(.static) .pd.pd-armed .pd-dia__apex span { color: oklch(88% 0.01 90 / .85); }
html:not(.static) .pd.pd-armed .pd-dia__mid b { color: oklch(98% 0.003 120); }
html:not(.static) .pd.pd-armed .pd-dia__mid span { color: oklch(86% 0.008 100 / .8); }
html:not(.static) .pd.pd-armed .pd-study {
  margin-top: 6px; color: oklch(94% 0.006 100); border-color: oklch(94% 0.006 100 / .5);
}
html:not(.static) .pd.pd-armed .pd-study:hover,
html:not(.static) .pd.pd-armed .pd-study:focus-visible {
  color: oklch(99% 0.002 120); border-color: oklch(99% 0.002 120);
}
/* the big name centres with the dial instead of hugging the bottom-left */
html:not(.static) .pd.pd-armed .pd-read {
  background: oklch(16% 0.006 80 / .78);
}
@media (max-width: 900px) {
  /* Phone keeps the CLUSTER layout (dial -> readout -> OPEN, all keyed off
     --pd-cluster-top), so the panel must NOT take a translateY of its own —
     that stacked on top of the cluster offset and pushed the dial to y=154 on
     an 844px screen. Horizontal centring only; the vertical centring is done
     by re-deriving --pd-cluster-top below. */
  html:not(.static) .pd.pd-armed .pd-inst {
    left: 50%; transform: translateX(-50%);
    /* WIDTH MUST BE RESTATED HERE. The dark-instrument rule above sets
       width: min(430px, 34vw) with no media gate, so it lands AFTER the
       @media (max-width: 1060px) width: 308px and wins on source order.
       At 390px that resolved to 132px — narrower than the 184px dial inside
       it. An over-constrained block box drops both auto margins to 0, so
       `.pd-dia { margin: auto }` stopped centring and left-aligned instead:
       the whole diamond sat ~27px right of centre with the R2 chip a few px
       off the screen edge. Restating the phone width here (the last word in
       the cascade) is what keeps the dial centred. Verified at 320/375/390/430. */
    width: min(308px, calc(100vw - 24px));
  }
}

/* The instrument goes DARK. With the white panel removed the dial's plate was
   still a pale drawing-glass square, and the corner chips are pale too — so on
   a sunlit photograph the labels washed straight into the plate (hit-testing
   proved they were on top; it was contrast, not z-order). A dark plate with
   light chips reads on any frame, and matches the diamond stage on the sub
   pages so the two selectors are visibly the same instrument. */
html:not(.static) .pd.pd-armed .pd-dia__sq {
  background: linear-gradient(160deg, oklch(26% 0.008 80 / .86), oklch(17% 0.006 80 / .88) 52%, oklch(23% 0.008 80 / .86));
  border-color: oklch(80% 0.02 90 / .5);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / .12), 0 20px 44px oklch(0% 0 0 / .5);
}
html:not(.static) .pd.pd-armed .pd-dia__sq::after { border-color: oklch(84% 0.02 90 / .18); }
html:not(.static) .pd.pd-armed .pd-dia__c button {
  background: oklch(21% 0.006 80 / .95);
  border-color: oklch(84% 0.02 90 / .4);
  box-shadow: 0 8px 20px oklch(0% 0 0 / .45);
}
html:not(.static) .pd.pd-armed .pd-dia__c button span { color: oklch(96% 0.004 120); }
html:not(.static) .pd.pd-armed .pd-dia__c button b { color: oklch(80% 0.13 68); }
/* the active corner inverts to a lit plate — the one bright thing in the dial */
html:not(.static) .pd.pd-armed .pd-dia__c button.is-top {
  background: oklch(95% 0.004 120); border-color: oklch(95% 0.004 120);
  box-shadow: 0 12px 28px oklch(0% 0 0 / .55);
}
html:not(.static) .pd.pd-armed .pd-dia__c button.is-top span { color: oklch(17% 0.006 80); }
html:not(.static) .pd.pd-armed .pd-dia__c button.is-top b { color: oklch(52% 0.19 25); }

/* ═══ PHONE: DRUM CENTRING + SECTION-HEAD SPACING (2026-08-14) ══════════════
   Two owner calls on mobile.

   1. The drum read low in its own screen. `.vdrum__pin` centres its content
      but pads the TOP by the nav height and the bottom by only the safe-area
      inset — measured, that pushed the stage's centre to y=469 on an 844px
      screen against a true centre of 422, with 236px of dead sky above and
      142px below. Balancing the two paddings puts the optical centre back on
      the screen centre; the stage still has 688px of room for a 466px column,
      so nothing is squeezed.

      SUPERSEDED 2026-08-15 — see below. Balancing the paddings centred the
      card against the RAW viewport, but the top ~76px of that viewport is
      behind the fixed nav and can never hold the card. So the bottom copy of
      the nav-height padding cleared a nav that is not there: measured at
      393x852, 159px dead above the HUD and 159px below the hint, 37% of the
      screen, constant at every seat. The optical centre now balances against
      the VISIBLE screen below the nav, which is what the owner was actually
      asking for.

   2. `.sec__head` reserves `clamp(30px, 6vh, 70px)` beneath it. 6vh is a big
      number on a tall phone — it measured 35px under ALUMINUM ARCHITECTURAL
      SYSTEMS and 51px under PERGOLAS, which the owner reads as a hole. On
      phones the head sits closer to its section. */
@media (max-width: 900px) {
  .vdrum__pin {
    padding-block: calc(var(--nav-h, 52px) + clamp(10px, 2.4svh, 26px))
      max(16px, env(safe-area-inset-bottom));
  }
  .sec__head { margin-bottom: clamp(16px, 2.4vh, 26px); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   INQUIRY + BOOKING (2026-08-15)

   Authored as ONE self-contained block at the very end of the file, base rules
   first and its own media queries immediately after, because main.css authors
   base component rules AFTER its responsive blocks and a media query adds no
   specificity. `.contact` is defined at line 319 but re-padded by an ungated
   @media at ~2617; anything written near its relatives is at the mercy of
   whatever lands below it later. Down here nothing can.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── file input ──────────────────────────────────────────────────────────── */
.cform__file {
  width: 100%; font: inherit; font-size: 14px; color: var(--ink);
  padding: 13px 14px; background: transparent;
  border: 1px dashed var(--hair); border-radius: 0;
}
.cform__file::file-selector-button {
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink); background: transparent;
  border: 1px solid var(--hair); border-radius: 0;
  padding: 9px 14px; margin-right: 14px; cursor: pointer;
  transition: border-color .3s var(--ease-magic), color .3s var(--ease-magic);
}
.cform__file:hover { border-color: color-mix(in oklch, var(--ink) 45%, transparent); }
.cform__file::file-selector-button:hover { border-color: var(--ink); }
.cform__file:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
.cform__file[aria-invalid="true"] { border-color: oklch(46% 0.15 35); }

.cform__note {
  margin: 8px 0 0; font-family: var(--mono); font-size: 10px;
  letter-spacing: .1em; color: var(--dim);
}
/* Named files are data, not chrome: give them the ink the note does not get. */
.cform__files {
  margin: 6px 0 0; font-family: var(--mono); font-size: 10px;
  letter-spacing: .08em; color: var(--ink); word-break: break-word;
}
.cform__files:empty { margin: 0; }

/* Off-screen rather than display:none — some bots skip what is display:none,
   which is the whole point of the field. Never focusable, never announced. */
.cform__trap {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; opacity: 0; pointer-events: none;
}

/* ── booking panel ───────────────────────────────────────────────────────── */
.book {
  margin: 44px 0 34px; max-width: 720px;
  padding-top: 34px; border-top: 1px solid var(--hair);
}
.book__k {
  font-family: var(--mono); font-size: 11px; letter-spacing: .3em;
  color: var(--accent-text); margin: 0 0 18px;
}
.book__t {
  font-size: clamp(22px, 2.6vw, 30px); line-height: 1.15;
  letter-spacing: -0.01em; margin: 0 0 14px;
}
.book__x {
  font-size: 16px; line-height: 1.6; color: var(--dim);
  max-width: 52ch; margin: 0 0 26px;
}
.book .btn { margin-top: 0; }

/* ── cross-page CTA band ─────────────────────────────────────────────────── */
.pcta {
  border-top: 1px solid var(--hair);
  padding: clamp(54px, 9vh, 96px) var(--pad);
}
.pcta__k {
  font-family: var(--mono); font-size: 11px; letter-spacing: .3em;
  color: var(--accent-text); margin: 0 0 18px;
}
.pcta__t {
  font-size: clamp(22px, 3vw, 34px); line-height: 1.15;
  letter-spacing: -0.01em; margin: 0 0 28px; max-width: 22ch;
}
.pcta__row { display: flex; gap: 14px; flex-wrap: wrap; }
.pcta__row .btn { margin-top: 0; }

/* ── responsive (authored AFTER the base rules above, on purpose) ────────── */
@media (max-width: 700px) {
  .book { margin: 36px 0 30px; padding-top: 28px; }
  .book__x { font-size: 15px; margin-bottom: 22px; }
}
/* Sized against 375 (SE 2/3, 12/13 mini), not 390 — 390 carries ~22px of slack
   and hides exactly this constraint. Full-width actions stop the long phone
   number from setting the button width and overflowing the row. */
@media (max-width: 420px) {
  .cform__file { font-size: 13px; padding: 11px 12px; }
  .cform__file::file-selector-button { margin-right: 10px; padding: 8px 11px; }
  .pcta__row { flex-direction: column; align-items: stretch; }
  .pcta__row .btn { width: 100%; text-align: center; }
  .book .btn { width: 100%; text-align: center; }
}

/* ═══ 10a · PHONE TYPE FLOOR + TOUCH TARGETS (2026-08-15) ═══════════════════
   Measured at 393x852 on index.html before this block: 915 text nodes
   rendering below 11px, of which 229 were the product-spec `dt` at 9px and
   three were at 8px — under the site's own 10px floor and well under the 11px
   a customer can actually read on a phone held at arm's length.

   The floor is applied HERE, phone-gated and last in the file, rather than by
   editing the ~90 base declarations: those same declarations set desktop, and
   desktop is required to stay byte-identical. Source order does the winning,
   so each selector below is written at the specificity of the rule it lifts.

   Two tiers, per the brief: 11px for anything a customer READS, 10.5px for
   pure glance labels — counters, tags, eyebrows, state chips. */
@media (max-width: 860px) {
  /* ── 11px · read ───────────────────────────────────────────────────────── */
  .product-tech__row dt,
  .product-tech__apps,
  .product-tech__colors,
  .product__name,
  .system-family__lede,
  .wcard__d,
  .vcard__d,
  .kv dt,
  .tech__table th,
  .range__fig figcaption,
  .pd-wall__sub,
  .pd-wall .px-fam,
  .pd-wall .pxchip__c,
  .pd-wall .px-range__foot,
  .pd-read em,
  .pd-row--note > span:last-child,
  .msheet__apps,
  .fam__specs div,
  .asas__columns,
  .asas__note,
  .asas__duplicate,
  .cform__label,
  .cform__err,
  .cform__note,
  .cform__files,
  .cform__opt,
  .cform__file::file-selector-button,
  .gdrop__h,
  .wk-rail__t,
  .wk-fr__cap,
  .wk-fam__t,
  .wk-strip__t,
  .wk-sched__s,
  .wk-plate__await,
  .wk-c > b,
  .wk-sys,
  .wk-srow__n,
  .wk-srow__r a,
  .work__key,
  /* set as clamp(9px, .72vw, 11px) — the vw term is 2.8px on a phone, so the
     9px floor is what actually renders there */
  .work__sub { font-size: 11px; }

  /* ── 10.5px · glance ───────────────────────────────────────────────────── */
  .doc__cta,
  .doc__section-current,
  .aitem__no,
  .tag,
  .tag--record,
  .rtag,
  .cover__hint,
  .mq__label,
  .wheel__hint,
  .wheel__close,
  .drum__partial,
  .wheel__technical .drum__partial,
  .plate__no,
  .plate__count,
  .product-tech__eyebrow,
  .product-tech__capability,
  .product-tech__status,
  .product-tech__action,
  .system-family__no,
  .system-family__partial,
  .vcard__cta,
  .vdrum__hint,
  .msheet__fno,
  .msheet__cap,
  .wcard__cta,
  .fam__action,
  .fam__action--pending,
  .asas__index,
  .asas__pages,
  .asas__size,
  .asas__action,
  .asas__action--missing,
  .pd-dia__apex span,
  .pd-dia__mid span,
  .pd-dia__c button b,
  .pd-strip b,
  .pd-strip em,
  .pd-paint__tag,
  .pd-paint__cap span:nth-child(3),
  .pd-paint__cap span:nth-child(4),
  .pd-door__id b,
  .pd-door__prov,
  .gdrop > summary,
  .gdrop__no,
  .gdrop__c,
  .wk-idx__a i,
  .wk-idx__a em,
  .wk-c--lo > span,
  .work__sect,
  /* the chapter-crossing register: clamp(8.5px, .68vw, 10px), so 8.5px on a
     phone — the smallest type anywhere on the site */
  .xing { font-size: 10.5px; }

  /* the armed state chip carries its own 4-class specificity, so it has to be
     lifted with the same selector it was set with */
  html:not(.static) .pd.pd-armed .pd-state__open { font-size: 10.5px; }

  /* ── 44px hit areas ─────────────────────────────────────────────────────
     The dial's four corner buttons already carry 44px of LAYOUT height, but
     the dial is drawn in perspective and the hit area follows the TRANSFORMED
     shape: measured at three scroll positions inside the chapter, three of the
     four foreshorten to 40.2-42.9px on screen while `offsetHeight` reports a
     compliant 44. So the layout box has to overshoot the target — 49px lands
     the shortest corner at ~44.8px of real, tappable screen. */
  .pd-dia__c button { min-height: 49px; }
  /* `.pd-state__open` sets a 44px floor at line 2667 and the armed override in
     the <=1060px block then took it back down to 40px. Put it back. */
  html:not(.static) .pd.pd-armed .pd-state__open { min-height: 44px; }
}
