/* Self-hosted variable fonts — no external request, no FOUT dependency on a third party.
   Archivo (wdth 62..125, wght 400..900) · Inter Tight (400..600) · Martian Mono (wdth 87.5..112.5, wght 400..700) */
/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(../fonts/archivo-k3kQo8UDI-1M0wlSfdboLnnA.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(../fonts/archivo-k3kQo8UDI-1M0wlSfdfoLnnA.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(../fonts/archivo-k3kQo8UDI-1M0wlSfdnoLg.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsK8ah8QA.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsD8ah8QA.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsL8ah8QA.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsE8ah8QA.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsI8ah8QA.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsJ8ah8QA.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsH8ag.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsK8ah8QA.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsD8ah8QA.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsL8ah8QA.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsE8ah8QA.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsI8ah8QA.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsJ8ah8QA.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsH8ag.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsK8ah8QA.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsD8ah8QA.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsL8ah8QA.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsE8ah8QA.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsI8ah8QA.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsJ8ah8QA.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(../fonts/intertight-NGSwv5HMAFg6IuGlBNMjxLsH8ag.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Martian Mono';
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 87.5% 112.5%;
  font-display: swap;
  src: url(../fonts/martianmono-2V0aKIcADoYhV6w87xrTKjsSCKnIV2U.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Martian Mono';
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 87.5% 112.5%;
  font-display: swap;
  src: url(../fonts/martianmono-2V0aKIcADoYhV6w87xrTKjsSAanIV2U.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* latin-ext */
@font-face {
  font-family: 'Martian Mono';
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 87.5% 112.5%;
  font-display: swap;
  src: url(../fonts/martianmono-2V0aKIcADoYhV6w87xrTKjsSC6nIV2U.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Martian Mono';
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 87.5% 112.5%;
  font-display: swap;
  src: url(../fonts/martianmono-2V0aKIcADoYhV6w87xrTKjsSBanI.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* ==========================================================================
   CONNEXT — APPLIED AI SYSTEMS
   Art direction: KINETIC MACHINE / "Connext Assembly Line"
   Doc CX-WEB-001 · REV 4

   THE RULES THIS FILE ENFORCES
   - Zero border-radius, zero box-shadow, zero blur, zero backdrop-filter.
     Depth is four tonal steps of graphite plus 1px rules. Anything else is a bug.
   - One accent (--signal) rationed; --volt is live-status only, never type.
   - Three durations only: 0.24s state / 0.6s lock / 1.1s assemble.
   - CSS ships every element in its FINAL state. Animation start states live
     ONLY under html.js-anim, which JS adds after confirming window.gsap.
     Vendor scripts blocked => complete, readable page.

   ==========================================================================
   PLATE MANIFEST — THE CLIENT ASSET BRIEF
   Every .plate is a photo slot. Drop <img class="plate__img" src="…" alt="…">
   in as the plate's FIRST child and the placeholder art hides itself; the
   registration marks, reticle, IMG tag and caption bar stay as furniture.
   aspect-ratio is pre-reserved, so there is zero layout shift on handover.

     ID              SECTION        ASPECT   MIN PX        SUBJECT
     CX-IMG-0031     industries     16 / 10  1600 × 1000   financial services floor
     CX-IMG-0032     industries     16 / 10  1600 × 1000   insurance operations team
     CX-IMG-0033     industries     16 / 10  1600 × 1000   manufacturing line
     CX-IMG-0034     industries     16 / 10  1600 × 1000   logistics yard / city grid
     CX-IMG-0035     industries     16 / 10  1600 × 1000   data centre / server hall
     CX-IMG-0036     industries     16 / 10  1600 × 1000   public sector control room
     CX-IMG-0041     evidence       16 / 10  1600 × 1000   insurer — claims operations
     CX-IMG-0042     evidence        4 / 5   1200 × 1500   manufacturer — plant floor
     CX-IMG-0043     evidence       16 / 10  1600 × 1000   logistics — dispatch desk
     CX-IMG-0051     contact         3 / 2   1500 × 1000   Sofia office exterior
   ========================================================================== */

/* ---------- 1. DESIGN TOKENS ---------- */
:root {
    /* Ground — four tonal steps of graphite, nothing else */
    --ink-900: #08090B;
    --ink-800: #0E1014;
    --ink-700: #14171D;
    --ink-600: #1B1F27;

    /* Structure */
    --steel-500: #262B35;
    --steel-400: #39404E;
    --steel-350: #5C6675;   /* DECORATIVE ONLY — never carries a character */
    --steel-300: #7B8798;   /* darkest tone permitted for text */

    /* Type */
    --bone-300: #9AA2AE;
    --bone-200: #C7CBD2;
    --bone-100: #F0EEE9;
    --paper-100: #E9E6DF;
    --paper-ink: #0B0C0F;

    /* Accent — rationed */
    --signal: #FC6E02;
    --signal-600: #D35C01;
    --signal-wash: rgba(252,110,2, 0.10);
    --signal-rule: rgba(252,110,2, 0.38);

    /* Live status only */
    --volt: #C6F24A;
    --volt-wash: rgba(198, 242, 74, 0.14);

    /* Blueprint data lanes */
    --lane-a: #4C7FB8;
    --lane-b: #FC6E02;
    --lane-c: #C6F24A;

    /* Printed grid + atmosphere */
    --grid-line: rgba(57, 64, 78, 0.55);
    --grid-line-soft: rgba(57, 64, 78, 0.28);
    --scan: rgba(252,110,2, 0.55);
    --scan-edge: rgba(252,110,2, 0.30);
    --lattice: rgba(57, 64, 78, 0.42);
    --noise: rgba(240, 238, 233, 0.024);
    --focus-ring: rgba(252,110,2, 0.55);

    /* Hard geometry */
    --radius: 0px;
    --rule: 1px;
    --shadow-none: none;

    /* Families */
    --font-display: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
    --font-body: 'Inter Tight', 'Helvetica Neue', Arial, sans-serif;
    --font-mono: 'Martian Mono', ui-monospace, 'SFMono-Regular', Consolas, monospace;

    /* Scale */
    --fs-hero: clamp(3.2rem, 9.2vw, 8.5rem);
    --fs-title: clamp(2.1rem, 5vw, 4.4rem);
    --fs-block: clamp(1.3rem, 2.2vw, 1.85rem);
    --fs-figure: clamp(3.6rem, 8vw, 8rem);
    --fs-body: 1.0125rem;
    --fs-mono: 0.66rem;
    --fs-mono-sm: 0.6rem;

    /* Measure & rhythm */
    --measure: 58ch;
    --container-max: 1320px;
    --container-wide: 1560px;
    --container-pad: clamp(20px, 4.4vw, 56px);
    --gutter: clamp(14px, 1.6vw, 26px);
    --section-pad: clamp(88px, 11vw, 160px);
    --bar-h: 64px;

    /* Motion — CSS mirrors of the two registered CustomEases */
    --ease-machine: cubic-bezier(0.12, 0.62, 0.16, 1);
    --ease-servo: cubic-bezier(0.28, 1.02, 0.4, 0.99);
    --t-state: 0.24s;
    --t-lock: 0.6s;
    --t-assemble: 1.1s;

    /* The depth law */
    --depth-grid: 0.15;
    --depth-canvas: 0.35;
    --depth-svg: 0.55;
    --depth-panel: 0.7;
    --depth-type: 1;
    --parallax-pointer: 22px;
    --parallax-scroll: 120px;

    --plate-ar: 16 / 10;
    --pin-budget: 400vh;   /* platform 240vh + architecture 160vh */
}

/* ---------- 2. RESET & BASE ---------- */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

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

body {
    font-family: var(--font-body);
    font-size: var(--fs-body);
    font-weight: 400;
    line-height: 1.62;
    color: var(--bone-200);
    background: var(--ink-900);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
    font-variant-numeric: tabular-nums;
}

img, svg, canvas, video { display: block; max-width: 100%; }
svg { overflow: visible; }
p { max-width: var(--measure); }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; background: none; border: 0; border-radius: var(--radius); }
button { cursor: pointer; }
ul, ol { list-style: none; }
::selection { background: var(--signal); color: var(--paper-ink); }

:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
    border-radius: var(--radius);
}

.skip-link {
    position: fixed;
    top: 8px; left: 8px;
    z-index: 10000;
    padding: 12px 20px;
    background: var(--signal);
    color: var(--paper-ink);
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    transform: translateY(-200%);
    transition: transform var(--t-state) var(--ease-machine);
}
.skip-link:focus { transform: translateY(0); }

.visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---------- 3. LAYOUT ---------- */
.container {
    width: 100%;
    max-width: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--container-pad);
}
.container--wide { max-width: var(--container-wide); }

.section {
    position: relative;
    padding-block: var(--section-pad);
    background: var(--ink-900);
}
.section--alt { background: var(--ink-800); }
.section--flush { padding-block: 0; }

.section-header { margin-bottom: clamp(48px, 6vw, 88px); }
.section-header--center { text-align: center; margin-inline: auto; max-width: 760px; }
.section-header--center .section-desc { margin-inline: auto; }

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

/* Column span utilities — the only way to place on the grid */
.c1-4  { grid-column: 1 / 5; }
.c1-5  { grid-column: 1 / 6; }
.c1-6  { grid-column: 1 / 7; }
.c1-7  { grid-column: 1 / 8; }
.c1-12 { grid-column: 1 / -1; }
.c2-9  { grid-column: 2 / 10; }
.c5-11 { grid-column: 5 / 12; }
.c6-12 { grid-column: 6 / -1; }
.c7-12 { grid-column: 7 / -1; }
.c8-12 { grid-column: 8 / -1; }
.c10-12 { grid-column: 10 / -1; }

/* The printed 12-column grid, used as a background layer */
.printed-grid {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image:
        repeating-linear-gradient(90deg, var(--grid-line) 0 1px, transparent 1px calc(100% / 12)),
        repeating-linear-gradient(180deg, var(--grid-line-soft) 0 1px, transparent 1px 88px);
    background-size: calc(100% / 1) 100%, 100% 88px;
    opacity: 0.5;
}

/* ---------- 4. TYPOGRAPHY ---------- */
.section-label {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 700;
    font-variation-settings: 'wdth' 112.5;
    letter-spacing: 0.18em;
    line-height: 1;
    text-transform: uppercase;
    color: var(--signal);
}
.section-label::before {
    content: '';
    width: 8px; height: 8px;
    background: var(--signal);
    flex: none;
}
.section-label--center { justify-content: center; }

.section-title {
    font-family: var(--font-display);
    font-size: var(--fs-title);
    font-weight: 800;
    font-variation-settings: 'wdth' 118;
    line-height: 0.92;
    letter-spacing: -0.02em;
    text-transform: uppercase;
    color: var(--bone-100);
    margin-top: 24px;
    text-wrap: balance;
}

.section-desc {
    font-size: var(--fs-body);
    line-height: 1.62;
    color: var(--bone-200);
    max-width: var(--measure);
    margin-top: 24px;
}

.mono {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 400;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--steel-300);
    line-height: 1.4;
}
.mono--label {
    font-size: var(--fs-mono);
    font-weight: 700;
    letter-spacing: 0.18em;
    font-variation-settings: 'wdth' 112.5;
}

/* Emphasis is width: accent words are wider AND orange.

   The relay state is read from two INHERITED custom properties, not written on the
   word itself. SplitText's autoSplit destroys and recreates these spans when the
   fonts land, and anything written on the node — a class, an inline style, a JS flag
   — dies with it or gets baked into the snapshot. The properties live on the section,
   which SplitText never touches, so a recreated word inherits whatever the relay has
   reached. Their defaults are the FINAL values, so with no JS at all the word is
   simply orange. */
.text-accent {
    display: inline-block;
    contain: layout;
    color: var(--relay-color, var(--signal));
    font-variation-settings: 'wdth' var(--relay-wdth, 125);
}

.ghost-num {
    font-family: var(--font-display);
    font-weight: 400;
    font-variation-settings: 'wdth' 125;
    line-height: 0.78;
    color: transparent;
    -webkit-text-stroke: 1px var(--steel-400);
    user-select: none;
    pointer-events: none;
    transform: translateZ(0);
}

/* The oversized numeral primitive */
.figure {
    display: inline-flex;
    align-items: baseline;
    gap: 0.12em;
    font-family: var(--font-display);
    font-size: var(--fs-figure);
    font-weight: 900;
    font-variation-settings: 'wdth' 125;
    font-feature-settings: 'tnum' 1;
    font-variant-numeric: tabular-nums;
    line-height: 0.86;
    letter-spacing: -0.03em;
    color: var(--bone-100);
}
.figure__value { display: inline-flex; align-items: baseline; }
.figure__unit {
    font-size: 0.4em;
    font-weight: 700;
    letter-spacing: 0;
    color: var(--signal);   /* final state; the relay starts it at --steel-400 */
}
/* Digit reel: one 1ch × 1lh window per digit, built by JS when GSAP is present */
.figure__digit {
    display: inline-block;
    overflow: hidden;
    width: 0.62em;
    height: 0.86em;
    vertical-align: baseline;
}
.figure__strip { display: block; }
.figure__strip span { display: block; height: 0.86em; line-height: 0.86em; }
.figure__sep { display: inline-block; }

/* ---------- 5. BUTTONS ---------- */
.btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 14px 28px;
    min-height: 44px;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 700;
    font-variation-settings: 'wdth' 100;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    isolation: isolate;
    transition: color var(--t-state) var(--ease-machine),
                border-color var(--t-state) var(--ease-machine),
                background-color var(--t-state) var(--ease-machine);
}
/* Hover is a clip wipe from the left — never a transform, never a shadow */
.btn::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    clip-path: inset(0 100% 0 0);
    transition: clip-path var(--t-state) var(--ease-machine);
}
.btn:hover::before, .btn:focus-visible::before { clip-path: inset(0); }

.btn--accent { background: var(--signal); color: var(--paper-ink); border-color: var(--signal); }
.btn--accent::before { background: var(--paper-ink); }
.btn--accent:hover, .btn--accent:focus-visible { color: var(--signal); }

.btn--outline { color: var(--bone-100); border-color: var(--steel-500); }
.btn--outline::before { background: var(--signal); }
.btn--outline:hover, .btn--outline:focus-visible { color: var(--paper-ink); border-color: var(--signal); }

.btn--invert { background: var(--paper-ink); color: var(--signal); border-color: var(--paper-ink); }
.btn--invert::before { background: var(--signal); }
.btn--invert:hover, .btn--invert:focus-visible { color: var(--paper-ink); border-color: var(--paper-ink); }

.btn--lg { padding: 18px 36px; }
.btn--full { width: 100%; }
.btn__arrow { flex: none; }

/* ---------- 6. RULES, PANELS, CHIPS ---------- */
.rule {
    display: block;
    width: 100%;
    height: 1px;
    background: var(--steel-500);
    transform-origin: left center;
    border: 0;
}
.rule--signal { background: var(--signal); height: 2px; }
.rule--v { width: 1px; height: 100%; transform-origin: top center; }

.panel {
    position: relative;
    background: var(--ink-700);
    border: 1px solid var(--steel-500);
    border-radius: var(--radius);
    transition: border-color var(--t-state) var(--ease-machine);
}
.panel--raised { background: var(--ink-600); }
.panel--flush { margin: -0.5px; }        /* adjacent borders collapse to one hairline */
.panel:hover { border-color: var(--signal-rule); }

.chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    background: var(--ink-600);
    border: 1px solid var(--steel-500);
    border-radius: var(--radius);
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    line-height: 1.2;
    color: var(--steel-300);
    transition: border-color var(--t-state) var(--ease-machine), color var(--t-state) var(--ease-machine);
}
.chip:hover { border-color: var(--signal-rule); }
.chip--status { background: var(--volt-wash); color: var(--bone-200); }
.chip__led { width: 6px; height: 6px; background: var(--volt); flex: none; animation: led 2s steps(1) infinite; }
.chip--week { color: var(--bone-100); }
.chip--accent { color: var(--signal); border-color: var(--signal-rule); }

@keyframes led { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0.25; } }

/* ---------- 7. SPEC ROW — the universal dot leader ---------- */
.spec-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 0;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    line-height: 1.3;
}
.spec-row + .spec-row { border-top: 1px solid rgba(38, 43, 53, 0.6); }
.spec-row__label { color: var(--steel-300); flex: none; }
.spec-row__leader {
    flex: 1 1 auto;
    min-width: 20px;
    height: 1px;
    align-self: center;
    transform-origin: left center;
    color: var(--steel-350);
    background-image: repeating-linear-gradient(90deg, currentColor 0 1px, transparent 1px 6px);
}
.spec-row__value { color: var(--bone-200); flex: none; text-align: right; }
.spec-row__value--accent { color: var(--signal); }

/* ---------- 8. PLATE — the universal photo placeholder ---------- */
.plate {
    position: relative;
    aspect-ratio: var(--plate-ar);
    background: var(--ink-700);
    border: 1px solid var(--steel-500);
    border-radius: var(--radius);
    overflow: hidden;
    isolation: isolate;
}
.plate__img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.plate__screen, .plate__grid, .plate__subject {
    position: absolute;
    inset: 0 0 28px 0;
    pointer-events: none;
    transition: opacity var(--t-state) var(--ease-machine);
}
.plate__screen {
    background-image: repeating-linear-gradient(180deg, rgba(240,238,233,0.035) 0 1px, transparent 1px 6px);
}
.plate__grid {
    background-image:
        repeating-linear-gradient(90deg, rgba(57,64,78,0.22) 0 1px, transparent 1px 24px),
        repeating-linear-gradient(180deg, rgba(57,64,78,0.22) 0 1px, transparent 1px 24px);
}
.plate__subject {
    opacity: 0.10;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 76% auto;
    transition: opacity var(--t-state) var(--ease-machine);
}
.plate:hover .plate__subject { opacity: 0.18; }

/* Six distinct orthogonal silhouettes — no tile ever repeats */
.plate[data-plate="server"] .plate__subject {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 100' fill='%239AA2AE'%3E%3Crect x='14' y='14' width='38' height='72'/%3E%3Crect x='60' y='14' width='38' height='72'/%3E%3Crect x='106' y='14' width='38' height='72'/%3E%3Crect x='20' y='22' width='26' height='4' fill='%2308090B'/%3E%3Crect x='20' y='34' width='26' height='4' fill='%2308090B'/%3E%3Crect x='66' y='22' width='26' height='4' fill='%2308090B'/%3E%3Crect x='66' y='46' width='26' height='4' fill='%2308090B'/%3E%3Crect x='112' y='34' width='26' height='4' fill='%2308090B'/%3E%3Crect x='112' y='58' width='26' height='4' fill='%2308090B'/%3E%3C/svg%3E");
}
.plate[data-plate="control-room"] .plate__subject {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 100' fill='%239AA2AE'%3E%3Crect x='12' y='10' width='40' height='26'/%3E%3Crect x='58' y='6' width='44' height='30'/%3E%3Crect x='108' y='10' width='40' height='26'/%3E%3Crect x='10' y='60' width='140' height='8'/%3E%3Crect x='26' y='68' width='10' height='22'/%3E%3Crect x='75' y='68' width='10' height='22'/%3E%3Crect x='124' y='68' width='10' height='22'/%3E%3Crect x='40' y='46' width='16' height='14'/%3E%3Crect x='104' y='46' width='16' height='14'/%3E%3C/svg%3E");
}
.plate[data-plate="city"] .plate__subject {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 100' fill='%239AA2AE'%3E%3Crect x='8' y='52' width='22' height='40'/%3E%3Crect x='34' y='30' width='18' height='62'/%3E%3Crect x='56' y='44' width='26' height='48'/%3E%3Crect x='86' y='18' width='20' height='74'/%3E%3Crect x='110' y='38' width='16' height='54'/%3E%3Crect x='130' y='58' width='22' height='34'/%3E%3Crect x='90' y='26' width='12' height='4' fill='%2308090B'/%3E%3Crect x='38' y='40' width='10' height='4' fill='%2308090B'/%3E%3C/svg%3E");
}
.plate[data-plate="team"] .plate__subject {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 100' fill='%239AA2AE'%3E%3Crect x='18' y='24' width='16' height='16'/%3E%3Crect x='12' y='46' width='28' height='38'/%3E%3Crect x='58' y='16' width='16' height='16'/%3E%3Crect x='52' y='38' width='28' height='46'/%3E%3Crect x='98' y='24' width='16' height='16'/%3E%3Crect x='92' y='46' width='28' height='38'/%3E%3Crect x='132' y='34' width='14' height='14'/%3E%3Crect x='128' y='54' width='22' height='30'/%3E%3C/svg%3E");
}
.plate[data-plate="warehouse"] .plate__subject {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 100' fill='%239AA2AE'%3E%3Crect x='10' y='16' width='4' height='72'/%3E%3Crect x='66' y='16' width='4' height='72'/%3E%3Crect x='122' y='16' width='4' height='72'/%3E%3Crect x='10' y='16' width='116' height='4'/%3E%3Crect x='10' y='44' width='116' height='4'/%3E%3Crect x='10' y='72' width='116' height='4'/%3E%3Crect x='20' y='24' width='18' height='18'/%3E%3Crect x='44' y='28' width='14' height='14'/%3E%3Crect x='76' y='24' width='20' height='18'/%3E%3Crect x='20' y='52' width='16' height='18'/%3E%3Crect x='84' y='52' width='24' height='18'/%3E%3Crect x='132' y='60' width='18' height='28'/%3E%3C/svg%3E");
}
.plate[data-plate="abstract"] .plate__subject {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 100' fill='none' stroke='%239AA2AE' stroke-width='6'%3E%3Crect x='12' y='10' width='136' height='80'/%3E%3Crect x='34' y='24' width='92' height='52'/%3E%3Crect x='56' y='38' width='48' height='24'/%3E%3Cpath d='M12 50h22M126 50h22M80 10v14M80 76v14'/%3E%3C/svg%3E");
}

/* THE SWAP CONTRACT — dropping in <img class="plate__img"> is the whole handover */
.plate:has(.plate__img) .plate__screen,
.plate:has(.plate__img) .plate__grid,
.plate:has(.plate__img) .plate__subject,
.plate.has-img .plate__screen,
.plate.has-img .plate__grid,
.plate.has-img .plate__subject { opacity: 0; }

/* Permanent furniture — never hidden, image or not */
.plate__reg, .plate__reticle { position: absolute; inset: 0 0 28px 0; pointer-events: none; }
.plate__reg {
    background-repeat: no-repeat;
    background-image:
        linear-gradient(var(--signal), var(--signal)), linear-gradient(var(--signal), var(--signal)),
        linear-gradient(var(--signal), var(--signal)), linear-gradient(var(--signal), var(--signal)),
        linear-gradient(var(--signal), var(--signal)), linear-gradient(var(--signal), var(--signal)),
        linear-gradient(var(--signal), var(--signal)), linear-gradient(var(--signal), var(--signal));
    background-size: 14px 2px, 2px 14px, 14px 2px, 2px 14px, 14px 2px, 2px 14px, 14px 2px, 2px 14px;
    background-position:
        10px 10px, 10px 10px,
        calc(100% - 10px) 10px, calc(100% - 10px) 10px,
        10px calc(100% - 10px), 10px calc(100% - 10px),
        calc(100% - 10px) calc(100% - 10px), calc(100% - 10px) calc(100% - 10px);
}
.plate__reticle::before, .plate__reticle::after { content: ''; position: absolute; background: var(--steel-350); }
.plate__reticle::before {
    left: 0; right: 0; top: 50%; height: 1px;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(50% - 22px), transparent calc(50% - 22px), transparent calc(50% + 22px), #000 calc(50% + 22px));
    mask-image: linear-gradient(90deg, #000 calc(50% - 22px), transparent calc(50% - 22px), transparent calc(50% + 22px), #000 calc(50% + 22px));
}
.plate__reticle::after {
    top: 0; bottom: 0; left: 50%; width: 1px;
    -webkit-mask-image: linear-gradient(180deg, #000 calc(50% - 22px), transparent calc(50% - 22px), transparent calc(50% + 22px), #000 calc(50% + 22px));
    mask-image: linear-gradient(180deg, #000 calc(50% - 22px), transparent calc(50% - 22px), transparent calc(50% + 22px), #000 calc(50% + 22px));
}
.plate__tag {
    position: absolute;
    top: 10px; right: 30px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.14em;
    color: var(--steel-300);
}
.plate__tag::before { content: ''; width: 10px; height: 10px; background: var(--signal); }
.plate__caption {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding-inline: 10px;
    background: var(--ink-800);
    border-top: 1px solid var(--steel-500);
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--steel-300);
    white-space: nowrap;
    overflow: hidden;
}
.plate__dim { color: var(--steel-350); }

/* ---------- 9. MARQUEE ---------- */
.marquee {
    position: relative;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.marquee__track { display: flex; width: max-content; will-change: transform; }
.marquee__content { display: flex; align-items: center; flex: none; }
.marquee__chip { display: inline-flex; align-items: center; white-space: nowrap; }

/* ---------- 10. FORM VOCABULARY ---------- */
.form-field { position: relative; margin-bottom: 22px; }
.form-label {
    display: block;
    margin-bottom: 8px;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--steel-300);
    transition: color var(--t-state) var(--ease-machine);
}
.form-input {
    width: 100%;
    padding: 14px 16px;
    background: var(--ink-600);
    border: 1px solid var(--steel-500);
    border-radius: var(--radius);
    color: var(--bone-100);
    font-family: var(--font-body);
    font-size: 0.95rem;
    transition: border-color var(--t-state) var(--ease-machine), background-color var(--t-state) var(--ease-machine);
}
.form-input::placeholder { color: var(--steel-350); }
.form-input:focus { outline: none; border-color: var(--signal); background: var(--ink-700); }
.form-input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
select.form-input { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--steel-300) 50%), linear-gradient(135deg, var(--steel-300) 50%, transparent 50%); background-position: calc(100% - 20px) 22px, calc(100% - 14px) 22px; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat; }
.form-textarea { min-height: 132px; resize: vertical; }
.form-status {
    margin-top: 16px;
    min-height: 20px;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--steel-300);
}
.form-status--success { color: var(--volt); }
.form-status--error { color: var(--signal); }

