/* =====================================================================
   GravenReachMedia — v4 "Fire and Rigor"
   Ember on Bone · engraved didone + mono + technical-instrument layer
   Resting/default state == final visible state (so reduced-motion / no-JS
   shows the finished page). JS animates FROM offsets back to these defaults.
   ===================================================================== */

@import url("fonts.css");

/* ---------- tokens ---------- */
:root{
  /* ember — the one loud colour */
  --ember-50:#FBE3DB; --ember-100:#F2B6A6; --ember-300:#E8836E;
  --ember-500:#D7331B; --ember-700:#A82812; --ember-900:#7E2A0F; --ember-950:#5A1E0B;
  /* bone & stone */
  --paper-0:#FBF7EE; --bone:#F2EBDD; --paper-2:#E7DECB;
  --stone-300:#CFC4AD; --stone-500:#B8AE9A; --stone-700:#8C8472;
  /* ink & steel */
  --ink:#14110D; --surface:#1E1A14; --edge:#2E2820;
  --ink-2:#3A332A; --ink-3:#6B6252;
  /* teal — "verified" only */
  --teal-300:#9FCFC6; --teal-500:#1F5E57; --teal-700:#143F3A;
  /* white-hot — strike spark */
  --hot:#FFF3DE;

  --didone:'Bodoni Moda',Georgia,serif;
  --mono:'Space Mono',ui-monospace,monospace;
  --sans:'Archivo',system-ui,-apple-system,sans-serif;

  /* type scale (few sizes, hierarchy by weight + colour) */
  --fs-display:clamp(82px,15.5vw,232px);
  --fs-h1:clamp(54px,9.2vw,158px);
  --fs-h2:clamp(38px,6vw,96px);
  --fs-h3:clamp(26px,3.4vw,52px);
  --fs-lede:clamp(18px,2.1vw,23px);
  --fs-body:17px;
  --fs-mono:13px;
  --fs-micro:11px;

  --pad:clamp(20px,4.4vw,64px);
  --gutter:56px;
  --rule:1px solid rgba(20,17,13,.16);
  --rule-ink:1px solid rgba(242,235,221,.16);
}

/* ---------- reset ---------- */
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
html,body{height:100%}
body{
  font-family:var(--sans);background:var(--bone);color:var(--ink);
  font-size:var(--fs-body);line-height:1.5;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
body.lenis,html.lenis{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto !important}
img,svg{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--ember-500);outline-offset:3px}

/* skip link — visually hidden until focused, sits above the sticky header */
.skip-link{position:fixed;top:0;left:0;z-index:210;transform:translateY(-120%);
  background:var(--ink);color:var(--bone);font-family:var(--mono);font-size:var(--fs-micro);
  letter-spacing:.08em;text-transform:uppercase;padding:12px 20px;
  transition:transform .15s ease}
.skip-link:focus{transform:translateY(0);outline:2px solid var(--ember-500);outline-offset:-2px}

/* visually hidden — accessible to screen readers only */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
/* utility text */
.mono{font-family:var(--mono);letter-spacing:.08em}
.eyebrow{font-family:var(--mono);font-size:var(--fs-micro);letter-spacing:.22em;
  text-transform:uppercase;color:var(--ink-3)}
.verified{color:var(--teal-500);display:inline-flex;align-items:center;gap:8px}
.verified::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--teal-500);flex:none}
.dia{color:var(--ember-500)}

/* ---------- the STRIKE primitive ----------
   each display word is .strike-word > .strike-line(s) > .glyph
   default = engraved at rest. JS sets the FROM offset. */
.glyph{display:inline-block;will-change:transform}
.strike-line{display:block;overflow:hidden;padding-bottom:.06em}
/* .word groups a word's glyphs into one atomic inline-block so the line can
   only wrap BETWEEN words, never between two adjacent glyph spans (the old
   markup let the browser treat every letter as its own breakable inline box,
   which is what produced the 390px "ventu/res." mid-word split). */
.word{display:inline-block;overflow-wrap:normal;word-break:keep-all}

/* =====================================================================
   instrument primitives
   ===================================================================== */
