    /* ── TYPE — both faces bundled, both variable, both subset from the exact
          files the app ships in mobility-flutter/assets/fonts/. ───────────── */
    @font-face {
        font-family: "Archivo";
        src: url("/fonts/Archivo.woff2") format("woff2-variations");
        font-weight: 100 900;
        font-stretch: 62% 125%;
        font-display: swap;
    }
    @font-face {
        font-family: "Plus Jakarta Sans";
        src: url("/fonts/PlusJakartaSans.woff2") format("woff2-variations");
        font-weight: 200 800;
        font-display: swap;
    }

    /* ── VIEW TRANSITIONS — moving between pages is one continuous world ────
          Cross-document, same-origin, declared on both ends because every page
          extends this shell. A browser without it simply navigates; there is no
          script involved either way. The ground is named, so the terrain you
          are standing on is the SAME element before and after the navigation
          rather than two pages crossfading over each other. */
    @view-transition { navigation: auto; }

    :root {
        /* ── GROUND — the land after sunset, and the table laid on it ──────── */
        --ground-deep:  #131020;                      /* groundDeep   — the canvas   */
        --ground-ridge: #1A1630;                      /* groundRidge  — ridge vs sky */
        --table:        #1C1830;                      /* table        — cards        */
        --table-raised: #262138;                      /* tableRaised  — sheets, nav  */
        --table-cut:    #322C48;                      /* tableCut     — nested       */

        /* ── INK — drafting ink, drawn by hand ─────────────────────────────── */
        --ink:          rgba(255, 255, 255, 0.078);   /* ink       0x14FFFFFF        */
        --ink-strong:   rgba(255, 255, 255, 0.149);   /* inkStrong 0x26FFFFFF        */
        --ink-fresh:    #F4F1FC;                      /* inkFresh  — wet ink         */

        /* ── BEARING — the needle; primary action ──────────────────────────── */
        --bearing:      #A78BFA;                      /* bearing                     */
        --bearing-deep: #8B6EF3;                      /* bearingDeep                 */

        /* ── LAMP — effort, heat, now ──────────────────────────────────────── */
        --lamp:         #FF9E7D;                      /* lamp                        */

        /* ── GAIN — elevation gained ───────────────────────────────────────── */
        --gain:         #5EE6C4;                      /* gain                        */

        /* ── BRASS — the instruments and the marks you earned ──────────────── */
        --brass:        #E5C078;                      /* brass    — instrument face  */
        --brass-hi:     #F2D9A2;                      /* brassHi  — engraved highlight */
        --brass-low:    #A8823F;                      /* brassLow — engraved shadow  */
        --deep-ink:     #1A1530;                      /* deepInk  — engraved text    */

        /* ── STONE — the benchmark cut into rock. Never glows ──────────────── */
        --stone:        #2B2839;                      /* stone     — the carved face */
        --stone-edge:   rgba(0, 0, 0, 0.251);         /* stoneEdge 0x40000000        */
        --stone-lip:    rgba(255, 255, 255, 0.059);   /* stoneLip  0x0FFFFFFF        */

        /* ── The dial ramp — valley violet → slope blue → summit gain. The
              hypsometric tint, and the one honest use of it. ───────────────── */
        --dial-low:     #A78BFA;                      /* dialLow                     */
        --dial-mid:     #7FB8F0;                      /* dialMid                     */
        --dial-high:    #5EE6C4;                      /* dialHigh                    */

        /* ── Text ladder ───────────────────────────────────────────────────── */
        --text-primary:   #F4F1FC;                    /* 16.78:1 on ground-deep      */
        --text-secondary: #A59DC0;                    /*  7.29:1 on ground-deep      */
        --text-tertiary:  #665F80;                    /*  3.13:1 — glyphs only       */

        /* ═══════ THE FLUID SCALE (W5d) ═════════════════════════════════════
           ONE scale, 390 → 2560. Nothing on this site is "the mobile size" or
           "the desktop size": every step is a line through those two widths,
           clamped at both ends. Every clamp below reads
           `clamp(<value at 390>, <intercept> + <slope>vw, <value at 2560>)`. */

        /* Type. The display face gets genuinely large at the top end — this is
           an engraved instrument plate and it can carry it. */
        --fs-hero: clamp(40px,   24.9px + 3.871vw, 124px);   /* h1            */
        --fs-h2:   clamp(28px,   19.4px + 2.212vw,  76px);
        --fs-h3:   clamp(20px,   17.3px + 0.691vw,  35px);
        --fs-lede: clamp(18px,   16.6px + 0.369vw,  26px);
        --fs-body: clamp(16.5px, 15.7px + 0.207vw,  21px);
        --fs-sm:   clamp(14px,   13.3px + 0.184vw,  18px);
        --fs-xs:   clamp(12.5px, 12.0px + 0.138vw, 15.5px);
        --fs-over: clamp(11px,   10.5px + 0.138vw,  14px);   /* engraved overline */

        /* Space, on the same line through 390 → 2560. */
        --sp-1: clamp(4px,  3.3px + 0.184vw,   8px);
        --sp-2: clamp(8px,  6.9px + 0.276vw,  14px);
        --sp-3: clamp(12px, 10.2px + 0.461vw, 22px);
        --sp-4: clamp(16px, 13.5px + 0.645vw, 30px);
        --sp-5: clamp(24px, 20.4px + 0.922vw, 44px);
        --sp-6: clamp(32px, 26.3px + 1.475vw, 64px);
        --sp-7: clamp(48px, 39.4px + 2.212vw, 96px);
        --sp-8: clamp(64px, 52.5px + 2.949vw, 128px);
        --sp-9: clamp(80px, 63.5px + 4.240vw, 172px);        /* band rhythm   */

        /* THE FRAME. The ground bleeds; the content does not. The composition
           sits on a bounded, centred measure — wide enough that 1440 is nearly
           filled, capped so that 2560 does not sprawl — and the terrain fills
           whatever is left. That is the difference between an island in empty
           margins and a composition standing on ground. */
        --frame:  1680px;
        --gutter: clamp(14px, 4.4vw, 72px);
        --gap:    clamp(12px, 1.05vw, 26px);
        /* The reading measure. Body copy never exceeds it, at any width. */
        --measure: 68ch;

        /* The world's two curves. line-draw is 450ms easeInOutCubic; settle is
           a spring with no bounce, which on the web is an ease-out that lands
           and stays landed. */
        --draw: cubic-bezier(.65, 0, .35, 1);
        --settle: cubic-bezier(.22, .8, .3, 1);

        /* The contour field's ink, lifted off the app's 4–6%: the same alpha
           that whispers on a 6-inch phone is an absence on a 1440px page. One
           number tunes the whole field. */
        --contour-a: 3.0;
    }

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

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

    body {
        background: var(--ground-deep);
        color: var(--text-primary);
        font-family: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont,
                     "Segoe UI", system-ui, sans-serif;
        font-size: var(--fs-body);
        line-height: 1.6;
        font-variant-numeric: tabular-nums;
        -webkit-font-smoothing: antialiased;
        overflow-wrap: break-word;
        /* The body never scrolls sideways. `clip`, not `hidden`: `hidden` makes
           the body a scroll container, and a scroll container between a sticky
           element and the viewport is a sticky element that never sticks. The
           pinned survey depends on this one keyword. */
        overflow-x: clip;
        min-height: 100vh;
        min-height: 100dvh;
    }

    img { max-width: 100%; height: auto; display: block; }
    a { color: inherit; }

    /* Focus is an ink ring — never the browser default. */
    :focus-visible {
        outline: 2px solid var(--ink-fresh);
        outline-offset: 3px;
        border-radius: 4px;
    }

    /* ═══════════ THE PAGE GRID (W5d) ══════════════════════════════════════
       A named-area grid with a bounded content frame and two bleeding rails.
       `content` is the twelve columns inside the frame; `c 1 … c 12` are the
       column lines themselves, so a block can say "columns 1 to 7" and mean it;
       `full` is the whole viewport, edge to edge.

           [full-start] pad [content-start c] 12 columns [content-end] pad [full-end]

       `--pad` is the rail, and it is what caps the composition: it is the
       gutter until the viewport passes the frame, and from there it grows so
       the twelve columns stay at --frame and the extra width goes to GROUND.

       **Only atmosphere bleeds.** The contour field, the lamp cones, a section's
       own tint and the horizontal contact sheet take `full`. Everything a
       reader actually reads sits in the frame — which is the default, so
       bleeding has to be asked for. */
    .bleed {
        --pad: max(var(--gutter), calc((100% - var(--frame)) / 2 - var(--gap)));
        display: grid;
        grid-template-columns:
            [full-start] var(--pad)
            [content-start c] minmax(0, 1fr)
            repeat(11, [c] minmax(0, 1fr))
            [content-end] var(--pad) [full-end];
        column-gap: var(--gap);
        row-gap: var(--sp-4);
        align-content: start;
    }
    .bleed > * { grid-column: content; min-width: 0; }
    .bleed > .full { grid-column: full; }

    section { position: relative; }
    /* `clip` rather than `hidden` — see body. The lamp cones are still clipped
       to the band; the pinned survey inside it can still stick. */
    .band { padding-block: var(--sp-9); position: relative; overflow: clip; }

    /* ═══════════ GROUND — the terrain, fixed behind every page ═════════════
       Not wallpaper: the ridge is the sample survey's ten per-area readings,
       smoothed, and every run whose end has no reading draws DASHED. Same law
       as the app (CONTOUR §2). Generated per request by App\Support\Survey. */
    .ground {
        position: fixed;
        top: 0; left: 0;
        width: 100%;
        height: 100vh;
        height: 100lvh;
        z-index: 0;
        pointer-events: none;
        overflow: hidden;
        transform: translateZ(0);
        background: radial-gradient(120% 80% at 50% 18%,
                    var(--ground-ridge) 0%, var(--ground-deep) 72%);
        /* One continuous world: the terrain is the same element on either side
           of a navigation, so it does not blink between pages. */
        view-transition-name: ground;
    }
    /* Taller than the frame, and hung above it: the three depth layers drift by
       a few percent of travel, and the overhang means the drift never exposes
       an edge. */
    .ground svg { position: absolute; left: 0; top: -7%; width: 100%; height: 114%; display: block; }
    .ground .c {
        fill: none;
        stroke: var(--ink-fresh);
        stroke-opacity: calc(var(--o, 0.05) * var(--contour-a));
        stroke-width: 0.75;
        stroke-linecap: round;
        stroke-linejoin: round;
        vector-effect: non-scaling-stroke;
    }
    .ground .u { stroke-dasharray: 7 6; }   /* unsurveyed ground reads dashed */

    /* 3% grain — one seeded 64px tile, never regenerated at runtime. */
    .grain {
        position: absolute;
        inset: 0;
        opacity: 0.03;
        background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAAAMFBMVEXg4ODAwMCgoKCAgIBgYGBAQEAgICAAAABPjHZeAAAACHRSTlP///////8AhKZ/DwAAAr9JREFUeJyNlbtu4zAQRSlbsluJThynFPKAtxTyAbtAamPRVaogv7C/n1lLIu9wOJTdxJZ8OI/LGdvcT2HFmTZPXAcfhLU3+wPXwYcQdvbtF7fBiwDf3nMbfAhh6+3n7oGb4EMIe/vwzk3wIYSDvfvHTfAhhKO9v+cm+BDCyd7ecRN8COHK3v7lJvgQwtne3HITfAjhYq9vuAk+hHBhr6+4CT6EcLZXl9wEH0K42MtfvAKcxUYUFRWJdWMeCiOFo3zpDlv0jrTRakBpjKhKrOEJRhYnp8t+2gtHZaZ0RC4a4E1nnJHTLwOnnA6amQ+dgQmnzE7BUeQlOnfzWFvKF/roLQU2RJRcJ8CTGm+wNsA3lVGP9yrizI16E0d5vBuqUxrgWlbSMFCw11UMy1Q0lRq31j8pCcMKuqi9NuHNZ6NrGCpyEE3TLtHJqYQTKS0S7StE4RSXbQ0dyz1YnMJhGtSK1G8x/xkNlaMBgdw4Y7Vt2iAJIS8pOAiHzJUqTQpxRZLmwG91zGKa7pRnjs2sSc9sVzz4bmL9vaN4y6xZTX0h4JzHy2A0DBWjO7Y7X5nnWnhq0WMEbaKGWFOKjhVJl2QLtvUt7XhCQXm42q60G/EhFq2dLTsjNCX9wPXwXbmyZOsn3AarGjMYSy6uMlaK3G5CQuXPtNMS5nzMYbdcO6dNz9lRr8fnRFXFmwrtj6iSPBv5jGXpsUOTgW9NefwSXjupO/xkyPqO0THLwGpXX0ubfWmuiDhkiVI4S/BqUJfPFT+ldiUq+7uAZ0e5Pfrl9GxAY05zSDRTBKR58l6ZPYuxNANeQC69bh9EBnttA8P/w1r24CjW2Cl1QCtqAKhldQ7Y+ppMDbCtV9v1yl6ryAoq+j1V7lFVCvfr6+dqu72kYuzUpP8DKihsCq6tqEQAAAAASUVORK5CYII=");
        background-size: 64px 64px;
    }

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

    /* ═══════════ LAMP — one warm cone per section, always from ABOVE ═══════ */
    .lamp {
        position: absolute;
        top: -200px;
        left: 50%;
        width: min(1400px, 150%);
        height: 660px;
        transform: translateX(-50%);
        pointer-events: none;
        z-index: 0;
        background: radial-gradient(52% 100% at 50% 0%,
            rgba(255, 158, 125, 0.085) 0%,
            rgba(255, 158, 125, 0.030) 42%,
            rgba(255, 158, 125, 0) 72%);
    }

    /* ═══════════ TYPE ═════════════════════════════════════════════════════ */
    h1, h2, h3, .legend-over, .stone-label, .panel-over, .step-n,
    .wordmark, .eyebrow, .inst-label, .col-label {
        font-family: "Archivo", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
    }
    /* Headings set themselves evenly rather than leaving one orphan word on the
       last line — which at 124px is not a nicety, it is the composition. */
    h1, h2, h3 { text-wrap: balance; }
    p, li { text-wrap: pretty; }

    h1 {
        font-size: var(--fs-hero);
        font-weight: 700;
        font-stretch: 118%;
        line-height: 0.96;
        letter-spacing: -0.028em;
    }
    h2 {
        font-size: var(--fs-h2);
        font-weight: 700;
        font-stretch: 112%;
        line-height: 1.08;
        letter-spacing: -0.018em;
        max-width: 20ch;
    }
    h3 { font-size: var(--fs-h3); font-weight: 700; font-stretch: 110%; line-height: 1.2;
         letter-spacing: -0.01em; margin-bottom: var(--sp-2); }

    .lede {
        font-size: var(--fs-lede);
        line-height: 1.5;
        color: var(--text-secondary);
        max-width: min(46ch, 100%);
    }
    .body { color: var(--text-secondary); max-width: min(var(--measure), 100%); }
    .note { font-size: var(--fs-sm); line-height: 1.5; color: var(--text-secondary);
            max-width: min(var(--measure), 100%); }

    .wordmark {
        font-size: var(--fs-xs); font-weight: 700; font-stretch: 118%;
        letter-spacing: 0.26em; text-transform: uppercase;
        color: var(--text-secondary);
    }

    /* ── INK — the map legend: engraved overline, a struck tick, a rule that
          runs the width of the frame. ──────────────────────────────────── */
    .legend {
        display: flex; align-items: flex-end; gap: var(--sp-3);
        margin-bottom: var(--sp-6);
    }
    .legend-over {
        flex: none; font-size: var(--fs-over); font-weight: 700; font-stretch: 118%;
        letter-spacing: 0.2em; text-transform: uppercase;
        color: var(--text-secondary); line-height: 1; padding-bottom: 1px;
    }
    .legend-tick { flex: none; width: 5px; height: 11px; }
    .legend-rule { flex: 1 1 auto; height: 2px; min-width: 40px; margin-bottom: 4px; }
    .legend-tick .tick { fill: none; stroke: var(--ink-strong); stroke-width: 1.2; stroke-linecap: round; }
    .legend-rule .rule, .foot-rule .rule, .h1-rule .rule { fill: none; stroke: rgba(255,255,255,.115); stroke-width: 1; stroke-linecap: round; }

    /* Type sets itself: the h1 draws its baseline rule. The letters do not
       animate in one by one — that is a different app's world. */
    .h1-rule { height: 2px; margin: var(--sp-3) 0 var(--sp-4); }
    .h1-rule svg { width: 100%; height: 2px; display: block; }

    /* line-draw — the tick strikes, then the rule runs right. 450ms. */
    .js .legend-tick .tick, .js .legend-rule .rule, .js .foot-rule .rule,
    .js .h1-rule .rule {
        stroke-dasharray: 1; stroke-dashoffset: 1;
        transition: stroke-dashoffset 450ms var(--draw);
    }
    .js .legend-rule .rule { transition-delay: 130ms; }
    /* Each of these has to out-specify its `.js …` partner above, or the rule
       stays at dashoffset 1 and never draws — which is a line that is simply
       absent, not a line that is animating. */
    .in .legend-tick .tick, .in .legend-rule .rule, .in .foot-rule .rule,
    .in .h1-rule .rule, .in .rule { stroke-dashoffset: 0; }

    /* ── rise-in, 8px, one shot, staggered 70ms. Only ever hidden when JS is
          present to bring it back. ───────────────────────────────────────── */
    .js .rise {
        opacity: 0; transform: translateY(8px);
        transition: opacity 420ms var(--settle), transform 420ms var(--settle);
    }
    .js .in .rise, .js .rise.in { opacity: 1; transform: none; }
    .js .in .rise:nth-child(2) { transition-delay: 70ms; }
    .js .in .rise:nth-child(3) { transition-delay: 140ms; }
    .js .in .rise:nth-child(4) { transition-delay: 210ms; }

    /* ═══════════ BRASS — the instrument, and the only metal on screen ══════
       Lit from above. The pointer moves the lamp: --lx follows the cursor and
       the machined highlight travels with it. Nothing bounces, nothing pops. */
    .brass {
        --lx: 50%;
        display: inline-flex; align-items: center; justify-content: center;
        min-height: 52px; padding: 0 var(--sp-5); border-radius: 12px;
        background: linear-gradient(100deg,
            var(--brass-low) 0%, var(--brass) 26%, var(--brass-hi) 50%,
            var(--brass) 74%, var(--brass-low) 100%);
        color: var(--deep-ink);
        font-family: "Archivo", system-ui, sans-serif;
        font-size: max(17px, var(--fs-sm)); font-weight: 700; font-stretch: 110%;
        letter-spacing: 0.01em; text-decoration: none; cursor: pointer;
        border: 0; position: relative; overflow: hidden;
        /* the machined edge: a 0.5px highlight on top, a 0.5px shadow beneath */
        box-shadow: inset 0 0.5px 0 rgba(255, 255, 255, 0.55),
                    inset 0 -0.5px 0 rgba(0, 0, 0, 0.34),
                    0 0.5px 0 rgba(0, 0, 0, 0.5);
        transition: transform 90ms var(--draw);
        -webkit-tap-highlight-color: transparent;
    }
    /* The lamp moved: a soft highlight that tracks the pointer across the face.
       It is the light that moves, never the metal. */
    .brass::after {
        content: ""; position: absolute; inset: 0; pointer-events: none;
        background: radial-gradient(60% 180% at var(--lx) -20%,
                    rgba(255, 255, 255, 0.40), rgba(255, 255, 255, 0) 62%);
        opacity: 0; transition: opacity 260ms ease;
    }
    .brass:hover::after { opacity: 1; }
    .brass:active { transform: scale(0.97); }
    .brass span { position: relative; }

    /* ═══════════ STONE — the benchmark. Matte, chiselled, never a glow ═════
       A query container: a stone block responds to ITS OWN box, so the same
       component works pulled into a 300px margin or spread across six columns. */
    .stone {
        background: var(--stone);
        border-radius: 14px;
        padding: var(--sp-4);
        box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.40),
                    inset 0 -1px 0 rgba(255, 255, 255, 0.14);
        container-type: inline-size;
        container-name: stone;
    }
    .stone-label {
        font-size: var(--fs-over); font-weight: 700; font-stretch: 118%;
        letter-spacing: 0.18em; text-transform: uppercase;
        color: var(--text-secondary); margin-bottom: var(--sp-2);
        text-shadow: 0 -0.5px 0 var(--stone-edge);   /* chiselled, CONTOUR §8 */
    }
    .stone-value {
        font-size: clamp(32px, 15cqi, 76px); font-weight: 700; line-height: 1;
        letter-spacing: -0.03em; font-variant-numeric: tabular-nums;
    }
    .stone-note { margin-top: var(--sp-2); font-size: var(--fs-xs); line-height: 1.4; color: var(--text-secondary); }

    /* ═══════════ THE INSTRUMENT — the elevation profile, drawn ═════════════
       Not a screenshot of the crown jewel: the crown jewel, in SVG, from the
       same geometry (App\Support\Survey). CONTOUR §7.

       **It sizes itself off its own box, not off the viewport.** The same
       component is the full-bleed terrain across the fold, a panel inside the
       distance section and a pinned plate beside the loop's four steps; each
       one reads its own width in `cqi` and none of them knows how wide the
       window is. That is what makes it reusable across the grid. */
    .inst, .pin { container-type: inline-size; container-name: inst; }
    .inst { position: relative; }
    .inst-head { display: flex; align-items: flex-end; gap: var(--sp-2); }
    .inst-label {
        font-size: clamp(10px, 0.85cqi, 15px); font-weight: 700; font-stretch: 118%;
        letter-spacing: 0.2em; text-transform: uppercase;
        color: var(--text-secondary); padding-bottom: 6px;
    }
    .inst-spacer { flex: 1 1 auto; }
    /* The state the plate is in, engraved beside the reading. Tertiary ink and
       never metal: brass is for a number that was MEASURED, and the whole
       point of this word is that there is not one yet. */
    .inst-note {
        font-family: "Archivo", system-ui, sans-serif;
        font-size: clamp(10px, 0.85cqi, 15px); font-weight: 700; font-stretch: 118%;
        letter-spacing: 0.18em; text-transform: uppercase;
        color: var(--text-secondary); padding-bottom: 0.75em; white-space: nowrap;
        text-shadow: 0 -0.5px 0 var(--stone-edge);   /* chiselled, CONTOUR §8 */
    }
    .inst-reading {
        font-size: clamp(40px, 6.8cqi, 120px); font-weight: 800; line-height: 0.9;
        letter-spacing: -0.035em; font-variant-numeric: tabular-nums;
    }
    /* The delta: gain for a gain. Solid brass only when it is an all-time high
       — the one chip-sized earned mark the world allows metal on. */
    /* 17px / 700 is not a taste: it is the floor `deep-ink` on metal is
       allowed at (CONTOUR §8), which is why this clamp bottoms out there and
       not at whatever the container would like. The tinted variant keeps the
       same size so the mark does not jump when a scrub turns it brass. */
    .inst-delta {
        font-size: clamp(17px, 1.5cqi, 26px); font-weight: 700;
        padding: 0.18em 0.55em; border-radius: 8px;
        margin-bottom: 0.5em; line-height: 1.25; font-variant-numeric: tabular-nums;
        background: rgba(94, 230, 196, 0.149); color: var(--gain);
    }
    .inst-delta--earned {
        background: linear-gradient(100deg, var(--brass-low), var(--brass) 40%,
                    var(--brass-hi) 55%, var(--brass) 70%, var(--brass-low));
        color: var(--deep-ink);
        box-shadow: inset 0 0.5px 0 rgba(255,255,255,.5), inset 0 -0.5px 0 rgba(0,0,0,.35);
    }
    /* The engraved brass rule under the reading — the only brass up here. */
    .inst-rule {
        height: 2px; margin-top: var(--sp-2); border-radius: 1px;
        background: linear-gradient(90deg,
            rgba(168,130,63,.55), rgba(229,192,120,.55) 30%,
            rgba(242,217,162,.55) 50%, rgba(229,192,120,.55) 70%, rgba(168,130,63,.55));
        box-shadow: 0 0.5px 0 rgba(26, 21, 48, 0.7);
    }
    .inst-plot { margin-top: var(--sp-2); position: relative; }
    .inst-plot svg { width: 100%; height: auto; display: block; overflow: visible; }

    /* Every stroke on the instrument is non-scaling: the drawn line is 2px of
       ink at 390 and at 2560, the way a nib does not know how wide the paper is. */
    .prof .run { fill: none; stroke: var(--ink-fresh); stroke-width: 2;
                 stroke-linecap: round; stroke-linejoin: round; stroke-opacity: 0.88;
                 vector-effect: non-scaling-stroke; }
    .prof .run--halo { stroke-width: 2.7; stroke-opacity: 0.14; }
    .prof .run--dash { stroke-dasharray: 6 4; stroke-opacity: 0.45; }
    .prof .run--dash.run--halo { stroke-opacity: 0.07; }
    .prof .st { fill: var(--ink-fresh); fill-opacity: 0.88; }
    .prof .st--open { fill: none; stroke: var(--ink-fresh); stroke-opacity: 0.45;
                      stroke-width: 1; vector-effect: non-scaling-stroke; }
    .prof .base { stroke: var(--ink-fresh); stroke-opacity: 0.09; stroke-width: 0.75;
                  fill: none; vector-effect: non-scaling-stroke; }
    /* THE SPECIMEN — somebody else's survey, printed on the sheet under yours.
       Thinner than your ink, a seventh of its opacity, and it never carries a
       station mark, a tint or a dash: dashed means "you have not measured
       this", and a specimen is not about you at all. It is the one line on
       this plot that is allowed to be an example, and it says so. */
    .prof .spec { fill: none; stroke: var(--ink-fresh); stroke-opacity: 0.22;
                  stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round;
                  vector-effect: non-scaling-stroke; }
    /* The brass elevation scale: marginal marks that cross the plot's edge.
       No vertical spine — a rule down the left plus the ground line along the
       bottom is an L-frame, which is a chart's axes and nothing else. */
    .prof .grad { stroke: var(--brass); stroke-opacity: 0.55; stroke-width: 1;
                  stroke-linecap: round; vector-effect: non-scaling-stroke; }
    .prof .grad-hi { stroke: var(--brass-hi); stroke-opacity: 0.28; stroke-width: 0.5;
                     vector-effect: non-scaling-stroke; }
    /* The datum, cut in stone across the plot: a 2px band, the cut's dark top
       edge, its light bottom lip. It never glows. */
    .prof .datum-band { stroke: var(--stone); stroke-width: 2; vector-effect: non-scaling-stroke; }
    .prof .datum-edge { stroke: var(--stone-edge); stroke-width: 0.75; vector-effect: non-scaling-stroke; }
    .prof .datum-lip  { stroke: rgba(255,255,255,0.12); stroke-width: 0.75; vector-effect: non-scaling-stroke; }

    /* The engraved figures: real HTML, so a graduation is legible at 390 and
       still proportionate at 2560 — off the plot's own width, never the page's. */
    .plot-labs { position: absolute; inset: 0; pointer-events: none; }
    .grad-lab {
        position: absolute; left: 0; width: calc(var(--gut) - 6px);
        text-align: right; transform: translateY(-50%); white-space: nowrap;
        font-size: clamp(9.5px, 0.95cqi, 15px); font-weight: 600; line-height: 1;
        color: var(--brass); opacity: 0.62; font-variant-numeric: tabular-nums;
    }
    .datum-lab {
        position: absolute; transform: translateY(0.6em); margin-left: 8px;
        font-family: "Archivo", system-ui, sans-serif;
        font-size: clamp(9.5px, 0.92cqi, 14px); font-weight: 700; font-stretch: 118%;
        letter-spacing: 0.14em; text-transform: uppercase; line-height: 1;
        color: var(--text-secondary);
        text-shadow: 0 -0.5px 0 var(--stone-edge);   /* chiselled, CONTOUR §8 */
    }
    .datum-lab--r { margin-left: 0; margin-right: 8px; }

    /* The specimen names itself, on the plot, beside its own first station.
       Secondary ink, not tertiary: this is the label that stops a specimen
       being a lie, so it is set to be READ, not to be found. */
    .spec-lab {
        position: absolute; transform: translate(2px, -1.75em); white-space: nowrap;
        font-family: "Archivo", system-ui, sans-serif;
        font-size: clamp(10.5px, 0.85cqi, 14px); font-weight: 700; font-stretch: 110%;
        letter-spacing: 0.1em; line-height: 1; color: var(--text-secondary);
    }

    /* The station columns under the plot: the legend, standing on the same x
       as the reading above it. */
    .inst-cols { display: flex; margin-top: 4px; }
    .inst-col { flex: 1 1 0; min-width: 0; text-align: center; padding: 4px 2px; }
    .col-label {
        display: block; white-space: nowrap; line-height: 1.2;
        font-size: clamp(8px, 0.72cqi, 14px); font-weight: 700; font-stretch: 100%;
        letter-spacing: 0.04em; color: var(--text-tertiary);
    }
    @container inst (min-width: 640px) { .col-label { font-stretch: 118%; letter-spacing: 0.09em; } }
    .col-value {
        display: block; margin-top: 3px; font-size: clamp(14px, 1.35cqi, 28px);
        font-weight: 700; font-variant-numeric: tabular-nums;
    }
    .col-value--none { color: var(--text-tertiary); font-weight: 600; }
    /* An open station with a way to close it: the instrument that surveys this
       ground, standing on the same x as the mark it would fill. On a phone the
       columns are 70px wide and a two-word instrument name breaks into a
       ladder, so below 480px of PLOT the ledger under the plate carries them
       instead — the same links, in a place with room for them. */
    .col-note { display: none; }
    @container inst (min-width: 480px) {
        .col-note {
            display: block; margin-top: 6px; padding: 2px 0;
            font-size: clamp(9.5px, 0.8cqi, 14px); font-weight: 500; line-height: 1.25;
            color: var(--bearing); text-decoration: none;
        }
        a.col-note:hover { color: var(--ink-fresh); text-decoration: underline;
                           text-underline-offset: 3px; }
        .col-note--none { color: var(--text-tertiary); }
    }
    .inst-cap { margin-top: var(--sp-3); font-size: var(--fs-xs); line-height: 1.5;
                color: var(--text-secondary); max-width: min(52ch, 100%); }

    /* ── line-draw, on the instrument: the nib crosses the plot left→right and
          the ink, the tint and the stations appear behind it. 450ms. The datum
          is cut LAST, once the line it measures from has been drawn. ─────── */
    @keyframes nib { from { transform: scaleX(0); } to { transform: scaleX(1); } }
    @keyframes cut { from { opacity: 0; } to { opacity: 1; } }
    .prof .nib-sweep {
        transform-box: fill-box; transform-origin: 0 50%;
        animation: nib 450ms var(--draw) both;
    }
    .prof .datum, .datum-lab { animation: cut 160ms linear 340ms both; }
    /* The scrubbed instrument is already drawn — it moves, it does not enter. */
    .prof--live .nib-sweep { animation: none; transform: none; }
    .prof--live .datum, .inst--live .datum-lab { animation: none; opacity: 1; }

    /* ── the ground's line-draw ────────────────────────────────────────────
       Fallback (and first paint): each contour draws left→right, 450ms,
       staggered 60ms behind the one above it — CONTOUR §6.1 unchanged. */
    .ground .gsweep {
        transform-box: fill-box; transform-origin: 0 50%;
        animation: nib 450ms var(--draw) both;
    }
    .ground .gs1 { animation-delay:  60ms; }
    .ground .gs2 { animation-delay: 120ms; }
    .ground .gs3 { animation-delay: 180ms; }
    .ground .gs4 { animation-delay: 240ms; }

    /* ── W5c: the terrain is drawn as you walk down it ─────────────────────
       The same nib, re-hung on the document's own scroll progress. You arrive
       on unmapped ground — the whole field dashed — and the survey resolves
       west→east as you descend. Off the main thread: no scroll listener, no
       rAF, no library. */
    @supports (animation-timeline: scroll()) {
        .ground .gsweep {
            animation-duration: auto;
            animation-delay: 0s;
            animation-timing-function: var(--draw);
            animation-timeline: scroll(root block);
        }
        .ground .gs0 { animation-range: 0%  44%; }
        .ground .gs1 { animation-range: 3%  49%; }
        .ground .gs2 { animation-range: 6%  54%; }
        .ground .gs3 { animation-range: 9%  59%; }
        .ground .gs4 { animation-range: 12% 64%; }

        /* Parallax as depth of ground, not as decoration: three layers, far
           ridges slowest. A few percent of travel over the whole page — the
           amount real terrain moves, not a slide show. */
        .ground .gp {
            animation: drift linear both;
            animation-timeline: scroll(root block);
        }
        .ground .gp-far  { --dy: -14px; }
        .ground .gp-mid  { --dy: -34px; }
        .ground .gp-near { --dy: -58px; }
        @keyframes drift { from { transform: none; } to { transform: translateY(var(--dy)); } }

        /* THE LAMP IS CARRIED. One light per section, and it travels with you:
           descending the page reads as walking a lamp across a drafting table.
           It drifts; it never strobes. */
        .lamp:not(.pin-lamp) {
            animation: carried linear both;
            animation-timeline: view();
            animation-range: cover 0% cover 100%;
        }
        @keyframes carried {
            0%   { transform: translateX(-50%) translate(-5%, -46px); opacity: 0.5; }
            48%  { transform: translateX(-50%) translate(0, 0);       opacity: 1; }
            100% { transform: translateX(-50%) translate(5%, 34px);   opacity: 0.45; }
        }
    }

    /* ═══════════ CAPTURES — evidence, not the composition ═════════════════ */
    .shot { border-radius: 22px; overflow: hidden; background: var(--ground-deep);
            box-shadow: 0 0 0 0.5px var(--ink-strong); isolation: isolate; }
    .shot img { border-radius: inherit; }

    /* ═══════════ PROSE — the legal pages, on the same ground ══════════════
       They sit on the SAME grid as the landing page: left-aligned in the first
       columns with the page's title in the margin, rather than a second,
       centred layout that would read as a different site. */
    .prose { padding-block: var(--sp-8) var(--sp-9); row-gap: 0; }
    .prose > * { grid-column: c 1 / c 9; max-width: min(var(--measure), 100%); }
    .prose .back {
        display: inline-flex; align-items: center; min-height: 44px; min-width: 44px; gap: 8px;
        font-size: var(--fs-sm); font-weight: 600; color: var(--text-secondary);
        text-decoration: none; margin-bottom: var(--sp-3);
        justify-self: start;
        view-transition-name: mark;   /* the wordmark travels between pages */
    }
    .prose .back:hover { color: var(--text-primary); }
    .prose h1 { font-size: clamp(34px, 21.9px + 3.09vw, 101px); letter-spacing: -0.03em; }
    .prose .eff { margin-top: var(--sp-1); color: var(--text-secondary); font-size: var(--fs-sm); }
    .prose .intro { margin-top: var(--sp-4); font-size: var(--fs-lede); color: var(--text-secondary); }
    .prose h2 { font-size: var(--fs-h3); margin-top: var(--sp-6); max-width: none; }
    .prose h3 { font-size: var(--fs-body); margin-top: var(--sp-4); }
    .prose p { margin-top: var(--sp-3); color: var(--text-secondary); }
    .prose ul { margin-top: var(--sp-3); padding-left: 20px; color: var(--text-secondary); }
    .prose li { margin-top: 8px; }
    .prose a { color: var(--bearing); text-decoration: underline; text-underline-offset: 2px; }
    .prose a:hover { color: var(--bearing-deep); }
    .prose strong { color: var(--text-primary); font-weight: 700; }
    .prose .todo {
        margin-top: var(--sp-4); padding: var(--sp-3) var(--sp-4); border-radius: 12px;
        background: var(--table); box-shadow: 0 0 0 0.5px var(--ink);
        font-size: var(--fs-sm); color: var(--text-secondary);
    }
    .prose .todo b {
        font-family: "Archivo", system-ui, sans-serif; font-size: var(--fs-over);
        font-weight: 700; font-stretch: 118%; letter-spacing: 0.16em;
        text-transform: uppercase; color: var(--text-secondary); margin-right: 8px;
    }
    /* Wide: the way back stands in the left margin and rides with you, and the
       document moves off the edge into the columns. A legal page on a 2560
       screen is still a document — what changes is that the margin is doing
       something rather than being empty. */
    @media (min-width: 1360px) {
        .prose > * { grid-column: c 3 / c 10; }
        .prose .back {
            grid-column: c 1 / c 3;
            grid-row: 1 / span 3;
            position: sticky;
            top: var(--sp-6);
            align-self: start;
            margin-bottom: 0;
        }
    }

    /* ═══════════ FOOTER ═══════════════════════════════════════════════════ */
    footer { position: relative; padding-block: var(--sp-6) var(--sp-8); }
    .foot-rule { height: 2px; margin-bottom: var(--sp-5); }
    .foot-rule svg { width: 100%; height: 2px; display: block; }
    .foot-grid { display: flex; flex-wrap: wrap; gap: 8px var(--sp-6); align-items: center;
                 justify-content: space-between; }
    .foot-brand { font-size: var(--fs-sm); color: var(--text-secondary); }
    .foot-links { display: flex; flex-wrap: wrap; gap: 4px var(--sp-5); align-items: center; }
    .foot-links a { display: inline-flex; align-items: center; justify-content: center;
                    min-height: 44px; min-width: 44px;
                    font-size: var(--fs-sm); color: var(--bearing); text-decoration: none; }
    .foot-links a:hover { color: var(--bearing-deep); text-decoration: underline; }
    .foot-note { margin-top: var(--sp-4); font-size: var(--fs-xs); line-height: 1.6;
                 color: var(--text-secondary); max-width: min(var(--measure), 100%); }

    /* ═══════════ REDUCED MOTION — every signature has a reduce path ════════
       Disabled, and the END STATE painted. No exceptions. */
    @media (prefers-reduced-motion: reduce) {
        html { scroll-behavior: auto; }
        /* Every scroll-driven animation dies here too: a scroll timeline is
           still an animation, and `animation: none` unhooks it from the
           scroller. What is left is each element's BASE value, and every base
           value on this site is authored as the completed end state. */
        *, *::before, *::after {
            animation: none !important;
            transition: none !important;
            scroll-behavior: auto !important;
        }
        /* The view-transition tree is not matched by `*` — it hangs off the
           document root — so it is disabled by name. */
        ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) {
            animation: none !important;
        }
        .rise, .js .rise { opacity: 1 !important; transform: none !important; }
        .legend-tick .tick, .legend-rule .rule, .foot-rule .rule, .h1-rule .rule,
        .js .legend-tick .tick, .js .legend-rule .rule, .js .foot-rule .rule,
        .js .h1-rule .rule {
            stroke-dashoffset: 0 !important;
        }
        .prof .nib-sweep, .ground .gsweep, .ground .gp { transform: none !important; }
        .prof .datum, .datum-lab { opacity: 1 !important; }
        .brass::after { opacity: 0; }

        /* W5c end states, painted without a frame of motion: the survey is
           drawn, the datum is cut, the delta is brass, the captures are
           developed, and the steps are all lit. */
        .pin .pin-datum, .pin .pin-datum-lab, .pin .pin-delta,
        .pin .pin-delta::before, .pin .pin-num, .survey-step {
            opacity: 1 !important;
        }
        .pin .pin-em, .pin .pin-col-em[data-pin-col-em] { opacity: 0 !important; }
        .plate-img img, .js .plate-img img { opacity: 1 !important; }
        .plate-img::after { opacity: 0 !important; }
    }

    /* The world's own pace, applied to the page transition: 420ms on the
       line-draw curve, which is the same curve every rule on the site draws
       with. Quiet enough that you notice the continuity, not the effect. */
    ::view-transition-old(root), ::view-transition-new(root) {
        animation-duration: 420ms;
        animation-timing-function: var(--draw);
    }