/* ---------- 11. FIXED INSTRUMENTS ---------- */
/* Grain: a plain low-alpha texture. No mix-blend-mode — a full-viewport blended
   layer forces the entire page into one composited group (measurable cost on
   hardware, and it blanks headless captures outright). */
.noise {
    position: fixed;
    inset: 0;
    z-index: 9999;
    pointer-events: none;
    opacity: 1;
}
.cursor {
    position: fixed;
    top: 0; left: 0;
    z-index: 9998;
    width: 22px; height: 22px;
    pointer-events: none;
    opacity: 0;
    will-change: transform;
}
.cursor__box { display: block; width: 100%; height: 100%; border: 1px solid var(--signal); }
@media (pointer: coarse) { .cursor { display: none; } }

/* ---------- 12. THE DEPTH LAW ---------- */
[data-depth] {
    transform: translate3d(var(--px, 0px), calc(var(--py, 0px) + var(--sy, 0px)), 0);
}
html.js-anim [data-depth] { will-change: transform; }

/* ---------- 13. MASTHEAD — the console bar ---------- */
.masthead {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 900;
    height: var(--bar-h);
    background: rgba(8, 9, 11, 0.90);
    border-bottom: 1px solid var(--steel-500);
    transition: height var(--t-state) var(--ease-machine), border-color var(--t-state) var(--ease-machine);
}
.masthead.is-scrolled { height: 56px; border-bottom-color: var(--steel-400); }
.masthead__inner {
    height: 100%;
    max-width: var(--container-wide);
    margin-inline: auto;
    padding-inline: var(--container-pad);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
}
.masthead__progress {
    position: absolute;
    left: 0; bottom: -2px;
    width: 100%; height: 2px;
    background: var(--signal);
    transform: scaleX(0);
    transform-origin: left center;
}

/* The wordmark is the supplied logo asset — a flat #FC6E02 lockup on transparent,
   which is exactly --signal, so it sits in the accent system rather than beside it.
   Height-driven so the bar controls it; width follows the intrinsic 453x61 ratio. */
.wordmark { display: inline-flex; align-items: center; flex: none; }
.wordmark__img {
    height: 19px;
    width: auto;
    display: block;
}
.masthead.is-scrolled .wordmark__img { height: 17px; }
.wordmark--footer .wordmark__img { height: 24px; }

.masthead__nav {
    position: relative;
    display: flex;
    align-items: stretch;
    height: 100%;
    border-left: 1px solid var(--steel-500);
}
.masthead__link {
    position: relative;
    display: inline-flex;
    align-items: center;
    padding: 0 22px;
    border-right: 1px solid var(--steel-500);
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--steel-300);
    transition: color var(--t-state) var(--ease-machine);
}
.masthead__link:hover, .masthead__link.is-active { color: var(--bone-100); }
.masthead__box {
    position: absolute;
    top: 0; left: 0;
    width: 10px; height: 10px;
    border: 1px solid var(--signal);
    opacity: 0;
    pointer-events: none;
}
.masthead__aside { display: flex; align-items: center; gap: 14px; flex: none; }
.masthead__cta { padding: 11px 20px; min-height: 40px; }

.masthead__toggle {
    display: none;
    width: 44px; height: 44px;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 6px;
    border: 1px solid var(--steel-500);
}
.masthead__toggle span {
    display: block;
    width: 20px; height: 2px;
    background: var(--bone-100);
    transition: transform var(--t-state) var(--ease-machine), opacity var(--t-state) var(--ease-machine);
}
.masthead__toggle.is-open span:first-child { transform: translateY(4px) rotate(45deg); }
.masthead__toggle.is-open span:last-child { transform: translateY(-4px) rotate(-45deg); }

/* ---------- 14. MOBILE OVERLAY ---------- */
.mobile-menu {
    position: fixed;
    inset: 0;
    z-index: 890;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 40px;
    padding: calc(var(--bar-h) + 40px) var(--container-pad) 40px;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--t-state) var(--ease-machine), visibility 0s linear var(--t-state);
}
.mobile-menu.is-open {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
    transition: opacity var(--t-state) var(--ease-machine), visibility 0s;
}
.mobile-menu__shutters { position: absolute; inset: 0; display: flex; z-index: -1; }
.mobile-menu__shutter { flex: 1; background: var(--ink-900); border-right: 1px solid var(--steel-500); transform-origin: top center; }
.mobile-menu__nav { display: flex; flex-direction: column; }
.mobile-menu__link {
    display: flex;
    align-items: baseline;
    gap: 18px;
    padding: 14px 0;
    border-bottom: 1px solid var(--steel-500);
    font-family: var(--font-display);
    font-size: clamp(2.2rem, 9vw, 3.6rem);
    font-weight: 800;
    font-variation-settings: 'wdth' 110;
    line-height: 1;
    text-transform: uppercase;
    color: var(--bone-100);
    overflow: hidden;
}
.mobile-menu__index {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 400;
    letter-spacing: 0.14em;
    color: var(--signal);
}
.mobile-menu__foot { display: flex; flex-direction: column; gap: 18px; }
.mobile-menu__mail {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--steel-300);
    text-align: center;
}

/* ---------- 15. FOOTER — title block ---------- */
.footer {
    position: relative;
    background: var(--ink-900);
    border-top: 1px solid var(--steel-500);
    padding-top: clamp(64px, 7vw, 104px);
    overflow: hidden;
}
.footer__grid {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1.4fr;
    gap: var(--gutter);
    padding-bottom: 56px;
}
.footer__tagline { margin-top: 20px; color: var(--bone-300); max-width: 34ch; }
.footer__status {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-top: 24px;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--steel-300);
}
.footer__led { width: 6px; height: 6px; background: var(--volt); flex: none; animation: led 2s steps(1) infinite; }
.footer__col { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.footer__col-title {
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 700;
    letter-spacing: 0.18em;
    color: var(--bone-100);
    margin-bottom: 6px;
}
.footer__link {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.12em;
    color: var(--steel-300);
    transition: color var(--t-state) var(--ease-machine);
    min-height: 24px;
    display: inline-flex;
    align-items: center;
}
a.footer__link:hover { color: var(--signal); }
.footer__link--static { cursor: default; }
.footer__block {
    display: grid;
    /* Not three equal columns: the entity row carries the registered name, the city
       and the UIC on one line and overruns an even third, colliding with the next
       label. The middle column takes the room it actually needs. */
    grid-template-columns: 0.85fr 1.7fr 0.95fr;
    gap: var(--gutter);
    padding: 22px 0 28px;
    border-top: 1px solid var(--steel-500);
}
.footer__spec { padding: 0; }
.footer__wordmark {
    font-family: var(--font-display);
    font-size: 22vw;
    font-weight: 900;
    font-variation-settings: 'wdth' 125;
    line-height: 0.72;
    letter-spacing: -0.02em;
    text-align: center;
    color: transparent;
    -webkit-text-stroke: 1px var(--steel-400);
    margin-bottom: -0.28em;
    user-select: none;
    transform: translate3d(var(--px, 0px), calc(var(--py, 0px) + var(--sy, 0px)), 0);
}

/* ---------- 16. ENTRANCE HOOKS — final state ships in CSS ---------- */
.reveal { clip-path: none; opacity: 1; }

/* Start states exist ONLY once JS has confirmed GSAP is present. */
html.js-anim .reveal { clip-path: inset(0 0 100% 0); }
html.js-anim .rule { transform: scaleX(0); }
html.js-anim .rule--v { transform: scaleY(0); }
html.js-anim .spec-row__leader { transform: scaleX(0); }
/* .text-accent deliberately has NO start state here. SplitText's autoSplit
   recreates these nodes when the fonts land, and a recreated node keeps none of the
   JS bookkeeping — under a CSS start state it would stay dim forever (this is exactly
   what happened in Firefox, where the re-split lands after the last ScrollTrigger
   refresh). The dim state is applied by JS in boot() instead, so the worst case for a
   recreated node is that it is already at its final colour. */
html.js-anim .masthead__progress { transform: scaleX(0); }

/* ---------- 17. FOUNDATION RESPONSIVE (sections may override; their CSS loads after) ---------- */
@media (max-width: 1024px) {
    .masthead__nav, .chip--status { display: none; }
    .masthead__toggle { display: flex; }
}

@media (max-width: 899.98px) {
    /* Footer links are a 24px hit area on desktop, where there is a pointer. On a
       phone they are the only navigation left once the overlay is closed, so the
       row height carries the 44px minimum and the column gap stands down. */
    .footer__link { min-height: 44px; }
    .footer__col { gap: 0; }
    .wordmark--footer { padding-block: 14px; }

    .grid12 { grid-template-columns: 1fr; }
    .c1-4, .c1-5, .c1-6, .c1-7, .c2-9, .c5-11, .c6-12, .c7-12, .c8-12, .c10-12 { grid-column: 1 / -1; }
    .footer__grid { grid-template-columns: 1fr 1fr; row-gap: 44px; }
    .footer__block { grid-template-columns: 1fr; gap: 0; }
    .footer__spec { padding: 5px 0; }
    .footer__wordmark { font-size: 34vw; transform: none; }
}

@media (max-width: 640px) {
    :root { --fs-figure: clamp(3rem, 14vw, 4rem); }
    .masthead__cta { display: none; }
    .footer__grid { grid-template-columns: 1fr; }
    .btn { width: 100%; }
    .btn--auto { width: auto; }
}

@media print {
    .noise, .cursor, .masthead, .mobile-menu { display: none !important; }
    body { background: #fff; color: #000; }
}

/* ============================ HERO ============================ */
/* ==========================================================================
   #hero — "THE ASSEMBLY"
   Cols 1-7 lede / cols 8-12 axonometric assembly. Printed grid + lattice
   canvas behind, ghost numeral bleeding off the left gutter, telemetry and
   scroll rail on the bottom rule, page-load shutter over the lot.
   Every element ships in its FINAL state; start states live under html.js-anim.
   ========================================================================== */

.hero {
    position: relative;
    min-height: 720px;
    min-height: max(720px, 100svh);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    isolation: isolate;
    padding-block: calc(var(--bar-h) + clamp(28px, 4.4vh, 64px)) clamp(22px, 3.4vh, 44px);
    background: var(--ink-900);
}

/* ---------- background stack ---------- */
.hero__bg {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
}
.hero__grid {
    opacity: 0.72;
    -webkit-mask-image: radial-gradient(120% 78% at 26% 44%, transparent 0%, transparent 26%, #000 74%);
    mask-image: radial-gradient(120% 78% at 26% 44%, transparent 0%, transparent 26%, #000 74%);
}
/* A <canvas> is a replaced element: with `inset` alone and width:auto it falls
   back to its 300x150 intrinsic box, so the field is sized explicitly. */
.hero__field {
    position: absolute;
    top: -52px;
    left: -44px;
    width: calc(100% + 88px);
    height: calc(100% + 104px);
    max-width: none;
    opacity: 1;
}
.hero__wash {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(180deg, var(--ink-900) 0%, rgba(8, 9, 11, 0) 15%, rgba(8, 9, 11, 0) 86%, var(--ink-900) 100%),
        linear-gradient(90deg, rgba(8, 9, 11, 0.84) 0%, rgba(8, 9, 11, 0.42) 26%, rgba(8, 9, 11, 0) 54%);
}

/* ---------- ghost numeral ---------- */
.hero__ghost {
    position: absolute;
    z-index: 1;
    left: -0.17em;
    /* clear of the foot rule at every viewport height — two hairlines 15px
       apart in the lower gutter read as an error, not as a stamp. */
    bottom: clamp(150px, 19vh, 235px);
    font-size: clamp(13rem, 25vw, 27rem);
    letter-spacing: -0.04em;
    -webkit-text-stroke-color: var(--steel-500);
}

/* ---------- layout ---------- */
.hero__inner {
    position: relative;
    z-index: 2;
    flex: 1 1 auto;
    display: grid;
    grid-template-rows: 1fr auto;
    align-items: stretch;
    row-gap: clamp(34px, 5vh, 72px);
}
.hero__grid12 {
    align-self: center;
    width: 100%;
    align-items: center;
    row-gap: clamp(40px, 6vw, 64px);
}

/* ---------- lede ---------- */
.hero__lede { position: relative; }

.hero__eyebrow {
    overflow: hidden;
    color: var(--bone-300);
    font-size: var(--fs-mono);
}
.hero__lift { display: block; }
.hero__eyebrow .hero__lift { display: inline-flex; align-items: center; gap: 11px; }
.hero__eyebrow-mark { width: 8px; height: 8px; background: var(--signal); flex: none; }

.hero__rule { margin: 22px 0 26px; background: var(--steel-400); }

/* The accent line is set at 'wdth' 125 by the relay, so the whole headline is
   sized off the WIDE measure of its longest line, never the narrow one. */
.hero__title {
    font-family: var(--font-display);
    font-size: clamp(2.3rem, 4.4vw, 4rem);
    font-weight: 800;
    font-variation-settings: 'wdth' 110;
    line-height: 0.92;
    letter-spacing: -0.022em;
    text-transform: uppercase;
    color: var(--bone-100);
    hyphens: none;
    -webkit-hyphens: none;
}

.hero__body {
    overflow: hidden;
    margin-top: 30px;
    max-width: var(--measure);
    color: var(--bone-200);
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 38px;
}
.hero__act { display: inline-block; overflow: visible; }
.hero__act .btn { width: 100%; }

/* ---------- stage: the axonometric assembly ---------- */
.hero__stage {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
}
.hero__assembly {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 12px;
    border-left: 1px solid var(--steel-500);
    padding-left: clamp(12px, 1.6vw, 22px);
}
.hero__svg {
    width: 100%;
    height: auto;
    max-height: min(68vh, 620px);
    overflow: visible;
}
.hero__figcap {
    font-size: var(--fs-mono-sm);
    color: var(--steel-300);
    border-top: 1px solid var(--steel-500);
    padding-top: 10px;
}

/* SVG vocabulary — hairlines and four graphite tones, nothing else */
.hero__reg path { fill: none; stroke: var(--steel-400); stroke-width: 2; }
.hero__tick path { fill: none; stroke: var(--steel-500); stroke-width: 1; }

.hero__riser { fill: none; stroke: var(--steel-400); stroke-width: 1.5; stroke-linecap: butt; }
.hero__leader { fill: none; stroke: var(--steel-500); stroke-width: 1; }

.hero__face { fill: var(--ink-600); stroke: var(--steel-350); stroke-width: 1.25; }
.hero__side { fill: var(--ink-900); stroke: var(--steel-400); stroke-width: 1; }
.hero__side--lit { fill: var(--ink-700); }
.hero__inset { fill: none; stroke: var(--steel-400); stroke-width: 1; }
.hero__centre { fill: none; stroke: var(--steel-500); stroke-width: 1; stroke-dasharray: 2 5; }
.hero__slot { fill: var(--steel-400); }
.hero__port { fill: none; stroke: var(--steel-400); stroke-width: 1; }

.hero__junction { fill: var(--ink-900); stroke: var(--signal); stroke-width: 1.5; }
.hero__spine { fill: none; stroke: none; }
.hero__payload { fill: var(--volt); }

.hero__name {
    font-family: var(--font-mono);
    font-size: 17px;
    font-weight: 700;
    letter-spacing: 1.3;
    fill: var(--bone-100);
}
.hero__part {
    font-family: var(--font-mono);
    font-size: 11.5px;
    font-weight: 400;
    letter-spacing: 1.1;
    fill: var(--steel-300);
}
.hero__idx {
    font-family: var(--font-display);
    font-size: 23px;
    font-weight: 700;
    letter-spacing: 0.4;
    fill: var(--steel-300);
}

/* ---------- foot: telemetry + scroll rail ---------- */
.hero__foot {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 24px;
    border-top: 1px solid var(--steel-500);
    padding-top: 16px;
}
.hero__telemetry {
    overflow: hidden;
    max-width: none;
    margin: 0;
}
.hero__tel-lift {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    line-height: 1.4;
}
.hero__tel-led { width: 6px; height: 6px; background: var(--volt); flex: none; animation: led 2s steps(1) infinite; }
.hero__tel-text { color: var(--bone-200); white-space: nowrap; }
.hero__tel-note {
    color: var(--steel-300);
    border-left: 1px solid var(--steel-500);
    padding-left: 12px;
    white-space: nowrap;
}

.hero__scroll {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    flex: none;
}
.hero__rail {
    position: relative;
    display: block;
    width: 1px;
    height: 72px;
    background: var(--steel-500);
}
.hero__rail-block {
    position: absolute;
    top: 0;
    left: -0.5px;
    width: 2px;
    height: 18px;
    background: var(--signal);
}
.hero__scroll-label {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--steel-300);
}

/* ---------- page-load shutter ---------- */
.hero__shutters {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex;
    pointer-events: none;
}
.hero__shutter {
    flex: 1 1 25%;
    background: var(--ink-900);
    border-right: 1px solid var(--steel-500);
    transform: scaleY(0);
    transform-origin: top center;
}
.hero__shutter:last-child { border-right: 0; }

/* ==========================================================================
   START STATES — only once JS has confirmed GSAP
   ========================================================================== */
html.js-anim .hero__shutter { transform: scaleY(1); }
html.js-anim .hero__act { overflow: hidden; }

/* Reduced motion: never strand a start state the animation will not clear. */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .hero__shutter { transform: scaleY(0); }
    html.js-anim .hero__act { overflow: visible; }
    .hero__tel-led { animation: none; opacity: 1; }
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 899.98px) {
    .hero {
        min-height: 0;
        padding-block: calc(var(--bar-h) + 44px) 40px;
    }
    .hero__inner { display: block; }
    .hero__ghost { display: none; }
    .hero__grid12 { row-gap: 46px; }
    .hero__title { font-size: clamp(2.1rem, 6.4vw, 3.4rem); }
    .hero__stage { margin-top: 6px; }
    .hero__assembly {
        width: 100%;
        border-left: 0;
        padding-left: 0;
    }
    .hero__svg {
        width: 70vw;
        max-width: 460px;
        max-height: none;
        margin-inline: auto;
    }
    /* the drawing is smaller, so its stamped type is set larger in user units */
    .hero__name { font-size: 23px; letter-spacing: 0.9; }
    .hero__part { font-size: 15px; letter-spacing: 0.6; }
    .hero__idx  { font-size: 30px; }
    .hero__figcap { text-align: center; }
    .hero__foot { margin-top: 52px; }
    .hero__wash {
        background: linear-gradient(180deg, var(--ink-900) 0%, rgba(8, 9, 11, 0.45) 12%, rgba(8, 9, 11, 0.45) 88%, var(--ink-900) 100%);
    }
}

@media (max-width: 640px) {
    .hero__title { font-size: clamp(1.85rem, 8.2vw, 2.6rem); }
    .hero__actions { flex-direction: column; align-items: stretch; gap: 12px; }
    .hero__act { display: block; }
    .hero__eyebrow { font-size: 0.56rem; }
    .hero__eyebrow .hero__lift { gap: 9px; letter-spacing: 0.08em; }
    .hero__figcap { font-size: 0.55rem; letter-spacing: 0.08em; }
    .hero__svg { width: 88vw; }
    .hero__foot {
        flex-direction: column;
        align-items: flex-start;
        gap: 26px;
    }
    .hero__scroll { flex-direction: row; align-items: center; align-self: flex-end; gap: 14px; }
    .hero__rail { width: 56px; height: 1px; }
    .hero__rail-block { width: 18px; height: 2px; top: -0.5px; left: 0; }
    .hero__tel-lift { flex-wrap: wrap; gap: 8px 10px; }
    .hero__tel-note { border-left: 0; padding-left: 0; }
}

/* ============================ READOUT ============================ */
/* ==========================================================================
   #readout — OPERATING READOUT
   A full-bleed instrument band: four hard figures on split-flap digit reels,
   separated by real 1px verticals that draw outward from their midpoints.

   Fallback inversion: every rule below ships the FINAL state.
   Start states live only under html.js-anim (and, for the divider draw, only
   once init() has confirmed DrawSVGPlugin is actually present).
   ========================================================================== */

.readout {
    border-top: 1px solid var(--steel-500);
    border-bottom: 1px solid var(--steel-500);
    padding-block: clamp(64px, 7.4vw, 112px);
    overflow: hidden;
}

/* The printed 12-column grid, dropped a tone so the numerals stay the subject */
.readout__bg {
    top: -40px;
    bottom: -40px;
    opacity: 0.22;
    z-index: 0;
}

.readout__inner { position: relative; z-index: 1; }

/* ---------- header ---------- */
.readout__head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    margin-bottom: clamp(28px, 3.4vw, 44px);
}
.readout__title {
    margin-top: 18px;
    max-width: 18ch;
    /* Trimmed a step below --fs-title: in this band the figures are the subject
       and the headline is the caption. */
    font-size: clamp(1.9rem, 4.4vw, 3.9rem);
}

/* ---------- the two band hairlines ---------- */
.readout__band { background: var(--steel-500); }

/* ---------- the cell field ---------- */
.readout__cells {
    --readout-rowgap: 0px;
    --readout-bleed: clamp(34px, 4vw, 54px);
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    column-gap: var(--gutter);
    row-gap: var(--readout-rowgap);
    padding-block: clamp(34px, 4vw, 54px);
}

.readout__cell {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
}
.readout__cell + .readout__cell { padding-inline-start: clamp(6px, 0.8vw, 12px); }

/* ---------- the structural dividers ---------- */
.readout__div,
.readout__hdiv {
    position: absolute;
    display: block;
    pointer-events: none;
}
.readout__div {
    top: calc(var(--readout-bleed) * -1);
    bottom: calc(var(--readout-bleed) * -1);
    left: calc(var(--gutter) / -2);
    width: 1px;
}
.readout__hdiv { display: none; }

.readout__divsvg { width: 100%; height: 100%; display: block; overflow: visible; }
.readout__divline {
    stroke: var(--steel-400);
    stroke-width: 1;
    fill: none;
}
/* Cell 01 opens the row — it is the container edge, not a divider */
.readout__cell:first-child > .readout__div { display: none; }

/* ---------- cell type ---------- */
.readout__label {
    display: block;
    overflow: hidden;
    max-width: 100%;
    padding-block-end: 2px;
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 700;
    font-variation-settings: 'wdth' 112.5;
    letter-spacing: 0.18em;
    line-height: 1.3;
    text-transform: uppercase;
    color: var(--steel-300);
}
.readout__idx { color: var(--signal); }
/* --steel-350/400 are structure tones and may never carry a character, so the
   separator sits at --steel-300 and is separated by tracking instead. */
.readout__sep { letter-spacing: 0.28em; }

.readout__fig {
    margin-top: clamp(16px, 1.8vw, 26px);
    max-width: 100%;
}
/* Sized so the WIDEST value ("99.98 %") clears its 3-of-12 cell in BOTH paths:
   the GSAP reel (0.62em digit boxes) and the no-GSAP vanilla counter, which
   renders at the font's natural tabular advance and is the wider of the two. */
.readout__figure {
    font-size: clamp(2.4rem, 4.6vw, 4.1rem);
    line-height: 0.88;
}

.readout__clar {
    display: block;
    overflow: hidden;
    margin-top: clamp(14px, 1.6vw, 22px);
    max-width: 26ch;
    font-size: 0.9375rem;
    line-height: 1.5;
    color: var(--bone-300);
}

.readout__lift { display: block; }

/* ---------- footnote row ---------- */
.readout__foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 20px;
    padding-top: clamp(18px, 2vw, 26px);
    flex-wrap: wrap;
}
.readout__note { color: var(--steel-300); max-width: none; }
.readout__stamp { color: var(--steel-300); max-width: none; }