.bp-grid{position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.5;
  background-image:linear-gradient(rgba(20,17,13,.05) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(20,17,13,.05) 1px,transparent 1px);
  background-size:60px 60px;
  -webkit-mask-image:radial-gradient(ellipse 92% 90% at 50% 40%,#000 38%,transparent 92%);
          mask-image:radial-gradient(ellipse 92% 90% at 50% 40%,#000 38%,transparent 92%);}
.bp-grid.on-ink{background-image:linear-gradient(rgba(242,235,221,.06) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(242,235,221,.06) 1px,transparent 1px);}
.halftone{position:absolute;width:280px;height:280px;z-index:0;opacity:.5;pointer-events:none;
  background-image:radial-gradient(var(--stone-500) 1.4px,transparent 1.5px);background-size:13px 13px;
  -webkit-mask-image:radial-gradient(circle at 70% 30%,#000,transparent 70%);
          mask-image:radial-gradient(circle at 70% 30%,#000,transparent 70%);}
.draw{stroke-dasharray:var(--len,1200);stroke-dashoffset:0}      /* rest = drawn */
.tick{transform-origin:bottom}

/* =====================================================================
   header
   ===================================================================== */
.site-header{position:fixed;top:0;left:0;right:0;z-index:60;
  display:flex;align-items:center;gap:24px;height:84px;padding:0 var(--pad);
  border-bottom:var(--rule);background:rgba(242,235,221,.72);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  transition:transform .4s ease,background .3s ease,color .3s ease}
.brand{display:flex;align-items:center;gap:13px}
.brand .mark{width:34px;height:34px;flex:none}
.brand .wm{font-family:var(--didone);font-weight:700;font-size:25px;line-height:1;color:var(--ink)}
.brand .wm .med{font-family:var(--mono);font-weight:700;font-size:9px;letter-spacing:.22em;
  color:var(--ink-3);vertical-align:middle;margin-left:8px}
.nav{margin-left:auto;display:flex;gap:28px;font-family:var(--mono);font-size:12px;
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2)}
.nav a{position:relative;padding:4px 0;white-space:nowrap}
/* nav underline strike: transform:scaleX (compositor-only) with a small
   overshoot bezier so it reads as struck-in, not wiped-in. */
.nav a::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:1px;
  background:var(--ember-500);transform:scaleX(0);transform-origin:left;
  transition:transform .3s cubic-bezier(.34,1.56,.64,1)}
.nav a:hover::after,.nav a:focus-visible::after{transform:scaleX(1)}
@media (min-width:761px) and (max-width:1024px){
  .nav{gap:16px}
}
/* P5 LOW: "Start a project ->" wrapped to 2 lines at 768. Scoped to the
   header CTA only (not .btn globally — a page-wide nowrap made other .btn
   instances' automatic flex/grid minimum size jump to their full unwrapped
   text width, overflowing narrower containers elsewhere on the page, e.g.
   the feature/contact/catalog CTAs). Tighten padding/gap in this band too
   so the nowrapped label still fits beside the full nav. */
.site-header .btn-primary{white-space:nowrap;flex:none}
@media (min-width:700px) and (max-width:900px){
  .site-header{gap:16px}
  .site-header .btn-primary{padding:11px 14px;font-size:12px;gap:7px}
}
.btn{font-family:var(--sans);font-weight:700;letter-spacing:.01em;
  display:inline-flex;align-items:center;gap:9px;border:none;cursor:pointer}
/* ember-700 fill keeps bone text at WCAG-AA (5.95:1); ember-500 stays the glow */
.btn-primary{background:var(--ember-700);color:var(--bone);
  padding:12px 18px;border-radius:9px;font-size:13px;
  box-shadow:0 10px 26px -12px rgba(215,51,27,.7),inset 0 0 0 1px rgba(215,51,27,.5);
  transition:transform .25s ease,box-shadow .25s ease}
.btn-primary:hover{transform:translateY(-2px);box-shadow:0 16px 32px -12px rgba(215,51,27,.7)}
.btn-lg{padding:16px 26px;border-radius:11px;font-size:15px}
.link-strike{font-family:var(--mono);font-size:13px;letter-spacing:.04em;
  text-decoration:underline;text-underline-offset:6px;text-decoration-color:var(--stone-500)}
.link-strike:hover{text-decoration-color:var(--ember-500)}
/* W-1: mobile menu trigger — hidden by default (desktop has the full text
   nav instead); shown only <=760px, sitting between the brand and CTA. */
.menu-btn{display:none;align-items:center;justify-content:center;
  background:none;border:1px solid rgba(20,17,13,.22);border-radius:7px;
  padding:8px 12px;font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink);cursor:pointer}
.menu-btn:hover{border-color:var(--ember-500)}
@media (max-width:760px){
  .nav{display:none}
  /* F-07: .nav carried the header's only margin-left:auto — with it removed
     from flow at this width the CTA lost its right-alignment and the
     brand+CTA combined width overflowed the fixed header, clipping the
     button past the viewport's right edge. Restore the push here. */
  .site-header .btn-primary{margin-left:auto}
  .menu-btn{display:inline-flex;margin-left:auto}
  .site-header .btn-primary{margin-left:14px}
}
@media (max-width:480px){
  .site-header{gap:10px;padding:0 16px}
  .brand{gap:8px}
  .brand .mark{width:26px;height:26px}
  .brand .wm{font-size:18px}
  .brand .wm .med{display:none}
  .site-header .btn-primary{padding:9px 12px;font-size:11px;gap:6px}
  .menu-btn{padding:7px 10px;font-size:10px}
}

/* mobile nav overlay — full-screen ink panel, bone-on-ink, same mono/didone
   vocabulary as the rest of the page. Not in flow, not painted at >760px. */
.mobile-nav{display:none;position:fixed;inset:0;z-index:250;background:var(--ink);
  color:var(--bone);flex-direction:column;padding:20px var(--pad) 40px;
  opacity:0;pointer-events:none}
.mobile-nav.open{opacity:1;pointer-events:auto}
@media (max-width:760px){
  .mobile-nav{display:flex}
  body.nav-open{overflow:hidden}
}
/* RM: instant show/hide (no transition); motion users get a single <=240ms
   fade so the overlay reads as struck-in rather than popping. */
.no-rm .mobile-nav{transition:opacity .22s ease}
.mobile-nav-top{display:flex;align-items:center;justify-content:space-between;height:64px}
.mobile-nav-mark{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--stone-500)}
.mobile-nav-mark .dia{color:var(--ember-500)}
.mobile-nav .menu-btn-close{color:var(--bone);border-color:rgba(242,235,221,.25)}
.mobile-nav .menu-btn-close:hover{border-color:var(--ember-500)}
.mobile-nav-links{display:flex;flex-direction:column;gap:6px;margin:auto 0;padding:24px 0}
.mobile-nav-links a{font-family:var(--didone);font-weight:700;font-size:clamp(40px,13vw,68px);
  line-height:1.14;color:var(--bone);letter-spacing:-.01em}
.mobile-nav-links a:hover,.mobile-nav-links a:focus-visible{color:var(--ember-500)}
.mobile-nav-cta{align-self:flex-start}
.mobile-nav::after{content:"◆";position:absolute;right:var(--pad);bottom:36px;
  color:var(--ember-500);font-size:16px}

/* =====================================================================
   loader
   ===================================================================== */
.loader{position:fixed;inset:0;z-index:200;background:var(--ink);color:var(--bone);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:22px}
/* BRIEF-J item 2 remould: the STRIKE mark assembles/heats on a coarse pixel
   grid instead of the prior heat-ramp bar. .loader-mark-wrap stacks the
   static bone/ink SVG (immediate paint, no-JS/RM fallback — the "static
   mark" RM variant) under a same-box canvas that JS fills cell-by-cell
   (ink -> ember) on top of it; the canvas paints only the revealed cells so
   the bone silhouette still reads underneath the unrevealed ones. */
.loader-mark-wrap{position:relative;width:64px;height:64px}
.loader-mark-wrap .mark{position:absolute;inset:0;width:64px;height:64px}
.loader-pixel{position:absolute;inset:0;width:100%;height:100%;display:block}
.loader .boot{font-family:var(--mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--stone-500);min-height:1.4em}
.loader.done{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .5s ease,visibility .5s}

/* =====================================================================
   section scaffold
   ===================================================================== */
main{position:relative;z-index:1}
/* F-09: the fixed .site-header (84px, shrinks to 68px on scroll) isn't in
   flow, so a scrollIntoView({block:'start'}) — anchor nav, or a capture
   instrument's per-section jump — aligns the section's own top edge to
   viewport y:0 and the header then sits OVER the first ~84px of section
   content. scroll-margin-top makes the browser reserve that clearance. */
.section{position:relative;padding:clamp(96px,13vh,168px) var(--pad);overflow:hidden;
  scroll-margin-top:96px}
.section.ground-bone{background:var(--bone);color:var(--ink)}
.section.ground-ink{background:var(--ink);color:var(--bone)}
.section.ground-stone{background:linear-gradient(180deg,var(--bone),var(--paper-2))}
.section.ground-ember{background:var(--ember-500);color:var(--bone)}
.section .label{display:flex;align-items:center;gap:14px;margin-bottom:34px}
.section .label .idx{font-family:var(--mono);font-size:var(--fs-micro);letter-spacing:.2em;
  color:var(--ember-700)}
.ground-ink .label .idx,.proof .label .idx,.process .label .idx{color:var(--ember-300)}
.section .label .ln{flex:1;height:1px;background:currentColor;opacity:.18;
  transform-origin:left center}
.on-ink .eyebrow,.ground-ink .eyebrow{color:var(--stone-500)}
.ground-ember .eyebrow,.ground-ember .section-foot{color:var(--ember-50)}

/* display type helpers */
.display{font-family:var(--didone);font-weight:900;line-height:.86;letter-spacing:-.015em}
.display .em{color:var(--ember-500)}
.h1{font-size:var(--fs-h1)}
.h2{font-size:var(--fs-h2)}
.h3{font-size:var(--fs-h3);font-weight:700;line-height:1.02}

/* =====================================================================
   1 · HERO
   ===================================================================== */
.hero{position:relative;min-height:100vh;min-height:100svh;padding:104px var(--pad) 0;
  display:flex;flex-direction:column}
.hero .halftone{right:-40px;top:130px}
.hero .eye{position:relative;z-index:2;display:flex;flex-wrap:wrap;align-items:center;gap:8px 22px;
  margin-top:clamp(20px,4vh,48px);font-family:var(--mono);font-size:var(--fs-micro);
  letter-spacing:.2em;text-transform:uppercase;color:var(--ink-3)}
.hero .eye .ver{margin-left:auto}
/* D3 item 1: reserve horizontal room on the right of the eye row so its
   flex-wrapped content (the "Measured before it ships" badge) never sits
   under the relocated emblem — wraps to a second line instead of colliding. */
@media (min-width:881px){
  .hero .eye{padding-right:clamp(160px,17vw,260px)}
}
/* tablet band (761-880px): the emblem is still absolutely positioned here
   (smaller, see the .emblem media query below) — reserve a smaller matching
   gap so the eye row's right-aligned "Measured before it ships" badge can't
   sit under it either. Below 760px the emblem goes static/inline, so no
   reserve is needed there. */
@media (max-width:880px) and (min-width:761px){
  .hero .eye{padding-right:clamp(130px,18vw,200px)}
}
.hero h1{position:relative;z-index:2;font-family:var(--didone);font-weight:900;
  /* fit-based size: keeps line 2 ("Nothing shipped unmeasured.") from ever
     exceeding the available inline width (100vw - 2*pad) at any viewport, so
     it never clips under white-space:nowrap; 15.2 is the measured worst-case
     rendered scrollWidth/font-size ratio for that line (Bodoni Moda 900,
     -.018em tracking, Playwright-measured at 1440/1024/880/1920 to confirm
     the ratio holds across widths) plus safety margin — recalculated for the
     B-05c headline (longer than the retired "digital ventures." line, hence
     the larger ratio vs. the old 8.2). Still grows with viewport like
     --fs-display, just clamped to what actually fits. */
  font-size:clamp(54px,calc((100vw - 2 * var(--pad)) / 8.22),232px);
  line-height:.84;letter-spacing:-.018em;
  margin-top:clamp(14px,2.6vh,30px);white-space:nowrap}
.hero h1 .l2{margin-left:-.01em}
.hero h1 .em{color:var(--ember-500)}
/* hero headline is fully static per Aditya 2026-08-04 finding: "just let it
   be a static writing" — no entrance animation, no hover color-shift. */
.hero .wave{position:absolute;left:var(--pad);right:0;bottom:30vh;height:150px;z-index:1;
  pointer-events:none;opacity:.9}
.hero .ruler{position:absolute;left:var(--pad);right:var(--pad);bottom:calc(30vh - 22px);
  height:14px;z-index:1;opacity:.65}
/* D3 item 1: decoupled from the emblem's old position — tied to the wave's
   own bottom:30vh instead, with a fixed clearance gap, so it can never drift
   into the relocated emblem's box regardless of viewport height. */
.hero .struck-note{position:absolute;right:calc(var(--pad) + 4px);top:calc(70vh - 160px);z-index:2;
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--ember-500);transform:rotate(90deg);transform-origin:right top}
/* W-4: label for the live frame-time waveform — sits just above the wave
   graphic's own box so it can't collide with the ruler/struck-note band
   below it. Same hide threshold as the wave itself (see the <=1180px rule
   further down) since it has nothing to label once the wave is hidden. */
/* A1 (H2 adjudicated): the caption must sit in the empty band between the
   H1's descender zone and the sparkline stroke. The wave SVG box is
   bottom:30vh, height:150px; the actual ink stroke starts ~20px below the
   SVG box's top edge (the SVG has padding above the waveform path). Place
   the caption's bottom 8px below the wave box's own top edge — this lands
   it in the dead zone inside the SVG, above the visible stroke and below
   the H1. Anchored to the same 30vh + 150px reference the wave uses. */
.hero .wave-caption{position:absolute;left:var(--pad);bottom:calc(30vh + 150px - 10px);z-index:2;
  font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);margin:0}
.hero .lower{position:relative;z-index:2;margin-top:auto;padding:34px 0 56px;
  display:flex;align-items:flex-end;justify-content:space-between;gap:40px;flex-wrap:wrap}
.hero .sub{max-width:42ch;font-size:var(--fs-lede);line-height:1.45;color:var(--ink-2)}
.hero .tag{font-family:var(--mono);font-size:13px;letter-spacing:.03em;color:var(--ember-900);margin-top:18px}
.hero .row{display:flex;align-items:center;gap:26px;margin-top:24px;flex-wrap:wrap}
.scrollcue{position:absolute;left:var(--pad);bottom:20px;z-index:2;font-family:var(--mono);
  font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-3)}

/* lab readout (instrument telemetry card) */
.readout{font-family:var(--mono);font-size:11px;color:var(--ink-3);
  border:1px solid rgba(20,17,13,.18);border-radius:11px;padding:14px 16px;min-width:236px;
  background:rgba(251,247,238,.6);position:relative;overflow:hidden}
.readout .r{display:flex;justify-content:space-between;gap:18px;padding:3px 0;letter-spacing:.06em}
.readout .r b{color:var(--ink)} .readout .ok{color:var(--teal-500)}
.readout .hd{color:var(--ink-2);border-bottom:1px dashed rgba(20,17,13,.2);
  padding-bottom:6px;margin-bottom:6px;letter-spacing:.16em;text-transform:uppercase}
.readout .r.foot{display:block;border-top:1px dashed rgba(20,17,13,.2);
  margin-top:6px;padding-top:8px;font-size:10px;line-height:1.5;color:var(--ink-3);
  letter-spacing:.03em;max-width:26ch}
