    /* ── 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; }

    /* ── PRINT DECLARES ITS OWN SCHEME ─────────────────────────────────────
          The shell ships <meta name="color-scheme" content="dark">, and that
          meta paints the browser CANVAS dark — the surface under the page,
          including the whole @page margin area. `html, body { background:#fff }`
          in a print block cannot reach it, because the canvas is not an
          element. So a printable on this site came out of Chrome as a white
          sheet inside a solid near-black border (measured #131312 across the
          full A4 margin), which is a cartridge of toner and a page nobody
          would pin to a wall.
          One line, print only: paper is light, and the on-screen world is
          untouched. Any future printable inherits it. */
    @media print { :root { color-scheme: light; } }

    :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; }

    /* ═══════════ STORE BADGES — the listings, and the day before them ══════
       Ziggy, 2026-08-17: the two badges stand on every page, and they say
       "Coming soon" until the listings exist. A badge with no URL renders as a
       span with no href — it goes nowhere because there is nowhere to go — and
       the ribbon says so. See resources/views/partials/store-badges.blade.php.

       Cut from the world's own materials: a raised table face, a hairline of
       ink, the lamp on the ribbon. Both marks are paths in the document, so a
       badge costs no request. */
    .store-badges {
        display: flex; flex-wrap: wrap; align-items: center;
        gap: var(--sp-3);
        padding-top: 10px;              /* the ribbon hangs above the face */
    }
    .store-badges .badge {
        position: relative;
        display: inline-flex; align-items: center; gap: var(--sp-2);
        min-height: 52px; padding: 0 var(--sp-4);
        border-radius: 12px;
        background: var(--table-raised);
        box-shadow: inset 0 0.5px 0 var(--ink-strong), 0 0 0 0.5px var(--ink);
        color: var(--text-primary); text-decoration: none;
        transition: transform 90ms var(--draw), background 160ms var(--draw);
        -webkit-tap-highlight-color: transparent;
    }
    .store-badges a.badge:hover { background: var(--table-cut); }
    .store-badges a.badge:active { transform: scale(0.97); }
    /* Not yet a link, and drawn as not yet: dimmed, and the pointer does not
       change into a hand over something that cannot be followed. */
    .store-badges .badge.is-disabled { opacity: 0.62; cursor: default; }
    .store-badges .b-glyph { flex: none; display: block; }
    .store-badges .b-txt { display: flex; flex-direction: column; line-height: 1.15; text-align: left; }
    .store-badges .b-small {
        font-size: var(--fs-over); font-weight: 600;
        letter-spacing: 0.06em; color: var(--text-secondary);
    }
    .store-badges .b-big {
        font-family: "Archivo", system-ui, sans-serif;
        font-size: max(16px, var(--fs-sm)); font-weight: 700; font-stretch: 110%;
    }
    /* line-height is SET here, never inherited: the reading measure's 1.7 made
       the ribbon tall enough to sit over the words beneath it. */
    .store-badges .ribbon {
        position: absolute; top: -9px; right: 10px;
        padding: 2px 8px; border-radius: 999px;
        background: var(--lamp); color: var(--deep-ink);
        font-family: "Archivo", system-ui, sans-serif;
        font-size: 9.5px; line-height: 1.35; font-weight: 700; font-stretch: 112%;
        letter-spacing: 0.09em; text-transform: uppercase; white-space: nowrap;
    }
    /* The Play mark's four facets, inked in the world's own colours rather
       than a brand sheet's. */
    .store-badges .g-a { fill: var(--bearing); }
    .store-badges .g-b { fill: var(--lamp); }
    .store-badges .g-c { fill: var(--brass); }
    .store-badges .g-d { fill: var(--gain); }

    /* ═══════════ THE APP ROW — the app named once, above the fold ══════════
       One line under the trail on every tool page and every article: the app,
       one clause about what it does, and the two places it will be. Page
       furniture, not an advert. See resources/views/partials/app-row.blade.php.

       REBUILT 2026-08-24. Ziggy rejected the first cut of this row on the
       sibling site for three faults, and all three lived in this block:

         1. THE SURFACE WAS INVISIBLE. `--table` over `--ground-deep` is barely
            a step, and a 0.5px ink hairline is below the perceptible floor: a
            dark shape on a dark page reads as a broken or disabled element, not
            as a panel. It now stands on `--table-raised`, a real rung up the
            ladder, with a full-weight `--ink-strong` hairline and a lamp catch
            on the top edge — because in this world the light comes from above.
            Quiet is the brief; invisible was the bug.

         2. THE MARK WAS A BLOB. Limber's icon is a brass tick on near-black, so
            on a dark panel with a 0.5px ring the tile had no silhouette at all.
            It is now 40px on its own lighter plinth (`--table-cut`) with a full
            brass ring and a seat under it, so the chip's edge reads even though
            the artwork's own ground is dark. (The Flutter repo's
            assets/icon/icon.png is NOT an alternative: it is still the parent
            brand's sage lotus.)

         3. A LIVE STORE LINK LOOKED EXACTLY LIKE A DEAD ONE — both were
            secondary text, so the one conversion element on the page had no
            affordance. A live mark is now a button: bearing ink on a bearing
            tint with a bearing edge, 38px tall, brightening on hover. A pending
            mark keeps no tint, no edge and no pill. Brass still touches only
            the mark, and the bearing — this world's one primary action — touches
            only the thing that actually does something.

       Nothing sticky, and never a second line on a laptop: a row tall enough to
       push an h1 down has stopped being furniture. */
    .app-row {
        display: flex; align-items: center;
        gap: var(--sp-3);
        margin-bottom: var(--sp-4);
        padding: 10px var(--sp-3);
        /* NOT the reading measure. 68ch is what PROSE is capped at; this row is
           furniture, and capping it there squeezed the clause onto a second line
           while 70px of the head column sat empty beside it. */
        max-width: 100%;
        border-radius: 14px;
        background: var(--table-raised);
        box-shadow:
            inset 0 1px 0 rgba(255, 255, 255, 0.055),
            0 0 0 1px var(--ink-strong);
    }
    .app-row .ar-mark {
        flex: none; display: block;
        width: 40px; height: 40px; border-radius: 11px;
        /* A lighter plinth under a dark icon, and a full brass ring on it: the
           chip's edge must not depend on the artwork being bright. */
        background: var(--table-cut);
        box-shadow:
            0 0 0 1px rgba(229, 192, 120, 0.42),
            0 2px 8px -2px rgba(0, 0, 0, 0.6);
    }
    .app-row .ar-what {
        flex: 1 1 auto; min-width: 0; margin: 0;
        font-size: var(--fs-sm); line-height: 1.4; color: var(--text-secondary);
    }
    .app-row .ar-name { font-weight: 700; color: var(--text-primary); }
    .app-row .ar-dash { margin: 0 6px; color: var(--text-tertiary); }
    .app-row .ar-stores {
        flex: none; display: flex; align-items: center; gap: var(--sp-2);
    }

    /* A LIVE mark: a control, and drawn as one. */
    .app-row a.ar-store {
        display: inline-flex; align-items: center; gap: 7px;
        min-height: 38px; padding: 0 13px; border-radius: 10px;
        font-size: var(--fs-xs); font-weight: 700; letter-spacing: -0.01em;
        color: #C9B6FF; text-decoration: none;
        background: rgba(167, 139, 250, 0.15);
        box-shadow: inset 0 0 0 1px rgba(167, 139, 250, 0.42);
        transition: background 160ms var(--draw), box-shadow 160ms var(--draw), color 160ms var(--draw);
        -webkit-tap-highlight-color: transparent;
    }
    .app-row a.ar-store:hover {
        color: #E0D5FF; text-decoration: none;
        background: rgba(167, 139, 250, 0.25);
        box-shadow: inset 0 0 0 1px rgba(167, 139, 250, 0.66);
    }
    .app-row a.ar-store:active { background: rgba(167, 139, 250, 0.31); }
    .app-row a.ar-store svg { flex: none; display: block; width: 15px; height: 15px; }

    /* A PENDING mark: a caption beside a control, never a second control. The
       pointer does not become a hand over something that cannot be followed. */
    .app-row .ar-store.is-soon {
        display: inline-flex; align-items: center; gap: 6px;
        padding: 0 4px;
        font-size: var(--fs-xs); font-weight: 600;
        /* A caption is read, so it is on the text ladder proper. --text-tertiary
           is the glyph rung (3.13:1 on the ground, 2.59:1 on this panel) and a
           pending store name printed in it is unreadable, not quiet. The live
           mark still wins the row: it carries the violet tint and an edge. */
        color: var(--text-secondary); cursor: default;
    }
    .app-row .ar-store.is-soon svg { flex: none; display: block; width: 14px; height: 14px; opacity: 0.5; }

    /* The note carries its own size and line-height rather than inheriting the
       reading measure's 1.7. */
    .app-row .ar-soon {
        font-size: var(--fs-xs); font-weight: 600; line-height: 1.2;
        white-space: nowrap; color: var(--text-secondary);
    }
    .app-row .ar-soon::before { content: "\00b7\00a0"; }
    @media (max-width: 640px) {
        /* Two short lines: the sentence, then the marks. Three is a box. */
        .app-row { flex-wrap: wrap; gap: 10px var(--sp-3); }
        .app-row .ar-what { flex: 1 1 60%; }
        .app-row .ar-stores { flex: 1 1 100%; gap: var(--sp-3); }
    }

    /* ═══════════ 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%); }
    /* The badges sit between the links and the note on every page of the site,
       so the note reads as the sentence about the thing above it. */
    footer .store-badges, .nb-sign .store-badges { margin-top: var(--sp-4); }

    /* ═══════════ 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);
    }