/* ==========================================================================
   START STATES — only once GSAP is confirmed
   ========================================================================== */
html.js-anim .readout__lift { transform: translateY(110%); }
html.js-anim .readout__idx { color: var(--steel-400); }
/* init() adds .readout--draw only when DrawSVGPlugin actually exists, so a
   blocked plugin can never strand the dividers invisible. */
html.js-anim .readout--draw .readout__divline { stroke-dasharray: 0 4000; }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */

/* 2 x 2 — vertical between the columns, horizontal between the rows */
@media (max-width: 899.98px) {
    .readout__cells {
        --readout-rowgap: clamp(34px, 6vw, 52px);
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .readout__figure { font-size: clamp(3rem, 9vw, 5rem); }
    .readout__clar { max-width: 30ch; }

    /* verticals: only the one between column 1 and column 2 */
    .readout__cell:nth-child(3) > .readout__div { display: none; }
    .readout__cell:nth-child(2) > .readout__div {
        display: block;
        top: calc(var(--readout-bleed) * -1);
        bottom: calc(var(--readout-rowgap) / -2);
    }
    .readout__cell:nth-child(4) > .readout__div {
        display: block;
        top: calc(var(--readout-rowgap) / -2);
        bottom: calc(var(--readout-bleed) * -1);
    }

    /* horizontals: above the second row */
    .readout__cell:nth-child(3) > .readout__hdiv,
    .readout__cell:nth-child(4) > .readout__hdiv {
        display: block;
        left: 0;
        right: 0;
        top: calc(var(--readout-rowgap) / -2);
        height: 1px;
    }
    .readout__cell:nth-child(4) > .readout__hdiv { left: calc(var(--gutter) / -2); }
    .readout__cell:nth-child(3) { padding-inline-start: 0; }
}

/* one column */
@media (max-width: 559.98px) {
    .readout__cells {
        --readout-rowgap: clamp(30px, 8vw, 44px);
        grid-template-columns: minmax(0, 1fr);
    }
    .readout__figure { font-size: clamp(3rem, 14vw, 4rem); }
    .readout__cell + .readout__cell { padding-inline-start: 0; }
    .readout__cell > .readout__div { display: none !important; }
    .readout__cell:nth-child(2) > .readout__hdiv,
    .readout__cell:nth-child(3) > .readout__hdiv,
    .readout__cell:nth-child(4) > .readout__hdiv {
        display: block;
        left: 0;
        right: 0;
        top: calc(var(--readout-rowgap) / -2);
        height: 1px;
    }
    .readout__clar { max-width: 34ch; }
    .readout__title { max-width: none; }
    .readout__foot { gap: 10px; }
}

/* ==========================================================================
   REDUCED MOTION — nothing this section hides may stay hidden
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .readout__lift { transform: none; }
    html.js-anim .readout__idx { color: var(--signal); }
    html.js-anim .readout--draw .readout__divline { stroke-dasharray: none; }
}

/* ============================ RAIL ============================ */
/* ==========================================================================
   #RAIL — THE LOAD RAIL
   Two counter-running marquee bars proving integration surface with zero
   logo files. Row A: systems, Archivo wdth 125 / 600. Row B: sectors,
   Martian Mono. Separators are 10x10 --signal squares turned 45 degrees.
   Everything here ships in its FINAL state; start states live only under
   html.js-anim (or are applied by gsap.set inside anim()).
   ========================================================================== */

.rail {
    position: relative;
    /* the one variable the separator relay writes — see rail.js */
    --sep-col: var(--signal);
}

/* --------------------------------------------------------------------------
   1. HEAD — label, statement, surface stamp
   -------------------------------------------------------------------------- */
.rail__head {
    padding-block: clamp(72px, 9vw, 132px) clamp(40px, 5vw, 68px);
}

.rail__head-grid {
    align-items: end;
    row-gap: clamp(32px, 4vw, 48px);
}

.rail__title {
    max-width: 15ch;
}

/* the surface stamp sits on the baseline of the statement */
.rail__meta {
    display: flex;
    flex-direction: column;
    align-self: end;
}
.rail__meta .rule {
    margin-bottom: 10px;
}
.rail__meta .spec-row:first-of-type {
    border-top: 0;
}

/* --------------------------------------------------------------------------
   2. BARS — full bleed, hairline top on each, hairline bottom on the last
   -------------------------------------------------------------------------- */
.rail__bars {
    position: relative;
    /* the bars are full bleed, but their content starts on the page gutter */
    --rail-inset: calc(max(0px, (100% - var(--container-max)) / 2) + var(--container-pad));
}

.rail__bar {
    position: relative;
    display: flex;
    align-items: stretch;
    height: 56px;
    padding-left: var(--rail-inset);
    border-top: 1px solid var(--steel-500);
    background: var(--ink-900);
    overflow: hidden;
    user-select: none;
    -webkit-user-select: none;
    transition: background-color var(--t-state) var(--ease-machine);
}
.rail__bar:last-child {
    border-bottom: 1px solid var(--steel-500);
}
.rail__bar.is-held {
    background: var(--ink-800);
    cursor: grabbing;
}
.rail__bar:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: -3px;
}

/* the print head — a hairline that runs the bar once as it wipes open */
.rail__scan {
    position: absolute;
    top: 0;
    bottom: 0;
    left: -2px;
    z-index: 3;
    width: 2px;
    background: var(--signal);
    pointer-events: none;
    opacity: 0;
}
html.js-anim .rail__scan { opacity: 1; }

/* channel stamp — opaque, sits outside the marquee mask */
.rail__stamp {
    position: relative;
    z-index: 2;
    flex: none;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    width: clamp(96px, 10vw, 138px);
    padding-inline: 0 14px;
    border-right: 1px solid var(--steel-500);
    background: var(--ink-900);
    font-family: var(--font-mono);
    text-transform: uppercase;
    line-height: 1;
    white-space: nowrap;
}
.rail__bar.is-held .rail__stamp { background: var(--ink-800); }

.rail__stamp-key {
    font-size: var(--fs-mono-sm);
    font-weight: 700;
    letter-spacing: 0.18em;
    color: var(--steel-300);
}
.rail__stamp-name {
    font-size: var(--fs-mono);
    font-weight: 700;
    font-variation-settings: 'wdth' 112.5;
    letter-spacing: 0.14em;
    color: var(--bone-100);
    transition: color var(--t-state) var(--ease-machine);
}
.rail__bar.is-held .rail__stamp-name,
.rail__bar:focus-visible .rail__stamp-name { color: var(--signal); }

/* --------------------------------------------------------------------------
   3. MARQUEE CONTENT
   -------------------------------------------------------------------------- */
.rail__marquee {
    flex: 1 1 auto;
    min-width: 0;
}
.rail__marquee .marquee__track,
.rail__marquee .marquee__content {
    align-items: center;
    height: 100%;
}
.rail__set {
    display: inline-flex;
    align-items: center;
    flex: none;
}

.rail__item {
    font-size: 1rem;
    line-height: 1;
}
.rail__bar--a .rail__item {
    font-family: var(--font-display);
    font-weight: 600;
    font-variation-settings: 'wdth' 125;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--bone-100);
}
.rail__bar--b .rail__item {
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 500;
    font-variation-settings: 'wdth' 100;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--bone-300);
}

/* the only orange in the band until the relay closes */
.rail__sep {
    flex: none;
    width: 10px;
    height: 10px;
    background: var(--sep-col);
    transform: rotate(45deg);
}
.rail__bar--a .rail__sep { margin-inline: clamp(20px, 2.4vw, 38px); }
.rail__bar--b .rail__sep { margin-inline: clamp(26px, 3.2vw, 52px); }

/* --------------------------------------------------------------------------
   4. FOOT — the affordance stamp
   -------------------------------------------------------------------------- */
.rail__foot {
    padding-block: 18px clamp(72px, 9vw, 132px);
}
.rail__hint {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    color: var(--steel-300);
}
.rail__hint-mark {
    width: 6px;
    height: 6px;
    background: var(--sep-col);
    flex: none;
}

/* --------------------------------------------------------------------------
   5. START STATES — only once GSAP is confirmed present
   -------------------------------------------------------------------------- */
html.js-anim .rail { --sep-col: var(--steel-400); }
html.js-anim .rail__bar { cursor: grab; }

/* No GSAP: the rails are static text, so the leading edge must not be faded
   away by a mask that only earns its keep while the row is moving. The
   trailing fade stays — the row still runs off the right edge. */
html.no-anim .rail__marquee {
    -webkit-mask-image: linear-gradient(90deg, #000 90%, transparent);
    mask-image: linear-gradient(90deg, #000 90%, transparent);
}
/* …and an affordance stamp for a gesture that cannot happen is a lie. */
html.no-anim .rail__hint { display: none; }

/* --------------------------------------------------------------------------
   6. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 899.98px) {
    .rail__head-grid { align-items: start; }
    .rail__meta { align-self: start; }
    .rail__title { max-width: 18ch; }
}

@media (max-width: 720px) {
    .rail__bar { height: 48px; }
    .rail__stamp { width: clamp(84px, 24vw, 108px); }
    .rail__bar--a .rail__item { font-size: 0.9rem; }
    .rail__bar--a .rail__sep { margin-inline: 18px; }
    .rail__bar--b .rail__sep { margin-inline: 22px; }
}

@media (max-width: 420px) {
    .rail__stamp { width: 84px; padding-inline: 0 10px; }
    .rail__hint { letter-spacing: 0.1em; }
}

/* Reduced motion: nothing here may be left stranded in a start state, and
   nothing may promise an interaction the reduced branch never wires up. */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .rail { --sep-col: var(--signal); }
    html.js-anim .rail__scan { opacity: 0; }
    html.js-anim .rail__bar { cursor: auto; }
    .rail__hint { display: none; }
}

/* ============================ DIAGNOSTIC ============================ */
/* ==========================================================================
   #diagnostic — WHERE AI STALLS
   Sticky diagnosis on the left, four fault plates on the right.
   Every element below ships in its FINAL state; start states live only
   under html.js-anim (and are unwound again under reduced motion).
   ========================================================================== */

.diagnostic { position: relative; isolation: isolate; }

/* The printed grid bleeds past the section edges so the depth-law translate
   never exposes a hard boundary; a mask fades it out top and bottom. */
.diagnostic__bg {
    inset: -140px 0;
    opacity: 0.26;
    -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 18%, #000 82%, transparent 100%);
    mask-image: linear-gradient(180deg, transparent 0, #000 18%, #000 82%, transparent 100%);
}

.diagnostic__layout {
    position: relative;
    z-index: 1;
    row-gap: clamp(56px, 7vw, 92px);
    align-items: start;
}

/* ---------- LEFT COLUMN ---------- */
.diagnostic__col {
    position: sticky;
    top: calc(var(--bar-h) + 48px);
    align-self: start;
    min-width: 0;
}
.diagnostic__sticky { position: relative; }

/* Three authored lines, the accent phrase isolated on the last one. The
   breaks are hard, so the balancer is switched off; the small width slack
   only absorbs face-metric variance and never reaches column 6. */
.diagnostic__title {
    position: relative;
    width: calc(100% + clamp(0px, 3vw, 44px));
    font-size: clamp(1.35rem, 2.35vw, 1.95rem);
    line-height: 1.04;
    letter-spacing: -0.015em;
    margin-top: 24px;
    text-wrap: wrap;
}

.diagnostic .section-desc { margin-top: 22px; }

.diagnostic__fig {
    margin-top: clamp(32px, 3.4vw, 46px);
    /* the figure fills its column so its right edge and caption rule line up
       with the description measure instead of stopping short of it */
    max-width: 100%;
}
.diagnostic__chart {
    width: 100%;
    height: auto;
    overflow: visible;
}
.diagnostic__gridlines line { stroke: var(--grid-line-soft); stroke-width: 1; }
.diagnostic__axis { stroke: var(--steel-400); stroke-width: 1; }

.diagnostic__plateau {
    fill: none;
    stroke: var(--steel-400);
    stroke-width: 1.5;
    stroke-dasharray: 3 4;
    stroke-linecap: butt;
}
.diagnostic__stepline {
    fill: none;
    stroke: var(--signal);
    stroke-width: 2;
    stroke-linejoin: miter;
    stroke-linecap: butt;
}
.diagnostic__playhead { stroke: var(--signal-rule); stroke-width: 1; stroke-dasharray: 2 4; }

.diagnostic__chartlabel text {
    font-family: var(--font-mono);
    font-size: 8.5px;
    font-weight: 500;
    letter-spacing: 0.16em;
    fill: var(--steel-300);
}

.diagnostic__cap {
    display: block;
    margin-top: 16px;
    padding-top: 10px;
    border-top: 1px solid var(--steel-500);
    color: var(--steel-300);
}

/* ---------- RIGHT COLUMN — FAULT PLATES ---------- */
.diagnostic__faults {
    display: flex;
    flex-direction: column;
    gap: 40px;
    min-width: 0;
}

.diag-fault-row {
    position: relative;
    --fleader: clamp(28px, 3.6vw, 64px);
    --fpad: clamp(22px, 2.1vw, 30px);
}

/* the 1px leader that draws out of the left gutter to meet the plate */
.diag-fault__leader {
    position: absolute;
    top: calc(var(--fpad) + 7px);
    left: calc(-1 * var(--fleader));
    width: var(--fleader);
    height: 1px;
    background: var(--steel-400);
    transform-origin: left center;
    pointer-events: none;
}

.diag-fault {
    position: relative;
    overflow: hidden;
    padding: var(--fpad);
    display: grid;
    grid-template-columns: minmax(0, 1fr) 120px;
    grid-template-areas:
        "head  head"
        "body  chart";
    column-gap: clamp(20px, 2.2vw, 32px);
    row-gap: 20px;
}

.diag-fault__ghost {
    position: absolute;
    top: calc(var(--fpad) - 4px);
    right: var(--fpad);
    font-size: clamp(2.4rem, 3.1vw, 3.3rem);
    z-index: 0;
}

.diag-fault__head {
    grid-area: head;
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 16px;
    padding-right: 68px;
    min-height: 14px;
}
.diag-fault__code {
    flex: none;
    color: var(--steel-300);
    line-height: 1;
}
.diag-fault__rule { flex: 1 1 auto; min-width: 16px; }

.diag-fault__body {
    grid-area: body;
    position: relative;
    z-index: 1;
}
.diag-fault__title {
    font-family: var(--font-display);
    font-size: clamp(1.12rem, 1.35vw, 1.32rem);
    font-weight: 700;
    font-variation-settings: 'wdth' 112;
    line-height: 1.12;
    letter-spacing: -0.01em;
    color: var(--bone-100);
}
.diag-fault__text {
    margin-top: 10px;
    max-width: 44ch;
    font-size: 0.94rem;
    line-height: 1.6;
    color: var(--bone-300);
}

.diag-fault__chart {
    grid-area: chart;
    align-self: end;
    justify-self: end;
    width: 120px;
    position: relative;
    z-index: 1;
}
.mc { width: 120px; height: 36px; display: block; }
.mc__bar  { fill: var(--steel-350); }
.mc__base { fill: var(--steel-500); }
.mc__scan { fill: var(--signal); }

/* ==========================================================================
   ANIMATION START STATES — only once GSAP is confirmed present
   ========================================================================== */
html.js-anim .diag-fault { clip-path: inset(0 100% 0 0); }
html.js-anim .diag-fault__leader { transform: scaleX(0); }
html.js-anim .diag-fault__code { color: var(--steel-400); }
html.js-anim .diagnostic__stepline { stroke: var(--steel-400); }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 899.98px) {
    .diagnostic__col {
        position: static;
        top: auto;
    }
    .diagnostic__title {
        width: 100%;
        /* the accent phrase is an unbreakable inline-block: it governs the size */
        font-size: clamp(1.25rem, 5.6vw, 2.3rem);
    }
    .diagnostic__fig { max-width: 520px; }
    .diag-fault-row { --fleader: 16px; }
    .diagnostic__faults { gap: 32px; }
}

@media (max-width: 719.98px) {
    .diag-fault {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "head"
            "body"
            "chart";
    }
    .diag-fault__chart { justify-self: start; }
    .diag-fault__text { max-width: none; }
}

/* the figure scales with the column, so the annotations are re-cut in
   viewBox units to stay legible once the SVG is drawn under ~420px wide */
@media (max-width: 640px) {
    .diagnostic__chartlabel text { font-size: 11px; letter-spacing: 0.12em; }
}

@media (max-width: 460px) {
    .diag-fault__ghost { font-size: 2.2rem; }
    .diag-fault__head { padding-right: 46px; }
}

/* ==========================================================================
   REDUCED MOTION — never leave a start state stranded
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .diag-fault { clip-path: none; }
    html.js-anim .diag-fault__leader { transform: none; }
    html.js-anim .diag-fault__code { color: var(--steel-300); }
    html.js-anim .diagnostic__stepline { stroke: var(--signal); }
}

/* ============================ PRINCIPLES ============================ */
/* ==========================================================================
   #principles — THE SIGNATURE FLIP
   Three loose parts on the bench lock flush into one row; adjacent borders
   collapse to a single shared hairline and a 2px signal line draws beneath.

   FALLBACK INVERSION: everything below ships the LOCKED, fully drawn state.
   The scattered layout and the clip start states exist only under
   html.js-anim + (min-width:900px) + (prefers-reduced-motion:no-preference),
   which is exactly the one matchMedia branch that performs the Flip.
   ========================================================================== */

.principles { overflow: hidden; }

/* ---------- header ---------- */
.principles__header { align-items: end; }

/* The copy's marked break is after THREE RULES; text-wrap:balance was splitting
   the second line again and stranding "WE" on a line of its own. */
.principles__headline { text-wrap: wrap; }

.principles__header-aside {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
}
.principles__header-aside .section-desc { margin-top: 0; }

.principles__aside-rule { max-width: 180px; }

.principles__aside-note {
    color: var(--steel-300);
    letter-spacing: 0.18em;
}

/* ---------- meta strip above the rack ---------- */
.principles__meta {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: 22px;
}
.principles__meta-tag {
    flex: none;
    color: var(--steel-300);
    white-space: nowrap;
}
.principles__meta-tag--end { color: var(--steel-300); }
.principles__meta-rule { flex: 1 1 auto; width: auto; min-width: 24px; }

/* ---------- the stage reserves the locked height, in CSS, for both states ---------- */
.principles__stage { position: relative; }

/* ---------- the rack: LOCKED is the shipped state ---------- */
.principles__rack {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
}

/* ---------- the panel ---------- */
.principles__panel {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding: clamp(22px, 2.2vw, 34px);
    overflow: hidden;
    isolation: isolate;
}
.principles__panel--1 { z-index: 1; }
.principles__panel--2 { z-index: 2; }
.principles__panel--3 { z-index: 3; }

/* adjacent borders collapse to one shared hairline */
.principles__panel + .principles__panel { margin-left: -1px; }

.principles__ghost {
    position: absolute;
    top: -0.14em;
    right: -0.12em;
    z-index: 0;
    font-size: clamp(96px, 11vw, 178px);
    letter-spacing: -0.04em;
}

.principles__top,
.principles__foot {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 14px;
    flex: none;
}
/* the void under the part number is where the ghost numeral lives */
.principles__top { margin-bottom: clamp(48px, 5vw, 76px); }
.principles__foot { margin-top: 26px; }
.principles__hair { flex: 1 1 auto; width: auto; min-width: 20px; }

.principles__part {
    flex: none;
    color: var(--bone-100);
    letter-spacing: 0.2em;
}

.principles__body { position: relative; z-index: 1; flex: 1 1 auto; }

.principles__title {
    font-family: var(--font-display);
    font-size: var(--fs-block);
    font-weight: 700;
    font-variation-settings: 'wdth' 110;
    line-height: 1.06;
    letter-spacing: -0.01em;
    color: var(--bone-100);
    margin-bottom: 16px;
    text-wrap: balance;
}

.principles__text {
    font-size: 0.95rem;
    line-height: 1.6;
    color: var(--bone-200);
    max-width: 42ch;
}

.principles__stamp {
    flex: none;
    color: var(--steel-300);
    letter-spacing: 0.2em;
}

/* ---------- the 2px signal line beneath all three ---------- */
.principles__underline {
    display: block;
    width: 100%;
    height: 2px;
    margin-top: 0;
}
/* Final state ships here: the line is drawn and orange. */
.principles__underline-line { stroke: var(--signal); }

/* ==========================================================================
   DESKTOP — the stage reserves one constant height so the Flip cannot move
   the document. The rack fills it absolutely in BOTH states.
   ========================================================================== */
@media (min-width: 900px) {
    /* Nine columns for the headline so "WE DO NOT BEND." holds one line and
       the copy's marked break is the only break; three for the margin note. */
    .principles__header-lead  { grid-column: 1 / 10; }
    .principles__header-aside { grid-column: 10 / -1; }

    /* One constant height for BOTH states, measured against the tallest
       scattered part (343px + its 30px drop) and the tallest locked part. */
    .principles__stage {
        height: 380px;
        min-height: 380px;
    }
    .principles__rack {
        position: absolute;
        inset: 0;
    }
    .principles__panel { height: 100%; }
}

/* ==========================================================================
   THE SCATTERED START STATE — only ever seen in the one branch that flips it
   ========================================================================== */
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {

    html.js-anim .principles__panel { clip-path: inset(0 0 100% 0); }

    html.js-anim .principles__rack.is-scattered { display: block; }

    /* Loose parts on the bench: narrower than their slot, standing apart, each
       one dropped a little further than the last. Every part stays completely
       readable before the lock — nothing is stacked on top of anything. */
    html.js-anim .principles__rack.is-scattered .principles__panel {
        position: absolute;
        margin-left: 0;
        width: 32%;
        height: auto;
    }
    /* Not a diagonal: three parts resting at three different levels on the
       bench, which the lock levels, closes up and stretches to one height. */
    html.js-anim .principles__rack.is-scattered .principles__panel--1 { top: 30px; left: 0; }
    html.js-anim .principles__rack.is-scattered .principles__panel--2 { top: 0;    left: 34%; }
    html.js-anim .principles__rack.is-scattered .principles__panel--3 { top: 22px; left: 68%; }

    /* the signal arrives last: the line draws in steel and relays to orange */
    html.js-anim .principles__underline-line {
        stroke: var(--steel-400);
        stroke-dasharray: 1200;
        stroke-dashoffset: 1200;
    }
}

/* ==========================================================================
   BELOW 900px — the scattered state is never used. Panels stack flush and
   enter with the standard clip wipe.
   ========================================================================== */
@media (max-width: 899.98px) {
    .principles__header { row-gap: 34px; }
    .principles__header-aside { align-items: flex-start; }
    .principles__aside-rule { max-width: 100%; }

    .principles__rack {
        grid-template-columns: 1fr;
    }
    .principles__panel { min-height: 0; }
    .principles__top { margin-bottom: 52px; }
    .principles__panel + .principles__panel {
        margin-left: 0;
        margin-top: -1px;
    }
    .principles__ghost { font-size: clamp(84px, 24vw, 132px); }
    .principles__text { max-width: 52ch; }
}

@media (max-width: 899.98px) and (prefers-reduced-motion: no-preference) {
    html.js-anim .principles__panel { clip-path: inset(0 0 100% 0); }
    html.js-anim .principles__underline-line {
        stroke: var(--steel-400);
        stroke-dasharray: 1200;
        stroke-dashoffset: 1200;
    }
}

@media (max-width: 400px) {
    /* 320px of well at 360px: one step down keeps THREE RULES WE on a single line
       rather than stranding THREE. Font-size only — no token is redefined. */
    .principles__headline { font-size: 1.85rem; }
}

@media (max-width: 640px) {
    /* The desktop break gives "THREE RULES / WE DO NOT BEND." Below 640 the accent —
       an inline-block, so it cannot be broken into — no longer fits beside WE and drops
       whole, stranding WE on a line of its own. Dropping the hard break lets the line
       fall naturally as "THREE RULES WE / DO NOT BEND." */
    .principles__headline br { display: none; }
    .principles__meta { gap: 12px; }
    .principles__meta-tag--end { display: none; }
    .principles__panel { padding: 24px 20px; }
}

/* ============================ PLATFORM ============================ */
/* ==========================================================================
   #platform — "THE PIPELINE"
   A 100vh stage: compact header strip, a horizontal track of five station
   panels, and a HUD carrying the STATION n / 05 counter and five dot buttons
   on a 1px rail. One --signal conveyor runs across the top of the rail through
   every panel and a --volt payload rides it.

   FALLBACK INVERSION, APPLIED TO LAYOUT. The track ships as a REAL scroll
   container at every width — swipe, shift-wheel, arrow keys and the dot
   buttons all work with no JS at all. The pinned, GSAP-transformed variant is
   switched on only under html.js-anim + (min-width:900px) + no-preference,
   which is exactly the one matchMedia branch that pins. Nothing in this file
   hides anything: no start state lives outside html.js-anim.
   ========================================================================== */

.platform { overflow: hidden; isolation: isolate; }

/* ---------- the stage: one viewport, three rows ---------- */
.platform__stage {
    position: relative;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    row-gap: clamp(16px, 2.4vh, 32px);
    height: 100vh;
    height: 100svh;
    /* A floor, not a target: any value above the real viewport pushes the HUD
       off the bottom of a pinned stage, so it stays under every laptop height. */
    min-height: 600px;
    padding-block: calc(var(--bar-h) + clamp(18px, 3vh, 44px)) clamp(16px, 2.4vh, 30px);
    overflow: hidden;
}
.platform__bg { opacity: 0.34; z-index: 0; }
.platform__top,
.platform__track,
.platform__hud { position: relative; z-index: 1; }

/* ---------- header strip ---------- */
.platform__header { align-items: end; row-gap: 20px; }

/* The section title is set small here on purpose: it shares a single viewport
   with the track and the HUD, so it is a stamped header, not a hero. */
.platform__title {
    font-size: clamp(1.75rem, 2.9vw, 2.75rem);
    line-height: 0.94;
    margin-top: 16px;
}
.platform__aside {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
}
.platform__lede {
    margin-top: 0;
    font-size: 0.95rem;
    line-height: 1.55;
    color: var(--bone-300);
}
.platform__aside-rule { max-width: 180px; background: var(--steel-400); }
.platform__aside-note { color: var(--steel-300); letter-spacing: 0.18em; }

/* ---------- the track ---------- */
.platform__track {
    display: flex;
    align-items: center;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -ms-overflow-style: none;
    overscroll-behavior-x: contain;
}
.platform__track::-webkit-scrollbar { width: 0; height: 0; display: none; }

.platform__rail {
    position: relative;
    display: flex;
    align-items: stretch;
    width: max-content;
    /* On a very tall desktop a 100%-height rail would stretch every panel past
       1000px and strand each drawing in a void, so the band is capped and
       centred: header at the top, machine across the middle, HUD on the rule. */
    height: min(100%, 660px);
    padding-top: 28px;   /* the conveyor band */
    /* past --container-wide the track still bleeds, but the first spine lines
       up with the header's container edge instead of stranding it */
    padding-left: max(0px, calc((100vw - var(--container-wide)) / 2));
}

/* ---------- the conveyor ---------- */
.platform__conveyor {
    position: absolute;
    top: 0; left: 0;
    width: 100%;
    height: 28px;
    pointer-events: none;
}
/* preserveAspectRatio="none": the viewBox is 1000 wide and the SVG stretches to
   the whole rail. The stroke is horizontal, so only the y-scale (1:1) governs
   its rendered weight — it stays a true 1px hairline at any rail width, and
   DrawSVG's dash maths stays in unscaled user units. */
.platform__conveyor-svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 28px;
    overflow: visible;
}
.platform__conveyor-rest {
    fill: none;
    stroke: var(--steel-400);
    stroke-width: 1;
}
.platform__conveyor-line {
    fill: none;
    stroke: var(--signal);
    stroke-width: 1;
}
.platform__payload {
    position: absolute;
    top: 0; left: 0;
    width: 12px; height: 12px;
    margin: -6px 0 0 -6px;
    background: var(--volt);
    transform: translate(20px, 14px);   /* no-JS: parked on the conveyor line */
}