@media (max-width:880px){
  .hero h1{white-space:normal}
  .hero .readout{display:none}
}
/* F-14 (SA-1/SA-2): .wave/.ruler are anchored off vh (bottom:30vh) and
   .struck-note off a vh-derived top offset, decoupled from the H1's own
   width-driven font-size formula — at 1024/1176 (both >880, so previously
   still shown) the vh math and the H1's actual rendered height diverge
   enough that the ruler hairline strikes the .sub line and the rail
   collides with the H1's final "ventures." glyph/period. Widened the
   existing hide-threshold (already used <=880 for the identical reason)
   up to 1180 so it covers 1024/1176 too; unaffected at 1440+ where the
   original SA-1/2 spot-audit and this pass found both elements clear. */
@media (max-width:1180px){
  .hero .wave,.hero .ruler,.hero .struck-note,.hero .wave-caption{display:none}
}
/* W-6a: with the wave graphic hidden at this width (rule above), the only
   in-flow content between the H1 and .lower was empty space that the
   section's forced min-height:100vh + .lower's margin-top:auto stretched
   into a dead zone (~850px measured at 768; confirmed present 700-1180,
   worst where the emblem is also still out of flow, 761-1180 — but the
   underlying cause, an auto-margin distributing leftover height inside a
   forced full-viewport box, applies across the whole band). Let content
   height govern here instead of forcing a full viewport, with a bounded
   margin standing in for the auto push. Below 1180 the wave never shows
   again (rule above), so there's no motion reason left to reserve a full
   screen of height. */
@media (max-width:1180px){
  .hero{min-height:0}
  .hero .lower{margin-top:clamp(40px,7vh,140px)}
}

/* hero emblem (§5a F1 2D ink-strike fallback) — D3 item 1 RELAYOUT.
   Moved from the old bottom-anchored slot (which collided with the tagline/
   lower row at some viewports) into the dead space to the right of the SHORT
   first H1 line ("We forge"): the H1's nowrap-fit font formula sizes off the
   LONGER second line ("digital ventures."), so line 2 spans nearly the full
   available width — the emblem must stay clear of line 2's vertical band
   entirely and only occupy line 1's row + the gap above it (eye row height),
   which is where "We forge" leaves real dead space on the right. Restored
   toward the intended concept size now that it's out of the tagline's
   column. top is anchored from the hero's own content start (not the H1,
   which shifts with vh-based clamps) so it tracks consistently. */
.emblem{position:absolute;z-index:3;right:var(--pad);top:clamp(70px,9vh,110px);
  width:clamp(180px,16vw,260px);aspect-ratio:1;pointer-events:auto}
.emblem-svg{width:100%;height:100%;overflow:visible}
/* E: GL liquid-metal canvas overlay — sits above the SVG, same size */
.emblem-gl{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;opacity:0;
  border-radius:50%;z-index:1}
.emblem.gl-live .emblem-svg{pointer-events:none}
.emblem.gl-live .emblem-gl{pointer-events:auto}
.no-rm .emblem-mark{opacity:0}
.no-rm .emblem-ring{opacity:0}
@media (max-width:880px){.emblem{width:clamp(110px,15vw,170px);top:clamp(64px,9vh,96px)}}
/* F-06 (wave F): position:static broke the JS-appended .emblem-gl canvas
   (position:absolute;inset:0 inside #emblem resolves against the nearest
   POSITIONED ancestor — with the parent static, that ancestor became .hero
   itself, so the GL canvas filled the whole hero section and covered the H1
   "ventures" line). Fix: keep .emblem position:relative (so its own box is
   the containing block for the GL canvas) and lay it out as its own in-flow
   row between the H1 and the sub-copy (DOM order already places it there),
   right-aligned via the cross-axis auto margin in the .hero column flex. */
@media (max-width:760px){
  .emblem{position:relative;top:auto;right:auto;
    width:clamp(120px,34vw,180px);margin:clamp(10px,3vh,24px) 0 clamp(10px,3vh,24px) auto}
}

/* =====================================================================
   2 · PRESS BAND — three hairline-separated running tracks (§2c)
   ===================================================================== */
.press{overflow:hidden;border-top:var(--rule-ink);border-bottom:var(--rule-ink)}
.press .pb-row{background:var(--bone);color:var(--ink);overflow:hidden;padding:16px 0;
  border-top:1px solid rgba(20,17,13,.14)}
.press .pb-row:first-child{border-top:none}
.press .pb-track{display:flex;gap:0;white-space:nowrap;width:max-content;
  font-family:var(--didone);font-weight:700;font-size:clamp(22px,3.8vw,48px);letter-spacing:-.01em}