/* ---------- a station panel ---------- */
.pl-station {
    position: relative;
    flex: none;
    display: flex;
    width: min(74vw, 620px);
    height: 100%;
    border-left: 1px solid var(--steel-500);
    scroll-snap-align: start;
}
.pl-station:last-child {
    width: min(88vw, 720px);
    border-right: 1px solid var(--steel-500);
}

/* the 90°-rotated station stamp, sitting on the divider */
.pl-station__index {
    position: absolute;
    top: 0; left: 0;
    width: 34px; height: 100%;
    display: flex;
    align-items: flex-start;      /* never let the stamp stretch — a stretched
                                     box rotates into the middle of the panel */
    justify-content: center;
    pointer-events: none;
}
.pl-station__index span {
    display: block;
    margin-top: 34px;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 700;
    letter-spacing: 0.26em;
    line-height: 1;
    text-transform: uppercase;
    white-space: nowrap;
    /* --steel-350 is a structure tone and may never carry a character, so the
       rotated stamp sits at --steel-300 and is held back by tracking instead. */
    color: var(--steel-300);
    transform: rotate(90deg);
    transform-origin: center center;
}

/* the tap off the conveyor: a junction square on the line, a drop into the head */
.pl-station__junction {
    position: absolute;
    top: -19px; left: 30px;
    width: 10px; height: 10px;
    background: var(--ink-800);
    border: 1px solid var(--signal);
}
.pl-station__drop {
    position: absolute;
    top: -7px; left: 34px;
    width: 1px; height: 7px;
    background: var(--signal-rule);
}

/* overflow:hidden keeps the x:60 entrances from extending the track's
   scrollable width while they are in flight. */
.pl-station__inner {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: clamp(10px, 1.5vh, 18px);
    padding: 0 clamp(16px, 2vw, 34px) 0 46px;
}

.pl-station__head {
    flex: none;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    border-bottom: 1px solid var(--steel-500);
}
.pl-station__part {
    flex: none;
    color: var(--signal);      /* FINAL state — the relay starts it at --steel-400 */
}
.pl-station__title {
    font-family: var(--font-display);
    font-size: clamp(1.1rem, 1.45vw, 1.45rem);
    font-weight: 800;
    font-variation-settings: 'wdth' 118;
    letter-spacing: -0.01em;
    line-height: 1;
    color: var(--bone-100);
}

.pl-station__figure {
    position: relative;
    flex: 1 1 auto;
    min-height: 132px;
}
.pl-diagram {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.pl-station__text {
    flex: none;
    max-width: 56ch;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--bone-300);
}

.pl-station__specs { flex: none; border-top: 1px solid var(--steel-500); }
.pl-station__specs .spec-row:first-child { padding-top: 11px; }

/* ---------- the diagram vocabulary: hairlines and four graphite tones ---------- */
/* Four tonal steps, read at ~0.7 of the drawn scale: every weight here is one
   step lighter than the same part would be at full size, or the hairlines
   disappear once the SVG is scaled down into a panel. */
.pl-diagram .d-line   { fill: none; stroke: var(--steel-350); stroke-width: 1; }
.pl-diagram .d-bus    { fill: none; stroke: var(--steel-300); stroke-width: 1.5; }
.pl-diagram .d-hair   { fill: none; stroke: var(--steel-400); stroke-width: 1; }
.pl-diagram .d-dash,
.pl-diagram .d-dash-draw { fill: none; stroke: var(--steel-400); stroke-width: 1; stroke-dasharray: 2 5; }
.pl-diagram .d-step   { fill: none; stroke: var(--bone-300); stroke-width: 1.5; }
.pl-diagram .d-box    { fill: var(--ink-700); stroke: var(--steel-400); stroke-width: 1; }
.pl-diagram .d-box--raised { fill: var(--ink-600); stroke: var(--steel-350); stroke-width: 1; }
.pl-diagram .d-hair-box { fill: none; stroke: var(--steel-400); stroke-width: 1; }
.pl-diagram .d-fill   { fill: var(--steel-300); }
.pl-diagram .d-fill--soft { fill: var(--steel-400); }
.pl-diagram .d-key    { fill: var(--ink-800); stroke: var(--signal); stroke-width: 1.5; }
.pl-diagram .d-key--frame { fill: none; }
.pl-diagram .d-tag {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1.1px;
    fill: var(--steel-300);
}
.pl-diagram .d-tag--lit { fill: var(--bone-200); }

/* ---------- HUD ---------- */
.platform__hud-inner {
    display: flex;
    align-items: center;
    gap: clamp(14px, 2.4vw, 34px);
}
.pl-counter {
    flex: none;
    display: inline-flex;
    align-items: baseline;
    gap: 9px;
    max-width: none;
    margin: 0;
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 700;
    letter-spacing: 0.2em;
    line-height: 1;
    text-transform: uppercase;
    color: var(--bone-100);
}
.pl-counter__total { color: var(--steel-300); font-weight: 400; }

.platform__hud-rule { flex: 1 1 auto; width: auto; min-width: 20px; }

.pl-dots { position: relative; display: flex; flex: none; }
.pl-dots::before {
    content: '';
    position: absolute;
    left: 22px; right: 22px;
    top: 50%;
    height: 1px;
    background: var(--steel-500);
}
.pl-dot {
    position: relative;
    width: 44px; height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.pl-dot__mark {
    position: relative;
    width: 11px; height: 11px;
    background: var(--ink-800);
    border: 1px solid var(--steel-400);
    transition: border-color var(--t-state) var(--ease-machine),
                background-color var(--t-state) var(--ease-machine);
}
.pl-dot:hover .pl-dot__mark,
.pl-dot:focus-visible .pl-dot__mark { border-color: var(--signal); }
.pl-dot.is-active .pl-dot__mark { background: var(--signal); border-color: var(--signal); }

/* ==========================================================================
   THE PINNED VARIANT — only in the one matchMedia branch that pins
   ========================================================================== */
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
    html.js-anim .platform__track {
        overflow: hidden;
        scroll-snap-type: none;
    }
}

/* ==========================================================================
   THE SHORT DESKTOP — a 13" laptop is ~700px of viewport, not 900
   The stage is one viewport tall, so the panel's four blocks (head, drawing,
   prose, three spec rows) have to fit inside whatever is left after the
   header and the HUD. Below ~780px of viewport they do not, and the third
   spec row is guillotined by .pl-station__inner's overflow. The header and
   the rhythm give the height back, and the drawing — the only elastic block
   — is released to absorb whatever is still missing.
   ========================================================================== */
@media (min-width: 900px) and (max-height: 780px) {
    .platform__stage {
        row-gap: 14px;
        padding-block: calc(var(--bar-h) + 14px) 14px;
    }
    .platform__title { font-size: clamp(1.5rem, 2.3vw, 2.1rem); margin-top: 12px; }
    .platform__lede { font-size: 0.9rem; line-height: 1.5; }
    .pl-station__inner { gap: 10px; }
    .pl-station__figure { min-height: 0; }
    .pl-station__text { font-size: 0.85rem; line-height: 1.45; }
    .pl-station__specs .spec-row { padding: 7px 0; }
    .pl-station__specs .spec-row:first-child { padding-top: 9px; }
}

/* ==========================================================================
   RESPONSIVE — below 900px the pin is gone; the track is swiped
   ========================================================================== */
@media (max-width: 899.98px) {
    .platform__stage {
        height: auto;
        min-height: 0;
        row-gap: 30px;
        padding-block: clamp(64px, 11vw, 104px) clamp(40px, 8vw, 68px);
        overflow: visible;
    }
    .platform__header { row-gap: 26px; }
    .platform__title { font-size: clamp(1.375rem, 5.7vw, 2.6rem); }
    .platform__aside-rule { max-width: 120px; }

    .platform__track { display: block; }
    .platform__rail { height: auto; }
    .pl-station,
    .pl-station:last-child { width: 86vw; height: auto; }
    .pl-station__inner {
        padding: 0 20px 0 42px;
        gap: 18px;
        padding-bottom: 4px;
    }
    .pl-station__figure { position: static; flex: none; min-height: 0; }
    .pl-diagram {
        position: static;
        width: 100%;
        height: auto;
        aspect-ratio: 620 / 320;
    }
    .pl-station__index span { margin-top: 30px; }
    .pl-station__text { font-size: 0.9rem; }

    /* The drawing is rendered at roughly half its desktop scale here, so its
       stamped type and every hairline are set larger IN USER UNITS — the same
       correction the hero applies to its assembly. */
    .pl-diagram .d-tag { font-size: 17px; letter-spacing: 1.5px; }
    .pl-diagram .d-line,
    .pl-diagram .d-hair,
    .pl-diagram .d-hair-box,
    .pl-diagram .d-box,
    .pl-diagram .d-box--raised { stroke-width: 1.7; }
    .pl-diagram .d-dash,
    .pl-diagram .d-dash-draw { stroke-width: 1.7; stroke-dasharray: 3 7; }
    .pl-diagram .d-bus,
    .pl-diagram .d-step { stroke-width: 2.4; }
    .pl-diagram .d-key { stroke-width: 2.6; }

    .platform__hud-inner { gap: 14px; }
    .pl-counter { font-size: var(--fs-mono-sm); letter-spacing: 0.16em; }
}

@media (max-width: 640px) {
    .pl-station,
    .pl-station:last-child { width: 90vw; }
    .pl-station__inner { padding-left: 40px; }
    .platform__hud-inner { flex-wrap: wrap; row-gap: 10px; }
    .platform__hud-rule { display: none; }
    .pl-dots { margin-left: auto; }
    .pl-diagram { aspect-ratio: 620 / 340; }
}

/* Reduced motion: the payload never rides, so park it on the first junction
   and leave the track as the native scroller it already is. */
@media (prefers-reduced-motion: reduce) {
    .platform__payload { transform: translate(20px, 14px); }
}

/* ============================ SOLUTIONS ============================ */
/* ==========================================================================
   #solutions — "THE LINE ITEMS"
   Five numbered rows on a hairline ledger. A row is a button: hovering wipes
   an orange fill across it from the left and inverts every character to
   --paper-ink; opening it grows the row into a spec header and runs a drawer
   out beneath on --ink-700.

   FALLBACK INVERSION: every drawer below ships OPEN and fully drawn. The
   closed state exists only once js/solutions.js has run (.solutions.is-live),
   and the row entrance start state only under html.js-anim. Block the vendor
   scripts and this section reads as five printed spec sheets.
   ========================================================================== */

.solutions {
    position: relative;
    overflow: hidden;
    isolation: isolate;

    /* the ledger grid — the row and its drawer share these four tracks so the
       lede lands under the title and the specs land under the description */
    --sol-num: clamp(104px, 9vw, 140px);
    --sol-t: minmax(0, 3.6fr);
    --sol-d: minmax(0, 5fr);
    --sol-a: minmax(184px, auto);
    --sol-h: 132px;
    --sol-h-open: 176px;
}

.solutions__bg {
    z-index: 0;
    opacity: 0.34;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 46%);
    mask-image: linear-gradient(180deg, #000 0%, transparent 46%);
}
.solutions .container { position: relative; z-index: 1; }

/* ---------- header ---------- */
.solutions__header { align-items: end; }

.solutions__aside {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
}
.solutions__aside .section-desc { margin-top: 0; }
.solutions__aside-rule { max-width: 180px; }
.solutions__aside-note { color: var(--steel-300); letter-spacing: 0.18em; }

/* ---------- instrument strip ---------- */
.solutions__meta {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: 20px;
}
.solutions__meta-tag { flex: none; color: var(--steel-300); white-space: nowrap; }
.solutions__meta-rule { flex: 1 1 auto; width: auto; min-width: 24px; }

/* ---------- the ledger ---------- */
.solutions__list { position: relative; }
.solutions__rows { border-top: 1px solid var(--steel-500); }

.solution {
    position: relative;
    border-bottom: 1px solid var(--steel-500);
}

/* the open marker: a 3px signal bar drawn top-down in the left margin — it
   sits OUTSIDE the text column so it never crosses a character, and it takes
   its colour only in the last 0.24s of the open sequence */
.solution__mark {
    position: absolute;
    left: -14px;
    top: 0;
    bottom: -1px;
    z-index: 3;
    width: 3px;
    background: var(--signal);
    transform-origin: top center;
    pointer-events: none;
}
/* FALLBACK INVERSION: the marker ships DRAWN — with the scripts blocked every
   sheet stands open and every sheet is marked. It can only retract once
   js/solutions.js has run and taken ownership of the open state. */
.solutions.is-live .solution:not(.is-open) .solution__mark { transform: scaleY(0); }

/* the heading wraps the control — APG accordion, so the row is reachable by
   heading navigation and by TAB, and Enter/Space run the identical path */
.solution__h { margin: 0; font: inherit; font-weight: inherit; }

.solution-row {
    position: relative;
    display: block;
    width: 100%;
    overflow: hidden;
    isolation: isolate;
    text-align: left;
    color: inherit;
    -webkit-tap-highlight-color: transparent;
}
.solution-row:focus-visible { outline-offset: -3px; }

/* HOVER IS A WIPE, NEVER A TRANSFORM */
.solution__fill {
    position: absolute;
    inset: 0;
    z-index: 0;
    background: var(--signal);
    clip-path: inset(0 100% 0 0);
    transition: clip-path var(--t-state) var(--ease-machine);
    pointer-events: none;
}
.solution:not(.is-open) .solution-row:hover .solution__fill,
.solution:not(.is-open) .solution-row:focus-visible .solution__fill { clip-path: inset(0); }

/* ---------- the row grid ---------- */
.solution__lift {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: var(--sol-num) var(--sol-t) var(--sol-d) var(--sol-a);
    align-items: center;
    gap: var(--gutter);
    min-height: var(--sol-h);
    padding-block: 20px;
}
/* OPEN: the row becomes the drawer's header — everything settles to the
   bottom rule and the stamp strip takes the air above it. */
.solution.is-open .solution__lift {
    align-items: end;
    min-height: var(--sol-h-open);
}
/* on an open sheet the line number is stamped larger — the Flip carries the
   size change through `props: fontSize`, so it grows rather than jumping */
.solution.is-open .solution__num { font-size: clamp(72px, 7.7vw, 112px); }

.solution__num {
    font-size: clamp(56px, 6.2vw, 92px);
    letter-spacing: -0.04em;
    margin-left: -0.05em;
    transition: -webkit-text-stroke-color var(--t-state) var(--ease-machine);
}

.solution__title {
    font-family: var(--font-display);
    font-size: var(--fs-block);
    font-weight: 700;
    font-variation-settings: 'wdth' 110;
    line-height: 1.06;
    letter-spacing: -0.01em;
    color: var(--bone-100);
    text-wrap: balance;
    transition: color var(--t-state) var(--ease-machine);
}

/* no max-width: the ledger column IS the measure, so a one-line item stays on
   one line and the gap before the chip stays even down the whole stack */
.solution__desc {
    font-size: 0.95rem;
    line-height: 1.5;
    color: var(--bone-300);
    transition: color var(--t-state) var(--ease-machine);
}

.solution__aside-cell {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 18px;
}
.solution__chip { flex: none; }
.solution__arrow {
    flex: none;
    display: block;
    width: 24px;
    height: 24px;
    color: var(--steel-300);
    transition: transform var(--t-state) var(--ease-machine), color var(--t-state) var(--ease-machine);
}
.solution.is-open .solution__arrow { transform: rotate(90deg); color: var(--signal); }

/* the stamp strip: only ever visible on an open row */
.solution__stamp {
    position: absolute;
    top: 16px;
    left: 0;
    right: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 14px;
    pointer-events: none;
}
/* ships stamped, for the same reason as the marker */
.solutions.is-live .solution:not(.is-open) .solution__stamp { clip-path: inset(0 0 100% 0); }
.solution__stamp-label { flex: none; color: var(--steel-300); letter-spacing: 0.2em; }
.solution__stamp-state { flex: none; color: var(--signal); letter-spacing: 0.2em; }
.solution__stamp-rule { flex: 1 1 auto; width: auto; min-width: 24px; background: var(--steel-500); }

/* THE INVERSION — every character on the row flips to --paper-ink over the fill */
.solution:not(.is-open) .solution-row:hover .solution__title,
.solution:not(.is-open) .solution-row:focus-visible .solution__title,
.solution:not(.is-open) .solution-row:hover .solution__desc,
.solution:not(.is-open) .solution-row:focus-visible .solution__desc,
.solution:not(.is-open) .solution-row:hover .solution__arrow,
.solution:not(.is-open) .solution-row:focus-visible .solution__arrow { color: var(--paper-ink); }

.solution:not(.is-open) .solution-row:hover .solution__num,
.solution:not(.is-open) .solution-row:focus-visible .solution__num { -webkit-text-stroke-color: var(--paper-ink); }

.solution:not(.is-open) .solution-row:hover .solution__chip,
.solution:not(.is-open) .solution-row:focus-visible .solution__chip {
    color: var(--paper-ink);
    border-color: var(--paper-ink);
    background: transparent;
}

/* ---------- the drawer ---------- */
.solution__drawer {
    position: relative;
    overflow: hidden;
    background: var(--ink-700);
    border-top: 1px solid var(--signal-rule);
}
/* The closed state only exists once the module has run. */
.solutions.is-live .solution:not(.is-open):not(.is-closing) .solution__drawer { display: none; }

.solution__drawer-inner {
    display: grid;
    grid-template-columns: var(--sol-num) var(--sol-t) var(--sol-d) var(--sol-a);
    gap: var(--gutter);
    padding: 32px 0 38px;
}

.solution__lede-col {
    grid-column: 2 / 3;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
}
.solution__ref { color: var(--signal); letter-spacing: 0.18em; }
.solution__lede-rule { max-width: 64px; background: var(--steel-400); }
.solution__lede {
    font-size: 0.95rem;
    line-height: 1.58;
    color: var(--bone-200);
    max-width: 42ch;
}

.solution__specs { grid-column: 3 / 4; align-self: start; }
.solution__specs .spec-row { padding: 11px 0; }
.solution__specs .spec-row:first-child { padding-top: 0; }
.solution__specs .spec-row__value { flex: 0 1 auto; text-align: right; }

.solution__schema {
    grid-column: 4 / 5;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    margin: 0;
    align-self: start;
}
.solution__schema-svg {
    width: 100%;
    height: auto;
    background: var(--ink-800);
    border: 1px solid var(--steel-500);
    padding: 10px;
}
.solution__schema-cap { color: var(--steel-300); }

/* schematic vocabulary — hairlines and graphite, one signal path per figure */
.solution__sch-box { fill: none; stroke: var(--steel-400); stroke-width: 1; }
.solution__sch-box--fill { fill: var(--ink-600); }
.solution__sch-line { fill: none; stroke: var(--steel-350); stroke-width: 1; }
.solution__sch-hair { fill: none; stroke: var(--steel-500); stroke-width: 1; }
.solution__sch-live { fill: none; stroke: var(--signal); stroke-width: 1.5; }

/* ---------- foot strip — bookends the head strip ---------- */
.solutions__foot {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-top: 20px;
}
.solutions__foot-tag { flex: none; color: var(--steel-300); white-space: nowrap; }
.solutions__foot-rule { flex: 1 1 auto; width: auto; min-width: 24px; }

/* ---------- the floating plate ---------- */
/* A pointer ornament, like the core's square cursor: it carries no information
   and it does not exist at all until GSAP is confirmed. Its hidden start state
   therefore lives under html.js-anim, never in the default cascade. */
.solutions__plate {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 4;
    width: 340px;
    pointer-events: none;
}
html.js-anim .solutions__plate {
    display: block;
    visibility: hidden;
    clip-path: inset(0 0 100% 0);
}
/* 340px of caption bar is a tight measure: this plate stamps its brief at a
   smaller size so the id and the dimension stamp both survive. */
.solutions__plate .plate__caption {
    font-size: 0.46rem;
    letter-spacing: 0.04em;
    padding-inline: 8px;
    gap: 8px;
}

.solutions__reticle {
    position: absolute;
    inset: 0 0 28px 0;
    width: 100%;
    height: auto;
    pointer-events: none;
}
.solutions__reticle-line { stroke: var(--steel-350); stroke-width: 1; vector-effect: non-scaling-stroke; }

/* ==========================================================================
   START STATES — only once JS has confirmed GSAP
   ========================================================================== */
html.js-anim .solution__lift { transform: translateY(100%); }

@media (prefers-reduced-motion: reduce) {
    html.js-anim .solution__lift { transform: none; }
}

/* ==========================================================================
   RESPONSIVE — below 900px the row is a three-line stack and the plate is off
   ========================================================================== */
@media (max-width: 899.98px) {
    .solutions__header { row-gap: 34px; }
    .solutions__aside-rule { max-width: 120px; }

    .solution__lift {
        grid-template-columns: auto minmax(0, 1fr);
        grid-template-areas:
            "num   title"
            "desc  desc"
            "aside aside";
        align-items: center;
        min-height: 0;
        gap: 14px 18px;
        padding-block: 26px 24px;
    }
    .solution.is-open .solution__lift { align-items: center; min-height: 0; }

    .solution__num,
    .solution.is-open .solution__num { grid-area: num; font-size: clamp(40px, 12vw, 56px); margin-left: 0; }
    .solution__title { grid-area: title; }
    .solution__desc { grid-area: desc; }
    .solution__aside-cell { grid-area: aside; justify-content: space-between; }
    .solution__stamp { display: none; }
    .solution__mark { left: -12px; }

    .solution__drawer-inner {
        grid-template-columns: 1fr;
        gap: 28px;
        padding: 26px 0 32px;
    }
    .solution__lede-col,
    .solution__specs,
    .solution__schema { grid-column: 1 / -1; }
    .solution__lede { max-width: none; }
    .solution__schema-svg { max-width: 320px; }

    html.js-anim .solutions__plate { display: none; }
}

@media (pointer: coarse) {
    html.js-anim .solutions__plate { display: none; }
}

@media (max-width: 640px) {
    .solutions__meta { gap: 12px; }
    .solutions__meta-tag { font-size: 0.52rem; letter-spacing: 0.1em; }
    .solution__title { font-size: 1.18rem; }
    .solution__desc { font-size: 0.9rem; }
    .solution__aside-cell { gap: 12px; }
    /* the foot strip has two long stamps: below 640 it becomes a printed block
       with the hairline as its divider rather than a single overflowing line */
    .solutions__foot {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }
    .solutions__foot-tag { font-size: 0.52rem; letter-spacing: 0.1em; white-space: normal; }
    .solutions__foot-tag--end { text-align: right; }
    .solutions__foot-rule { flex: none; width: 100%; }
    .solution__specs .spec-row { flex-wrap: wrap; }
    .solution__specs .spec-row__value { text-align: left; }
}

/* ============================ PROCESS ============================ */
/* ==========================================================================
   #process — "SIGNATURE TO PRODUCTION IN 90 DAYS"

   A vertical Manhattan spine runs down cols 3, jogging left/right between
   stages; four stage panels sit at cols 5–11 with their week stamp, stage
   numeral and index in the left gutter at cols 1–2. A horizontal leader taps
   off each junction square into the panel it belongs to.

   The spine's geometry is WRITTEN BY process.js at 1 unit = 1 CSS pixel, in
   init(), so it is correct with or without GSAP. Everything below therefore
   ships the FINAL state — spine solid, leaders drawn, junctions orange — and
   the undrawn start states live only under html.js-anim.
   ========================================================================== */

.process { overflow: hidden; }

.process__bg {
    opacity: 0.3;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 20%, #000 74%, transparent 100%);
    mask-image: linear-gradient(180deg, transparent 0%, #000 20%, #000 74%, transparent 100%);
}

/* ---------- header ---------- */
.process__header { align-items: end; }

/* The copy's marked break is after PRODUCTION; balance would re-break it. */
.process__headline { text-wrap: wrap; }

.process__header-aside {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
}
.process__header-aside .section-desc { margin-top: 0; }
.process__aside-rule { max-width: 180px; }
.process__aside-note { color: var(--steel-300); letter-spacing: 0.18em; }

/* ==========================================================================
   THE TIMELINE
   ========================================================================== */
.process__timeline {
    position: relative;
    /* run-out below the last stage: the route ends on its stop bar clear of
       the closing rule, not hard against the last panel. */
    padding-bottom: clamp(76px, 8vw, 124px);
}

/* Zero-size layout marker. CSS parks it exactly on the spine axis at every
   breakpoint; process.js reads its x so no coordinate is hard-coded in JS.
   col 3 starts at 2·colw + 2·gutter = 100%/6 + gutter/6. */
.process__rail {
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(100% / 6 + var(--gutter) / 6 + 10px);
    width: 0;
    opacity: 0;
    pointer-events: none;
}

.process__spine {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

/* SVG vocabulary — hairlines and four graphite tones. The track is the
   route the payload has not reached yet; the line is the route it has. */
.process__track  { fill: none; stroke: var(--steel-500); stroke-width: 1; }
.process__line   { fill: none; stroke: var(--steel-350); stroke-width: 1.5; }
.process__leader { fill: none; stroke: var(--steel-400); stroke-width: 1; }

.process__junction { fill: var(--ink-900); stroke: var(--signal); stroke-width: 1.5; }
/* the stop bar the payload seats against at the end of the route */
.process__terminal { fill: var(--signal); }
.process__payload  { fill: var(--volt); }

/* ---------- one stage row ---------- */
/* The row IS a .grid12 — the house grid, not a second one. This block only
   adds the stacking context the spine sits behind. */
.process__stage {
    position: relative;
    z-index: 1;
    align-items: start;
}
.process__stage + .process__stage { margin-top: clamp(58px, 6vw, 100px); }

/* ---------- left gutter: week stamp, numeral, index ---------- */
.process__aside {
    grid-column: 1 / 3;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
    /* seats the week chip on the same line as the panel's title rule */
    padding-top: 30px;
}
.process__chip {
    gap: 9px;
    white-space: nowrap;
    min-height: 30px;
}
/* The live square: steel until the payload arrives, then the relay closes. */
.process__led {
    width: 6px;
    height: 6px;
    flex: none;
    background: var(--signal);
}
/* line-height .78 pulls the box tighter than the glyph, and the depth law
   swings this numeral +/-33px on scroll. Both are reserved here so the stage
   index below it can never be touched at any scroll position. */
.process__ghost {
    font-size: clamp(74px, 8.4vw, 128px);
    letter-spacing: -0.045em;
    margin-bottom: 44px;
}
.process__stage-no {
    color: var(--steel-300);
    letter-spacing: 0.2em;
    white-space: nowrap;
}

/* ---------- the panel ---------- */
.process__panel {
    grid-column: 5 / 12;
    display: flex;
    flex-direction: column;
    padding: clamp(24px, 2.2vw, 34px);
    overflow: hidden;
    isolation: isolate;
}
/* The panel border rides the shared 0.24s .panel transition; the steps(3)
   relay itself is carried by the LED, the week chip and the junction square. */
.process__stage.is-live > .process__panel { border-color: var(--signal-rule); }

.process__head {
    display: flex;
    align-items: center;
    gap: 16px;
    min-height: 28px;
}
.process__title {
    flex: none;
    font-family: var(--font-display);
    font-size: var(--fs-block);
    font-weight: 700;
    font-variation-settings: 'wdth' 110;
    line-height: 1.06;
    letter-spacing: -0.01em;
    color: var(--bone-100);
}
.process__hair { flex: 1 1 auto; width: auto; min-width: 20px; }
.process__code {
    flex: none;
    color: var(--steel-300);
    letter-spacing: 0.2em;
    white-space: nowrap;
}

/* ---------- body: three deliverables + the hero figure ---------- */
.process__body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 216px;
    gap: clamp(20px, 2.4vw, 36px);
    margin-top: clamp(22px, 2.4vw, 30px);
}
.process__list {
    display: flex;
    flex-direction: column;
    gap: 13px;
}
.process__item {
    position: relative;
    padding-left: 20px;
    font-size: 0.95rem;
    line-height: 1.58;
    color: var(--bone-200);
    max-width: 48ch;
}
.process__item::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.6em;
    width: 6px;
    height: 6px;
    background: var(--steel-400);
}

/* The divider runs the full body height; the numeral is centred against the
   deliverables rather than stranded at the top of a half-empty column. */
.process__metric {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 12px;
    border-left: 1px solid var(--steel-500);
    padding-left: clamp(18px, 1.8vw, 26px);
}
.process__figure { font-size: clamp(2.6rem, 4.4vw, 4.4rem); }
.process__metric-label {
    color: var(--steel-300);
    letter-spacing: 0.16em;
}

/* ---------- the ownership line ---------- */
.process__own {
    display: flex;
    align-items: baseline;
    gap: 16px;
    margin-top: clamp(24px, 2.6vw, 34px);
    padding: 14px 18px;
    background: var(--ink-600);
    border: 1px solid var(--steel-500);
}
.process__own-tag {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    color: var(--bone-100);
    letter-spacing: 0.18em;
}
.process__own-tag::before {
    content: '';
    width: 6px;
    height: 6px;
    background: var(--signal);
    flex: none;
}
.process__own-text {
    font-size: 0.92rem;
    line-height: 1.55;
    color: var(--bone-200);
    max-width: none;
}

/* ==========================================================================
   CLOSING LINE
   ========================================================================== */
.process__close { margin-top: clamp(16px, 2vw, 28px); }
.process__close-grid {
    align-items: baseline;
    margin-top: clamp(22px, 2.4vw, 32px);
}
.process__close-tag { color: var(--signal); }
.process__close-text {
    font-family: var(--font-display);
    font-size: var(--fs-block);
    font-weight: 600;
    font-variation-settings: 'wdth' 106;
    line-height: 1.22;
    letter-spacing: -0.005em;
    color: var(--bone-100);
    max-width: 46ch;
}

/* ==========================================================================
   START STATES — only once JS has confirmed GSAP
   ========================================================================== */
/* Dash values are deliberately larger than any path this section can produce;
   DrawSVGPlugin overwrites both properties the instant its tween renders. */
html.js-anim .process__line   { stroke-dasharray: 6000; stroke-dashoffset: 6000; }
html.js-anim .process__leader { stroke-dasharray: 600;  stroke-dashoffset: 600; }
html.js-anim .process__junction { stroke: var(--steel-400); }
html.js-anim .process__terminal { fill: var(--steel-400); }
html.js-anim .process__led { background: var(--steel-400); }
html.js-anim .process__aside { clip-path: inset(0 0 100% 0); }
html.js-anim .process__panel { clip-path: inset(0 0 100% 0); }

/* Reduced motion: never strand a start state the animation will not clear. */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .process__line,
    html.js-anim .process__leader { stroke-dasharray: none; stroke-dashoffset: 0; }
    html.js-anim .process__junction { stroke: var(--signal); }
    html.js-anim .process__terminal { fill: var(--signal); }
    html.js-anim .process__led { background: var(--signal); }
    html.js-anim .process__aside,
    html.js-anim .process__panel { clip-path: none; }
}

/* ==========================================================================
   BELOW 900px — the spine moves to the far-left gutter and every panel
   sits to its right at full width.
   ========================================================================== */
@media (max-width: 899.98px) {
    .process__header { row-gap: 32px; }
    .process__header-aside { align-items: flex-start; }
    .process__aside-rule { max-width: 100%; }

    .process__rail { left: 13px; }
    .process__timeline { padding-bottom: clamp(58px, 9vw, 88px); }

    .process__stage {
        display: block;
        padding-left: 58px;
    }
    .process__stage + .process__stage { margin-top: 46px; }

    /* The numeral is dropped rather than squeezed: at this width it would sit
       on top of the stage index, and the index is the one that carries meaning. */
    .process__aside {
        flex-direction: row;
        align-items: center;
        gap: 14px;
        padding-top: 0;
        margin-bottom: 16px;
    }
    .process__ghost { display: none; }
    .process__stage-no { margin-left: auto; }

    .process__panel { width: 100%; }

    .process__body { grid-template-columns: 1fr; gap: 22px; }
    .process__item { max-width: 60ch; }
    .process__metric {
        flex-direction: row;
        align-items: baseline;
        justify-content: flex-start;
        gap: 16px;
        border-left: 0;
        border-top: 1px solid var(--steel-500);
        padding-left: 0;
        padding-top: 18px;
    }
    .process__figure { font-size: clamp(2.4rem, 11vw, 3.2rem); }

    .process__close-grid { row-gap: 16px; }
}

@media (max-width: 640px) {
    .process__rail { left: 11px; }
    .process__stage { padding-left: 44px; }
    .process__aside { gap: 12px; }
    .process__panel { padding: 22px 18px; }
    .process__head { gap: 12px; }
    .process__own {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
        padding: 14px;
    }
    /* the stamp is set down a step rather than allowed to break mid-phrase */
    .process__own-tag {
        font-size: var(--fs-mono-sm);
        letter-spacing: 0.14em;
        white-space: nowrap;
    }
    .process__close-text { font-size: 1.18rem; }
}

/* ============================ INDUSTRIES ============================ */
/* ==========================================================================
   #industries — "THE RACK"
   Six cards in 3x2 on --ink-800. Every card is a raised panel carrying a
   16:10 plate, a mono sector label, one sentence and one dot-leader metric.
   Adjacent borders collapse to a single hairline through .panel--flush, so
   the six read as one milled block rather than six floating tiles.

   FALLBACK INVERSION: everything below ships its FINAL state — plates
   unclipped, hairlines at scale 1, deltas already orange. The only start
   states in this file live under html.js-anim, which JS adds after it has
   confirmed window.gsap.
   ========================================================================== */

.industry {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

/* the printed grid is the only parallaxing layer here — depth 0.15, per the law */
.industry__bg {
    z-index: 0;
    opacity: 0.34;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 62%);
    mask-image: linear-gradient(180deg, #000 0%, transparent 62%);
}

.industry__inner { position: relative; z-index: 1; }

/* ---------- header ---------- */
.industry__head { align-items: end; }

/* The copy's marked break is after SIX SECTORS,; balance was re-breaking it. */
.industry__headline { text-wrap: wrap; }

.industry__head-aside {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
}
.industry__head-aside .section-desc { margin-top: 0; }

/* --steel-500 disappears against --ink-600 and --ink-800 at hairline width;
   every rule this section draws is set one tone up so it reads as machined. */
.industry__aside-rule { max-width: 180px; background: var(--steel-400); }

.industry__aside-note {
    color: var(--steel-300);
    letter-spacing: 0.18em;
}

/* ---------- bench strip above the rack ---------- */
.industry__meta {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: 22px;
}
.industry__meta-tag {
    flex: none;
    color: var(--steel-300);
    white-space: nowrap;
}
.industry__meta-rule { flex: 1 1 auto; width: auto; min-width: 24px; }

/* ---------- the rack ---------- */
.industry__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0;
}

.industry__card {
    display: flex;
    flex-direction: column;
    padding: clamp(15px, 1.4vw, 20px);
    overflow: hidden;
    isolation: isolate;
}

/* ---------- the plate, mounted in the card face ---------- */
/* The caption carries a 40-character asset brief, so its type is set tighter
   here than the component default — the bar must never clip the id. */
.industry__plate .plate__caption {
    font-size: 0.5rem;
    letter-spacing: 0.05em;
    gap: 8px;
    padding-inline: 9px;
}
/* Six plates share one row, so a plate here is a third of a column wide — the
   bar can hold the subject and the id or the dimension stamp, never all three.
   The subject and the id ARE the brief, so the dimensions are stamped once for
   all six plates in the section foot and the per-plate stamp stands down. */
.industry__plate .plate__dim { display: none; }
.industry__plate .plate__tag { font-size: 0.5rem; letter-spacing: 0.1em; }

/* The 24px pattern grid is offset through a variable so the registration
   jitter can jump it in whole steps without touching the layer's box. */
.industry__plate .plate__grid { background-position: var(--plate-jx, 0px) 0; }

/* The component's crosshair is two masked pseudo-elements, which DrawSVG
   cannot reach. This section hosts the identical crosshair — same 1px
   --steel-350 hairlines, same centre gap — as four SVG segments inside the
   same element, authored inner-end first so they draw out of the centre. */
.industry__ret::before,
.industry__ret::after { display: none; }

.industry__ret-svg {
    width: 100%;
    height: 100%;
    overflow: visible;
}
.industry__ret-line {
    fill: none;
    stroke: var(--steel-350);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

/* ---------- card body ---------- */
.industry__body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
}

.industry__top {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 20px 0 14px;
}
.industry__hair {
    flex: 1 1 auto;
    width: auto;
    min-width: 18px;
    background: var(--steel-400);
}

.industry__idx {
    flex: none;
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 900;
    font-variation-settings: 'wdth' 125;
    line-height: 1;
    letter-spacing: -0.01em;
    color: var(--bone-100);
}
.industry__code {
    flex: none;
    color: var(--steel-300);
    letter-spacing: 0.18em;
}

.industry__name {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 700;
    font-variation-settings: 'wdth' 112.5;
    letter-spacing: 0.16em;
    line-height: 1.3;
    text-transform: uppercase;
    color: var(--bone-100);
    margin-bottom: 12px;
}

.industry__text {
    flex: 1 1 auto;
    font-size: 0.9rem;
    line-height: 1.58;
    color: var(--bone-200);
    max-width: 44ch;
}

/* ---------- the metric: dot leader ending in a figure ---------- */
.industry__metric { margin-top: 22px; }
.industry__metric-rule { background: var(--steel-400); }

.industry__spec { padding-bottom: 0; }
.industry__spec .spec-row__label { letter-spacing: 0.1em; }

/* The value is a wrapping flex line, not one rigid item. A card is a third of a
   column at 1440 and half of one at 700, and the widest metric
   (EXCEPTIONS CLEARED / 3.4x / PER AGENT) does not fit that narrower card on one
   line — so the qualifier drops beneath the figure, right-aligned, instead of
   running under the card's own border and being guillotined by its overflow. */
.industry__spec .spec-row__value {
    display: flex;
    flex: 0 1 auto;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: flex-end;
    column-gap: 8px;
    row-gap: 2px;
    text-align: right;
}
.industry__delta, .industry__suffix { white-space: nowrap; }

/* The rack is one milled block, so every metric row across a row of cards must
   share one geometry — the qualifier drops beneath the figure for all six cards
   together, never card by card, which would step the hairlines and the labels
   out of line with their neighbours. These are exactly the bands where the
   widest metric (EXCEPTIONS CLEARED / 3.4x / PER AGENT) stops clearing its card
   on one line: the squeezed 3-column band, the squeezed 2-column band, and the
   narrowest phones. The wrap above stays as the safety net beneath them. */
@media (max-width: 1200px) and (min-width: 1025px),
       (max-width: 860px) and (min-width: 641px),
       (max-width: 430px) {
    .industry__spec .spec-row__value {
        flex-direction: column;
        flex-wrap: nowrap;
        align-items: flex-end;
        row-gap: 1px;
        /* One metric carries no qualifier, so its block reserves the second
           line anyway — figure line + rule of gap + qualifier line — and its
           label stays level with the five beside it. */
        min-height: calc(1.22rem * 0.9 + 1px + var(--fs-mono-sm) * 1.3);
    }
}

/* the figure — final state is orange; the relay start lives under js-anim */
.industry__delta {
    font-family: var(--font-display);
    font-size: 1.22rem;
    font-weight: 900;
    font-variation-settings: 'wdth' 125;
    font-feature-settings: 'tnum' 1;
    font-variant-numeric: tabular-nums;
    line-height: 0.9;
    letter-spacing: -0.02em;
    color: var(--signal);
}
.industry__suffix { color: var(--steel-300); }

/* ---------- hover: border + silhouette only. No transform, no shadow ---------- */
/* The card's border and the plate's border go steel -> signal together, and the
   silhouette under the grid lifts from 0.10 to 0.18. Nothing moves. */
.industry__card:hover { border-color: var(--signal-rule); }
.industry__card:hover .industry__plate { border-color: var(--signal-rule); }
.industry__card:hover .plate__subject { opacity: 0.18; }

/* ---------- section foot ---------- */
.industry__foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 24px;
    margin-top: 26px;
}
.industry__foot-tag { color: var(--steel-300); letter-spacing: 0.16em; }
.industry__foot-tag--end { color: var(--steel-300); }

/* ==========================================================================
   START STATES — only once JS has confirmed GSAP
   ========================================================================== */
/* The signal arrives last: every figure opens in steel and is relayed by the
   card timeline. .reveal, .rule and .spec-row__leader take their own start
   states from the foundation. */
html.js-anim .industry__delta { color: var(--steel-400); }

/* Reduced motion: never strand a start state the animation will not clear. */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .industry__delta { color: var(--signal); }
}

/* ==========================================================================
   RESPONSIVE — 2 columns below 1024px, 1 below 640px
   ========================================================================== */
@media (max-width: 1024px) {
    .industry__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 899.98px) {
    .industry__head { row-gap: 34px; }
    .industry__aside-rule { max-width: 100%; }
    .industry__text { max-width: 52ch; }
}

@media (max-width: 640px) {
    .industry__grid { grid-template-columns: minmax(0, 1fr); }
    .industry__meta { gap: 12px; }
    .industry__meta-tag--end { display: none; }
    .industry__card { padding: 16px; }
    .industry__top { margin-top: 18px; }

    /* One column, but the narrowest one: the metric row gives up four pixels of
       gutter either side of the leader so it still clears 320px. */
    .industry__spec { column-gap: 8px; }

    .industry__foot {
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
    }
}

/* Below 400px the caption bar is under 230px of usable width; the id is the one
   string in it that must never break, so the brief is set one step tighter. */
@media (max-width: 400px) {
    .industry__plate .plate__caption {
        font-size: 0.46rem;
        letter-spacing: 0.03em;
    }
}

/* ============================ ARCHITECTURE ============================ */
/* ==========================================================================
   #architecture — REFERENCE DEPLOYMENT
   A pinned blueprint sheet: cols 1-9 hold the 1200x700 drawing, cols 10-12
   the sequence readout, the six-row legend and the deployment spec block.

   Every element ships in its FINAL state — the finished drawing, the closed
   dashed perimeter, the legend fully lit. Start states are applied by
   gsap.set()/from() inside anim(), or live under html.js-anim below. With the
   vendor scripts blocked the sheet reads as a completed engineering drawing.
   ========================================================================== */

.architecture {
    position: relative;
    isolation: isolate;
    overflow: hidden;   /* the pin spacer must never widen the page */
}

/* The printed grid runs at full strength through the header and steps back
   under the drawing, so the hairlines of the diagram stay the loudest lines. */