.press .pb-track span{padding:0 .5em}
.press .pb-track .sep{color:var(--ember-500);font-family:var(--sans)}
/* row 1 — ink-on-bone, the frozen four verbs */
.no-rm .press .pb-1 .pb-track{animation:marquee 26s linear infinite}
/* row 2 — inverted, bone-on-ink, opposite direction */
.press .pb-row.pb-2{background:var(--ink);color:var(--bone);border-top-color:rgba(242,235,221,.16)}
.press .pb-row.pb-2 .pb-track{font-size:clamp(14px,1.6vw,18px);letter-spacing:.06em;font-family:var(--mono);font-weight:700}
.press .pb-row.pb-2 .pb-track .sep{color:var(--ember-300)}
.no-rm .press .pb-2 .pb-track{animation:marquee-rev 22s linear infinite}
/* row 3 — ghost, ink at 20%, repeats row 1's line */
.press .pb-row.pb-3 .pb-track{color:rgba(20,17,13,.2)}
.press .pb-row.pb-3 .pb-track .sep{color:rgba(215,51,27,.35)}
.no-rm .press .pb-3 .pb-track{animation:marquee 30s linear infinite}
@keyframes marquee{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
@keyframes marquee-rev{from{transform:translate3d(-50%,0,0)}to{transform:translate3d(0,0,0)}}

/* =====================================================================
   3 · MANIFESTO — words thrown to opposite corners
   ===================================================================== */
/* H2 item 2: at >=761px, re-composed as a single diagonal statement — "Fire"
   upper-left + "& Rigor." lower-right in ONE shared composition block (their
   bounding boxes nearly adjacent on a clear diagonal reading axis), with the
   letter-tile widget relocated BELOW the pair rather than wedged between them.
   Grid re-ordered: pairing block → mid (gapline+typecase) → copy.
   Section vertical budget: <=2.2vh at 1440 (was ~2000px gap alone). */
.manifesto{min-height:0;display:flex;flex-direction:column}
.manifesto .display{font-size:clamp(72px,16vw,260px)}
/* the diagonal pairing block — at >=761px, Fire top-left + & Rigor bottom-right
   with their boxes on a clear diagonal, total height ~1.4vh */
.manifesto .pair{display:flex;flex-direction:column;gap:0;
  margin-bottom:clamp(20px,3vh,40px)}
.manifesto .pair .word-tl{align-self:flex-start;text-align:left}
.manifesto .pair .word-br{align-self:flex-end;text-align:right;
  margin-top:clamp(-0.06em,-0.02em,0px)}
@media (min-width:761px){
  .manifesto .pair .word-br{margin-top:clamp(-20px,-1.2vw,-4px)}
}
.manifesto .mid{position:relative;display:flex;align-items:center;justify-content:center;
  padding:clamp(20px,3vh,40px) 0}
.manifesto .gapline{position:relative;width:min(640px,80%);height:1px;background:var(--stone-500)}
.manifesto .gapline .cap{position:absolute;top:-9px;width:1px;height:18px;background:var(--stone-700)}
.manifesto .gapline .cap.l{left:0}.manifesto .gapline .cap.r{right:0}
/* A2 (H2): at <=760px the gapline caption's baseline touched the typecase
   tile row's top border. Raised top:10→6px and the typecase grid gets
   margin-top:18px (below) to guarantee clearance at all widths. */
.manifesto .gapline .read{position:absolute;left:50%;top:6px;transform:translateX(-50%);
  font-family:var(--mono);font-size:var(--fs-micro);letter-spacing:.18em;color:var(--ink-3);
  text-transform:uppercase;white-space:nowrap}
.manifesto .copy{max-width:54ch;margin:clamp(20px,5vh,48px) auto 0;text-align:center;
  font-size:var(--fs-lede);color:var(--ink-2);font-family:var(--mono);line-height:1.7;letter-spacing:.01em}
.manifesto .copy b{color:var(--ink);font-family:var(--sans);font-weight:600}
/* W-3 / H2: mobile (<=760px) — unified left alignment, same as before H2 */
@media (max-width:760px){
  .manifesto .pair .word-tl{align-self:flex-start}
  .manifesto .pair .word-br{align-self:flex-start;text-align:left;margin-top:0}
  .manifesto .mid{align-items:flex-start;justify-content:center}
  .manifesto .typecase{margin:0}
  .manifesto .gapline{margin-left:0}
  .manifesto .tc-hint{text-align:left}
  .manifesto .copy{text-align:left;margin-left:0;margin-right:0}
}

/* type case (§2a) — the manifesto mid ground's strikeable row of sorts */
.manifesto .mid{flex-direction:column;gap:22px}
.manifesto .typecase{position:relative;z-index:1;display:grid;grid-template-columns:repeat(11,1fr);
  width:min(620px,86%);margin:0 auto;border-top:1px solid rgba(20,17,13,.2);
  border-left:1px solid rgba(20,17,13,.2)}
.manifesto .tc-cell{aspect-ratio:1;display:flex;align-items:center;justify-content:center;
  font-family:var(--didone);font-weight:700;font-size:clamp(16px,2.6vw,26px);color:var(--ink);
  background:rgba(20,17,13,0);border:none;border-right:1px solid rgba(20,17,13,.2);
  border-bottom:1px solid rgba(20,17,13,.2);cursor:pointer;padding:0;font-family:inherit}
.manifesto .tc-cell.struck{background:var(--ink);color:var(--bone)}
.manifesto .tc-hint{margin-top:2px;text-align:center;position:relative;font-size:var(--fs-micro);
  letter-spacing:.18em;color:var(--ink-3);text-transform:uppercase}
@media (max-width:620px){.manifesto .typecase{width:100%}
  .manifesto .tc-cell{font-size:15px}}

/* =====================================================================
   4 · THE FORGE — vertical strike list of disciplines
   ===================================================================== */
.forge .head{display:flex;justify-content:space-between;align-items:flex-end;gap:30px;
  flex-wrap:wrap;margin-bottom:clamp(30px,5vh,64px)}
.forge .head .lede{max-width:40ch;font-size:var(--fs-lede);color:var(--ink-2)}
/* G-01.1 — SCALE CAST: Web = master row (full display), others = journeymen
   (0.66x scale, tighter row, spec visible on hover only). */
/* G1-02 — explicit grid: numeral column is a fixed track so it lines up
   across master + journeyman rows; name/spec/kpi stack left-aligned in the
   main column; curve/disc sits right-aligned, vertically centered across
   both rows. Fixes the old auto/1fr/auto 3-col template silently wrapping
   the 4th flow item (spec-wrap) onto an implicit row under the numeral. */
.disc{display:grid;grid-template-columns:56px 1fr auto;grid-template-rows:auto auto;
  grid-template-areas:"num name curve" "num spec curve";
  align-items:start;column-gap:clamp(18px,4vw,40px);row-gap:6px;
  padding:clamp(22px,3.4vh,40px) 0;border-top:var(--rule);position:relative}
.disc:last-child{border-bottom:var(--rule)}
.disc .num{grid-area:num;font-family:var(--mono);font-size:13px;color:var(--ink-3);
  letter-spacing:.1em;padding-top:.3em}
.disc .name{grid-area:name;font-family:var(--didone);font-weight:900;font-size:clamp(40px,7vw,108px);
  line-height:.9;letter-spacing:-.02em;text-align:left;transition:color .3s ease}
.disc .curve{grid-area:curve;align-self:center}
/* journeyman rows: scaled down */
.disc-journeyman .name{font-size:clamp(28px,4.6vw,72px)}
.disc-journeyman{padding:clamp(14px,2.2vh,26px) 0}
.disc-journeyman .spec-wrap{opacity:0;transition:opacity .25s ease}
.no-rm .disc-journeyman:hover .spec-wrap,.disc-journeyman:focus-within .spec-wrap{opacity:1}
/* master row: full size, spec always visible */
.disc-master .name{font-size:clamp(48px,8vw,120px)}
.disc .spec-wrap{grid-area:spec;display:flex;flex-direction:column;align-items:flex-start;
  gap:6px;max-width:46ch}
.disc .spec{font-family:var(--mono);font-size:13px;color:var(--ink);text-align:left;
  letter-spacing:.03em;line-height:1.5}
.disc .kpi{position:relative;font-family:var(--mono);font-size:12px;color:var(--ink-3);text-align:left;
  letter-spacing:.02em;line-height:1.45}
/* spec line reveal: an underline strikes in under the KPI line on hover —
   compositor-only (transform:scaleX), text itself never toggles visibility
   so RM/no-JS keeps the finished static state. */
.disc .kpi::after{content:"";position:absolute;right:0;bottom:-5px;left:0;height:1px;
  background:var(--ember-500);transform:scaleX(0);transform-origin:right;
  transition:transform .32s cubic-bezier(.3,.9,.3,1)}
.disc:hover .kpi::after,.disc:focus-within .kpi::after{transform:scaleX(1);transform-origin:left}
.disc .curve{width:64px;height:40px;flex:none}
.disc:hover .name{color:var(--ember-500)}
/* instrument rows (§2b) — ember roller-fill on hover, proofed tick on click */
.disc>*{position:relative;z-index:1}
.disc .ember-plane{position:absolute;inset:0;z-index:0;background:var(--ember-500);
  transform:scaleX(0);transform-origin:left;pointer-events:none}
/* D3 item 4 — ambient warm drift: a very faint, independent wash (NOT the D2
   liquid-fill mechanism above, left untouched) that breathes while the
   section is on screen. Base opacity kept low (.35) so "0.9-1.1x of current"
   reads as a subtle pulse, never a flat colour block. */
.disc .ember-ambient{position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(90deg,rgba(215,51,27,.14),transparent 62%);opacity:.35}
@keyframes emberAmbientBreathe{0%,100%{opacity:.315}50%{opacity:.385}}
.no-rm .disc-list.in-view .ember-ambient{animation:emberAmbientBreathe 9s ease-in-out infinite}
.disc .magma-canvas{position:absolute;inset:0;z-index:0;pointer-events:none;display:block}
.disc.covered .num,.disc.covered .name,.disc.covered .spec,.disc.covered .kpi{color:var(--ink) !important}
.disc .proof-tick{position:absolute;right:2px;top:6px;z-index:2;font-size:12px;color:var(--ember-500);
  opacity:0;pointer-events:none}
.disc.proofed .proof-tick{opacity:1}
@media (max-width:760px){
  /* W-5 (S04, item 4a): a single word + one caption line was costing
     22-40px of vh-scaled padding per edge — at 5 rows that's most of the
     mobile "10 screens of scroll" complaint. Tightened to ~50-55% of the
     prior clamp ranges; type sizes (name/spec/kpi) are untouched so the
     hierarchy still reads the same, just paced tighter. */
  .disc{grid-template-columns:40px 1fr;grid-template-areas:"num name" "num spec";
    gap:10px;row-gap:4px;padding:clamp(12px,1.8vh,20px) 0}
  .disc-master{padding:clamp(13px,2vh,22px) 0}
  .disc-journeyman{padding:clamp(8px,1.2vh,13px) 0}
  .disc .curve{display:none}
  .disc .spec-wrap{display:flex;flex-direction:column;
    align-items:flex-start;gap:4px;max-width:100%;margin-top:0}
  .disc .spec{text-align:left;font-size:12px}
  .disc .kpi{text-align:left;font-size:11px}
}

/* emerging band — a sub-band inside 01/THE FORGE, deliberately NOT numbered
   as its own top-level section (the deck's D-11 "06/EMERGING" would collide
   with the page's real top-level count of four numbered sections: 01 THE
   FORGE, 02 PROOF, 03 THE CATALOG, 04 THE STRIKE). */
.emerging{border-top:var(--rule);padding:clamp(30px,4.4vh,52px) 0 0;margin-top:clamp(8px,2vh,18px)}
.emerging .em-label{font-size:var(--fs-micro);letter-spacing:.24em;text-transform:uppercase;
  color:var(--ember-700);margin-bottom:16px}
.emerging .em-h{font-family:var(--didone);font-weight:700;font-size:clamp(28px,4.2vw,58px);
  line-height:1.02;margin-bottom:16px;max-width:16ch}
.emerging .em-body{max-width:62ch;font-size:var(--fs-body);color:var(--ink-2);line-height:1.6}
/* F-13: --stone-700 on --bone measured 3.13:1 (axe serious, needs 4.5:1 at
   this 11px size); --ink-3 measures 5.07:1 — same quiet mono register. */
.emerging .em-kpi{font-family:var(--mono);font-size:11px;color:var(--ink-3);letter-spacing:.04em;
  line-height:1.6;max-width:62ch}

/* D3 item 5 — the SPLIT: a literal two-pane composition replacing the old
   plain text block. Left = SERP skeleton (ink hairlines), right = generated-
   answer skeleton (bone card, AI chip, looping type-on lines), sheared apart
   by a vertical ember hairline that responds to scroll progress. */
.emerging .em-split{position:relative;display:grid;grid-template-columns:1fr 1fr;
  gap:0;min-height:200px;margin:clamp(20px,3.4vh,32px) 0 4px;border:var(--rule);border-radius:14px;
  overflow:hidden}
.emerging .em-pane{position:relative;padding:26px 32px;display:flex;flex-direction:column;
  justify-content:center;gap:13px}
/* G-01.2 — Emerging re-skinned into proof-sheet vocabulary: bone panes with
   ink rules and mono type; no foreign grey browser-chrome. Registration marks
   at corners; the AI-answer pane retains its type-on (MEASURED). */
.emerging .em-pane-serp{background:var(--bone);border:1px solid rgba(20,17,13,.12);position:relative}
.emerging .em-reg-mark{position:absolute;top:8px;right:10px;font-size:9px;color:var(--ember-500);opacity:.5}
.emerging .em-serp-row{height:9px;border-radius:0;background:rgba(20,17,13,.18)}
.emerging .em-serp-row.em-serp-title{width:58%;height:12px;background:rgba(20,17,13,.32)}
.emerging .em-serp-row.em-serp-url{width:34%;background:rgba(20,17,13,.14)}
.emerging .em-serp-row.em-serp-snippet{width:86%}
.emerging .em-serp-row.em-serp-snippet.short{width:52%}
/* G1-03 — bone proof-sheet ground restored (was a solid-black panel); the
   generated-answer lines are ink hairline rules, matching the SERP pane's
   press vocabulary, with the AI chip ink-on-bone + ember diamond. */
.emerging .em-pane-answer{background:var(--bone);border-left:1px solid rgba(20,17,13,.12)}
.emerging .em-ai-chip{align-self:flex-start;color:var(--ink);border:1px solid rgba(20,17,13,.3);
  border-radius:20px;padding:3px 11px;font-size:10px;letter-spacing:.16em;margin-bottom:2px}
.emerging .em-ai-chip .dia{font-size:9px}
.emerging .em-answer-line{height:9px;border-radius:2px;background:rgba(20,17,13,.18)}
.emerging .em-answer-line.l1{width:84%}
.emerging .em-answer-line.l2{width:66%}
.emerging .em-answer-line.l3{width:40%}
.emerging .em-shear{position:absolute;left:50%;top:0;bottom:0;width:1px;transform:translateX(-50%);
  z-index:2;pointer-events:none}
.emerging .em-shear i{position:absolute;left:-1px;width:3px;background:var(--ember-500);display:block}
.emerging .em-shear-top{top:0;height:50%}
.emerging .em-shear-bottom{bottom:0;height:50%}
.emerging .em-copy-row{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,4vw,56px);
  margin-top:18px}