.architecture__bg {
    inset: 0;
    opacity: 0.92;
    -webkit-mask-image: linear-gradient(180deg, #000 0, #000 16%, rgba(0, 0, 0, 0.3) 34%, rgba(0, 0, 0, 0.3) 92%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 0, #000 16%, rgba(0, 0, 0, 0.3) 34%, rgba(0, 0, 0, 0.3) 92%, transparent 100%);
}

/* ---------- header ---------- */
.architecture__head { position: relative; z-index: 1; }
.architecture__lede {
    display: flex;
    flex-direction: column;
    align-self: end;
    padding-bottom: 6px;
}
.architecture__head-rule { background: var(--steel-400); }
.architecture__lede .section-desc { margin-top: 22px; }

/* ==========================================================================
   THE PINNED SHEET
   Height is capped as well as relative: a 100vh stage on a very tall window
   would strand the drawing in the middle of an empty field.
   ========================================================================== */
.architecture__stage {
    position: relative;
    z-index: 1;
    min-height: min(100svh, 940px);
    display: flex;
    align-items: center;
    margin-top: clamp(48px, 6vw, 88px);
}
.architecture__stage > .container { width: 100%; }

.architecture__layout {
    align-items: center;
    row-gap: clamp(36px, 4.4vw, 56px);
}

/* There is no .c1-9 span utility, and the spec puts the legend in 10-12. */
.arch-draw {
    grid-column: 1 / 10;
    position: relative;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.arch-draw__frame {
    position: relative;
    overflow: hidden;
    border: 1px solid var(--steel-500);
    background: var(--ink-800);
    padding: 2px;
}
.arch-draw__frame:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

.arch-draw__svg {
    width: 100%;
    height: auto;
    max-height: min(58vh, 620px);
    overflow: hidden;   /* the sheet is a sheet: nothing prints past its edge */
}

.arch-draw__cap {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 18px;
    border-top: 1px solid var(--steel-500);
    padding-top: 10px;
    font-size: var(--fs-mono-sm);
    color: var(--steel-300);
}
.arch-draw__capline { color: var(--bone-300); }
.arch-draw__capnote { color: var(--steel-300); text-align: right; }
.arch-draw__panhint { display: none; color: var(--steel-300); }

/* ==========================================================================
   SVG VOCABULARY — hairlines, four graphite tones, three lane colours
   ========================================================================== */
.arch-reg path { fill: none; stroke: var(--steel-400); stroke-width: 2; }
.arch-sheet-rule { fill: none; stroke: var(--steel-500); stroke-width: 1; }

.arch-stamp {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 1.6px;
    fill: var(--steel-300);
}

/* the packet rails: geometry only, never painted */
.arch-lane { fill: none; stroke: none; }

/* ---------- the boundary ---------- */
.arch-perimeter {
    fill: none;
    stroke: var(--signal-rule);
    stroke-width: 1;
    stroke-dasharray: 7 7;
    stroke-linecap: butt;
}
.arch-perimeter__mark { fill: var(--signal); }
.arch-perimeter__label {
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 2px;
    fill: var(--bone-100);
}
.arch-perimeter__sub {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 400;
    letter-spacing: 1.4px;
    fill: var(--steel-300);
}
.arch-note {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 1.4px;
    fill: var(--steel-300);
}

/* ---------- the control bus: quiet, dashed, never a data path ---------- */
.arch-bus path {
    fill: none;
    stroke: var(--steel-500);
    stroke-width: 1;
    stroke-dasharray: 2 5;
}
.arch-bus__label {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.9px;
    fill: var(--steel-300);
}

/* ---------- edges + junctions ---------- */
.arch-edge {
    fill: none;
    stroke: var(--steel-400);
    stroke-width: 1.5;
    stroke-linecap: butt;
    stroke-linejoin: miter;
}
.arch-edge__label {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 1px;
    fill: var(--steel-300);
}
.arch-junction { fill: var(--ink-900); stroke: var(--steel-400); stroke-width: 1.5; }
/* the two boundary crossings — the only squares that end up orange */
.arch-junction--gate { stroke: var(--signal); }

/* ---------- nodes ---------- */
.arch-node__box { fill: var(--ink-700); stroke: var(--steel-400); stroke-width: 1; }
.arch-node__rule { fill: none; stroke: var(--steel-500); stroke-width: 1; }
.arch-node__tag {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 1.2px;
    fill: var(--steel-300);
}
.arch-node__name {
    font-family: var(--font-mono);
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.9px;
    fill: var(--bone-100);
}
.arch-node__sub {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.6px;
    fill: var(--steel-300);
}
.arch-node__slot { fill: var(--ink-900); stroke: var(--steel-500); stroke-width: 1; }
/* the stage currently under the scrub head lifts one tonal step — a state
   cue, not a relay: no second helping of orange inside the drawing. */
.arch-node.is-live .arch-node__box { fill: var(--ink-600); stroke: var(--steel-300); }
.arch-node.is-live .arch-node__name { fill: var(--bone-100); }
.arch-node.is-live .arch-node__tag { fill: var(--bone-300); }
.arch-node__box, .arch-node__name, .arch-node__tag {
    transition: fill var(--t-state) var(--ease-machine), stroke var(--t-state) var(--ease-machine);
}

.arch-node__slot-label {
    font-family: var(--font-mono);
    font-size: 9.5px;
    letter-spacing: 0.5px;
    fill: var(--bone-300);
}
/* the two boxes that sit outside the line read one tone cooler */
#archNodeDs .arch-node__box,
#archNodeMp .arch-node__box { fill: var(--ink-800); stroke: var(--steel-500); }

/* ---------- packets + lane key ---------- */
.arch-packet--a { fill: var(--lane-a); }
.arch-packet--b { fill: var(--lane-b); }
.arch-packet--c { fill: var(--lane-c); }

.arch-key__sq--a { fill: var(--lane-a); }
.arch-key__sq--b { fill: var(--lane-b); }
.arch-key__sq--c { fill: var(--lane-c); }
.arch-key__label {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.9px;
    fill: var(--steel-300);
}

/* ==========================================================================
   COLS 10-12 — readout, legend, spec block
   ========================================================================== */
.arch-side {
    align-self: center;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: clamp(18px, 1.8vw, 26px);
}

.arch-side__readout {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 16px 16px;
}
.arch-side__key { color: var(--steel-300); }
.arch-side__text {
    display: block;
    min-height: 1.4em;
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--bone-100);
    line-height: 1.4;
}
.arch-side__strip { display: flex; gap: 4px; }
.arch-side__seg {
    flex: 1 1 auto;
    height: 3px;
    background: var(--steel-500);
    transition: background-color var(--t-state) var(--ease-machine);
}
.arch-side__seg.is-done { background: var(--steel-300); }
.arch-side__seg.is-live { background: var(--signal); }

/* ---------- the legend ---------- */
.arch-legend { border-top: 1px solid var(--steel-500); }

.arch-legend__row {
    position: relative;
    display: grid;
    grid-template-columns: 26px minmax(0, 1fr);
    gap: 12px;
    padding: 11px 0 12px 13px;
    border-bottom: 1px solid var(--steel-500);
}
/* the row's status bar — steel while pending, bone once passed, signal while live */
.arch-legend__row::before {
    content: '';
    position: absolute;
    left: 0;
    top: -1px;
    bottom: -1px;
    width: 2px;
    background: var(--steel-500);
    transition: background-color var(--t-state) var(--ease-machine);
}
.arch-legend__row.is-done::before { background: var(--steel-350); }
.arch-legend__row.is-live::before { background: var(--signal); }

.arch-legend__idx {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 700;
    letter-spacing: 0.08em;
    line-height: 1.5;
    color: var(--steel-300);
    transition: color var(--t-state) var(--ease-machine);
}
.arch-legend__row.is-done .arch-legend__idx { color: var(--bone-300); }
.arch-legend__row.is-live .arch-legend__idx { color: var(--signal); }

.arch-legend__body { display: block; min-width: 0; }
.arch-legend__title {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 700;
    font-variation-settings: 'wdth' 112.5;
    letter-spacing: 0.16em;
    line-height: 1.4;
    text-transform: uppercase;
    color: var(--bone-300);
    transition: color var(--t-state) var(--ease-machine);
}
.arch-legend__row.is-live .arch-legend__title,
.arch-legend__row.is-done .arch-legend__title { color: var(--bone-100); }

.arch-legend__text {
    display: block;
    margin-top: 5px;
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--steel-300);
    transition: color var(--t-state) var(--ease-machine);
}
.arch-legend__row.is-live .arch-legend__text { color: var(--bone-200); }

/* ---------- the spec block ---------- */
.arch-side__specs { border-top: 1px solid var(--steel-500); }
/* three cols is a narrow measure for a dot leader: the row is set one step
   tighter here so label, leader and value all survive at 1280px. */
.arch-side__specs .spec-row {
    font-size: 0.55rem;
    letter-spacing: 0.08em;
    gap: 10px;
}

/* ==========================================================================
   START STATES — only once JS has confirmed GSAP
   ========================================================================== */
html.js-anim .arch-draw__frame,
html.js-anim .arch-draw__cap,
html.js-anim .arch-side__readout,
html.js-anim .arch-side__specs { clip-path: inset(0 0 100% 0); }
html.js-anim .arch-legend__row { clip-path: inset(0 100% 0 0); }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
/* Three columns is a narrow shelf on a 1024–1180px desktop: the legend text
   runs to three lines and the spec values crowd their leaders. The sheet gives
   up one column there rather than letting the console overflow the pin. */
@media (min-width: 900px) and (max-width: 1180px) {
    .architecture__layout .arch-draw { grid-column: 1 / 9; }
    .architecture__layout .arch-side { grid-column: 9 / -1; }
}

/* A pinned stage MUST fit the window. The console column is the tall one and
   it does not shrink with the viewport, so on a short desktop window (a 768px
   laptop leaves ~640px of page) the spec block would sit below the fold for
   the whole 160vh pin. Here the console closes up and the sheet gives back
   height until the whole stage clears the window again. */
@media (min-width: 900px) and (max-height: 900px) {
    .architecture__stage { margin-top: clamp(34px, 4vw, 64px); }
    .architecture__layout { row-gap: 30px; }
    .arch-side { gap: 14px; }
    .arch-side__readout { gap: 8px; padding: 11px 13px 13px; }
    .arch-legend__row { padding: 7px 0 8px 12px; }
    .arch-legend__text { margin-top: 3px; font-size: 0.74rem; line-height: 1.44; }
    .arch-draw__svg { max-height: min(50vh, 620px); }
}
@media (min-width: 900px) and (max-height: 760px) {
    .arch-legend__row { padding: 5px 0 6px 12px; }
    .arch-legend__title { line-height: 1.3; }
    .arch-legend__text { font-size: 0.72rem; line-height: 1.38; }
    .arch-side__specs .spec-row { padding: 6px 0; }
    .arch-draw__svg { max-height: min(44vh, 620px); }
}

/* ---------- below 900px the pin is dropped and the sheet pans sideways ---------- */
@media (max-width: 899.98px) {
    .architecture__lede { align-self: start; padding-bottom: 0; }
    .architecture__lede .section-desc { margin-top: 20px; }
    .architecture__head-rule { margin-top: 30px; }

    .architecture__stage {
        min-height: 0;
        display: block;
        margin-top: clamp(38px, 7vw, 56px);
    }
    /* one column whose min track is 0: without this the headline's unbreakable
       accent span sets the column's min-content and pushes the body copy past
       the container's right padding. */
    .architecture__head .grid12,
    .architecture__layout {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 34px;
    }
    .architecture__lede .section-desc { max-width: 100%; }

    .arch-draw { grid-column: 1 / -1; }
    /* a real scroll region: focusable, arrow-key pannable, scroll-snapped */
    .arch-draw__frame {
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x proximity;
    }
    .arch-draw__svg {
        width: 1200px;
        min-width: 1200px;
        height: auto;
        max-height: none;
        scroll-snap-align: start;
    }
    .arch-draw__cap { flex-wrap: wrap; gap: 4px 18px; }
    .arch-draw__capnote { display: none; }
    .arch-draw__panhint { display: block; }

    .arch-side { align-self: start; }
}

@media (max-width: 640px) {
    /* the accent line is an unbreakable inline-block set at wdth 125 — it, not
       the first line, governs how large the headline may be at 360px. */
    .architecture__title { font-size: clamp(1.6rem, 7.4vw, 2.5rem); }
    .arch-draw__capnote { text-align: left; }
    .arch-legend__text { font-size: 0.82rem; }
    .arch-side__specs .spec-row { font-size: var(--fs-mono-sm); }
}

/* ==========================================================================
   REDUCED MOTION — never leave a start state the animation will not clear
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .arch-draw__frame,
    html.js-anim .arch-draw__cap,
    html.js-anim .arch-side__readout,
    html.js-anim .arch-side__specs,
    html.js-anim .arch-legend__row { clip-path: none; }
    .arch-node__box, .arch-node__name, .arch-node__tag { transition: none; }
}

/* ============================ EVIDENCE ============================ */
/* ==========================================================================
   #evidence — "THE SPREAD"
   The one sanctioned grid break on the page. Three dossiers on --ink-900,
   each one a plate, a mono sector descriptor, a one-sentence problem, an
   oversized outcome numeral, a currency figure and three dot-leader rows.
   Their columns are deliberately offset — 1-7, then 6-12 shoved 120px down,
   then 2-9 — so the page's own grid is visibly broken exactly once, and the
   ghost numerals stamp the gutters the offsets open up.

   Beneath the spread, a SUPPLEMENTARY slip rail: eight mono case slips on a
   Draggable strip over a 1px position rail. It is never the carrier of the
   evidence — the three dossiers read completely without it, and without JS
   the rail is a plain, natively scrollable, scroll-snapped region.

   FALLBACK INVERSION: everything below ships its FINAL state — plates
   unclipped, frames stroked, hairlines at scale 1, money figures already
   orange, the rail scrolling natively. The only start states in this file
   live under html.js-anim, which JS adds after confirming window.gsap.
   ========================================================================== */

.evidence {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

/* the printed grid is the only 0.15-depth layer here, per the depth law */
.evidence__bg {
    z-index: 0;
    opacity: 0.30;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 62%, transparent 92%);
    mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 62%, transparent 92%);
}

.evidence__inner { position: relative; z-index: 1; }

/* ---------- header ---------- */
.evidence__head { align-items: end; }

/* The copy's marked break is after THREE DEPLOYMENTS, and that is a long
   first line: at the full --fs-title it breaks a second time and strands
   THREE on a line of its own, so this one headline is set one step down. */
.evidence__headline {
    text-wrap: wrap;
    font-size: clamp(1.95rem, 3.9vw, 3.3rem);
}

.evidence__head-aside {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
}
.evidence__head-aside .section-desc { margin-top: 0; }

/* --steel-500 vanishes against --ink-900 at hairline width; every rule this
   section draws is set one tone up so it reads as machined, not as dirt. */
.evidence__aside-rule { max-width: 180px; background: var(--steel-400); }

.evidence__aside-note { color: var(--steel-300); letter-spacing: 0.18em; }

/* ---------- bench strip above the spread ---------- */
.evidence__meta {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: clamp(34px, 4vw, 56px);
}
.evidence__meta-tag {
    flex: none;
    color: var(--steel-300);
    white-space: nowrap;
}
.evidence__meta-rule {
    flex: 1 1 auto;
    width: auto;
    min-width: 24px;
    background: var(--steel-400);
}

/* ==========================================================================
   THE SPREAD — the grid break
   ========================================================================== */
.evidence__spread {
    position: relative;
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--gutter);
    row-gap: clamp(40px, 4.4vw, 64px);
}

.evidence__dossier {
    position: relative;
    z-index: 1;
    min-width: 0;
}

/* ---------- the stamped numeral in the gutter each offset opens ----------
   Centred on the dossier rather than hung off its top, because the three
   dossiers are deliberately three different heights. No transform here: the
   depth law owns transform on anything carrying data-depth. */
.evidence__ghost {
    position: absolute;
    z-index: 0;
    top: 50%;
    margin-top: -0.4em;
    font-size: clamp(110px, 15vw, 250px);
    letter-spacing: -0.05em;
}

/* ---------- the seam across the void the offset opens ---------- */
.evidence__seam {
    display: none;
    align-items: center;
    gap: 18px;
}
.evidence__seam-tag {
    flex: none;
    color: var(--steel-300);
    letter-spacing: 0.18em;
    white-space: nowrap;
}
.evidence__seam-rule {
    flex: 1 1 auto;
    width: auto;
    min-width: 24px;
    background: var(--steel-500);
}

/* ---------- one dossier ---------- */
.evidence__top {
    display: flex;
    align-items: center;
    gap: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--steel-500);
}
.evidence__top-rule {
    flex: 1 1 auto;
    width: auto;
    min-width: 20px;
    background: var(--steel-400);
}
.evidence__code {
    flex: none;
    color: var(--bone-100);
    letter-spacing: 0.2em;
}
.evidence__stamp {
    flex: none;
    color: var(--steel-300);
    letter-spacing: 0.2em;
    white-space: nowrap;
}

.evidence__body {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: clamp(20px, 2.4vw, 34px);
    margin-top: clamp(20px, 2.2vw, 30px);
}

.evidence__plate { min-width: 0; }

/* The caption IS the client's brief, so it must never be cropped — these
   plates are narrower than the industries rack's, so the stamp is set down
   one step and the tracking tightened until the dimension stamp survives. */
.evidence__plate .plate__caption {
    font-size: 0.48rem;
    letter-spacing: 0.04em;
    gap: 8px;
    padding-inline: 8px;
}

.evidence__copy {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
    min-width: 0;
}

.evidence__sector {
    color: var(--bone-100);
    letter-spacing: 0.16em;
    line-height: 1.4;
    text-wrap: balance;
}

.evidence__problem {
    font-size: 0.95rem;
    line-height: 1.6;
    color: var(--bone-200);
    max-width: 44ch;
}

/* ---------- the outcome numeral ---------- */
/* The label sits UNDER the numeral: beside it, the longer descriptors
   ("UNPLANNED DOWNTIME") ran straight out of the copy column. */
.evidence__outcome {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 9px;
    margin-top: 4px;
    width: 100%;
}
.evidence__figure { flex: none; gap: 0.05em; }
.evidence__sign {
    font-size: 0.56em;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--bone-100);
}
.evidence__outcome-label {
    color: var(--steel-300);
    letter-spacing: 0.16em;
}

/* ---------- the currency figure — the one that gets forwarded ---------- */
.evidence__money {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 12px;
    width: 100%;
    max-width: none;
    margin: 4px 0 0;
    padding-top: 14px;
    border-top: 1px solid var(--steel-500);
}
.evidence__money-value {
    font-family: var(--font-display);
    font-size: clamp(1.3rem, 1.9vw, 1.7rem);
    font-weight: 800;
    font-variation-settings: 'wdth' 118;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.015em;
    line-height: 1;
    color: var(--signal);          /* final state; the relay starts it at --steel-400 */
}
.evidence__money-label {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--steel-300);
    line-height: 1.4;
}

/* ---------- the three dot-leader rows ---------- */
/* Closed top AND bottom: each dossier has to terminate on a hairline, or the
   spread reads as three paragraphs that ran out rather than three documents. */
.evidence__specs {
    margin-top: clamp(18px, 2vw, 26px);
    border-top: 1px solid var(--steel-500);
    border-bottom: 1px solid var(--steel-500);
}

/* ---------- the scribed frame that draws around each plate ---------- */
.evidence__frame {
    position: absolute;
    inset: 5px 5px 33px 5px;
    z-index: 2;
    pointer-events: none;
}
.evidence__frame svg { width: 100%; height: 100%; }
.evidence__frame-rect {
    fill: none;
    stroke: var(--steel-350);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

/* ==========================================================================
   THE SLIP RAIL — supplementary
   ========================================================================== */
.evidence__slips { margin-top: clamp(76px, 9vw, 132px); }

.evidence__slips-head {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 18px;
}
.evidence__slips-title { flex: none; color: var(--bone-100); letter-spacing: 0.2em; }
.evidence__slips-rule {
    flex: 1 1 auto;
    width: auto;
    min-width: 20px;
    background: var(--steel-400);
}
.evidence__slips-note {
    flex: none;
    color: var(--steel-300);
    letter-spacing: 0.16em;
    white-space: nowrap;
}
.evidence__readout {
    flex: none;
    font-size: var(--fs-mono);
    font-weight: 700;
    font-variation-settings: 'wdth' 112.5;
    letter-spacing: 0.2em;
    color: var(--bone-100);
    white-space: nowrap;
}

/* Without JS this is a plain scroll-snapped region and the rail still works.
   Draggable only takes over once GSAP is confirmed present. */
.evidence__bounds {
    position: relative;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    border-top: 1px solid var(--steel-500);
    border-bottom: 1px solid var(--steel-500);
    padding-block: 18px;
}
.evidence__bounds::-webkit-scrollbar { display: none; }

.evidence__strip {
    display: flex;
    width: max-content;
    align-items: stretch;
    will-change: transform;
}
.evidence__strip:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; }

.evidence__slip {
    flex: none;
    width: clamp(256px, 22vw, 300px);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 26px;
    padding: 15px 17px 17px;
    scroll-snap-align: start;
}
.evidence__slip-top {
    display: flex;
    align-items: center;
    gap: 12px;
}
.evidence__slip-idx {
    flex: none;
    color: var(--steel-300);
    letter-spacing: 0.2em;
}
.evidence__slip-rule {
    flex: 1 1 auto;
    width: auto;
    min-width: 14px;
    background: var(--steel-400);
}
/* Martian Mono is a stamping face: the longest slip is 31 characters, so the
   size and tracking are set to hold it on one line, and TWO lines are reserved
   regardless so a wrap at a narrow width never changes the rail's height. */
.evidence__slip-text {
    max-width: none;
    margin: 0;
    min-height: 3.2em;
    font-family: var(--font-mono);
    font-size: 0.58rem;
    font-weight: 500;
    letter-spacing: 0.055em;
    line-height: 1.55;
    text-transform: uppercase;
    color: var(--bone-100);
}
.evidence__strip.is-dragging { cursor: grabbing; }

/* the 1px position rail and its --signal block */
.evidence__rail {
    position: relative;
    height: 1px;
    margin-top: 18px;
    background: var(--steel-500);
}
/* A fixed block travelling a 1px rail — the hero's scroll-rail idiom. A
   proportional scrollbar thumb would put 600px of orange on the page. */
.evidence__rail-block {
    position: absolute;
    top: -1px;
    left: 0;
    height: 3px;
    width: 72px;
    background: var(--signal);
    will-change: transform;
}

.evidence__foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 20px;
    margin-top: 22px;
}
.evidence__foot-tag {
    max-width: none;
    margin: 0;
    color: var(--steel-300);
    letter-spacing: 0.16em;
}

/* ==========================================================================
   DESKTOP — THE GRID BREAK ITSELF
   ========================================================================== */
@media (min-width: 900px) {
    .evidence__head-lead  { grid-column: 1 / 9; }
    .evidence__head-aside { grid-column: 9 / -1; }

    .evidence__dossier--1 { grid-column: 1 / 8;  grid-row: 1; }
    .evidence__dossier--2 { grid-column: 6 / -1; grid-row: 2; margin-top: 120px; }
    .evidence__dossier--3 { grid-column: 2 / 10; grid-row: 3; }

    /* it lives in row 2 and is pushed clear of both dossiers by hand, so the
       hairline sits in the middle of the void rather than under dossier one */
    .evidence__seam {
        display: flex;
        grid-column: 1 / -1;
        grid-row: 2;
        align-self: start;
        margin-top: 30px;
    }

    /* each ghost numeral stands in the gutter its dossier's offset opened */
    .evidence__dossier--1 .evidence__ghost { left: 100%; margin-left: 26px; }
    .evidence__dossier--2 .evidence__ghost { right: 100%; margin-right: 26px; }
    .evidence__dossier--3 .evidence__ghost { left: 100%; margin-left: 26px; }
}

@media (min-width: 900px) and (max-width: 1259.98px) {
    .evidence__ghost { font-size: clamp(84px, 11vw, 150px); }
}

/* ==========================================================================
   THE SIDE-BY-SIDE DOSSIER — only where the plate stays wide enough for its
   own caption. A .plate__caption IS the client's asset brief: below this the
   dimension stamp starts running off the right edge, so the plate takes the
   full dossier width and the copy sits under it instead of being cropped.
   ========================================================================== */
@media (min-width: 1260px) {
    /* 16:10 plate left, copy right */
    .evidence__dossier--1 .evidence__body,
    .evidence__dossier--3 .evidence__body { grid-template-columns: minmax(0, 53fr) minmax(0, 47fr); }

    /* the portrait plate is the narrow column, and it sits on the other side */
    .evidence__dossier--2 .evidence__body { grid-template-columns: minmax(0, 50fr) minmax(0, 50fr); }
    .evidence__dossier--2 .evidence__plate { grid-column: 2; grid-row: 1; }
    .evidence__dossier--2 .evidence__copy  { grid-column: 1; grid-row: 1; }
}

/* Stacked, the 4:5 plate would be a 650px block of placeholder — it is held
   back to the width where it still reads as the portrait of the three. */
@media (max-width: 1259.98px) {
    .evidence__dossier--2 .evidence__plate { max-width: max(58%, 340px); }
}

/* ==========================================================================
   BELOW 900px — the offsets are removed and the three dossiers stack
   full-width, in order. The slip rail keeps its horizontal drag.
   ========================================================================== */
@media (max-width: 899.98px) {
    .evidence__head { row-gap: 34px; }
    .evidence__aside-rule { max-width: 100%; }

    .evidence__spread {
        grid-template-columns: 1fr;
        row-gap: clamp(56px, 11vw, 88px);
    }
    .evidence__dossier--1,
    .evidence__dossier--2,
    .evidence__dossier--3 {
        grid-column: 1 / -1;
        grid-row: auto;
        margin-top: 0;
    }
    .evidence__dossier--2 .evidence__plate { max-width: max(74%, 296px); }

    /* the gutters the offsets opened are gone, so the stamp goes with them */
    .evidence__ghost { display: none; }

    .evidence__problem { max-width: 56ch; }

    .evidence__slips-head { flex-wrap: wrap; row-gap: 12px; }
}

@media (max-width: 640px) {
    /* The bar is under 300px of usable width down here and the dimension stamp
       is the first thing to run off its right edge — so the brief is set one
       step tighter, the same step the industries rack takes. Verified at 360px:
       the id and the stamp both survive with room to spare. */
    .evidence__plate .plate__caption {
        font-size: 0.46rem;
        letter-spacing: 0.03em;
        gap: 6px;
        padding-inline: 7px;
    }

    .evidence__meta { gap: 12px; }
    .evidence__meta-tag--end { display: none; }
    .evidence__slips-note { display: none; }
    .evidence__slip { width: clamp(244px, 70vw, 284px); }
    .evidence__outcome-label { flex-basis: 100%; }
    .evidence__foot { flex-direction: column; gap: 8px; }
    .evidence__foot-tag--end { align-self: flex-start; }
}

/* ==========================================================================
   START STATES — only once JS has confirmed GSAP
   ========================================================================== */
html.js-anim .evidence__bounds {
    overflow: hidden;
    scroll-snap-type: none;
}

/* Reduced motion: Draggable is never created, so the rail is handed straight
   back to the browser. Never strand a state the animation will not clear. */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .evidence__bounds {
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
    }
}

/* ============================ TRUST ============================ */
/* ==========================================================================
   #trust — PROCUREMENT ARMOUR
   A nine-row editorial spec table with real SVG dot leaders, nine
   certification chips, and THE SECOND FLIP: one segmented control moving the
   SAME eight node elements between three deployment topologies.

   FALLBACK INVERSION: everything below ships the FINAL, readable state —
   table drawn, chips present, the default topology laid out and its boundary
   stroked. Start states live only under html.js-anim.

   ONE DELIBERATE DEPARTURE, DOCUMENTED: the value column is set in the body
   face, not Martian Mono. Design law 13 caps a Martian Mono string at 40
   characters and two of the nine approved values run to 41 and 42. Labels,
   indices, counter, chips and every node stay mono; the values are the only
   thing on the page a procurement reader actually has to read.
   ========================================================================== */

.trust { overflow: hidden; }

.trust__grid {
    opacity: 0.32;
    -webkit-mask-image: linear-gradient(180deg, #000, transparent 62%);
    mask-image: linear-gradient(180deg, #000, transparent 62%);
}

/* The right column runs shorter than the left; the numeral occupies the void
   it leaves rather than the void being left as an accident. */
.trust__ghost {
    position: absolute;
    right: -0.06em;
    bottom: 62px;
    z-index: 0;
    font-size: clamp(120px, 15vw, 240px);
    letter-spacing: -0.05em;
}

.trust__layout {
    position: relative;
    z-index: 1;
    align-items: stretch;
    row-gap: clamp(56px, 6vw, 88px);
}

/* ---------- left column ---------- */
.trust__lead {
    display: flex;
    flex-direction: column;
    gap: clamp(40px, 4.4vw, 64px);
}

/* The column is five of twelve; --fs-title tops out at 4.4rem and would run
   "PROCUREMENT." straight through the gutter. One step down, same face. */
.trust__title {
    font-size: clamp(1.8rem, 2.9vw, 2.75rem);
    text-wrap: wrap;
    margin-top: 22px;
}

.trust__arg { margin-top: 20px; }
.trust__arg:first-of-type { margin-top: 24px; }

.trust__cta { margin-top: 30px; }
.trust__btn { width: auto; }

/* ==========================================================================
   THE TOPOLOGY SWITCH
   ========================================================================== */
.trust__topo-head {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 18px;
}
.trust__topo-title { flex: none; color: var(--bone-100); }
.trust__topo-rule { flex: 1 1 auto; width: auto; min-width: 20px; }
.trust__topo-stamp { flex: none; color: var(--steel-300); white-space: nowrap; }

/* ---------- the segmented control ---------- */
.trust__seg {
    --seg-i: 0;
    position: relative;
    display: flex;
    border: 1px solid var(--steel-500);
    background: var(--ink-900);
}

/* One square travelling between labels. Its CSS position is the no-GSAP
   truth; Flip.fit drives it at 0.24s and hands it straight back. */
.trust__seg-marker {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 0;
    width: calc(100% / 3);
    transform: translateX(calc(var(--seg-i) * 100%));
    background: var(--signal-wash);
    border: 1px solid var(--signal);
    pointer-events: none;
}

.trust__seg-btn {
    position: relative;
    z-index: 1;
    flex: 1 1 0%;
    min-height: 44px;
    padding: 13px 6px;
    border-right: 1px solid var(--steel-500);
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--steel-300);
    text-align: center;
    transition: color var(--t-state) var(--ease-machine);
}
.trust__seg-btn:last-child { border-right: 0; }
.trust__seg-btn:hover { color: var(--bone-100); }
.trust__seg-btn[aria-checked="true"] { color: var(--signal); }

/* ---------- the stage: SVG underlay + eight absolutely placed HTML nodes ---------- */
.trust__topo { margin-top: 22px; }

.trust__stage {
    position: relative;
    width: 100%;
    max-width: 470px;
    aspect-ratio: 420 / 300;
    background: var(--ink-900);
    border: 1px solid var(--steel-500);
}

.trust__svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.trust__reg { fill: none; stroke: var(--steel-400); stroke-width: 1; }

/* the perimeter — two paths so a state change is a DrawSVG crossfade */
.trust__bound {
    fill: none;
    stroke: var(--signal-rule);
    stroke-width: 1;
}

/* only the active topology's edges are on the board */
.trust__edges { visibility: hidden; }
.trust__topo-block[data-state="vpc"] .trust__edges--vpc,
.trust__topo-block[data-state="onprem"] .trust__edges--onprem,
.trust__topo-block[data-state="air"] .trust__edges--air { visibility: visible; }

.trust__edge {
    fill: none;
    stroke: var(--steel-400);
    stroke-width: 1;
}
.trust__edge--cross { stroke: var(--steel-350); }
.trust__edge--severed { stroke: var(--steel-400); }
.trust__edge--gap { stroke: var(--signal); stroke-width: 1; }

/* ---------- the eight shared nodes ---------- */
.trust__node {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22.857%;
    height: 11.333%;
    padding: 0 4px;
    background: var(--ink-600);
    border: 1px solid var(--steel-500);
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--bone-200);
    overflow: hidden;
}
.trust__node-label { display: block; white-space: nowrap; }

/* the runtime is the part everything else is arranged around */
.trust__node--runtime {
    border-color: var(--signal-rule);
    color: var(--bone-100);
}

/* anything outside the perimeter, in whichever state puts it there */
.trust__topo-block[data-state="vpc"] .trust__node--model,
.trust__topo-block[data-state="vpc"] .trust__node--updates,
.trust__topo-block[data-state="onprem"] .trust__node--updates,
.trust__topo-block[data-state="air"] .trust__node--updates {
    background: var(--ink-800);
    border-style: dashed;
    border-color: var(--steel-400);
    color: var(--steel-300);
}

/* ---------- STATE 01 · VPC ---------- */
.trust__topo-block[data-state="vpc"] .trust__node--sources { left: 5.714%;  top: 16%; }
.trust__topo-block[data-state="vpc"] .trust__node--ingest  { left: 33.333%; top: 16%; }
.trust__topo-block[data-state="vpc"] .trust__node--index   { left: 5.714%;  top: 38.667%; }
.trust__topo-block[data-state="vpc"] .trust__node--runtime { left: 33.333%; top: 38.667%; }
.trust__topo-block[data-state="vpc"] .trust__node--audit   { left: 5.714%;  top: 61.333%; }
.trust__topo-block[data-state="vpc"] .trust__node--keys    { left: 33.333%; top: 61.333%; }
.trust__topo-block[data-state="vpc"] .trust__node--model   { left: 71.429%; top: 27.333%; }
.trust__topo-block[data-state="vpc"] .trust__node--updates { left: 71.429%; top: 61.333%; }

/* ---------- STATE 02 · ON-PREM — the model comes inside ---------- */
.trust__topo-block[data-state="onprem"] .trust__node--sources { left: 5.714%;  top: 10.667%; }
.trust__topo-block[data-state="onprem"] .trust__node--ingest  { left: 33.333%; top: 10.667%; }
.trust__topo-block[data-state="onprem"] .trust__node--index   { left: 5.714%;  top: 32%; }
.trust__topo-block[data-state="onprem"] .trust__node--runtime { left: 33.333%; top: 32%; }
.trust__topo-block[data-state="onprem"] .trust__node--audit   { left: 5.714%;  top: 53.333%; }
.trust__topo-block[data-state="onprem"] .trust__node--keys    { left: 33.333%; top: 53.333%; }
.trust__topo-block[data-state="onprem"] .trust__node--model   { left: 33.333%; top: 74.667%; }
.trust__topo-block[data-state="onprem"] .trust__node--updates { left: 71.429%; top: 74.667%; }

/* ---------- STATE 03 · AIR-GAPPED — double wall, update channel severed ---------- */
.trust__topo-block[data-state="air"] .trust__node--sources { left: 7.143%;  top: 11.333%; }
.trust__topo-block[data-state="air"] .trust__node--ingest  { left: 34.762%; top: 11.333%; }
.trust__topo-block[data-state="air"] .trust__node--index   { left: 7.143%;  top: 32.667%; }
.trust__topo-block[data-state="air"] .trust__node--runtime { left: 34.762%; top: 32.667%; }
.trust__topo-block[data-state="air"] .trust__node--audit   { left: 7.143%;  top: 54%; }
.trust__topo-block[data-state="air"] .trust__node--keys    { left: 34.762%; top: 54%; }
.trust__topo-block[data-state="air"] .trust__node--model   { left: 20.952%; top: 75.333%; }
.trust__topo-block[data-state="air"] .trust__node--updates { left: 72.857%; top: 42.667%; }

.trust__figcap {
    margin-top: 10px;
    color: var(--steel-300);
    letter-spacing: 0.16em;
}

/* ---------- the note under the board: one constant height for all three ---------- */
.trust__notes {
    margin-top: 20px;
    min-height: 104px;
    border-top: 1px solid var(--steel-500);
    padding-top: 16px;
}
.trust__note { display: none; font-size: 0.94rem; line-height: 1.58; color: var(--bone-200); max-width: 46ch; }
.trust__topo-block[data-state="vpc"] .trust__note[data-topo="vpc"],
.trust__topo-block[data-state="onprem"] .trust__note[data-topo="onprem"],
.trust__topo-block[data-state="air"] .trust__note[data-topo="air"] { display: block; }

.trust__note-flag {
    display: block;
    margin-bottom: 8px;
    color: var(--signal);
    letter-spacing: 0.16em;
}

/* ==========================================================================
   RIGHT — the nine-row table
   ========================================================================== */
.trust__answers {
    position: relative;
    display: flex;
    flex-direction: column;
}
.trust__table-head,
.trust__table,
.trust__certs,
.trust__signoff { position: relative; z-index: 1; }

/* pushed to the foot of the column so both columns close on the same line */
.trust__signoff {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-top: auto;
    padding-top: clamp(48px, 6vw, 88px);
}
.trust__signoff-tag { flex: none; color: var(--steel-300); white-space: nowrap; }
.trust__signoff-rule { flex: 1 1 auto; width: auto; min-width: 24px; }

.trust__table-head,
.trust__certs-head {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 14px;
}
.trust__table-title,
.trust__certs-title { flex: none; color: var(--bone-100); }
.trust__table-rule,
.trust__certs-rule { flex: 1 1 auto; width: auto; min-width: 20px; }
.trust__counter {
    flex: none;
    color: var(--steel-300);
    letter-spacing: 0.18em;
    white-space: nowrap;
}
.trust__counter-num { color: var(--bone-100); }

.trust__table { border-top: 1px solid var(--steel-500); }

.trust__row {
    align-items: center;
    gap: 14px;
    padding: 14px 0;
}
.trust__row + .trust__row { border-top-color: var(--steel-500); }
.trust__row:last-child { border-bottom: 1px solid var(--steel-500); }

.trust__row-idx {
    flex: none;
    width: 22px;
    color: var(--steel-300);
    letter-spacing: 0.1em;
}

.trust__row-label {
    flex: none;
    max-width: 46%;
    color: var(--bone-300);
    letter-spacing: 0.14em;
}

/* the leader is a real SVG line so DrawSVG can run the dots toward the value */
.trust__leader {
    flex: 1 1 0%;
    min-width: 18px;
    height: 2px;
    background-image: none;
    color: var(--steel-350);
    overflow: hidden;
}
.trust__leader-line {
    stroke: currentColor;
    stroke-width: 1;
    stroke-dasharray: 1 5;
}

.trust__row-value {
    flex: 0 1 auto;
    font-family: var(--font-body);
    font-size: 0.9rem;
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1.4;
    text-transform: none;
    color: var(--bone-100);
    text-align: right;
}
.trust__row-value--last { color: var(--signal); }

/* ---------- the chips ---------- */
.trust__certs { margin-top: clamp(38px, 4vw, 54px); }
.trust__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.trust__chip {
    display: inline-flex;
    color: var(--bone-300);
}

/* ==========================================================================
   START STATES — only ever present once JS has confirmed window.gsap
   ========================================================================== */
html.js-anim .trust__row-label { clip-path: inset(0 100% 0 0); }
html.js-anim .trust__row-value { clip-path: inset(0 0 0 100%); }
html.js-anim .trust__chip     { clip-path: inset(0 0 100% 0); }
html.js-anim .trust__cta      { clip-path: inset(0 0 100% 0); }
html.js-anim .trust__node     { clip-path: inset(0 0 100% 0); }

/* the leader is drawn, not scaled — hand the shared scaleX start state back */
html.js-anim .trust__leader { transform: none; }
html.js-anim .trust__leader-line { stroke-dasharray: 400; stroke-dashoffset: 400; }

html.js-anim .trust__bound { stroke: var(--steel-400); stroke-dasharray: 1400; stroke-dashoffset: 1400; }
html.js-anim .trust__edge  { stroke-dasharray: 400; stroke-dashoffset: 400; }

/* Nothing may be left stranded if the tween that would clear it never runs. */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .trust__row-label,
    html.js-anim .trust__row-value,
    html.js-anim .trust__chip,
    html.js-anim .trust__cta,
    html.js-anim .trust__node { clip-path: none; }
}

/* ==========================================================================
   BELOW 900px — one column, table first, switch second
   ========================================================================== */
@media (max-width: 899.98px) {
    .trust__row { flex-wrap: wrap; }
    .trust__layout { row-gap: clamp(48px, 8vw, 72px); }
    .trust__answers { order: 1; }
    .trust__lead    { order: 2; }

    /* Stacked, the table runs the full width of the column, so the numeral can
       no longer sit behind its head — at any size it overprinted the first two
       values. It stays at the foot of the column and the sign-off reserves the
       void it needs, including the +-33px the depth law travels it. */
    .trust__ghost { font-size: clamp(72px, 18vw, 124px); top: auto; bottom: 64px; right: -0.04em; }
    .trust__signoff { padding-top: clamp(160px, 32vw, 215px); }
    /* At 2rem "BUILT TO SURVIVE" is one pixel wider than a 390px well and takes
       a third line, stranding SURVIVE. One step down holds the copy's marked
       break as the only break, from 320px up. */
    .trust__title { font-size: clamp(1.5rem, 7.2vw, 3.2rem); }
    .trust__stage { max-width: 100%; }
    .trust__notes { min-height: 0; }
    .trust__row-label { max-width: 42%; }
}

@media (max-width: 640px) {
    .trust__row-idx { display: none; }
    .trust__row { gap: 10px; padding: 12px 0; }
    .trust__row-label { max-width: none; letter-spacing: 0.1em; }
    /* Below 640 no value fits beside its label, and a value that wraps to a 62%-wide
       flex line right-aligns inside that box rather than to the page edge — so the
       column read ragged. Here every value takes its own full line: label and leader
       on one, value right-aligned to the edge on the next. Between 641 and 900 the
       min-width rule above still lets short values stay inline. */
    .trust__row-value { font-size: 0.86rem; max-width: none; flex: 1 1 100%; min-width: 0; margin-top: 3px; }
    .trust__topo-stamp { display: none; }
    .trust__signoff-tag:last-child { display: none; }
    .trust__node { font-size: 0.54rem; letter-spacing: 0.04em; }
    .trust__seg-btn { padding: 13px 2px; letter-spacing: 0.06em; }
    .trust__btn { width: 100%; }
}

/* ============================ MANIFESTO ============================ */
/* ==========================================================================
   #manifesto — THE INVERTED BAND
   The one tonal slam on the page: --paper-100 ground, --paper-ink type, the
   printed 12-column grid still showing through at 12% so the structure
   survives the inversion. Cols 1-2 are the margin (a 1px reading-progress
   hairline and three side notes that swap in their masks); cols 3-12 carry
   the quote, bracketed top-left and bottom-right by two 40px signal marks.
   Ten columns, not eight: at wdth 125 the marked five-line break needs every
   one of them, and the copy's line structure outranks the column diagram.

   FALLBACK INVERSION — the whole point of this section:
   every rule below ships the FINAL state. The band is open, every word is
   --paper-ink, both accent underlines are orange, all three side-note labels
   are up and the attribution is seated. The dimmed word colour is applied by
   gsap.set ONLY, and the three CSS start states (the shutter clip, the bracket
   dash offsets and the transparent underscore) live under html.js-anim + (prefers-reduced-motion:
   no-preference) — the exact branch that scrubs them back off. A blocked
   vendor script leaves the loudest moment on the page completely legible.
   ========================================================================== */

.manifesto {
    background: var(--ink-900);
    overflow: hidden;
}

/* ---------- the band: full-bleed paper, and the element the shutter clips ---------- */
.manifesto__band {
    position: relative;
    isolation: isolate;
    padding-block: var(--section-pad);
    background: var(--paper-100);
    color: var(--paper-ink);
}

/* The printed grid survives the inversion at 12%; the component supplies the
   geometry, this only re-weights it for a light ground. */
.manifesto__grid {
    opacity: 0.12;
    z-index: 0;
}

.manifesto__inner { position: relative; z-index: 1; }

/* ---------- head strip ---------- */
.manifesto__head {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: clamp(52px, 6vw, 92px);
}
/* On paper the accent cannot carry small type — the 8x8 square stays --signal,
   the characters go to --paper-ink. */
.manifesto__label {
    flex: none;
    color: var(--paper-ink);
}
.manifesto__head-rule {
    flex: 1 1 auto;
    width: auto;
    min-width: 24px;
    background: var(--steel-350);
}
.manifesto__stamp {
    flex: none;
    color: var(--steel-400);
    letter-spacing: 0.18em;
    white-space: nowrap;
}

.manifesto__grid12 { align-items: stretch; }

/* ==========================================================================
   THE MARGIN — cols 1-2
   ========================================================================== */
.manifesto__aside {
    grid-column: 1 / 3;
    position: relative;
    display: flex;
    flex-direction: column;
    padding-left: 22px;
}

/* the reading-progress hairline down the left margin */
.manifesto__track {
    position: absolute;
    left: 0;
    top: 4px;
    bottom: 4px;
    width: 1px;
    background: var(--bone-300);
}
.manifesto__track-fill {
    display: block;
    width: 100%;
    height: 100%;
    background: var(--signal);
    transform-origin: top center;
}

.manifesto__notes {
    display: flex;
    flex-direction: column;
    /* The index is a scale, not a stack: it starts on the quote's first line and
       its last mark lands on the quote's last, so the reading head travelling the
       hairline beside it has three real stations to pass rather than a cluster at
       the top and 250px of bare rule underneath. */
    flex: 1 1 auto;
    justify-content: space-between;
    gap: clamp(22px, 2.4vw, 34px);
    padding-top: clamp(38px, 3.8vw, 58px);
    padding-bottom: clamp(64px, 6.8vw, 100px);
}
.manifesto__note {
    display: flex;
    align-items: baseline;
    gap: 12px;
}
.manifesto__note-num {
    flex: none;
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 700;
    font-variation-settings: 'wdth' 112.5;
    letter-spacing: 0.18em;
    line-height: 1.4;
    color: var(--steel-400);
}
/* the mask each label rises into */
.manifesto__note-win {
    display: block;
    overflow: hidden;
    min-width: 92px;
    line-height: 1.4;
}
.manifesto__note-label {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 400;
    letter-spacing: 0.14em;
    line-height: 1.4;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--paper-ink);
}

/* ==========================================================================
   THE QUOTE — cols 3-12
   ========================================================================== */
.manifesto__quote {
    grid-column: 3 / -1;
    position: relative;
    margin: 0;
}

.manifesto__body {
    position: relative;
    padding-block: clamp(38px, 3.8vw, 58px);
}

.manifesto__q {
    max-width: none;
    font-family: var(--font-display);
    font-size: clamp(1.9rem, 4.1vw, 3.4rem);
    font-weight: 900;
    font-variation-settings: 'wdth' 125;
    font-feature-settings: 'kern' 1;
    line-height: 1.02;
    letter-spacing: -0.028em;
    text-transform: uppercase;
    color: var(--paper-ink);
}

/* Emphasis is width, not colour: on paper the accent cannot carry a character,
   so the two marked words keep --paper-ink and take a 2px --signal underscore
   as the relay that closes last. */
/* `html` on the selector is load-bearing: foundation ships
   `html.js-anim .text-accent { color: var(--steel-400) }`, which outranks a plain
   two-class selector. Without the extra element the two marked words would sit at
   --steel-400 on paper whenever SplitText is missing and no inner word carries the
   ink for them. */
html .manifesto .text-accent {
    /* Layout containment suppresses an inline-block's baseline, which lifts a
       marked word clean off the line it shares. The width reservation JS puts
       on these two spans already does the job containment was there for. */
    contain: none;
    color: var(--paper-ink);
    padding-bottom: 0.04em;
    border-bottom: 2px solid var(--signal);
}

/* ---------- the two 40px brackets that stand in for quotation marks ---------- */
.manifesto__bracket {
    position: absolute;
    width: 40px;
    height: 40px;
    overflow: visible;
    pointer-events: none;
}
.manifesto__bracket--open { top: 0; left: 0; }
/* clear of the attribution rule below it — two hairlines 6px apart read as an error */
.manifesto__bracket--close { bottom: 20px; right: 0; transform: rotate(180deg); }
.manifesto__bracket-path { stroke: var(--signal); }

/* ---------- attribution ---------- */
.manifesto__attr-rule {
    background: var(--steel-350);
    margin-top: 4px;
}
.manifesto__attr {
    overflow: hidden;
    margin-top: 18px;
}
.manifesto__attr-lift {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-mono);
    font-weight: 500;
    letter-spacing: 0.16em;
    line-height: 1.5;
    text-transform: uppercase;
    color: var(--paper-ink);
}

/* ==========================================================================
   START STATES — only in the branch that scrubs them away
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
    /* the shutter: the band's ground AND its type travel together */
    html.js-anim .manifesto__band { clip-path: inset(0% 0% 100% 0%); }

    /* the brackets draw; DrawSVG takes the dash over from here */
    html.js-anim .manifesto__bracket-path {
        stroke-dasharray: 80;
        stroke-dashoffset: 80;
    }

    /* the underscore is the relay that closes last */
    html.js-anim .manifesto .text-accent { border-bottom-color: transparent; }
}

/* zz-responsive hands every .text-accent back to --signal under reduced motion.
   On paper that is a 2.7:1 character — this band keeps its ink. */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .manifesto .text-accent {
        color: var(--paper-ink);
        font-variation-settings: 'wdth' 125;
    }
}

/* Between 900 and 1160 the two-column margin is narrower than "01 THE POSITION"
   set on one line, so the label drops under its number rather than clipping. */
@media (min-width: 900px) and (max-width: 1159.98px) {
    .manifesto__note {
        flex-direction: column;
        align-items: flex-start;
        gap: 5px;
    }
    .manifesto__note-win { min-width: 0; }
}

/* ==========================================================================
   BELOW 900px — the margin becomes a header: the notes run as one horizontal
   row above the quote and the progress hairline moves to the top edge.
   ========================================================================== */
@media (max-width: 899.98px) {
    .manifesto__grid12 { row-gap: clamp(30px, 5vw, 44px); }
    .manifesto__head { margin-bottom: clamp(38px, 6vw, 56px); }

    .manifesto__aside {
        grid-column: 1 / -1;
        padding-left: 0;
        padding-top: 20px;
    }
    .manifesto__track {
        left: 0;
        right: 0;
        top: 0;
        bottom: auto;
        width: auto;
        height: 1px;
    }
    .manifesto__track-fill { transform-origin: left center; }

    .manifesto__notes {
        display: grid;
        /* minmax(0,1fr) so a long label can never push the row past the viewport */
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 14px;
        flex: none;
        padding-top: 0;
        padding-bottom: 0;
    }
    .manifesto__note {
        flex-direction: column;
        align-items: flex-start;
        gap: 5px;
    }
    .manifesto__note-win { min-width: 0; }

    .manifesto__quote { grid-column: 1 / -1; }
    .manifesto__body { padding-block: clamp(30px, 8vw, 48px); }
}

@media (max-width: 640px) {
    .manifesto__head { gap: 12px; }
    .manifesto__stamp { display: none; }

    /* The five marked breaks are what keeps each accent either line-final or one
       word from it, so below 640px the face gives up size and width before the
       copy gives up its structure. 5.4vw, not 5.9: at 5.9 the closing line breaks
       and strands ON. on a sixth line at 320 / 360 / 390 / 430 — all measured
       through a fixed-width iframe, since headless floors the layout viewport. */
    .manifesto__q {
        font-size: clamp(1.05rem, 5.4vw, 1.9rem);
        font-variation-settings: 'wdth' 100;
        letter-spacing: -0.035em;
    }
    .manifesto__bracket { width: 28px; height: 28px; }
    .manifesto__notes { gap: 8px 14px; }
    /* "THE POSITION" is wider than a third of a 320px column, and the mask that
       carries it clips. Let it break instead of losing characters. */
    .manifesto__note-label {
        white-space: normal;
        letter-spacing: 0.1em;
    }
    .manifesto__attr-lift {
        font-size: var(--fs-mono-sm);
        letter-spacing: 0.12em;
    }
}

/* ============================ CTA ============================ */
/* ==========================================================================
   #cta — "THE OFFER"
   The single loudest moment on the page and the only large colour field in the
   design: a full-bleed --signal ground carrying --paper-ink type. The ground is
   not a background-color, it is eight vertical shutter panels that open it.

   THE COLOUR INVERSION. On this band the accent is the ground, so every shared
   component that normally paints itself --signal has to paint itself
   --paper-ink instead. Those overrides are scoped under .cta and applied
   through this section's own classes (.cta__rule, .cta__chip, .cta__btn--ghost)
   so nothing outside this block is touched.

   FALLBACK INVERSION. Everything below ships in its FINAL state — shutters
   open, gauge full (--fill: 24), stamps and buttons seated. Start states live
   only under html.js-anim and are undone again under prefers-reduced-motion.
   ========================================================================== */

.cta {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    /* the ground before the shutters open — never a flash of orange */
    background: var(--ink-900);
    padding-block: clamp(84px, 10vw, 152px);
    color: var(--paper-ink);
}

/* --------------------------------------------------------------------------
   1. THE GROUND — eight shutters, seams in --signal-600
   -------------------------------------------------------------------------- */
.cta__ground {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: flex;
    pointer-events: none;
}
.cta__shutter {
    flex: 1 1 12.5%;
    background: var(--signal);
    border-right: 1px solid var(--signal-600);
    transform: scaleY(1);
    transform-origin: bottom center;
}
.cta__shutter:last-child { border-right: 0; }