@media (max-width:760px){
  .emerging .em-split{grid-template-columns:1fr}
  .emerging .em-pane-answer{border-left:none;border-top:var(--rule)}
  .emerging .em-shear{display:none}
  .emerging .em-copy-row{grid-template-columns:1fr;gap:16px}
}

/* 4f · FEATURE — Product & Apps (the differentiator)
   ground = ember-700 (deep heat) so bone body text clears AA (5.95:1). */
.feature{background:var(--ember-700);color:var(--bone);position:relative}
.feature .bp-grid{opacity:.2;-webkit-mask-image:none;mask-image:none;
  background-image:linear-gradient(rgba(20,17,13,.16) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(20,17,13,.16) 1px,transparent 1px)}
.feature .wrap{position:relative;z-index:2;display:grid;grid-template-columns:1.2fr .8fr;
  gap:clamp(30px,5vw,72px);align-items:center}
.feature h2{font-family:var(--didone);font-weight:900;font-size:clamp(48px,8.5vw,150px);
  line-height:.88;letter-spacing:-.02em;color:var(--bone)}
.feature .kicker{color:var(--hot)}
.feature p{max-width:42ch;margin-top:24px;font-size:var(--fs-lede);color:var(--bone)}
.feature .row{margin-top:30px;display:flex;gap:22px;align-items:center;flex-wrap:wrap}
.feature .btn-primary{background:var(--ink);color:var(--bone);box-shadow:0 12px 28px -14px rgba(0,0,0,.6)}
.feature .link-strike{color:var(--hot);text-decoration-color:var(--ember-100)}
/* gate-run inspection tag (§5b — press-room tag, bone card, ink mono) */
.term{font-family:var(--mono);font-size:12px;background:var(--paper-0);color:var(--ink);
  border-radius:8px;padding:20px 22px;line-height:1.85;border:1px solid rgba(20,17,13,.18);
  box-shadow:none;position:relative}
.term .tt{display:block;margin-bottom:12px;padding-bottom:10px;
  border-bottom:1px solid rgba(20,17,13,.12);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3)}
.term .ln{display:flex;gap:10px;flex-wrap:wrap}
.term .ln .p{color:var(--ember-700)}
.term .ok{color:var(--teal-500)}
.term .hl{color:var(--ink-3);font-weight:700}
/* W-6b: line-breaks inside a command/status token break the "real terminal
   output" illusion (a real shell never wraps mid-token) — e.g.
   "build.technical-floor" splitting after the hyphen, or "PASS (8/8" /
   "applicable)" splitting inside the parenthetical. Only the specific
   atomic tokens are kept nowrap (.tok) — the surrounding prose (WARN ·
   out-of-scope, etc.) still wraps normally, so a long multi-word status
   line can't force the whole card wider than its column (that blanket-
   nowrap approach was tried and caused a real horizontal-overflow
   regression on #feature at narrow widths — narrowed to just the tokens
   that actually need it). */
.term .tok{white-space:nowrap}
@media (max-width:420px){
  .term{font-size:10.5px}
}
.replay-btn{display:inline-flex;align-items:center;gap:4px;background:none;border:none;
  cursor:pointer;font-size:10px;letter-spacing:.14em;color:var(--ink-3);
  text-transform:uppercase;padding:8px 0 0;margin-top:10px}
.replay-btn:hover{color:var(--ink)}
.no-rm .replay-btn{opacity:0}
@media (max-width:880px){.feature .wrap{grid-template-columns:1fr}}

/* =====================================================================
   5 · VERIFIED, NOT VIBED — instrument dashboard (PROOF)
   ===================================================================== */
.proof{background:var(--ink);color:var(--bone)}
.proof .head{display:grid;grid-template-columns:1fr auto;gap:30px;align-items:end;
  margin-bottom:clamp(34px,6vh,72px)}
.proof h2{font-family:var(--didone);font-weight:700;font-size:clamp(34px,5vw,72px);
  line-height:.96;letter-spacing:-.01em}
.proof h2 .em{color:var(--ember-500)}
/* G-04 — PROOF section: teal KILLED; dial instrument faces; bone card surfaces
   with hairline rules; stamp as circular press stamp. */
.proof .grid-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.gauge{border:1px solid rgba(242,235,221,.12);border-radius:8px;padding:22px;
  background:var(--bone);position:relative;overflow:hidden;color:var(--ink)}
.gauge-dial{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px}
.gauge .dial{width:80px;height:56px;margin-bottom:4px}
.gauge .dial-needle{transform-origin:50px 60px}
.gauge .k{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3)}
.gauge .v{font-family:var(--didone);font-weight:900;font-size:clamp(44px,5.5vw,76px);
  line-height:1;margin:6px 0 4px;color:var(--ink)}
.gauge .v .u{font-family:var(--mono);font-size:14px;color:var(--ink-3);margin-left:4px}
.gauge .v.pending{font-size:clamp(14px,1.8vw,20px);font-weight:700;
  letter-spacing:.08em;color:var(--ink-3)}
.gauge .v.ok{color:var(--teal-500)}
.gauge .st{font-family:var(--mono);font-size:10px;color:var(--ink-3);letter-spacing:.06em;
  line-height:1.4;margin-top:4px}
/* G-04.3 — stamp card as circular press stamp */
.gauge-stamp{display:flex;flex-direction:column;justify-content:center;align-items:center;
  text-align:center;border-color:rgba(242,235,221,.12);gap:4px;position:relative}
.stamp-seal{width:100px;height:100px}
.stamp-text-top,.stamp-text-bot{font-family:var(--mono);font-size:7px;letter-spacing:.14em;
  fill:rgba(20,17,13,.6);text-transform:uppercase}
.stamp-center{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  color:var(--ember-500);font-size:14px}
.proof .foot{margin-top:26px;font-family:var(--mono);font-size:12px;color:var(--stone-500);
  letter-spacing:.04em;display:flex;gap:10px;align-items:center}
/* registration field (§4) — printer's alignment dots, behind proof content */
.reg-field{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.reg-dot{position:absolute;width:2px;height:2px;border-radius:50%;
  background:rgba(242,235,221,.07);transform:translate(-1px,-1px)}
/* guarantee content stacks above both background layers (bp-grid + reg-field
   are position:absolute z-index:0, which — per CSS stacking rules — would
   otherwise paint ABOVE static in-flow siblings regardless of DOM order) */
.proof>.label,.proof>.head,.proof>.grid-cards,.proof>.foot{position:relative;z-index:1}
@media (max-width:880px){.proof .grid-cards{grid-template-columns:repeat(2,1fr)}}

/* =====================================================================
   6 · THE CATALOG — pinned horizontal gallery
   ===================================================================== */
/* W-7 partial (S08 trim): the full-scale headline over 2 rows read thin
   against genuinely thin content underneath (one real client, one open
   slot) — tightening section padding + headline scale one notch narrows
   that type-to-content ratio without touching the content itself. */
.catalog{padding-bottom:0;padding-top:clamp(72px,9.6vh,132px)}
.catalog .head{margin-bottom:clamp(22px,3.4vh,44px)}
.catalog .head h2{font-size:clamp(32px,5.1vw,82px)}
/* G-02 — FORGE REGISTER: two ledger lines replace the horizontal card rail.
   Below the register: one featured spec sheet (ValTech), one expandable
   open-slot conversion device. */
.forge-register{border-top:var(--rule);border-bottom:var(--rule);margin-bottom:clamp(24px,4vh,48px)}
.reg-line{display:flex;align-items:baseline;gap:clamp(10px,2vw,24px);padding:clamp(14px,2vh,22px) 4px;
  border-bottom:var(--rule);font-family:var(--mono);font-size:clamp(12px,1.4vw,16px);
  letter-spacing:.08em;text-transform:uppercase;color:var(--ink)}
.reg-line:last-child{border-bottom:none}
.reg-num{color:var(--ember-700);font-weight:700}
.reg-name{font-family:var(--didone);font-weight:700;font-size:clamp(18px,2.6vw,30px);
  letter-spacing:-.01em;text-transform:none}
.reg-tags{color:var(--ink-3);font-size:clamp(10px,1.2vw,13px)}
.reg-date{color:var(--ink-3);font-size:clamp(10px,1.2vw,13px)}
.reg-sep{color:var(--stone-300);font-size:10px}
/* line 2 = conversion device */
.reg-line-2{cursor:pointer;transition:background .2s ease}
.no-rm .reg-line-2:hover,.reg-line-2:focus-visible{background:rgba(20,17,13,.03)}

/* ValTech featured spec sheet */
.vt-spec{background:var(--bone);border:var(--rule);border-radius:6px;padding:clamp(20px,3vw,36px);
  margin-bottom:clamp(20px,3vh,36px)}
.vt-spec-head{display:flex;align-items:baseline;gap:14px;margin-bottom:12px}
.vt-spec-head h3{font-family:var(--didone);font-weight:700;font-size:clamp(22px,3vw,36px);line-height:1}
.vt-stamp{color:var(--ember-500);font-size:14px}
.vt-tags{font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--ink-3)}
.vt-spec-body{max-width:60ch}
.vt-desc{font-size:var(--fs-lede);color:var(--ink-2);line-height:1.6}

/* open-slot expansion (G-02.3) */
.reg-open-slot{display:none;overflow:hidden}
.reg-open-slot.expanded{display:block}
.reg-proof-sheet{position:relative;background:var(--bone);border:1px dashed rgba(20,17,13,.2);
  border-radius:6px;padding:clamp(24px,3vw,40px);text-align:center}
.reg-sheet-mark{position:absolute;top:10px;left:12px;color:var(--ember-500);font-size:10px;opacity:.4}
.reg-sheet-mark-br{top:auto;left:auto;bottom:10px;right:12px}
.reg-sheet-title{font-family:var(--didone);font-weight:700;font-size:clamp(20px,3vw,32px);
  color:var(--ink-3);border-bottom:2px dotted rgba(20,17,13,.2);display:inline-block;
  padding-bottom:4px;margin-bottom:16px}
.reg-sheet-cta{font-size:var(--fs-lede);color:var(--ink-2);max-width:44ch;margin:0 auto 20px}
@media (max-width:620px){.reg-line{flex-wrap:wrap;gap:6px 10px}}

/* =====================================================================
   7 · THE STRIKE (process) — scroll spine
   ===================================================================== */
.process{background:var(--ink);color:var(--bone);position:relative}
.process .head{margin-bottom:clamp(30px,6vh,70px)}
.process h2 .em{color:var(--ember-500)}
.spine{position:relative;display:grid;gap:clamp(30px,6vh,72px);
  --rn-gutter:clamp(40px,7vw,120px);padding-left:var(--rn-gutter)}
.spine .rail{position:absolute;left:clamp(18px,3vw,54px);top:6px;bottom:6px;width:1px;
  background:var(--edge)}
.spine .rail i{position:absolute;left:-1px;top:0;width:3px;height:0;background:var(--ember-500);
  box-shadow:0 0 16px 2px rgba(215,51,27,.6)}      /* JS scrubs height */
.no-rm .spine .rail i{height:0}
/* ember-head: a bright tip riding at the leading edge of the fill, JS scrubs
   `top` in lockstep with the fill's `height` (same trigger/scrub config). */
.spine .rail .head{position:absolute;left:50%;top:0;width:8px;height:8px;border-radius:50%;
  background:var(--hot);transform:translate(-50%,-50%);
  box-shadow:0 0 14px 4px rgba(215,51,27,.75);opacity:0}
.no-rm .spine .rail .head{opacity:1}
.step{position:relative}
/* rn font-size is derived from the gutter (--rn-gutter) rather than its own
   independent vw clamp: the two used to drift apart at desktop/mid widths,
   letting the widest numeral ("III", ~1.42x its own font-size in rendered
   width) overrun the gutter and collide with .tagm/h3. Dividing the gutter
   by 1.65 keeps III inside the gutter with margin at every width. */
.step .rn{font-family:var(--didone);font-weight:900;
  font-size:clamp(28px,calc(var(--rn-gutter) / 1.65),64px);
  line-height:.9;color:var(--stone-700);position:absolute;left:calc(-1 * var(--rn-gutter));
  width:var(--rn-gutter);text-align:left;
  /* D3 item 8 — mask the rail behind the numeral: an opaque plate matching
     the section ground (ink) sized to the numeral's own box, which already
     spans the rail's x-position (0..rn-gutter) — so the rail visibly passes
     BEHIND the plate rather than through the glyph strokes. */
  background:var(--ink);padding:3px 10px 3px 0;z-index:1}
.no-rm .step .rn{transition:color .3s ease}
.step.active .rn{color:var(--ember-500)}
@media (max-width:760px){
  .step .rn{background:none;padding:0}
}
.step h3{font-family:var(--didone);font-weight:700;font-size:clamp(28px,4vw,56px);
  line-height:1;margin-bottom:12px}
.step p{max-width:54ch;color:var(--stone-300);font-size:var(--fs-lede)}
/* G-05 — step III climax: numeral one step larger, ember-tinted plate;
   quality-membrane list as four struck sub-rows */
.step-climax .rn-climax{font-size:clamp(36px,calc(var(--rn-gutter) / 1.3),80px);
  color:var(--ember-500);background:var(--ink)}
.strike-sub-rows{display:flex;flex-wrap:wrap;gap:8px 16px;margin-top:14px}
.strike-sub{font-size:11px;letter-spacing:.1em;color:var(--bone);
  border-bottom:1px solid var(--ember-500);padding-bottom:2px}
.step .tagm{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ember-300);margin-bottom:14px;display:block}
@media (max-width:760px){
  /* static/stacked: no gutter collision possible, so numeral goes back to its
     own (larger) size rather than the gutter-derived one used above 760px */
  .step .rn{position:static;display:block;margin-bottom:6px;width:auto;
    font-size:clamp(40px,10vw,72px)}
  .spine{padding-left:18px}.spine .rail{left:2px}}

/* =====================================================================
   7c · THE FLOOR — glyph field (D3 item 3), full-bleed night-floor band
   between the quench band and contact.
   ===================================================================== */
.floor-glyphs{position:relative;height:70vh;min-height:420px;max-height:760px;
  background:var(--ink);overflow:hidden;border-top:var(--rule-ink);border-bottom:var(--rule-ink)}
.floor-canvas{display:block;width:100%;height:100%}
.no-rm .floor-canvas{opacity:0;transition:opacity 2s ease}
.no-rm .floor-glyphs.in-view .floor-canvas{opacity:1}
/* F-10: rgba(...,.3) read as low-contrast against --ink at rest; raised to
   .68 (still a quiet label, not a heat accent) for legibility. */
.floor-label{position:absolute;left:var(--pad);bottom:18px;z-index:1;
  font-size:10px;letter-spacing:.18em;color:rgba(242,235,221,.68);text-transform:uppercase}
@media (max-width:620px){.floor-glyphs{height:56vh;min-height:320px}}

/* =====================================================================
   8 · CONTACT — bring us raw material
   ===================================================================== */
.contact{background:var(--ember-700);color:var(--bone);position:relative}
/* G-03.1 — "Start a project" demoted to section eyebrow (mono, small, ember dia prefix).
   "Tell us what you're building." is the only colossal heading. */
.contact-eyebrow{font-size:var(--fs-micro);letter-spacing:.22em;text-transform:uppercase;
  color:var(--ember-50);text-align:center;margin-bottom:12px;display:flex;
  align-items:center;justify-content:center;gap:8px}
.contact-eyebrow .dia{font-size:9px;color:var(--ember-300)}
/* G1-04 — one size step down + a wider measure so the ruled break ("Tell us
   what" / "you're building.") actually renders as 2 lines at 1440/1176/1024
   instead of each word wrapping to its own line. */
.contact h2{font-family:var(--didone);font-weight:900;font-size:clamp(34px,5.6vw,108px);
  text-align:center;line-height:.94;letter-spacing:-.02em;color:var(--bone);
  margin:6px 0 clamp(28px,3.6vw,48px);max-width:96%;margin-left:auto;margin-right:auto}
.contact .sub{text-align:center;max-width:48ch;margin:0 auto;color:var(--bone);
  font-size:var(--fs-lede)}
.contact .mail-first{text-align:center;max-width:52ch;margin:14px auto 0;color:var(--ember-50);
  font-family:var(--mono);font-size:12.5px;line-height:1.6;letter-spacing:.02em}
.contact .mail-first a{text-decoration:underline;text-underline-offset:4px;color:var(--hot)}
/* G-03.2 — JOB TICKET: bone card, ink hairline field rules, mono uppercase labels,
   registration mark + ticket number top-right, dotted tear-off rule above submit.
   "Strike ->" submit performs a press strike: scale 1.06->1 back.out + ink ring. */
.ticket{max-width:660px;margin:clamp(36px,6vh,64px) auto 0;background:var(--bone);
  border:1px solid rgba(20,17,13,.18);border-radius:8px;padding:clamp(24px,3.6vw,40px);
  position:relative;color:var(--ink)}
.ticket-head{display:flex;justify-content:space-between;align-items:center;
  margin-bottom:20px;padding-bottom:14px;border-bottom:1px solid rgba(20,17,13,.12)}
.ticket-num{font-size:11px;letter-spacing:.14em;color:var(--ink-3)}
.ticket-reg{color:var(--ember-500);font-size:12px}
.ticket form{display:grid;gap:16px}
.ticket .row2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.ticket .field{display:flex;flex-direction:column;gap:6px}
.ticket .field label{font-family:var(--mono);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3)}
.ticket .field input,.ticket .field textarea{font-family:var(--mono);font-size:14px;
  color:var(--ink);background:transparent;border:none;border-bottom:1px solid rgba(20,17,13,.2);
  border-radius:0;padding:10px 0;width:100%}
.ticket .field input::placeholder,.ticket .field textarea::placeholder{color:var(--stone-500)}
.ticket .field input:focus,.ticket .field textarea:focus{outline:none;
  border-bottom-color:var(--ember-500)}
.ticket-tear{border-top:2px dotted rgba(20,17,13,.18);margin:12px 0 8px}
.ticket-submit{justify-self:center;margin-top:4px;background:var(--ink);color:var(--bone);
  padding:15px 36px;border-radius:8px;font-family:var(--sans);font-weight:700;font-size:16px;
  cursor:pointer;border:none;display:inline-flex;gap:10px;align-items:center;
  transition:transform .15s ease}
.no-rm .ticket-submit:hover{transform:translateY(-2px)}
.contact .submit-msg{text-align:center;max-width:46ch;font-family:var(--mono);
  font-size:12.5px;color:var(--ink-3);letter-spacing:.02em;line-height:1.5;margin:8px auto 0}
.contact .submit-fallback{text-align:center;font-family:var(--mono);
  font-size:11px;color:rgba(20,17,13,.45);letter-spacing:.03em;margin-top:4px}
@media (max-width:620px){.ticket .row2{grid-template-columns:1fr}}

/* =====================================================================
   9 · FOOTER
   ===================================================================== */
.site-footer{background:var(--ink);color:var(--stone-500);padding:clamp(56px,8vh,96px) var(--pad) 40px;
  font-family:var(--mono);font-size:12px;letter-spacing:.04em}
.site-footer .top{display:flex;justify-content:space-between;gap:40px;flex-wrap:wrap;
  padding-bottom:34px;border-bottom:var(--rule-ink)}
.site-footer .big{font-family:var(--didone);font-weight:900;font-size:clamp(48px,9vw,140px);
  line-height:.86;color:var(--bone);letter-spacing:-.02em}