.cta__inner {
    position: relative;
    z-index: 2;
}

/* Orange kills the house focus ring (it is signal at 55%), so the band takes
   its own — same 2px square outline, inverted. */
.cta a:focus-visible,
.cta button:focus-visible {
    outline: 2px solid var(--paper-ink);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   2. STAMP BARS — top and foot
   -------------------------------------------------------------------------- */
.cta__bar {
    display: flex;
    align-items: center;
    gap: 18px;
}
.cta__bar--top  { margin-bottom: clamp(42px, 5vw, 76px); }
.cta__bar--foot { margin-top: clamp(42px, 5vw, 76px); }

.cta__stamp {
    flex: none;
    overflow: hidden;
    color: var(--paper-ink);
    letter-spacing: 0.18em;
    white-space: nowrap;
}
.cta__lift { display: block; }

/* the house hairline, repainted for the inverted ground */
.cta__rule {
    flex: 1 1 auto;
    width: auto;
    min-width: 24px;
    background: var(--paper-ink);
}

/* --------------------------------------------------------------------------
   3. GRID — lede | gauge on row 1, chips | actions on row 2
   -------------------------------------------------------------------------- */
.cta__grid {
    row-gap: clamp(30px, 3.6vw, 46px);
    align-items: stretch;
}

/* ---------- lede ---------- */
.cta__lede {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.cta__label {
    overflow: hidden;
    color: var(--paper-ink);
    margin-bottom: clamp(22px, 2.6vw, 34px);
}
.cta__label::before { background: var(--paper-ink); }

/* Uppercase display is sanctioned here. wdth 125 at 900 is the widest, heaviest
   setting in the build — this line is the loudest thing on the page. The
   perspective lives on the SplitText line (see .cta__line): CSS perspective
   applies to DIRECT children only, and the chars are children of the line. */
.cta__title {
    font-family: var(--font-display);
    /* wdth 125 at 900 is the widest setting in the build, so the size is
       pinned to the one thing that must not break: the copy's marked line
       ends at WITH, and stranding WITH on a line of its own would read as a
       typesetting accident. This is the largest size that holds it. */
    font-size: clamp(1.9rem, 3.3vw, 2.75rem);
    font-weight: 900;
    font-variation-settings: 'wdth' 125;
    line-height: 0.88;
    letter-spacing: -0.035em;
    text-transform: uppercase;
    color: var(--paper-ink);
    text-wrap: wrap;
    hyphens: none;
    -webkit-hyphens: none;
    perspective: 900px;
}
.cta__line { perspective: 900px; }

.cta__body {
    overflow: hidden;
    margin-top: clamp(22px, 2.6vw, 32px);
    max-width: 38ch;
    color: var(--paper-ink);
    font-size: clamp(1.02rem, 1.16vw, 1.18rem);
    line-height: 1.5;
}

/* ---------- reassurance chips ---------- */
.cta__chips {
    display: flex;
    flex-wrap: wrap;
    /* Top of row 2, NOT bottom. Bottom-aligning them onto the second button's
       baseline buys one flat closing line and costs a 145px hole between the
       supporting sentence and the reassurance it qualifies — the offer stops
       reading as one block. Closing the band is the foot bar's job anyway. */
    align-items: flex-end;
    align-self: start;
    gap: 10px;
}
.cta__chip-slot { display: inline-block; overflow: hidden; }
.cta__chip {
    background: transparent;
    border-color: var(--paper-ink);
    color: var(--paper-ink);
    font-weight: 500;
    letter-spacing: 0.16em;
    padding: 8px 13px;
}
.cta__chip:hover { border-color: var(--paper-ink); }

/* ---------- actions ---------- */
.cta__actions {
    display: flex;
    flex-direction: column;
    align-self: end;
    gap: 12px;
}
.cta__act { display: block; overflow: visible; }
.cta__act .btn { width: 100%; }

/* .btn--outline is drawn for graphite. On the inverted ground its hairline,
   its type and its wipe all become --paper-ink, and the wipe reveals --signal. */
.cta .cta__btn--ghost {
    color: var(--paper-ink);
    border-color: var(--paper-ink);
}
.cta .cta__btn--ghost::before { background: var(--paper-ink); }
.cta .cta__btn--ghost:hover,
.cta .cta__btn--ghost:focus-visible {
    color: var(--signal);
    border-color: var(--paper-ink);
}

/* --------------------------------------------------------------------------
   4. THE GAUGE — 24 segments, ONE custom property
   Every segment computes its own on/off from --fill on the frame. Nothing here
   is ever tweened individually: cta.js writes --fill exactly once per frame
   through a single quickSetter, and 24 transforms follow. --fill counts
   segments (0 - 24), so the arithmetic is (fill - index) with no scaling.
   -------------------------------------------------------------------------- */
.cta__gauge-wrap {
    display: flex;
    flex-direction: column;
}
.cta__gauge {
    --fill: 24;                       /* FINAL state ships here: full */
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-height: 282px;
    padding: 16px 18px;
    border: 1px solid var(--paper-ink);
}

.cta__tick {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: none;
    margin: 0;
    max-width: none;
}
.cta__tick-key {
    flex: none;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-sm);
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--paper-ink);
}
/* Axis leaders are SCALE FURNITURE, not data. On the orange ground the seam
   tone reads exactly like a --steel-350 dot leader does on graphite: present,
   subordinate, never mistaken for a segment. */
.cta__tick-rule { background: var(--signal-600); }

.cta__segs {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

.cta__seg {
    /* the whole gauge, in one declaration */
    --on: clamp(0, calc((var(--fill) - var(--i)) * 4), 1);
    display: block;
    /* --w ramps 28% -> 96% linearly up the stack, so the stack reads as one
       rising throughput profile. The four decades are marked by WEIGHT, not by
       width: a full-width major would saw the profile into a comb. */
    width: var(--w, 58%);
    height: 1px;
    background: var(--paper-ink);
    transform-origin: left center;
    transform: scaleX(var(--on));
}
.cta__seg--major { height: 2px; }

/* ==========================================================================
   START STATES — only once JS has confirmed GSAP
   ========================================================================== */
html.js-anim .cta__shutter { transform: scaleY(0); }
html.js-anim .cta__gauge   { --fill: 0; }
html.js-anim .cta__bar     { clip-path: inset(0 0 100% 0); }
html.js-anim .cta__gauge   { clip-path: inset(100% 0 0 0); }
html.js-anim .cta__lift    { transform: translateY(112%); }
html.js-anim .cta__chip    { transform: translateY(118%); }
html.js-anim .cta__act     { overflow: hidden; }
html.js-anim .cta__act .btn { transform: translateY(118%); }

/* Reduced motion: never strand a start state whose animation will not run. */
@media (prefers-reduced-motion: reduce) {
    html.js-anim .cta__shutter { transform: scaleY(1); }
    html.js-anim .cta__gauge   { --fill: 24; clip-path: none; }
    html.js-anim .cta__bar     { clip-path: none; }
    html.js-anim .cta__lift,
    html.js-anim .cta__chip,
    html.js-anim .cta__act .btn { transform: none; }
    html.js-anim .cta__act     { overflow: visible; }
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 899.98px) {
    /* One column, in the reading order the offer needs: statement, line,
       buttons, reassurance, instrument. */
    .cta__grid {
        display: flex;
        flex-direction: column;
        gap: clamp(26px, 5vw, 38px);
    }
    .cta__lede       { order: 1; }
    .cta__actions    { order: 2; align-self: stretch; }
    .cta__chips      { order: 3; align-self: flex-start; }
    .cta__gauge-wrap { order: 4; }

    .cta__title { font-size: clamp(1.95rem, 6.2vw, 3rem); }
    .cta__body  { max-width: 54ch; }

    /* The gauge lies down: a 120px full-width strip, 24 vertical hairlines
       filling left to right off exactly the same --fill arithmetic. */
    .cta__gauge {
        display: grid;
        grid-template-columns: auto 1fr auto;
        grid-template-rows: 1fr auto;
        align-items: center;
        column-gap: 14px;
        row-gap: 12px;
        min-height: 0;
        height: 120px;
        padding: 14px 16px;
    }
    .cta__segs {
        grid-column: 1 / -1;
        grid-row: 1;
        flex-direction: row-reverse;   /* DOM runs 23 -> 0, so 0 lands left */
        align-items: flex-end;
        height: 100%;
    }
    .cta__seg {
        width: 1px;
        height: var(--w, 58%);
        transform-origin: center bottom;
        transform: scaleY(var(--on));
    }
    .cta__seg--major { width: 2px; }

    .cta__tick-rule { display: none; }
    .cta__tick--lo { grid-column: 1; grid-row: 2; }
    .cta__tick--hi { grid-column: 3; grid-row: 2; justify-content: flex-end; }
}

@media (max-width: 640px) {
    .cta { padding-block: clamp(72px, 15vw, 104px); }
    .cta__bar { gap: 12px; }
    .cta__stamp--end { display: none; }
    .cta__title { font-size: clamp(1.75rem, 8vw, 2.4rem); letter-spacing: -0.02em; }
    .cta__body { font-size: 1rem; }
    .cta__chips { gap: 8px; }
    .cta__chip { padding: 8px 11px; letter-spacing: 0.12em; }
    .cta__act { display: block; }
    .cta__gauge { height: 104px; }
}

/* ============================ CONTACT ============================ */
/* ==========================================================================
   #contact — "OPEN A CHANNEL"
   An operator console. Left column: the address block, six dot-leader
   particulars and a code-drawn orthogonal locator schematic (1px street grid,
   one --signal marker square, no map, no photograph). Right column: the form,
   a console panel on --ink-700 with square --ink-600 inputs, a mono field
   counter top-right and a status slot on its own hairline.

   FALLBACK INVERSION: every rule below ships the FINAL state. The only start
   states are the focus edge (scaleY 0) and the success seal (scaleX 0), which
   are STATE indicators — not entrances — and are correct at rest with or
   without GSAP. Nothing here is hidden outside html.js-anim.
   ========================================================================== */

.contact {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.contact__bg {
    z-index: 0;
    opacity: 0.3;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 26%, #000 70%, transparent 100%);
    mask-image: linear-gradient(180deg, transparent 0%, #000 26%, #000 70%, transparent 100%);
}

.contact__inner { position: relative; z-index: 1; }

.contact__grid {
    align-items: start;
    row-gap: clamp(44px, 5vw, 68px);
}

/* ---------- left, row 1: the address block ---------- */
/* Cols 1-5 is a narrow measure and .text-accent sets AN ENGINEER. at wdth 125,
   so the headline is sized off its WIDE line and holds the copy's two lines. */
.contact__title {
    text-wrap: wrap;
    font-size: clamp(2.1rem, 3.6vw, 3.3rem);
}
.contact__desc { color: var(--bone-200); }

/* ---------- left, row 2: particulars ---------- */
.contact__strip {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 6px;
}
.contact__strip-title { flex: none; color: var(--bone-100); }
.contact__strip-rule { flex: 1 1 auto; width: auto; min-width: 20px; }
.contact__strip-note { flex: none; color: var(--steel-300); letter-spacing: 0.18em; }

.contact__rows { border-top: 1px solid var(--steel-500); }
.contact__row { padding: 11px 0; }
.contact__row .spec-row__value { color: var(--bone-100); }

/* The mailto/tel rows are the only links in the block. Padding + a matching
   negative margin buys a 44px tap target without changing the row rhythm; the
   rule under the address is a text-decoration, not a border, so it stays welded
   to the glyphs instead of dropping to the bottom of the padded box. */
.contact__link {
    display: inline-block;
    padding: 16px 0;      /* 44px minimum touch target, measured */
    margin: -16px 0;
    color: inherit;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-decoration-color: var(--steel-500);
    text-underline-offset: 4px;
    transition: color var(--t-state) var(--ease-machine),
                text-decoration-color var(--t-state) var(--ease-machine);
}
.contact__link:hover, .contact__link:focus-visible {
    color: var(--signal);
    text-decoration-color: var(--signal);
}

/* ---------- left, row 2: the locator sheet ---------- */
.contact__locator {
    position: relative;
    margin-top: clamp(30px, 3.2vw, 44px);
    background: var(--ink-800);
    border: 1px solid var(--steel-500);
    overflow: hidden;
}
.contact__map {
    display: block;
    width: 100%;
    height: auto;
    overflow: hidden;   /* the sheet is a framed drawing; nothing leaves it */
}
.contact__loccap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 12px;
    border-top: 1px solid var(--steel-500);
    color: var(--steel-300);
    white-space: nowrap;
    overflow: hidden;
}
.contact__locnote { color: var(--steel-300); }

/* SVG vocabulary — hairlines and four graphite tones, nothing else.
   The street lattice carries the drawing, so it sits a tone above the blocks:
   at --steel-500 on --ink-800 the grid disappeared and the sheet read empty. */
.cx-block        { fill: var(--ink-600); }
.cx-block--b     { fill: var(--steel-500); }
.cx-block--ghost { fill: var(--ink-700); }
.cx-block--hq    { fill: var(--signal-wash); }
.cx-street       { fill: none; stroke: var(--steel-400); stroke-width: 1; }
.cx-arterial     { fill: none; stroke: var(--steel-350); stroke-width: 1.5; }
.cx-tick         { fill: none; stroke: var(--steel-400); stroke-width: 1; }
.cx-frame        { fill: none; stroke: var(--steel-400); stroke-width: 1.5; }
/* The guides are DASHED, so they are drawn by an axis-locked scale, never by
   DrawSVG — DrawSVG writes its own stroke-dasharray and would flatten them
   into two solid orange rules fighting the marker for the eye. */
.cx-guide        { fill: none; stroke: var(--signal-rule); stroke-width: 1; stroke-dasharray: 2 5; }
.cx-leader       { fill: none; stroke: var(--steel-400); stroke-width: 1; }
.cx-plate        { fill: var(--ink-800); }
.cx-marker-box   { fill: none; stroke: var(--signal); stroke-width: 1.5; }
.cx-marker-core  { fill: var(--signal); }
.cx-north        { fill: none; stroke: var(--steel-400); stroke-width: 1; }
.cx-label {
    font-family: var(--font-mono);
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.08em;
    fill: var(--bone-100);
}
.cx-north-label {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    fill: var(--steel-300);
}

/* ==========================================================================
   RIGHT — THE CONSOLE
   ========================================================================== */
.contact__console { position: relative; }
.contact__panel {
    position: relative;
    z-index: 1;
    padding: clamp(22px, 2.2vw, 34px);
}

/* The gutter hairline and the sheet numeral only exist on desktop, where the
   address column runs taller than the console and the block needs a spine. */
.contact__divider, .contact__ghost { display: none; }

.contact__console-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
}
.contact__console-id { color: var(--bone-100); }
.contact__counter {
    flex: none;
    font-size: var(--fs-mono);
    font-weight: 700;
    letter-spacing: 0.22em;
    color: var(--steel-300);
    font-variant-numeric: tabular-nums;
}
.contact__console-rule { margin: 16px 0 30px; }

/* Twelve sub-columns, not two: COMPANY and WORK EMAIL pair on the head row,
   then ROLE takes the full sheet width (its placeholder is 38 characters and
   clipped in every half-width column) and COMPANY SIZE keeps the left half so
   the select is sized to its data, not stretched to the panel. */
.contact__fields {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    column-gap: var(--gutter);
}
.contact__field { grid-column: span 6; }
.contact__field--role { grid-column: 1 / -1; }
.contact__field--size { grid-column: span 6; }
.contact__field--full { grid-column: 1 / -1; }

.contact__field {
    position: relative;
    padding-top: 14px;      /* headroom for the 10px label lift on focus */
    margin-bottom: 20px;
}

.contact__index {
    position: absolute;
    top: 14px;
    right: 0;
    line-height: 1.4;
    letter-spacing: 0.18em;
    color: var(--steel-300);
    pointer-events: none;
    transition: transform var(--t-state) var(--ease-machine);
}
.contact__req { color: var(--bone-300); }

/* The stamp travels with the label so the field's header row never shears. */
.contact__field .form-label {
    padding-right: 76px;    /* never runs under the index stamp */
    transition: color var(--t-state) var(--ease-machine),
                transform var(--t-state) var(--ease-machine);
}
.contact__field.is-focused .form-label { color: var(--bone-100); transform: translateY(-10px); }
.contact__field.is-focused .contact__index { transform: translateY(-10px); }

.contact__control { position: relative; }

/* The focus edge: a 2px --signal rule down the left of the control. It is a
   STATE, not an entrance — closed at rest, drawn on focus by GSAP on steps(3)
   or, with no GSAP, by this transition. */
.contact__edge {
    position: absolute;
    top: 0; bottom: 0; left: 0;
    z-index: 1;
    width: 2px;
    background: var(--signal);
    transform: scaleY(0);
    transform-origin: top center;
    transition: transform var(--t-state) var(--ease-machine);
    pointer-events: none;
}
.contact__field.is-focused .contact__edge { transform: scaleY(1); }

.contact__helper {
    margin-top: 9px;
    max-width: 46ch;
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--steel-300);
}

.contact__submit { position: relative; margin-top: 10px; }
.contact__btn { width: 100%; }

/* The success seal — a 1px --volt rule that draws across the button when a
   send is acknowledged. Closed at rest; nothing here is ever pre-drawn. */
.contact__seal {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    z-index: 2;
    height: 1px;
    background: var(--volt);
    transform: scaleX(0);
    transform-origin: left center;
    pointer-events: none;
}

.contact__statusbar {
    display: flex;
    align-items: baseline;
    gap: 14px;
    margin-top: 22px;
    padding-top: 14px;
    border-top: 1px solid var(--steel-500);
}
.contact__status-key {
    flex: none;
    font-weight: 700;
    letter-spacing: 0.2em;
    color: var(--steel-300);
}
.contact__status {
    margin-top: 0;
    max-width: none;
    line-height: 1.5;
    color: var(--bone-300);
}
/* A console never shows a key with nothing beside it. The resting readout is a
   statement of fact about the form, not instrumentation: it disappears the
   moment the core writes a real message into the live region. */
.contact__status:empty::after {
    content: 'AWAITING INPUT';
    color: var(--steel-300);
}

.contact__console-foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    margin-top: 20px;
    padding-top: 14px;
    border-top: 1px solid var(--steel-500);
}
.contact__foot-note { color: var(--steel-300); letter-spacing: 0.14em; }

/* ==========================================================================
   DESKTOP — cols 1-5 stacked in two rows, the console spanning both
   ========================================================================== */
@media (min-width: 900px) {
    .contact__head    { grid-column: 1 / 6;  grid-row: 1; }
    .contact__detail  { grid-column: 1 / 6;  grid-row: 2; }
    /* The console column is panel THEN sheet numeral, in flow — the numeral used
       to be absolute against a stretched cell, which parked it behind the panel
       the moment the form grew tall enough to fill the row. */
    .contact__console {
        grid-column: 7 / -1;
        grid-row: 1 / span 2;
        align-self: start;
        display: flex;
        flex-direction: column;
        align-items: flex-end;
    }
    .contact__panel { width: 100%; }

    .contact__divider {
        grid-column: 6;
        grid-row: 1 / span 2;
        justify-self: center;
        align-self: stretch;   /* the grid is align-items:start; the spine is not */
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 20px;
    }
    .contact__divider-rule { flex: 1 1 auto; height: auto; min-height: 30px; }
    .contact__divider-stamp {
        flex: none;
        writing-mode: vertical-rl;
        text-orientation: mixed;
        letter-spacing: 0.3em;
        color: var(--steel-300);
        white-space: nowrap;
    }

    /* The sheet numeral answers the 00 / 05 counter at the top of the console:
       it hangs off the console's bottom-right in its own band, the way a plate
       number hangs off a drawing. */
    .contact__ghost {
        display: block;
        margin-top: 18px;
        margin-right: -0.04em;
        font-size: clamp(84px, 8.4vw, 128px);
        letter-spacing: -0.04em;
    }
}

/* ==========================================================================
   BELOW 900px — one column, form first, fields stacked
   ========================================================================== */
@media (max-width: 899.98px) {
    .contact__grid { row-gap: 40px; }
    .contact__fields { grid-template-columns: 1fr; }
    .contact__field,
    .contact__field--role,
    .contact__field--size,
    .contact__field--full { grid-column: 1 / -1; }
    .contact__helper { max-width: none; }
    .contact__locator { margin-top: 30px; }
    /* the drawing is smaller, so its stamped type is set larger in user units */
    .cx-label { font-size: 19px; }
    .cx-north-label { font-size: 14px; }
}

@media (max-width: 640px) {
    .contact__panel { padding: 22px 18px; }
    .contact__console-head { gap: 12px; }
    .contact__console-id { font-size: var(--fs-mono-sm); letter-spacing: 0.14em; }
    .contact__strip-note { display: none; }
    .contact__row { font-size: 0.58rem; letter-spacing: 0.08em; }
    .contact__field .form-label { padding-right: 68px; }
    .contact__loccap { font-size: 0.55rem; letter-spacing: 0.08em; }
    .contact__statusbar { flex-direction: column; align-items: flex-start; gap: 8px; }
    .contact__console-foot { flex-direction: column; align-items: flex-start; gap: 7px; }
}

/* Reduced motion: no start state may be left stranded, and the focus edge and
   seal switch instantly rather than sliding. */
@media (prefers-reduced-motion: reduce) {
    .contact__edge,
    .contact__index,
    .contact__field .form-label { transition: none; }
}

/* ==========================================================================
   START STATES — only once JS has confirmed GSAP
   The fields are the one entrance whose start state cannot be expressed by the
   shared .reveal hook: they arrive from the LEFT edge, so they need their own
   horizontal inset. anim() hands each one back with clipPath:'none' the moment
   it lands, so no inline clip is left cropping a 2px focus ring.
   ========================================================================== */
html.js-anim .contact__field { clip-path: inset(0 100% 0 0); }

/* The no-GSAP error state: the message is the signal, the border only echoes it. */
.contact__panel.is-error { border-color: var(--signal); }

@media (prefers-reduced-motion: reduce) {
    html.js-anim .contact__field { clip-path: none; }
}

/* ============================ RESPONSIVE & MOTION PREFERENCES ============================ */
/* ==========================================================================
   PLATE CAPTION LEGIBILITY — loaded last so it outranks the per-section rules.

   Every section shrank its .plate caption independently (0.46-0.5rem, i.e. 7.4px)
   so the "[ 1600 x 1000 ]" dimension stamp would still fit beside the brief. No
   plate on this page is wider than 403px, so that arithmetic never had a solution
   at a legible size, and the caption is the client's asset brief - the part that
   has to be readable. #industries had already solved it correctly: drop the
   dimension stamp, keep the subject and the id. That decision is made here for
   every plate. The dimensions are still stamped in the plate manifest at the top
   of this stylesheet and in README.md, keyed by the same id, and the element stays
   in the DOM so restoring it is one line.
   ========================================================================== */
.plate .plate__dim { display: none; }

.plate .plate__caption {
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.08em;
    gap: 8px;
    padding-inline: 9px;
}

.plate .plate__tag {
    font-size: var(--fs-mono-sm);
    letter-spacing: 0.1em;
}

/* The industries rack carries the longest brief on the page. Between 380 and 440
   it clears its bar only with the tracking closed up — not with the type dropped. */
@media (max-width: 440px) {
    .plate .plate__caption {
        letter-spacing: 0.05em;
        gap: 6px;
        padding-inline: 8px;
    }
}

/* Under 340px even a closed-up single line cannot hold "PLATE 01 - FINANCIAL
   FLOOR . CX-IMG-0031", and what a one-line bar clips is the right-hand end —
   the id, the one part of the brief that has to survive. So the bar wraps to two
   lines there and the placeholder art is inset to clear it. */
@media (max-width: 340px) {
    .plate .plate__caption {
        height: auto;
        min-height: 28px;
        white-space: normal;
        line-height: 1.25;
        padding-block: 5px;
    }
    .plate .plate__screen,
    .plate .plate__grid,
    .plate .plate__subject,
    .plate .plate__reg,
    .plate .plate__reticle { inset: 0 0 44px 0; }
}

/* The industries rack stamps the longest brief on the page — subject plus id in
   one bar. On a 360px handset that string needs the tracking closed up rather
   than the type dropped to an illegible size. */
@media (max-width: 380px) {
    .plate .plate__caption {
        font-size: 0.56rem;
        letter-spacing: 0.02em;
        gap: 6px;
        padding-inline: 6px;
    }
}

/* Reduced motion is a first-class branch, not an afterthought.
   GSAP handles its own branch in js/main.js; this block covers everything CSS drives. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }

    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }

    .cursor { display: none !important; }
    .chip__led, .footer__led { animation: none; opacity: 1; }
    .marquee__track { transform: none !important; }

    /* Never leave a start state stranded when the animation that would clear it never runs. */
    html.js-anim .reveal { clip-path: none; }
    html.js-anim .rule, html.js-anim .rule--v, html.js-anim .spec-row__leader { transform: none; }
}