.site-footer .big .em{color:var(--ember-500)}
/* title block (§2d) — footer construction drawing beside the wordmark */
.title-block{flex:none;width:clamp(150px,14vw,210px);align-self:flex-start}
.title-block .tb-svg{width:100%;height:auto;overflow:visible}
.title-block .tb-line{stroke:rgba(242,235,221,.4);stroke-width:1.2;fill:none;transition:stroke .2s ease;cursor:default}
.title-block .tb-line:hover{stroke:var(--ember-500)}
.title-block .tb-tick{stroke:rgba(242,235,221,.4);stroke-width:1.2}
.title-block .tb-label{font-family:var(--mono);font-size:8px;letter-spacing:.05em;
  fill:rgba(242,235,221,.75);transition:fill .2s ease;cursor:default}
.title-block .tb-label:hover{fill:var(--ember-500)}
.title-block .tb-cap{margin-top:8px;font-size:10px;letter-spacing:.18em;color:var(--stone-500);
  text-align:right;text-transform:uppercase}
@media (max-width:760px){.title-block{width:120px}}
.site-footer .cols{display:flex;gap:clamp(30px,6vw,80px);flex-wrap:wrap}
.site-footer .cols h3{color:var(--stone-300);text-transform:uppercase;letter-spacing:.16em;
  font-size:10px;font-weight:700;margin-bottom:14px}
.site-footer .cols a{display:block;padding:5px 0;color:var(--stone-500)}
.site-footer .cols a:hover{color:var(--ember-300)}
.site-footer .bot{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;
  padding-top:26px;color:var(--stone-700);text-transform:uppercase;letter-spacing:.12em;font-size:10px}
/* teal-500 fails on ink; teal-300 reads as "verified" and clears AA */
.site-footer .verified,.ground-ink .verified,.proof .verified{color:var(--teal-300)}
.site-footer .verified::before,.ground-ink .verified::before,.proof .verified::before{background:var(--teal-300)}

/* =====================================================================
   cursor (burin) — desktop pointer only
   ===================================================================== */
.burin{position:fixed;top:0;left:0;width:14px;height:14px;z-index:300;pointer-events:none;
  mix-blend-mode:difference;transform:translate3d(-100px,-100px,0);will-change:transform}
.burin svg{width:100%;height:100%;transition:transform .22s cubic-bezier(.3,.9,.3,1)}
@media (hover:none),(pointer:coarse){.burin{display:none}}

/* burin per-context states (F3) — transform-only swaps on the inner svg (or
   a pseudo-ring for the loupe), so the fixed-position tween driving x/y in
   JS is never touched. State classes are additive on #burin, set by JS. */
.burin.--link svg{transform:rotate(18deg) scale(1.15)}
.burin.--cta svg{transform:rotate(-14deg) scale(1.35)}
.burin.--nib svg{transform:scaleX(.42) scaleY(1.9) rotate(0deg)}
.burin.--drag svg{transform:rotate(90deg) scaleX(1.5) scaleY(.85)}
.burin.--loupe svg{opacity:0;transform:scale(.4)}
/* ::after ring exists at all times (hidden/collapsed by default) so the
   loupe reveal can transition in, rather than popping a freshly-created
   pseudo-element straight to its final state. */
.burin::after{content:"";position:absolute;inset:-12px;border:1.5px solid var(--bone);
  border-radius:50%;opacity:0;transform:scale(.4);
  transition:opacity .22s ease,transform .22s cubic-bezier(.3,.9,.3,1)}
.burin.--loupe::after{opacity:1;transform:scale(1)}

/* =====================================================================
   5c · SLASH DIVIDER — unpinned section between PROOF and THE CATALOG
   ===================================================================== */
.slash{position:relative;min-height:55vh;overflow:hidden;background:var(--bone);
  /* D3 item 7: clip guaranteed at the section box regardless of amplified
     scroll travel, so the wider shear/shift range below can never spill a
     horizontal scrollbar at narrow viewports. */
  display:flex;flex-direction:column;align-items:stretch;justify-content:center;
  padding:clamp(40px,8vh,80px) 0}
.slash-bar{position:absolute;left:-8%;right:-8%;top:50%;height:56px;background:var(--ember-500);
  transform:translateY(-50%) rotate(-1deg);transform-origin:center center;z-index:0;will-change:transform}
.slash-word{position:relative;z-index:1;font-family:var(--didone);font-weight:900;
  letter-spacing:-.02em;line-height:.88;color:var(--ink);font-size:clamp(44px,8.6vw,132px);
  padding:0 var(--pad);will-change:transform}
.sw-tl{align-self:flex-start;text-align:left}
.sw-br{align-self:flex-end;text-align:right;margin-top:clamp(20px,6vh,60px)}
@media (max-width:620px){.slash{min-height:40vh}.slash-bar{height:36px}}

/* =====================================================================
   2g · THE SPEC BOOK — Forge section, beneath disciplines + emerging band
   ===================================================================== */
.specbook{border-top:var(--rule);padding-top:clamp(30px,4.4vh,52px);margin-top:clamp(24px,4vh,44px)}
.sb-label{font-size:var(--fs-micro);letter-spacing:.24em;text-transform:uppercase;
  color:var(--ember-700);margin-bottom:22px}

/* D3 item 6 — PLAN-CHEST / flat-file drawer rework. The rotated-card spread
   (kept above as historical record in this comment) is replaced with a flat,
   legible index ledger: full-width rows, no rotation, no card clutter,
   hairline rules between rows — architectural rather than "bench spread". */
.sb-ledger{display:flex;flex-direction:column;width:100%;padding:2px 0 0;
  border-top:var(--rule)}
/* G-01.3 — drawer fronts: thin top-edge highlight + pull-notch at right */
.sb-row{position:relative;display:grid;grid-template-columns:auto 1fr auto;
  align-items:baseline;column-gap:clamp(14px,2.4vw,32px);width:100%;text-align:left;
  font:inherit;color:var(--ink);background:none;border:none;border-bottom:var(--rule);
  border-top:1px solid rgba(242,235,221,.6);
  cursor:pointer;padding:16px 4px;overflow:hidden}
.no-rm .sb-row{transition:transform .22s ease}
.sb-row-head{display:flex;align-items:baseline;gap:16px;min-width:0}
.sb-row .sb-num{font-family:var(--mono);font-size:11px;letter-spacing:.08em;color:var(--ember-700);flex:none}
.sb-row .sb-h{font-family:var(--didone);font-weight:700;font-size:clamp(16px,2vw,22px);
  line-height:1.1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sb-row .sb-spec{font-family:var(--mono);font-size:11.5px;line-height:1.5;color:var(--ink-2);
  opacity:.6;text-align:right;justify-self:end;max-width:38ch}
/* G-01.3 — drawer-front pull notch: the tick becomes a small pull-notch glyph
   at right. Visible at rest (drawer closed); rotates on open. */
.sb-row .sb-pull{color:var(--ink-3);font-size:11px;opacity:.5;transition:transform .22s ease}
.sb-row.open .sb-pull{transform:rotate(180deg);opacity:1;color:var(--ember-500)}
/* hover (PRESSED): the row's own bottom rule warms ember, row lifts 2px,
   spec line inks 60%->100% */
.sb-row::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--ember-500);opacity:0;transition:opacity .22s ease}
.no-rm .sb-row{transition:transform .22s ease, padding-bottom .32s cubic-bezier(.3,.9,.3,1)}
.no-rm .sb-row:hover,.no-rm .sb-row:focus-visible{transform:translateY(-2px)}
.no-rm .sb-row:hover::after,.no-rm .sb-row:focus-visible::after{opacity:1}
.no-rm .sb-row:hover .sb-spec,.no-rm .sb-row:focus-visible .sb-spec{opacity:1}
.sb-row:focus-visible{outline:2px solid var(--ember-500);outline-offset:-2px}

/* click/Enter — the row slides OPEN like a drawer: height expands, revealing
   the same spec line restyled at reading size, full-width, plus a tick. RM
   gets an instant snap (no transition outside .no-rm). Only one drawer open
   at a time (JS-enforced). */
/* Wave I: proof sheet open — lift + expand for diagram/description */
.sb-row.open{padding-bottom:16px;transform:translateY(-4px);
  box-shadow:0 4px 16px -4px rgba(20,17,13,.12)}
.sb-row.open .sb-spec{display:none}
.sb-row.open .sb-h{letter-spacing:.04em}
.no-rm .sb-row .sb-spec{transition:opacity .22s ease}
.no-rm .sb-row.open .sb-spec{transition:opacity .3s ease .1s}
@media (max-width:760px){
  /* W-5 (S04, item 4b): 17 rows all showing their full spec line at once
     was the other big driver of mobile scroll length. Collapse to the head
     line only (num + title) — the spec shows only once a row is opened
     (specbookBase JS already toggles .open on tap/Enter; same mechanism as
     desktop, just a different rest/open visual here). */
  .sb-row{grid-template-columns:1fr auto;row-gap:0;padding:13px 4px}
  .sb-row-head{grid-column:1/-1}
  .sb-row .sb-h{white-space:normal}
  .sb-row .sb-spec{display:none}
  .sb-row.open{padding-bottom:12px}
  .sb-row.open .sb-spec{display:none}
}
.sb-hint{margin-top:12px;font-size:var(--fs-micro);letter-spacing:.14em;color:var(--ink-3);text-transform:uppercase}
/* touch vs keyboard hint copy: rows open on tap at <=760px (no hover state
   to imply "click"), keyboard/arrow copy stays for pointer+keyboard widths */
.sb-hint-touch{display:none}
@media (max-width:760px){
  .sb-hint-kb{display:none}
  .sb-hint-touch{display:block}
}

/* Wave I — proof sheet (expanded service view with value diagram) */
.sb-proof{display:none}
.sb-row.open .sb-proof{display:block;grid-column:1/-1;margin-top:12px}
.sb-proof-body{display:grid;grid-template-columns:1fr 1.2fr;gap:8px 24px;align-items:start}
.sb-proof-desc{display:flex;flex-direction:column;gap:8px;align-self:center}
.sb-proof-spectext{font-family:var(--mono);font-size:13px;line-height:1.55;color:var(--ink);
  letter-spacing:.02em;max-width:36ch}
.sb-proof-value{font-family:var(--mono);font-size:11.5px;line-height:1.5;color:var(--ink-2);
  letter-spacing:.02em;max-width:36ch;border-top:1px dashed rgba(20,17,13,.15);padding-top:8px;
  margin-top:2px}
.sb-diag{width:100%;height:auto;display:block}
.sb-diag-label{font-family:'Space Mono',ui-monospace,monospace;font-size:8px;letter-spacing:.1em;
  fill:var(--ink-3);text-transform:uppercase}
.sb-diag-anno{font-family:'Space Mono',ui-monospace,monospace;font-size:7.5px;letter-spacing:.08em;
  fill:var(--ember-500);text-transform:uppercase}
.sb-diag-node{transform-box:fill-box;transform-origin:50% 30%}

/* Wave I — diagram draw-on choreography (motion users only, <=2.4s) */
.no-rm .sb-row.open .sb-diag-base{animation:sbDraw .4s ease-out forwards}
.no-rm .sb-row.open .sb-diag-node{animation:sbStamp .25s cubic-bezier(.3,.9,.3,1) calc(.45s + var(--nd,0) * .15s) both}
.no-rm .sb-row.open .sb-diag-curve{animation:sbDraw .7s ease-out 1.3s forwards}
.no-rm .sb-row.open .sb-diag-tick{animation:sbDraw .2s ease-out 2.0s forwards}
.no-rm .sb-row.open .sb-diag-anno{animation:sbFadeIn .3s ease 2.1s both}
@keyframes sbDraw{to{stroke-dashoffset:0}}
@keyframes sbStamp{0%{opacity:0;transform:scale(1.6)}60%{opacity:1;transform:scale(.9)}100%{opacity:1;transform:scale(1)}}
@keyframes sbFadeIn{from{opacity:0}to{opacity:1}}

/* Wave I — mobile: pull positioning + close affordance */
@media (max-width:760px){
  /* Fix: place pull in the title row (grid-row:1, col 2) instead of auto-placing
     to a second row under the row number (stray "-" glyph finding). Narrow
     sb-row-head to col 1 so pull can occupy col 2 on the same row. */
  .sb-row .sb-pull{grid-column:2;grid-row:1;align-self:baseline;justify-self:end}
  .sb-row-head{grid-column:1}
  .sb-row.open .sb-pull{font-size:10px;color:var(--ember-500)}
  /* Fix: counter-rotate the CLOSE label (display:inline-block required for
     transform) so it reads correctly despite the pull's rotate(180deg). */
  .sb-row.open .sb-pull::after{content:' CLOSE';font-family:var(--mono);font-size:9px;
    letter-spacing:.1em;display:inline-block;transform:rotate(180deg);
    vertical-align:middle;margin-right:4px}
  .sb-proof-body{grid-template-columns:1fr;gap:12px}
  .sb-diag{max-width:100%;max-height:120px}
  .sb-proof-spectext{max-width:none}
  .sb-proof-value{max-width:none}
}

/* =====================================================================
   2f · THE SORTS — contact section right visual field
   ===================================================================== */
.contact-top{display:grid;grid-template-columns:1fr clamp(200px,26vw,320px);gap:clamp(24px,4vw,64px);
  align-items:center;max-width:1180px;margin:0 auto}
.sorts{width:100%;position:relative;z-index:1}
.sorts-svg{width:100%;height:auto;display:block}
.sort-top{fill:color-mix(in srgb, var(--ink) 12%, var(--bone));stroke:var(--ember-900);stroke-opacity:.18;stroke-width:.5}
.sort-front{fill:var(--ink);stroke:var(--ember-900);stroke-opacity:.18;stroke-width:.5}
.sort-right{fill:color-mix(in srgb, var(--ink) 80%, var(--bone));stroke:var(--ember-900);stroke-opacity:.18;stroke-width:.5}
@media (max-width:880px){.contact-top{grid-template-columns:1fr}.sorts{display:none}}

/* =====================================================================
   5c · QUENCH BAND — between THE STRIKE and CONTACT (variant A: ink dries)
   ===================================================================== */
.quench{position:relative;height:120px;background:var(--ink);overflow:hidden;
  border-top:var(--rule-ink);border-bottom:var(--rule-ink)}
.quench-canvas{display:block;width:100%;height:100%}
.quench-readout{position:absolute;right:var(--pad);bottom:8px;z-index:1;font-size:10px;
  letter-spacing:.14em;color:var(--bone);opacity:.75;text-transform:uppercase}
@media (max-width:620px){.quench{height:80px}}

/* =====================================================================
   D2 — hero ambient + liquid magma disc motion (all behind .no-rm)
   ===================================================================== */

/* scroll cue descend-fade loop (§D2 item 2.6) */
@keyframes scrollCueLoop{
  0%{opacity:1;transform:translateY(0)}
  60%{opacity:.15;transform:translateY(8px)}
  100%{opacity:1;transform:translateY(0)}
}
.no-rm .scrollcue{animation:scrollCueLoop 2.4s ease-in-out infinite}

/* readout cursor blink on Status row (§D2 item 2.3) */
@keyframes cursorBlink{0%,49.9%{opacity:1}50%,100%{opacity:0}}
.no-rm .readout .r:nth-child(5) b::after{content:' \258D';
  animation:cursorBlink 1s step-end infinite;color:var(--ink)}

/* =====================================================================
   7d · QUOTATION COMPOSER (Wave L) — pick rail + live proof ticket
   ===================================================================== */
.quotation{scroll-margin-top:96px}
.quot-head{margin-bottom:clamp(24px,4vh,48px)}
.quot-head h2{margin-bottom:12px}
.quot-lede{max-width:48ch;font-size:var(--fs-lede);color:var(--ink-2)}
.quot-body{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,4vw,56px);align-items:start}
@media (max-width:880px){.quot-body{grid-template-columns:1fr}}
.quot-rail-label{font-size:var(--fs-micro);letter-spacing:.24em;text-transform:uppercase;
  color:var(--ember-700);margin-bottom:14px}
.quot-chips{display:flex;flex-wrap:wrap;gap:8px}
.quot-chip{display:inline-flex;align-items:center;gap:10px;background:transparent;
  border:1px solid rgba(20,17,13,.2);border-radius:6px;padding:10px 14px;
  font-family:var(--mono);font-size:12px;letter-spacing:.04em;color:var(--ink);
  cursor:pointer;text-align:left;line-height:1.3}
.quot-chip:focus-visible{outline:2px solid var(--ember-500);outline-offset:2px}
.quot-chip[aria-pressed="true"]{background:var(--ink);color:var(--bone);
  border-color:var(--ink)}
.quot-chip[aria-pressed="true"] .quot-chip-num{color:var(--ember-300)}
.quot-chip-num{color:var(--ember-700);font-size:11px;flex:none}
.quot-chip-name{font-family:var(--sans);font-size:13px;font-weight:600}

/* proof ticket */
.quot-proof{position:sticky;top:100px}
@media (max-width:880px){.quot-proof{position:static}}
.quot-ticket{max-width:none;margin:0}
.quot-scope{min-height:80px;padding:0 0 8px}
.quot-empty{font-family:var(--mono);font-size:12px;color:var(--ink-3);letter-spacing:.04em;
  line-height:1.6;padding:16px 0}
.quot-line{display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:baseline;
  padding:10px 0;border-bottom:1px dashed rgba(20,17,13,.12)}
.quot-line:first-child{border-top:1px dashed rgba(20,17,13,.12)}
.quot-line-cat{font-family:var(--sans);font-weight:700;font-size:14px;color:var(--ink);
  white-space:nowrap}
.quot-line-val{font-family:var(--mono);font-size:11.5px;color:var(--ink-2);letter-spacing:.02em;
  line-height:1.5}
.quot-cta{margin-top:12px}
.quot-cta:disabled{opacity:.4;cursor:not-allowed;transform:none !important}

/* STRUCK motion on chip select + scope line press-in (motion users only).
   RM: the blanket rule below kills all animation/transition, so chips toggle
   instantly and scope lines appear without entrance — exactly the brief's
   "RM parity (instant state changes)" requirement. */
.no-rm .quot-chip{transition:background .15s ease,color .15s ease,border-color .15s ease,
  transform .12s cubic-bezier(.3,.9,.3,1)}
.no-rm .quot-line{animation:quotLineIn .28s cubic-bezier(.3,.9,.3,1) both}
@keyframes quotLineIn{0%{opacity:0;transform:translateY(6px) scale(.97)}
  60%{opacity:1;transform:translateY(-2px) scale(1.01)}100%{opacity:1;transform:translateY(0) scale(1)}}

/* =====================================================================
   reduced-motion — blanket collapse to clean static graven state
   ===================================================================== */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none !important;transition:none !important;
    scroll-behavior:auto !important}
  .glyph{transform:none !important}
  .spine .rail i{height:100% !important}
  .spine .rail .head{display:none !important}
  .cat-progress{display:none !important}
  .loader-pixel{display:none !important}
  .burin{display:none !important}
  /* type case (§2a) RM: static ghost-impression row; click still toggles
     stamped state instantly via the base (non-GSAP) handler in app.js */
  .manifesto .tc-cell{background:rgba(20,17,13,.12) !important;color:var(--ink) !important}
  .manifesto .tc-cell.struck{background:var(--ink) !important;color:var(--bone) !important}
  .replay-btn{display:none !important}
  /* D2 RM fallback: instant flat ember fill on hover */
  .disc:hover .ember-plane{transform:scaleX(1)}
  .disc:hover .num,.disc:hover .name,.disc:hover .spec,.disc:hover .kpi{color:var(--ink) !important}
}
