/* ==========================================================================
   TechSentinals — "Field Manual"
   Everything below the hero. Warm paper stock, chaptered like a field log:
   editorial serif for statements, mono for instrumentation.
   NOTE: this site sets html{font-size:10px} — 1rem = 10px throughout.
   ========================================================================== */

:root {
    /* Paper */
    --p: #FEF9ED;
    --p-2: #FBF8F0;
    --p-3: #FBF4E5;
    --p-4: #F7ECD9;
    --p-5: #F5EEE0;

    /* ── chapter grounds ──────────────────────────────────────────────────
       The page ran nine sections alternating #FEF9ED and #FBF8F0 — one
       percent of lightness apart, which over twenty-two thousand pixels is
       indistinguishable from a single flat colour. These give the scroll a
       cadence: light, warm, light, deep, and a clay note at the flagship so
       the one section carrying photography of people is not the same sheet
       as everything else. The whole set stays inside the paper family; the
       hue drifts about twenty degrees across the page, which reads as
       variety without reading as a second palette. */
    --g-cream: #FEF9ED;
    --g-lift: #FDF8EC;
    --g-sand: #F7EAD6;
    --g-sand-2: #F0E4CE;
    --g-clay: #F6E8DC;
    --g-olive: #F3EEE0;
    --g-stone: #EFE7D8;
    --g-warm: #F5E9D6;
    --g-sand-3: #EDE0C8;

    /* Ink */
    --ink: #2A1816;
    --ink-2: #5D524B;
    /* body copy on the deepest chapter ground clears 4.5:1 at 4.69 */
    --ink-3: #6A605A;
    /* opaque: as an rgba at .55 this rendered ~2.5:1 on paper, and all 14
       uses are label text, not borders. Darkened with the chapter grounds. */
    --ink-4: #6B6058;

    /* Single accent, plus one live note.
       --acc is a 26%-saturation tan: correct for large areas, but it never
       carries a small mark. --acc-hot is the same hue pushed to where it
       registers at label size (5.1:1 on cream), and is used only for marks
       a reader is meant to notice — chapter numerals, live states, the plus
       on a figure. Never for body copy, never for a fill. */
    --acc: #A67C52;
    /* 4.7:1 on the deepest chapter ground, 5.4:1 on the lightest */
    --acc-hot: #A6491A;
    --acc-soft: rgba(166, 124, 82, 0.10);
    --acc-line: rgba(166, 124, 82, 0.34);
    /* same hue, darkened — clears 4.5:1 at label sizes on every chapter
       ground, including the deepest. Tuned against #F0E4CE, not against
       cream: the grounds moved, so these had to. */
    --acc-2: #855A34;
    /* darker still: clears 4.5:1 on the sand/clay panel fills too */
    --acc-3: #6E4A2C;
    /* muted label ink for text sitting on those warm fills */
    --panel-mute: rgba(51, 36, 29, .88);
    /* Type ladder — six steps. Before this there were fifteen fixed sizes,
       several of them a fraction of a pixel apart and indistinguishable. */
    --t-xs: 1.05rem;
    --t-sm: 1.15rem;
    --t-md: 1.3rem;
    --t-body-s: 1.45rem;
    --t-body: 1.55rem;
    --t-lead: 1.75rem;


    /* Rules — very slightly cool. A warm rule on warm paper disappears into
       it; a cool one holds the edge and makes the ground read warmer. */
    --rule: rgba(78, 78, 88, 0.15);
    --rule-2: rgba(78, 78, 88, 0.27);

    /* Panel surfaces — warm skin/clay tones with real value separation, so a
       card never disappears into the cream sheet behind it. */
    --s-sand: #F1DEC2;
    --s-clay: #E3C09A;
    --s-tan: #D2A277;
    --s-umber: #33241D;
    --s-umber-ink: #FBF4E5;
    --s-umber-mute: rgba(251, 244, 229, .60);
    --s-umber-acc: #E8C9A0;
    --rule-warm: rgba(93, 82, 75, 0.22);

    /* Warm shadows, never black */
    --sh-1: 0 1px 2px rgba(93, 82, 75, .04), 0 3px 10px rgba(93, 82, 75, .05);
    --sh-2: 0 2px 6px rgba(82, 76, 82, .06), 0 16px 40px rgba(82, 76, 82, .11);
    --sh-3: 0 4px 10px rgba(82, 76, 82, .07), 0 34px 70px rgba(78, 72, 82, .17);

    --r-l: 22px;
    --r-m: 14px;
    --r-s: 9px;
    --r-x: 5px;

    --e: cubic-bezier(.16, 1, .3, 1);
    --e-io: cubic-bezier(.65, 0, .35, 1);

    --serif: "Bradford LL", Georgia, "Times New Roman", serif;
    --mono: "Red Hat Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

    /* Ten sections at ~150px top and bottom was 2,884px of the page — an
       eighth of it — before a word was read. Still generous, ~900px shorter. */
    --bay: clamp(7rem, 8vh + 3.4rem, 13rem);
    --gut: clamp(2.2rem, 5vw, 7rem);
    --max: 1400px;
}

/* ── Grain: breaks the digital flatness of a flat cream field ────────────── */
.fm-grain {
    position: fixed;
    inset: 0;
    z-index: 4;
    pointer-events: none;
    /* no blend mode: a fixed full-viewport multiply layer makes the browser
       re-blend the entire screen every scroll frame. Plain alpha looks the
       same on paper and costs nothing. */
    opacity: .32;
    transform: translateZ(0);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.32'/%3E%3C/svg%3E");
}

@media (prefers-reduced-motion: reduce) {
    .fm-grain {
        display: none;
    }
}

/* ── Section shell ───────────────────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════════════════
   HERO CORRECTION
   The hero button shipped as #89CFF0 baby blue on a 25%-white pill — about
   1.65:1, and a colour used nowhere else on the site. Kept as glass, but on
   the palette and readable. Overridden here rather than in index.css so the
   legacy template stays untouched.
   ══════════════════════════════════════════════════════════════════════════ */

.btn-hero-custom {
    background-color: rgba(42, 24, 22, .88);
    border: 1px solid rgba(254, 249, 237, .28);
    color: var(--p);
    font-weight: 500;
}

/* The button does not turn white on hover — it lights up. A signal crosses the
   dark glass from left to right, an amber bloom gathers at the arrow end as it
   arrives, and the arrow leaves on that beat and comes back in from the left.
   Same palette, same pill; the change is entirely motion and light. */
.btn-hero-custom {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    transition:
        color .4s var(--e),
        border-color .5s var(--e),
        letter-spacing .55s var(--e),
        transform .5s var(--e),
        box-shadow .5s var(--e);
}

/* the bloom that gathers where the arrow is */
.btn-hero-custom::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: 0;
    transform: scale(.5);
    transform-origin: calc(100% - 2.1em) 50%;
    background: radial-gradient(9rem 9rem at calc(100% - 2.1em) 50%,
            rgba(226, 168, 92, .55) 0%,
            rgba(198, 132, 60, .28) 38%,
            rgba(166, 124, 82, 0) 72%);
    transition: opacity .5s var(--e), transform .7s cubic-bezier(.22, .68, .26, 1);
}

/* the signal itself */
.btn-hero-custom::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(100deg,
            rgba(255, 240, 214, 0) 40%,
            rgba(255, 240, 214, .16) 47%,
            rgba(255, 247, 232, .62) 50%,
            rgba(255, 240, 214, .16) 53%,
            rgba(255, 240, 214, 0) 60%);
    background-size: 300% 100%;
    background-position: 160% 0;
}

.btn-hero-custom:hover,
.btn-hero-custom:focus-visible {
    background-color: rgba(46, 27, 22, .92);
    border-color: rgba(226, 168, 92, .62);
    color: #FFF4E1;
    letter-spacing: .012em;
    transform: translateY(-3px);
    box-shadow:
        0 16px 38px -14px rgba(52, 30, 12, .58),
        0 0 30px -6px rgba(214, 158, 84, .5),
        inset 0 1px 0 rgba(255, 240, 214, .22);
}

.btn-hero-custom:hover::before,
.btn-hero-custom:focus-visible::before {
    opacity: 1;
    transform: scale(1);
    transition-delay: .26s;
}

.btn-hero-custom:hover::after,
.btn-hero-custom:focus-visible::after {
    animation: bhSignal .82s cubic-bezier(.32, .64, .3, 1) both;
}

.btn-hero-custom:active {
    transform: translateY(-1px) scale(.986);
}

@keyframes bhSignal {
    0% {
        opacity: 0;
        background-position: 160% 0;
    }

    14% {
        opacity: 1;
    }

    86% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        background-position: -160% 0;
    }
}

/* the arrow leaves on the beat the signal reaches it, and a fresh one arrives */
.btn-hero-custom:hover svg,
.btn-hero-custom:focus-visible svg {
    animation: bhGo .74s cubic-bezier(.4, .05, .2, 1) .3s both;
}

@keyframes bhGo {
    0% {
        transform: translateX(0);
        opacity: 1;
    }

    38% {
        transform: translateX(1.2em);
        opacity: 0;
    }

    39% {
        transform: translateX(-1.2em);
        opacity: 0;
    }

    100% {
        transform: translateX(4px);
        opacity: 1;
    }
}

.btn-hero-custom:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {

    .btn-hero-custom:hover,
    .btn-hero-custom:focus-visible {
        transform: none;
    }

    .btn-hero-custom:hover::before,
    .btn-hero-custom:focus-visible::before {
        transform: scale(1);
        transition: opacity .2s linear;
        transition-delay: 0s;
    }

    .btn-hero-custom:hover::after,
    .btn-hero-custom:focus-visible::after,
    .btn-hero-custom:hover svg,
    .btn-hero-custom:focus-visible svg {
        animation: none;
    }
}

.fm {
    position: relative;
    z-index: 10;
    padding: var(--bay) 0;
    background: var(--p);
    color: var(--ink-2);
}

.fm--paper {
    background: var(--p-2);
}

.fm__inner {
    max-width: var(--max);
    margin: 0 auto;
    padding: 0 var(--gut);
}

/* Chapter label — the field-log stamp */
.fm-label {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--acc-2);
    margin: 0 0 3rem;
}

.fm-label i {
    font-style: normal;
    padding: .35em .5em;
    border: 1px solid rgba(166, 73, 26, .40);
    border-radius: var(--r-x);
    font-size: .9em;
    letter-spacing: .08em;
    color: var(--acc-hot);
}

.fm-label::after {
    content: "";
    flex: 1;
    height: 1px;
    max-width: 8rem;
    background: linear-gradient(to right, var(--acc-line), transparent);
}

.fm-head {
    max-width: 30ch;
    margin-bottom: clamp(5rem, 7vw, 9rem);
}

.fm-head--wide {
    max-width: 42ch;
}

.fm-title {
    font-family: var(--serif);
    font-size: clamp(3.6rem, 4.15vw, 5.98rem);
    font-weight: 450;
    line-height: 1.02;
    letter-spacing: -.025em;
    color: var(--ink);
    text-wrap: balance;
    margin: 0;
}

.fm-title em {
    font-style: italic;
    color: var(--acc);
}

.fm-lede {
    font-size: clamp(1.7rem, 0.498vw + 1.24rem, 1.74rem);
    line-height: 1.6;
    color: var(--ink-3);
    max-width: 52ch;
    text-wrap: pretty;
    margin: 2.6rem 0 0;
}

.fm-head .fm-lede {
    max-width: 46ch;
}

/* Inline CTA */
.fm-cta {
    display: inline-flex;
    align-items: center;
    gap: .6em;
    font-family: var(--mono);
    font-size: var(--t-md);
    font-weight: 500;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--acc);
    text-decoration: none;
    transition: gap .35s var(--e), color .35s var(--e);
}

.fm-cta svg {
    width: 1.15em;
    height: 1.15em;
    stroke-width: 1.6;
}

.fm-cta:hover {
    color: var(--ink);
    gap: 1em;
}

/* ── Motion primitives ───────────────────────────────────────────────────── */

.fm-js [data-reveal],
.fm-js [data-band] {
    opacity: 0;
    transform: translateY(2.4rem);
    transition: opacity .8s var(--e), transform .8s var(--e);
    transition-delay: var(--d, 0ms);
}

.fm-js [data-band] {
    display: block;
    transform: translateY(.5em) rotate(.6deg);
}

.fm-js [data-reveal].on,
.fm-js [data-band].on {
    opacity: 1;
    transform: none;
}

:where(a, button):focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
    border-radius: var(--r-x);
}

@media (prefers-reduced-motion: reduce) {

    .fm-js [data-reveal],
    .fm-js [data-band] {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   00 · PANEL WALL
   A bento whose cells are different *kinds* of thing — a statement, a live
   canvas, a counter, a list, a proof block. The card under the pointer lights
   and lifts while its siblings step back, so the wall has one focus at a time.
   ══════════════════════════════════════════════════════════════════════════ */

/* The cream sheet lifts over the WebGL hero instead of butting against it */
.fm--wall {
    background: var(--g-cream);
    margin-top: -4rem;
    padding-top: clamp(6rem, 8vh, 9rem);
    border-radius: 4rem 4rem 0 0;
    z-index: 11;
    box-shadow: 0 -3rem 6rem rgba(93, 82, 75, .10);
}

.pw {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: clamp(1rem, 1.3vw, 1.6rem);
    perspective: 1400px;
}

.pw-cell {
    position: relative;
    min-height: 0;
    border-radius: var(--r-l);
    transition: transform .5s var(--e), opacity .45s var(--e);
}

.pw-cell.is-hot {
    transform: translateY(-4px);
}

.pw-cell__in {
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    padding: clamp(2.2rem, 2.6vw, 3.4rem);
    background: var(--s-sand);
    border: 1px solid var(--rule-warm);
    border-radius: inherit;
    overflow: hidden;
    box-shadow: var(--sh-1);
    /* own stacking context so the aurora can sit behind the copy */
    isolation: isolate;
    transition: border-color .45s var(--e), box-shadow .45s var(--e), background-color .45s var(--e);
}

/* cursor-tracked aurora — warm, never a blue-purple AI glow */
.pw-cell__in::before {
    content: "";
    position: absolute;
    inset: -1px;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0;
    transition: opacity .45s var(--e);
    background: radial-gradient(22rem 22rem at var(--mx, 50%) var(--my, 50%),
            rgba(166, 124, 82, .16), transparent 62%);
}

.pw-cell.is-hot .pw-cell__in {
    border-color: var(--acc-line);
    box-shadow: var(--sh-2);
}

.pw-cell.is-hot .pw-cell__in::before {
    opacity: 1;
}

/* ── spans ───────────────────────────────────────────────────────────────── */
.pw-cell--stmt {
    grid-column: span 5;
}

.pw-cell--signal {
    grid-column: span 3;
    grid-row: span 2;
}

.pw-cell--fig {
    grid-column: span 4;
}

.pw-cell--list {
    grid-column: span 5;
}

.pw-cell--proof {
    grid-column: span 4;
}

/* ── A · statement ───────────────────────────────────────────────────────── */
.pw-cell--stmt .pw-cell__in {
    background: var(--s-clay);
    justify-content: space-between;
    gap: 2.6rem;
}

.pw-cell--stmt .pw-stmt__sub {
    color: var(--panel-mute);
}

.pw-stmt {
    font-family: var(--serif);
    font-size: clamp(2.8rem, 2.57vw, 3.57rem);
    font-weight: 450;
    line-height: 1.04;
    letter-spacing: -.028em;
    color: var(--ink);
    text-wrap: balance;
    margin: 0;
}

.pw-stmt em {
    font-style: italic;
    color: var(--acc-3);
}

.pw-stmt__sub {
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-3);
    max-width: 44ch;
    text-wrap: pretty;
    margin: 0;
}

/* ── B · live signal panel ───────────────────────────────────────────────── */
.pw-cell--signal .pw-cell__in {
    padding: 0;
    background: #EAD3B4;
    justify-content: flex-end;
    min-height: 34rem;
}

.pw-canvas {
    /* the softness is a compositor filter now — ctx.filter re-ran the blur on
       the main thread for every frame */
    filter: blur(9px);
    position: absolute;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    display: block;
}

.pw-signal__hud {
    position: absolute;
    z-index: 2;
    top: 2rem;
    left: 2rem;
    display: flex;
    align-items: center;
    gap: .7rem;
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-2);
}

.pw-dot {
    width: .6rem;
    height: .6rem;
    border-radius: 50%;
    background: var(--acc);
    animation: pwPulse 2.4s var(--e-io) infinite;
}

@keyframes pwPulse {

    0%,
    100% {
        opacity: 1;
        transform: scale(1);
    }

    50% {
        opacity: .35;
        transform: scale(.8);
    }
}

@media (prefers-reduced-motion: reduce) {
    .pw-dot {
        animation: none;
    }
}

/* scrim so the caption stays legible whatever the blades are doing */
.pw-cell--signal .pw-cell__in::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    z-index: 1;
    height: 48%;
    pointer-events: none;
    background: linear-gradient(to top, #EAD3B4 10%, rgba(234, 211, 180, .72) 46%, transparent);
}

.pw-signal__cap {
    position: relative;
    z-index: 2;
    margin: 0;
    padding: 2.4rem;
    font-family: var(--serif);
    font-size: clamp(2rem, 1.58vw, 2.16rem);
    line-height: 1.12;
    letter-spacing: -.018em;
    color: var(--ink);
}

/* ── C · headline figure ─────────────────────────────────────────────────
   The one dark cell. Deep warm umber (not black) anchors the wall and makes
   the 60 the loudest thing in the section. */
.pw-cell--fig .pw-cell__in {
    background: var(--s-umber);
    border-color: rgba(251, 244, 229, .12);
    justify-content: space-between;
    gap: 2rem;
}

.pw-cell--fig .pw-fig__k {
    color: var(--s-umber-mute);
}

.pw-cell--fig .pw-fig__n {
    color: var(--s-umber-ink);
}

.pw-cell--fig .pw-fig__n i {
    color: var(--s-umber-acc);
}

.pw-cell--fig .pw-fig__d {
    color: var(--s-umber-mute);
}

/* the aurora has to lighten on a dark surface, not darken it */
.pw-cell--fig .pw-cell__in::before {
    background: radial-gradient(22rem 22rem at var(--mx, 50%) var(--my, 50%),
            rgba(232, 201, 160, .16), transparent 62%);
}

.pw-cell--fig.is-hot .pw-cell__in {
    border-color: rgba(232, 201, 160, .38);
}

.pw-fig__k,
.pw-list__k {
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .15em;
    text-transform: uppercase;
    /* the sand fill is lighter than paper, so the faint ink does not carry */
    color: var(--ink-2);
    margin: 0;
}

.pw-fig__n {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    margin: 0;
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: clamp(6rem, 6.64vw, 8.71rem);
    font-weight: 500;
    line-height: .82;
    letter-spacing: -.055em;
    color: var(--ink);
}

.pw-fig__n i {
    font-style: normal;
    font-size: .18em;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--acc);
}

.pw-fig__d {
    font-size: var(--t-body-s);
    line-height: 1.55;
    color: var(--ink-3);
    max-width: 32ch;
    text-wrap: pretty;
    margin: 0;
}

/* ── D · what we bring ───────────────────────────────────────────────────── */
.pw-list {
    list-style: none;
    margin: 2.4rem 0 0;
    padding: 0;
}

.pw-list li {
    display: flex;
    align-items: baseline;
    gap: 1.4rem;
    padding: 1.4rem 0;
    border-top: 1px solid var(--rule);
    font-size: var(--t-body);
    line-height: 1.4;
    color: var(--ink-2);
    transition: color .3s var(--e), transform .4s var(--e);
}

.pw-cell--list:hover .pw-list li {
    color: var(--ink);
}

.pw-list li i {
    flex: none;
    font-family: var(--mono);
    font-style: normal;
    font-size: var(--t-sm);
    letter-spacing: .1em;
    color: var(--acc-3);
}

/* ── E · proof + entry ───────────────────────────────────────────────────── */
.pw-cell--proof .pw-cell__in {
    background: var(--s-tan);
    justify-content: space-between;
    gap: 2.6rem;
}

.pw-cell--proof .pw-mini dt {
    color: rgba(51, 36, 29, .88);
}

.pw-cell--proof .pw-mini dd {
    border-top-color: rgba(51, 36, 29, .3);
}

.pw-mini {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.2rem;
    margin: 0;
}

.pw-mini dt {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ink-4);
    margin-bottom: 1rem;
}

.pw-mini dd {
    margin: 0;
    padding-top: 1rem;
    border-top: 1px solid var(--rule-2);
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: clamp(2.6rem, 2.16vw, 2.99rem);
    font-weight: 500;
    line-height: .9;
    letter-spacing: -.045em;
    color: var(--ink);
}

.pw-mini dd i {
    font-style: normal;
    font-size: .45em;
    vertical-align: super;
    /* this strip sits on --s-tan; --acc measures 1.63:1 there, --acc-3 is the
       token that exists for the sand/clay/tan fills */
    color: var(--acc-3);
}

/* the one piece of outside standing the studio actually has — said plainly */
.pw-where {
    margin: 2.2rem 0 0;
    padding-top: 1.8rem;
    border-top: 1px solid rgba(42, 24, 22, .22);
    font-size: var(--t-md);
    line-height: 1.5;
    /* this cell is tan, so the muted inks do not carry here */
    color: rgba(42, 24, 22, .82);
    text-wrap: pretty;
}

.pw-where b {
    font-weight: 500;
    color: var(--ink);
}

.pw-go {
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.6rem;
    align-self: stretch;
    padding: 1.3em 1.6em;
    border-radius: 100px;
    background: var(--ink);
    color: var(--p);
    font-family: var(--mono);
    font-size: var(--t-md);
    letter-spacing: .06em;
    text-transform: uppercase;
    text-decoration: none;
    transition: background-color .35s var(--e), transform .35s var(--e), box-shadow .35s var(--e);
}

.pw-go svg {
    width: 1.4em;
    height: 1.4em;
    stroke-width: 1.5;
    transition: transform .35s var(--e);
}

.pw-go:hover {
    background: var(--acc);
    transform: translateY(-2px);
    box-shadow: var(--sh-2);
}

.pw-go:hover svg {
    transform: translateX(3px);
}

.pw-go:active {
    transform: translateY(0) scale(.99);
}

/* ── responsive: the wall folds down ─────────────────────────────────────── */
@media (max-width: 1080px) {
    .pw-cell--stmt {
        grid-column: span 7;
    }

    .pw-cell--signal {
        grid-column: span 5;
        grid-row: span 1;
    }

    .pw-cell--fig {
        grid-column: span 5;
    }

    .pw-cell--list {
        grid-column: span 7;
    }

    .pw-cell--proof {
        grid-column: span 12;
    }

    .pw-cell--proof .pw-cell__in {
        flex-direction: row;
        align-items: flex-end;
        justify-content: space-between;
    }

    .pw-mini {
        flex: 1;
        max-width: 46rem;
    }

    .pw-go {
        align-self: flex-end;
        flex: none;
    }
}

@media (max-width: 760px) {
    .fm--wall {
        margin-top: -2.4rem;
        border-radius: 2.4rem 2.4rem 0 0;
    }

    .pw-cell,
    .pw-cell--stmt,
    .pw-cell--signal,
    .pw-cell--fig,
    .pw-cell--list,
    .pw-cell--proof {
        grid-column: span 12;
        grid-row: auto;
        transform: none !important;
    }

    .pw-cell--signal .pw-cell__in {
        min-height: 26rem;
    }

    .pw-cell--proof .pw-cell__in {
        flex-direction: column;
        align-items: stretch;
    }

    .pw.is-focused .pw-cell:not(.is-hot) {
        opacity: 1;
        filter: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .pw-cell {
        transform: none !important;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   00b · SIGNAL (legacy statement block)
   ══════════════════════════════════════════════════════════════════════════ */

.fm--signal {
    padding-top: clamp(7rem, 10vh, 12rem);
    overflow: hidden;
}

.fm-statement {
    font-family: var(--serif);
    font-size: clamp(4.4rem, 6.97vw, 10.8rem);
    font-weight: 450;
    line-height: .96;
    letter-spacing: -.035em;
    color: var(--ink);
    margin: 0;
    text-wrap: balance;
}

.fm-statement em {
    font-style: italic;
    color: var(--acc);
}

.fm-statement__l:nth-child(2) {
    padding-left: clamp(0rem, 8vw, 12rem);
}

.fm-signal__body {
    display: grid;
    grid-template-columns: minmax(0, 32rem) minmax(0, 1fr);
    gap: clamp(3rem, 6vw, 8rem);
    align-items: start;
    margin-top: clamp(5rem, 8vw, 9rem);
    padding-top: clamp(3rem, 5vw, 5rem);
    border-top: 1px solid var(--rule);
}

.fm-trace {
    display: block;
    width: 100%;
    max-width: 30rem;
    height: auto;
    color: var(--acc);
    overflow: visible;
    opacity: .85;
}

.fm-trace path {
    stroke-dasharray: var(--len, 700);
    stroke-dashoffset: var(--len, 700);
    transition: stroke-dashoffset 2.2s var(--e-io);
}

.fm-trace.on path {
    stroke-dashoffset: 0;
}

.fm-signal__copy p {
    max-width: 56ch;
    margin: 0 0 1.8rem;
    font-size: var(--t-lead);
    line-height: 1.62;
    color: var(--ink-3);
    text-wrap: pretty;
}

.fm-signal__copy .fm-lede {
    margin-top: 0;
    color: var(--ink-2);
}

.fm-signal__copy p:last-child {
    margin-bottom: 0;
}

/* Figures — instrument readouts, not a stat bar */
.fm-figures {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0;
    margin: clamp(5rem, 8vw, 9rem) 0 0;
    border-top: 1px solid var(--rule);
}

.fm-figure {
    padding: 2.6rem clamp(1.4rem, 2.5vw, 3.2rem) 0 0;
    border-right: 1px solid var(--rule);
}

.fm-figure:last-child {
    border-right: 0;
}

.fm-figure:not(:first-child) {
    padding-left: clamp(1.4rem, 2.5vw, 3.2rem);
}

.fm-figure dt {
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--ink-4);
    margin-bottom: 1.4rem;
    max-width: 16ch;
}

.fm-figure dd {
    margin: 0;
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: clamp(4rem, 4.32vw, 5.31rem);
    font-weight: 500;
    line-height: .9;
    letter-spacing: -.045em;
    color: var(--ink);
}

.fm-figure dd i {
    font-style: normal;
    color: var(--acc);
    font-size: .5em;
    vertical-align: super;
}

@media (max-width: 900px) {
    .fm-signal__body {
        grid-template-columns: 1fr;
    }

    .fm-trace {
        max-width: 26rem;
    }

    .fm-figures {
        grid-template-columns: repeat(2, 1fr);
    }

    .fm-figure {
        padding: 2.4rem 1.6rem 2.4rem 0;
        border-bottom: 1px solid var(--rule);
    }

    .fm-figure:nth-child(2n) {
        border-right: 0;
        padding-left: 1.6rem;
    }

    .fm-figure:nth-last-child(-n+2) {
        border-bottom: 0;
    }
}

@media (max-width: 520px) {
    .fm-figures {
        grid-template-columns: 1fr;
    }

    .fm-figure,
    .fm-figure:nth-child(2n) {
        border-right: 0;
        border-bottom: 1px solid var(--rule);
        padding: 2.2rem 0;
    }

    .fm-figure:last-child {
        border-bottom: 0;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   01 · SIXTY DAYS — the delivery board
   Sixty day-cells on a dark inset panel, banded into four phases and lit in
   sequence as you arrive. After cult-ui's lightboard: a grid of lights with
   discrete states, here standing for real days rather than pixels.
   ══════════════════════════════════════════════════════════════════════════ */

.fm--board {
    background: var(--g-sand);
}

.bd {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, .8fr);
    gap: clamp(1.2rem, 1.8vw, 2rem);
    align-items: stretch;
    margin-top: clamp(5rem, 7vw, 8rem);
}

/* ── the dark board ──────────────────────────────────────────────────────── */

.bd-board {
    --b-bg: #2E211A;
    --b-ink: #FBF4E5;
    --b-mute: rgba(251, 244, 229, .55);
    --b-off: rgba(251, 244, 229, .09);

    position: relative;
    display: flex;
    flex-direction: column;
    gap: clamp(2.4rem, 3vw, 3.6rem);
    padding: clamp(2.4rem, 3vw, 3.6rem);
    background: var(--b-bg);
    border-radius: var(--r-l);
    box-shadow: var(--sh-2);
}

.bd-board__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 2rem;
    padding-bottom: 2rem;
    border-bottom: 1px solid rgba(251, 244, 229, .14);
}

.bd-board__k {
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--b-mute);
}

.bd-board__day {
    display: flex;
    align-items: baseline;
    gap: .7rem;
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    color: var(--b-ink);
}

.bd-board__day b {
    font-size: clamp(3.4rem, 3.32vw, 4.15rem);
    font-weight: 500;
    line-height: .85;
    letter-spacing: -.05em;
}

.bd-board__day i {
    font-style: normal;
    font-size: var(--t-sm);
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--b-mute);
}

/* ── the sixty lights ────────────────────────────────────────────────────── */

.bd-grid {
    display: grid;
    grid-template-columns: repeat(20, 1fr);
    gap: clamp(.4rem, .55vw, .7rem);
}

.bd-day {
    aspect-ratio: 1;
    border-radius: 3px;
    background: var(--b-off);
    transform: scale(.82);
    transition:
        background-color .5s var(--e) calc(var(--i) * 16ms),
        transform .5s var(--e) calc(var(--i) * 16ms),
        opacity .35s var(--e);
}

/* phase bands — warm scale that brightens toward launch */
.bd-grid.is-lit .bd-day {
    transform: scale(1);
}

.bd-grid.is-lit .bd-day[data-phase="1"] {
    background: #7C5738;
}

.bd-grid.is-lit .bd-day[data-phase="2"] {
    background: #A67C52;
}

.bd-grid.is-lit .bd-day[data-phase="3"] {
    background: #D2A277;
}

.bd-grid.is-lit .bd-day[data-phase="4"] {
    background: #F0D6B2;
}

/* Pointing at a phase runs a fill along that phase's own days. The rest step
   back in tone rather than dropping to a low opacity — fading them out left
   the board looking half-broken instead of half-lit. */
.bd-grid.is-keyed .bd-day:not(.is-keyed) {
    background: var(--b-off);
    transform: scale(.86);
    transition:
        background-color .4s var(--e),
        transform .4s var(--e);
    transition-delay: 0ms;
}

.bd-grid.is-keyed .bd-day.is-keyed {
    transform: scale(1);
    transition-delay: calc(var(--k, 0) * 26ms);
    animation: bdFill .5s var(--e) both;
    animation-delay: calc(var(--k, 0) * 26ms);
}

/* the day arrives from slightly below and settles — one motion, no glow */
@keyframes bdFill {
    from {
        transform: translateY(2px) scale(.86);
    }

    60% {
        transform: translateY(-1px) scale(1.04);
    }

    to {
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .bd-grid.is-keyed .bd-day.is-keyed {
        animation: none;
        transition-delay: 0ms;
    }
}


@media (prefers-reduced-motion: reduce) {
    .bd-day {
        transition-delay: 0ms !important;
        transform: scale(1) !important;
    }
}

/* ── the resident ─────────────────────────────────────────
   Four nested elements, one transform each: .bd-pet holds the position,
   .bd-pet__hop the arc and the squash, .bd-pet__face which way it is looking,
   and the svg itself the lean and the wobble. Put two of those on one node
   and the later rule silently wins.

   The expression is not drawn once and tinted — every brow, eye and mouth it
   owns is in the markup, and the mood class picks one of each. Morphing SVG
   paths in CSS is not a thing you can rely on; swapping whole groups is.
   Injected by JS on fine pointers at 760px and up only. */

.bd-pet {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 3;
    width: var(--pet-w, 42px);
    pointer-events: none;
    opacity: 0;
    /* it rests at y=147 of the 156-unit box, so 94% is what sets it down on
       the square instead of hovering above it */
    transform: translate3d(calc(var(--px, 0px) - 50%), calc(var(--py, 0px) - 94%), 0);
    transition: transform 300ms cubic-bezier(.33, .06, .5, 1), opacity .6s var(--e);
    will-change: transform;
}

.bd-pet.is-on {
    opacity: 1;
}

/* re-seating after a resize must not read as a sprint across the board */
.bd-pet.is-warp {
    transition: opacity .6s var(--e);
}

/* the only part of the creature that answers the pointer -- .bd-pet itself
   stays inert so the bubble, which is much wider, never becomes a hit target
   hovering over half the board */
.bd-pet__hop {
    display: block;
    transform-origin: 50% 100%;
    pointer-events: auto;
}

/* --pdir lives here and is inherited down into the drawing. It deliberately
   does NOT flip the whole character: the key light is off to the upper left,
   and mirroring the body would swing the light source across the board every
   time it turned round. Only the lean and the speed marks take a side. */
.bd-pet__face {
    display: block;
}

.bd-pet__svg {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
    transform-origin: 50% 94%;
    transition: transform .3s var(--e);
}

/* leave in a stretch, land in a squash, settle. --arc is set per move from
   the distance covered, so a shuffle and a leap are one animation at two
   heights. */
@keyframes bdPetHop {
    0% {
        transform: translateY(0) scale(1.07, .93);
    }

    18% {
        transform: translateY(calc(var(--arc, 12px) * -1)) scale(.95, 1.07);
    }

    60% {
        transform: translateY(calc(var(--arc, 12px) * -1.04)) scale(.98, 1.03);
    }

    88% {
        transform: translateY(0) scale(1.11, .89);
    }

    100% {
        transform: translateY(0) scale(1, 1);
    }
}

/* ── expressions ─────────────────────────────────────────────────────────
   Everything is drawn; the mood decides what is shown. */

.bd-pet .pt-eyes,
.bd-pet .pt-mouth,
.bd-pet .pt-brow,
.bd-pet .pt-blush,
.bd-pet .pt-cheer,
.bd-pet .pt-zzz,
.bd-pet .pt-orbit {
    display: none;
}

.bd-pet.is-calm .pt-eyes--open,
.bd-pet.is-calm .pt-mouth--calm,
.bd-pet.is-alert .pt-eyes--wide,
.bd-pet.is-alert .pt-mouth--o,
.bd-pet.is-alert .pt-brow--up,
.bd-pet.is-rush .pt-eyes--squint,
.bd-pet.is-rush .pt-mouth--grit,
.bd-pet.is-rush .pt-brow--down,
.bd-pet.is-happy .pt-eyes--happy,
.bd-pet.is-happy .pt-mouth--smile,
.bd-pet.is-happy .pt-blush,
.bd-pet.is-happy .pt-cheer,
.bd-pet.is-sleepy .pt-eyes--sleepy,
.bd-pet.is-sleepy .pt-mouth--sleep,
.bd-pet.is-sleepy .pt-zzz,
.bd-pet.is-dizzy .pt-eyes--dizzy,
.bd-pet.is-dizzy .pt-mouth--wobble,
.bd-pet.is-dizzy .pt-orbit,
.bd-pet.is-annoyed .pt-eyes--flat,
.bd-pet.is-annoyed .pt-mouth--flat,
.bd-pet.is-annoyed .pt-brow--flat,
.bd-pet.is-proud .pt-eyes--happy,
.bd-pet.is-proud .pt-mouth--smug,
.bd-pet.is-proud .pt-brow--up,
.bd-pet.is-proud .pt-blush,
.bd-pet.is-proud .pt-cheer {
    display: block;
}

/* ── calm: it is awake, it is just not doing anything ────────────────────── */

.bd-pet.is-calm .pt-eyes--open {
    transform-box: fill-box;
    transform-origin: 50% 50%;
    animation: ptBlink 5.6s var(--e-io) infinite;
}

@keyframes ptBlink {

    0%,
    91%,
    100% {
        transform: scaleY(1);
    }

    94% {
        transform: scaleY(.1);
    }

    96.5% {
        transform: scaleY(1);
    }
}

/* a slow lean side to side while it stands about */
.bd-pet.is-calm .bd-pet__svg {
    animation: ptSway 4.8s var(--e-io) infinite;
}

@keyframes ptSway {

    0%,
    100% {
        transform: rotate(-2.2deg) scaleY(1);
    }

    50% {
        transform: rotate(2.2deg) scaleY(.985);
    }
}

/* ── alert: something just called it ─────────────────────────────────────── */

.bd-pet.is-alert .bd-pet__svg {
    transform: rotate(0deg) scale(1.06);
}

.bd-pet .pt-spark {
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

.bd-pet.is-calm .pt-spark {
    animation: ptSpark 3.4s var(--e-io) infinite;
}

.bd-pet.is-alert .pt-spark {
    animation: ptSparkUp .38s cubic-bezier(.2, .9, .3, 1.4) both;
}

@keyframes ptSpark {

    0%,
    100% {
        transform: scale(1) rotate(0deg);
        opacity: .82;
    }

    50% {
        transform: scale(1.12) rotate(22deg);
        opacity: 1;
    }
}

@keyframes ptSparkUp {
    0% {
        transform: translateY(0) scale(1);
    }

    100% {
        transform: translateY(-9px) scale(1.4) rotate(45deg);
    }
}

/* ── rush: head down, going ──────────────────────────────────────────────── */

.bd-pet.is-rush .bd-pet__svg {
    transform: rotate(calc(9deg * var(--pdir, 1))) scale(1.02, .97);
}

.bd-pet .pt-dash {
    transform-box: view-box;
    transform-origin: 70px 84px;
}

.bd-pet.is-rush .pt-dash {
    animation: ptDash .34s linear infinite;
}

@keyframes ptDash {
    0% {
        opacity: 0;
        transform: scaleX(var(--pdir, 1)) translateX(6px);
    }

    35% {
        opacity: .85;
    }

    100% {
        opacity: 0;
        transform: scaleX(var(--pdir, 1)) translateX(-14px);
    }
}

/* ── happy: it got there ─────────────────────────────────────────────────── */

.bd-pet.is-happy .bd-pet__svg {
    animation: ptCheer .62s cubic-bezier(.2, .8, .3, 1.3) both;
}

@keyframes ptCheer {
    0% {
        transform: rotate(0deg) scale(1);
    }

    40% {
        transform: rotate(-5deg) scale(1.12, .94);
    }

    100% {
        transform: rotate(0deg) scale(1.04);
    }
}

.bd-pet .pt-cheer path {
    transform-box: fill-box;
    transform-origin: 50% 50%;
}

.bd-pet.is-happy .pt-cheer__a {
    animation: ptPop .8s var(--e-io) .1s both;
}

.bd-pet.is-happy .pt-cheer__b {
    animation: ptPop .8s var(--e-io) .22s both;
}

@keyframes ptPop {
    0% {
        opacity: 0;
        transform: scale(.2) rotate(-40deg);
    }

    40% {
        opacity: 1;
        transform: scale(1.15) rotate(10deg);
    }

    100% {
        opacity: 0;
        transform: scale(.9) rotate(30deg);
    }
}

.bd-pet.is-happy .pt-glow {
    animation: ptGlow .9s var(--e-io) both;
}

@keyframes ptGlow {

    0%,
    100% {
        opacity: 1;
    }

    40% {
        opacity: 1.6;
        transform: scale(1.18);
    }
}

.bd-pet .pt-glow {
    transform-box: fill-box;
    transform-origin: 50% 50%;
}

/* ── sleepy ──────────────────────────────────────────────────────────────
   Breathing slows and deepens, and the Z's climb away one after another. The
   sway stops entirely: a thing that is asleep should not still be swaying. */

.bd-pet.is-sleepy .bd-pet__hop {
    animation: ptDoze 4.6s var(--e-io) infinite;
}

@keyframes ptDoze {

    0%,
    100% {
        transform: scale(1, 1) translateY(0);
    }

    50% {
        transform: scale(1.035, .965) translateY(1.5%);
    }
}

.bd-pet .pt-zzz path {
    transform-box: fill-box;
    transform-origin: 50% 100%;
    opacity: 0;
}

.bd-pet.is-sleepy .pt-zzz {
    opacity: 1;
}

.bd-pet.is-sleepy .pt-zzz__a {
    animation: ptZ 3.6s var(--e-io) infinite;
}

.bd-pet.is-sleepy .pt-zzz__b {
    animation: ptZ 3.6s var(--e-io) .5s infinite;
}

.bd-pet.is-sleepy .pt-zzz__c {
    animation: ptZ 3.6s var(--e-io) 1s infinite;
}

@keyframes ptZ {
    0% {
        opacity: 0;
        transform: translate(0, 6px) scale(.6);
    }

    22% {
        opacity: .95;
    }

    70% {
        opacity: .5;
    }

    100% {
        opacity: 0;
        transform: translate(7px, -16px) scale(1.15);
    }
}

/* ── dizzy ───────────────────────────────────────────────────────────────
   The body wobbles off its own axis and three stars go round overhead. The
   stars orbit the head, not their own centres, so the group turns and each
   star counter-turns to stay upright. */

.bd-pet.is-dizzy .bd-pet__svg {
    animation: ptWobble .9s var(--e-io) infinite;
}

@keyframes ptWobble {

    0%,
    100% {
        transform: rotate(-4deg);
    }

    50% {
        transform: rotate(4deg);
    }
}

.bd-pet .pt-orbit {
    transform-box: view-box;
    transform-origin: 70px 40px;
}

.bd-pet.is-dizzy .pt-orbit {
    opacity: 1;
    animation: ptSpin 1.5s linear infinite;
}

.bd-pet .pt-orbit path {
    transform-box: fill-box;
    transform-origin: 50% 50%;
}

.bd-pet.is-dizzy .pt-orbit path {
    animation: ptSpinBack 1.5s linear infinite;
}

@keyframes ptSpin {
    to {
        transform: rotate(360deg);
    }
}

@keyframes ptSpinBack {
    to {
        transform: rotate(-360deg);
    }
}

/* ── annoyed ─────────────────────────────────────────────────────────────
   One slow, pointed sigh. No loop: a character that is permanently exasperated
   is just a grumpy asset. */

.bd-pet.is-annoyed .bd-pet__hop {
    animation: ptSigh 1.5s var(--e-io) both;
}

@keyframes ptSigh {

    0%,
    100% {
        transform: scale(1, 1);
    }

    30% {
        transform: scale(1.06, .94);
    }

    62% {
        transform: scale(.97, 1.04);
    }
}

/* ── proud ───────────────────────────────────────────────────────────────
   Chest out, and it stays out. */

.bd-pet.is-proud .bd-pet__svg {
    animation: ptPuff .8s cubic-bezier(.2, .8, .3, 1.3) both;
}

@keyframes ptPuff {
    0% {
        transform: scale(1) rotate(0deg);
    }

    45% {
        transform: scale(1.1, 1.06) rotate(2deg);
    }

    100% {
        transform: scale(1.05, 1.03) rotate(0deg);
    }
}

.bd-pet.is-proud .pt-cheer__a {
    animation: ptPop 1s var(--e-io) .1s both;
}

.bd-pet.is-proud .pt-cheer__b {
    animation: ptPop 1s var(--e-io) .26s both;
}

.bd-pet.is-proud .pt-cheer__c {
    animation: ptPop 1s var(--e-io) .42s both;
}

/* ── what it says ─────────────────────────────────────────────────────────
   A thought bubble, so it reads as the creature's own idea rather than a
   tooltip the interface is showing you. It is a sibling of .bd-pet__hop, not
   a child: inside the hop it would be squashed and stretched along with the
   body on every landing.

   It rides the character's position because .bd-pet carries that, and --say-dx
   slides it back inside the board near the ends of a row -- the two trailing
   dots shift by the opposite amount so they stay over its head. */

.bd-say {
    position: absolute;
    left: 50%;
    bottom: 108%;
    z-index: 2;
    margin: 0;
    width: max-content;
    max-width: 25rem;
    padding: 1.05rem 1.5rem;
    border-radius: 1.9rem;

    font-family: var(--mono);
    font-size: 1.2rem;
    line-height: 1.42;
    letter-spacing: .004em;
    text-align: center;
    text-wrap: balance;
    color: #33231A;

    /* Paper, not a flat chip: a top-lit gradient, a warm hairline that stops
       it dissolving into the board, a bright inner top edge and a soft inner
       shadow along the bottom. Same recipe as the cards, one tenth the size. */
    background:
        linear-gradient(168deg, #FFFBF2 0%, #FBF3E2 62%, #F5E9D3 100%);
    box-shadow:
        0 0 0 1px rgba(150, 116, 74, .22),
        0 2px 0 rgba(255, 255, 255, .7) inset,
        0 -7px 12px -8px rgba(120, 86, 48, .38) inset,
        0 14px 30px -12px rgba(18, 8, 2, .62),
        0 3px 8px -4px rgba(18, 8, 2, .3);

    pointer-events: none;
    opacity: 0;
    transform: translate(calc(-50% + var(--say-dx, 0px)), 10px) scale(.7) rotate(-1.2deg);
    transform-origin: 50% 130%;
    transition:
        opacity .2s var(--e),
        transform .5s cubic-bezier(.18, .96, .3, 1.28);
}

.bd-say.is-up {
    opacity: 1;
    transform: translate(calc(-50% + var(--say-dx, 0px)), 0) scale(1) rotate(0deg);
}

/* the two dots that make it a thought rather than a shout */
.bd-say::before,
.bd-say::after {
    content: "";
    position: absolute;
    left: 50%;
    border-radius: 50%;
    background: linear-gradient(168deg, #FDF7EA, #F4E7D0);
    box-shadow:
        0 0 0 1px rgba(150, 116, 74, .2),
        0 2px 6px -2px rgba(18, 8, 2, .4);
    opacity: 0;
    transform: scale(.2);
    transition: opacity .2s var(--e), transform .34s cubic-bezier(.18, .96, .3, 1.34);
}

.bd-say::before {
    width: 1.05rem;
    height: 1.05rem;
    bottom: -1.25rem;
    margin-left: calc(-.525rem - var(--say-dx, 0px) * .78);
    transition-delay: .08s;
}

.bd-say::after {
    width: .62rem;
    height: .62rem;
    bottom: -2.45rem;
    margin-left: calc(-.31rem - var(--say-dx, 0px) * .92);
    transition-delay: .15s;
}

.bd-say.is-up::before,
.bd-say.is-up::after {
    opacity: 1;
    transform: scale(1);
}

/* standing on the top row, it thinks downwards */
.bd-say.is-low {
    bottom: auto;
    top: 106%;
    transform-origin: 50% -30%;
    transform: translate(calc(-50% + var(--say-dx, 0px)), -10px) scale(.7) rotate(1.2deg);
}

.bd-say.is-low.is-up {
    transform: translate(calc(-50% + var(--say-dx, 0px)), 0) scale(1) rotate(0deg);
}

.bd-say.is-low::before {
    bottom: auto;
    top: -1.25rem;
}

.bd-say.is-low::after {
    bottom: auto;
    top: -2.45rem;
}


/* on a phone the board is a third of the width, so the type has to come back
   up or the thought is unreadable at arm's length */
@media screen and (max-width: 700px) {
    .bd-say {
        max-width: 20rem;
        padding: .85rem 1.2rem;
        font-size: 1.25rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .bd-pet {
        display: none;
    }
}

/* ── legend / tablist ────────────────────────────────────────────────────── */

.bd-legend {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1px;
    background: rgba(251, 244, 229, .14);
    border: 1px solid rgba(251, 244, 229, .14);
    border-radius: var(--r-m);
    overflow: hidden;
    margin-top: auto;
}

.bd-key {
    display: grid;
    justify-items: start;
    gap: .9rem;
    padding: 1.6rem;
    background: #2E211A;
    border: 0;
    cursor: pointer;
    text-align: left;
    transition: background-color .35s var(--e);
}

.bd-key:hover {
    background: #3A2A21;
}

.bd-key.is-active {
    background: #3A2A21;
}

.bd-key__sw {
    width: 2.6rem;
    height: .5rem;
    border-radius: 2px;
    background: var(--b-off);
    transition: background-color .35s var(--e), width .35s var(--e);
}

.bd-key[data-phase="1"] .bd-key__sw {
    background: #7C5738;
}

.bd-key[data-phase="2"] .bd-key__sw {
    background: #A67C52;
}

.bd-key[data-phase="3"] .bd-key__sw {
    background: #D2A277;
}

.bd-key[data-phase="4"] .bd-key__sw {
    background: #F0D6B2;
}

.bd-key.is-active .bd-key__sw {
    width: 4rem;
}

.bd-key__n {
    font-family: var(--serif);
    font-size: var(--t-lead);
    line-height: 1.1;
    letter-spacing: -.015em;
    color: rgba(251, 244, 229, .62);
    transition: color .35s var(--e);
}

.bd-key:hover .bd-key__n,
.bd-key.is-active .bd-key__n {
    color: var(--b-ink);
}

.bd-key__d {
    font-family: var(--mono);
    font-size: var(--t-xs);
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgba(251, 244, 229, .62);
}

/* ── the active phase, on paper ──────────────────────────────────────────── */

.bd-detail {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: clamp(2.4rem, 3vw, 3.6rem);
    background: var(--s-clay);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-l);
    box-shadow: var(--sh-1);
    overflow: hidden;
}

.bd-panel[hidden] {
    display: none;
}

.bd-panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    animation: bdIn .5s var(--e) both;
}

@keyframes bdIn {
    from {
        opacity: 0;
        transform: translateY(1.6rem);
        filter: blur(3px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .bd-panel {
        animation: none;
    }
}

.bd-panel__range {
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--acc-3);
    margin: 0 0 1.8rem;
}

.bd-panel__t {
    font-family: var(--serif);
    font-size: clamp(2.6rem, 2.32vw, 2.99rem);
    font-weight: 450;
    line-height: 1.04;
    letter-spacing: -.025em;
    color: var(--ink);
    text-wrap: balance;
    margin: 0 0 1.6rem;
}

.bd-panel__d {
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--panel-mute);
    text-wrap: pretty;
    margin: 0 0 2.8rem;
}

.bd-panel__k {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .15em;
    text-transform: uppercase;
    color: var(--panel-mute);
    margin: auto 0 1.4rem;
}

.bd-panel__l {
    list-style: none;
    margin: 0;
    padding: 0;
}

.bd-panel__l li {
    position: relative;
    padding: 1.1rem 0 1.1rem 2rem;
    border-top: 1px solid rgba(51, 36, 29, .16);
    font-size: var(--t-body-s);
    line-height: 1.45;
    color: var(--ink);
}

.bd-panel__l li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 1.75rem;
    width: .9rem;
    height: 1px;
    background: #7C5738;
}

/* ── closing CTA ─────────────────────────────────────────────────────────── */

/* the CTA sits centred under the whole board rather than hanging off the left */
.bd__cta {
    display: flex;
    justify-content: center;
}

.bd-go {
    display: inline-flex;
    align-items: center;
    gap: .8em;
    margin-top: clamp(2.4rem, 3vw, 3.6rem);
    padding: 1.3em 2em;
    border-radius: 100px;
    background: var(--ink);
    color: var(--p);
    font-family: var(--mono);
    font-size: var(--t-md);
    letter-spacing: .06em;
    text-transform: uppercase;
    text-decoration: none;
    box-shadow: var(--sh-1);
    transition: background-color .35s var(--e), transform .35s var(--e), box-shadow .35s var(--e);
}

.bd-go svg {
    width: 1.3em;
    height: 1.3em;
    stroke-width: 1.5;
    transition: transform .35s var(--e);
}

.bd-go:hover {
    background: var(--acc);
    transform: translateY(-2px);
    box-shadow: var(--sh-2);
}

.bd-go:hover svg {
    transform: translateX(3px);
}

.bd-go:active {
    transform: translateY(0) scale(.99);
}

/* ── responsive ──────────────────────────────────────────────────────────── */

@media (max-width: 1080px) {
    .bd {
        grid-template-columns: 1fr;
    }

    .bd-legend {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 620px) {
    .bd-grid {
        grid-template-columns: repeat(12, 1fr);
    }

    .bd-board__head {
        flex-direction: column;
        align-items: flex-start;
        gap: 1rem;
    }
}
/* ══════════════════════════════════════════════════════════════════════════
   02 · THE SYSTEM
   Capabilities shown as coverage of a real topology rather than a list of
   claims. Signal beams travel the wires — cult-ui's grid-beam motion, run
   along an actual graph instead of a grid.
   ══════════════════════════════════════════════════════════════════════════ */

.fm--system {
    background: var(--g-stone);
}

.fm--system .fm-lede {
    margin-bottom: clamp(4.5rem, 6vw, 7rem);
}


/* ══════════════════════════════════════════════════════════════════════════
   03 · SECTORS
   One strip, seven panels. Point at a panel and it opens; the others hold
   their spines. Tones graduate across the seven so the strip reads as a
   single machined object — bezel borrowed from cult-ui's texture-card, the
   open/close from its shift-card.
   ══════════════════════════════════════════════════════════════════════════ */

.fm--sectors {
    background: var(--g-cream);
}

.fm--sectors .fm-lede {
    margin-bottom: clamp(4.5rem, 6vw, 7rem);
}

/* ── nested bezel ────────────────────────────────────────────────────────── */

.sc-bezel {
    border: 1px solid rgba(255, 255, 255, .6);
    border-radius: 26px;
    background: linear-gradient(to bottom, var(--p-4), var(--p-2));
    box-shadow:
        rgba(51, 36, 29, .08) 0 0 0 1px,
        rgba(51, 36, 29, .08) 0 1px 2px -1px,
        rgba(51, 36, 29, .06) 0 8px 22px;
}

.sc-bezel__b {
    border: 1px solid rgba(51, 36, 29, .10);
    border-radius: 25px;
}

.sc-bezel__c {
    border: 1px solid rgba(255, 255, 255, .5);
    border-radius: 24px;
    padding: 6px;
}

/* ── the strip ───────────────────────────────────────────────────────────── */

.sc-strip {
    display: flex;
    gap: 6px;
    height: var(--sc-h, clamp(40rem, 52vh, 52rem));
    transition: height .45s var(--e);
    border-radius: 19px;
    overflow: hidden;
}

.sc-panel {
    position: relative;
    display: flex;
    min-width: 0;
    background: var(--tone);
    border-radius: 14px;
    overflow: hidden;
    /* collapsed by default; the open one takes the slack. Only flex-grow is
       animated: transitioning flex-basis as well reflowed the whole strip a
       second time every frame, which is what made the sweep feel heavy. */
    flex: 0 1 9rem;
    contain: layout style;
    transition: flex-grow .65s var(--e);
}

.sc-panel.is-open,
.sc-panel.is-measuring {
    flex-grow: 1;
}

/* measured, not shown: the panel takes its open width for one frame so the
   copy wraps exactly as it will when opened, then hands the number back. */
/* every panel holds still for the pass, not just the one being measured: the
   panel measured a moment ago is still easing back from grown to 7.2rem, and
   it eats the free space the next one needs. Left running, the seven measure
   669px wide, then 379, then 283 … down to 173, and the copy wraps worse each
   time until the strip is asked to be a thousand pixels tall. */
.sc-strip.is-sizing .sc-panel,
.sc-strip.is-sizing .sc-content {
    transition: none;
}

.sc-panel.is-measuring {
    transition: none;
}

.sc-panel.is-measuring .sc-content {
    opacity: 0;
    visibility: visible;
    transform: none;
    transition: none;
}

/* the spine stays put whether the panel is open or shut */
.sc-spine {
    flex: none;
    width: 9rem;
    margin: 0;
    font-weight: inherit;
}

.sc-spine__btn {
    display: flex;
    align-items: center;
    gap: 2.4rem;
    width: 100%;
    height: 100%;
    padding: 2.4rem 0;
    background: none;
    border: 0;
    cursor: pointer;
    /* reading bottom-to-top down the spine */
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    text-align: left;
}

.sc-spine__n {
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .16em;
    color: var(--panel-mute);
    transition: color .4s var(--e);
}

.sc-spine__name {
    flex: 1;
    font-family: var(--serif);
    font-size: clamp(2rem, 1.74vw, 2.24rem);
    line-height: 1;
    letter-spacing: -.015em;
    color: rgba(51, 36, 29, .72);
    /* a wrap in vertical writing mode makes a second column — never do that */
    white-space: nowrap;
    transition: color .4s var(--e);
}

.sc-spine__sdg {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .14em;
    color: var(--panel-mute);
    transition: color .4s var(--e);
}

.sc-panel:hover .sc-spine__name,
.sc-panel.is-open .sc-spine__name {
    color: var(--ink);
}

.sc-panel.is-open .sc-spine__n,
.sc-panel.is-open .sc-spine__sdg {
    color: var(--panel-mute);
}

/* ── the opened content ──────────────────────────────────────────────────── */

.sc-content {
    position: relative;
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 2rem;
    padding: 3rem 3.2rem 3rem 0;
    opacity: 0;
    visibility: hidden;
    transform: translateX(-1.2rem);
    transition: opacity .45s var(--e), transform .55s var(--e), visibility 0s linear .5s;
}

.sc-panel.is-open .sc-content {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: opacity .5s var(--e) .12s, transform .6s var(--e) .12s, visibility 0s;
}

.sc-content__in {
    max-width: 44ch;
}

.sc-goal {
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--panel-mute);
    margin: 0 0 1.8rem;
}

.sc-desc {
    font-size: clamp(1.7rem, 1.24vw, 1.83rem);
    line-height: 1.5;
    color: var(--ink);
    text-wrap: pretty;
    margin: 0 0 2.4rem;
}

.sc-k {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .15em;
    text-transform: uppercase;
    color: var(--panel-mute);
    margin: 0 0 1.4rem;
}

.sc-tags {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.sc-tags li {
    padding: .55em .9em;
    border: 1px solid rgba(51, 36, 29, .22);
    border-radius: 100px;
    font-family: var(--mono);
    font-size: var(--t-sm);
    letter-spacing: .05em;
    color: rgba(51, 36, 29, .82);
    white-space: nowrap;
}

/* ── keyboard ────────────────────────────────────────────────────────────── */

.sc-spine__btn:focus-visible {
    outline: 2px solid var(--ink);
    outline-offset: -4px;
    border-radius: 12px;
}

/* ── responsive: the strip becomes a stack ───────────────────────────────── */

@media (max-width: 1000px) {
    .sc-strip {
        flex-direction: column;
        height: auto;
    }

    .sc-panel,
    .sc-panel.is-open {
        flex: none;
        flex-direction: column;
        contain: none;
    }

    .sc-spine {
        width: auto;
    }

    .sc-spine__btn {
        writing-mode: horizontal-tb;
        transform: none;
        gap: 1.6rem;
        padding: 2.2rem 2.4rem;
    }

    .sc-spine__name {
        flex: 1;
    }

    /* shift-card's open: height 0 → auto with the content fading in */
    .sc-content {
        display: grid;
        grid-template-rows: 0fr;
        padding: 0 2.4rem;
        transform: none;
        transition: grid-template-rows .5s var(--e), opacity .4s var(--e), padding .5s var(--e), visibility 0s linear .5s;
    }

    .sc-panel.is-open .sc-content {
        grid-template-rows: 1fr;
        padding: 0 2.4rem 2.8rem;
        transform: none;
    }

    .sc-content__in {
        min-height: 0;
        overflow: hidden;
    }

}

@media (max-width: 560px) {
    .sc-spine__btn {
        flex-wrap: wrap;
        gap: .6rem 1.2rem;
        padding: 1.8rem;
    }

    .sc-spine__name {
        flex: 0 0 100%;
        order: 2;
    }

    .sc-spine__sdg {
        order: 3;
    }
}

@media (prefers-reduced-motion: reduce) {

    .sc-panel,
    .sc-content {
        transition: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   04 · NEXT
   The release runs as an editorial spread rather than a boxed card: the
   product bleeds off the right edge and the announcement plate rides over it
   from the left, so the two overlap instead of sitting in tidy columns. The
   capabilities read as a numbered strip, the facts as a thin rail. The rest
   of the work follows in two staggered columns — the right one dropped, so
   the eye travels diagonally instead of scanning a flat 2×2 of boxes.
   No dark slab, no card chrome, no blend modes dirtying the artwork.
   ══════════════════════════════════════════════════════════════════════════ */

.fm--next {
    background: var(--g-clay);
    overflow: hidden;
}

.fm--work {
    background: var(--g-sand-3);
}


.nx :where(a):focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

/* ══════════════════════════════════════════════════════════════════════════
   04 · NEXT + 05 · WORK — one plate language
   Every project on the page sits on the same plate: a warm frame, an inset
   image, a hairline. Section 04 is the same object given twice the room, so
   the flagship reads as bigger rather than as a different species.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── the shared plate ────────────────────────────────────────────────────── */

.pl-plate {
    position: relative;
    margin: 0;
    padding: clamp(.8rem, 1vw, 1.2rem);
    background: var(--p-4);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-l);
    box-shadow: var(--sh-2);
    overflow: hidden;
}

.pl-plate img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: calc(var(--r-l) - .8rem);
}

/* ── 04 · the flagship ───────────────────────────────────────────────────── */

.fl {
    margin-top: clamp(3rem, 4.5vw, 5rem);
}

.fl__head {
    display: grid;
    grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
    gap: clamp(2rem, 5vw, 6rem);
    align-items: end;
    margin-bottom: clamp(2.6rem, 4vw, 4rem);
}

.fl__name {
    margin: 0;
    font-family: var(--serif);
    font-size: clamp(4.4rem, 5.81vw, 7.88rem);
    font-weight: 450;
    line-height: .9;
    letter-spacing: -.04em;
    color: var(--ink);
}

.fl__pitch {
    margin: 0;
    font-size: var(--t-lead);
    line-height: 1.55;
    color: var(--ink-3);
    text-wrap: pretty;
}

.fl__meta {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.2rem 2rem;
    margin: 0;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-4);
}

.fl__badge {
    display: inline-flex;
    align-items: center;
    gap: .8rem;
    padding: .7rem 1.4rem;
    background: var(--s-sand);
    border: 1px solid var(--acc-line);
    border-radius: var(--r-x);
    color: var(--acc-3);
}

.fl__badge i {
    width: .7rem;
    height: .7rem;
    border-radius: 50%;
    background: var(--acc);
    animation: flBlink 2.4s var(--e-io) infinite;
}

@keyframes flBlink {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: .3;
    }
}

/* ── the photograph ──────────────────────────────────────────────────────── */

.fl__hero {
    position: relative;
    margin: 0;
}

/* the caption carries the one sentence that explains the product, so it is
   set as a statement rather than a footnote under a picture */
.fl__cap {
    display: grid;
    gap: .9rem;
    margin: clamp(2rem, 2.8vw, 2.8rem) 0 0;
    max-width: 62ch;
}

.fl__cap b {
    font-family: var(--serif);
    font-size: clamp(2.2rem, 2.16vw, 2.82rem);
    font-weight: 450;
    line-height: 1.15;
    letter-spacing: -.03em;
    color: var(--ink);
    text-wrap: balance;
}

.fl__cap span {
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-3);
    text-wrap: pretty;
}

/* ── the screens ─────────────────────────────────────────────────────────── */

.fl__screens {
    margin-top: clamp(3.4rem, 5vw, 5.4rem);
}

.fl__screens-k {
    margin: 0 0 clamp(1.8rem, 2.4vw, 2.2rem);
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--acc-2);
}

.fl__rail {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(1.6rem, 2.4vw, 2.8rem);
    list-style: none;
    margin: 0;
    padding: 0;
}

/* ══════════════════════════════════════════════════════════════════════════
   04 · the launch stage
   Three real states on one plate — the instrument turning, the instrument
   being used, and what it produces — and a card that rides over each. The
   card is what makes it a launch rather than a slideshow: an eyebrow wiping
   open, the line rising a word at a time out of a mask, a rule drawing under
   it, then the whole block lifting away before the next arrives. The fade
   between the pictures is deliberately the least interesting part.
   ══════════════════════════════════════════════════════════════════════════ */

.fl__hero .fl__frame {
    position: relative;
    padding: 0;
    overflow: hidden;
    background: #2A1816;
}

.st {
    position: relative;
    list-style: none;
    margin: 0;
    padding: 0;
    aspect-ratio: 16 / 8.4;
}

.st__i {
    position: absolute;
    inset: 0;
    opacity: 0;
    /* the incoming frame settles rather than cuts */
    transform: scale(1.035);
    transition: opacity .9s var(--e), transform 1.4s var(--e);
}

.st__i.is-on {
    opacity: 1;
    transform: none;
}

.st__i>img,
.st__v {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: calc(var(--r-l) - 1px);
}

/* the two handsets share the frame rather than being stretched into it —
   they are portrait screens and cropping them to 16:9 loses the screen */
.st__pair {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(2rem, 4vw, 5rem);
    width: 100%;
    height: 100%;
    padding: clamp(1.6rem, 3vw, 3.4rem);
    background: radial-gradient(120% 120% at 30% 10%, #4A2E22, #251512 70%);
}

.st__pair img {
    width: auto;
    height: 100%;
    max-width: 42%;
    object-fit: contain;
    border-radius: var(--r-s);
    box-shadow: 0 24px 60px -18px rgba(0, 0, 0, .6);
}

.st__pair img:first-child {
    transform: translateY(-3%) rotate(-1.5deg);
}

.st__pair img:last-child {
    transform: translateY(3%) rotate(1.5deg);
}

/* ── the card ────────────────────────────────────────────────────────────── */

.st__titles {
    position: absolute;
    left: 0;
    bottom: 0;
    z-index: 2;
    width: 100%;
    padding: clamp(2.4rem, 4vw, 5rem);
    pointer-events: none;
    background: linear-gradient(to top,
            rgba(20, 11, 9, .78) 0%,
            rgba(20, 11, 9, .48) 42%,
            rgba(20, 11, 9, 0) 100%);
}

.st__titles {
    display: grid;
}

.st__t {
    grid-area: 1 / 1;
    margin: 0;
    display: grid;
    justify-items: start;
    gap: clamp(.8rem, 1.2vw, 1.2rem);
}

.st__t:not(.is-on) {
    visibility: hidden;
}

/* the eyebrow wipes open from the left */
.st__k {
    overflow: hidden;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .28em;
    text-transform: uppercase;
    color: #E8C9A0;
}

.st__k b {
    display: block;
    font-weight: 500;
    clip-path: inset(0 100% 0 0);
}

.st__t.is-on .st__k b {
    animation: stWipe .7s var(--e) .1s both;
}

@keyframes stWipe {
    from {
        clip-path: inset(0 100% 0 0);
    }

    to {
        clip-path: inset(0 0 0 0);
    }
}

/* the line comes up a word at a time, each out of its own mask */
.st__h {
    font-family: var(--serif);
    font-size: clamp(2.4rem, 2.99vw, 4.15rem);
    font-weight: 450;
    line-height: 1.04;
    letter-spacing: -.035em;
    color: #FEF9ED;
    text-wrap: balance;
}

.st__h i {
    display: inline-block;
    overflow: hidden;
    font-style: normal;
    vertical-align: bottom;
    /* the descenders need somewhere to be, or the mask crops them */
    padding-bottom: .12em;
    margin-bottom: -.12em;
}

.st__h i>span {
    display: inline-block;
}

.st__t.is-on .st__h i>span {
    animation: stRise .85s var(--e) both;
}

.st__t.is-on .st__h i:nth-child(1)>span {
    animation-delay: .26s;
}

.st__t.is-on .st__h i:nth-child(2)>span {
    animation-delay: .33s;
}

.st__t.is-on .st__h i:nth-child(3)>span {
    animation-delay: .4s;
}

.st__t.is-on .st__h i:nth-child(4)>span {
    animation-delay: .47s;
}

.st__t.is-on .st__h i:nth-child(5)>span {
    animation-delay: .54s;
}

.st__t.is-on .st__h i:nth-child(6)>span {
    animation-delay: .61s;
}

@keyframes stRise {
    from {
        transform: translateY(105%);
        opacity: 0;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

/* and a rule draws under the whole thing */
.st__rule {
    width: clamp(6rem, 12vw, 14rem);
    height: 2px;
    background: var(--acc);
    transform: scaleX(0);
    transform-origin: left;
}

.st__t.is-on .st__rule {
    animation: stDraw .8s var(--e) .74s both;
}

@keyframes stDraw {
    from {
        transform: scaleX(0);
    }

    to {
        transform: scaleX(1);
    }
}

/* the block lifts away before the next one arrives */
.st__t.is-out {
    animation: stLeave .42s var(--e) both;
}

@keyframes stLeave {
    to {
        transform: translateY(-14px);
        opacity: 0;
    }
}

/* ── the dwell ───────────────────────────────────────────────────────────── */

.st__dwell {
    position: absolute;
    left: 0;
    bottom: 0;
    z-index: 3;
    height: 2px;
    width: 100%;
    background: rgba(232, 201, 160, .9);
    transform: scaleX(0);
    transform-origin: left;
}

.fl-js .st__dwell.is-live {
    animation: stDwell var(--st-dwell, 6s) linear both;
}

@keyframes stDwell {
    from {
        transform: scaleX(0);
    }

    to {
        transform: scaleX(1);
    }
}

/* ── narrow ──────────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
    .st {
        aspect-ratio: 4 / 3;
    }

    .st__pair img {
        max-width: 46%;
    }
}

@media (prefers-reduced-motion: reduce) {

    .st__i {
        transition: none;
        transform: none;
    }

    /* no cycle, no reveal: the first state stands still with its card set */
    .st__t.is-on .st__k b,
    .st__t.is-on .st__h i>span,
    .st__t.is-on .st__rule,
    .st__t.is-out,
    .fl-js .st__dwell.is-live {
        animation: none;
    }

    .st__k b {
        clip-path: none;
    }

    .st__h i>span {
        transform: none;
        opacity: 1;
    }

    .st__rule {
        transform: scaleX(1);
    }

    .st__dwell {
        display: none;
    }
}

/* ── the four moments ─────────────────────────────────────────────────────
   These were four app screenshots. At the width four of them get on this
   rail they were four grey rectangles with unreadable type — and the thing
   worth showing is what the product does, not what its UI looks like at
   240px. They are the same lit isometric language as the capability cards,
   and the photograph above still carries the real device in a real room.
   ───────────────────────────────────────────────────────────────────────── */

.fl__art {
    margin: 0;
    padding: 0;
    overflow: hidden;
    background: radial-gradient(120% 96% at 26% 8%, #FBF3E4 0%, #F1E1C9 62%, #E7D4B6 100%);
    border: 1px solid rgba(93, 82, 75, .14);
    border-radius: var(--r-m);
    transition: transform .55s var(--e), box-shadow .55s var(--e), border-color .55s var(--e);
}

.fl__scene {
    display: block;
    width: 100%;
    height: auto;
}

.fl__screen:hover .fl__art {
    transform: translateY(-8px);
    border-color: var(--acc-line);
    box-shadow: var(--sh-3);
}

/* the rail sits on a gentle arc, so it reads as a set rather than a table */
.fl__screen:nth-child(2) .fl__art,
.fl__screen:nth-child(3) .fl__art {
    transform: translateY(-1.6rem);
}

.fl__screen:nth-child(2):hover .fl__art,
.fl__screen:nth-child(3):hover .fl__art {
    transform: translateY(-2.6rem);
}

/* ── the four, running ───────────────────────────────────────────────────
   One motion each, and each is the thing the moment is about: the sensor
   travels down to the top of a head, the reading crosses to the handset,
   the series plots under the reference bands, the list fills and one of it
   is flagged. */

.fm-js [data-reveal].on .fl-head {
    animation: flSense 6.4s var(--e-io) 1s infinite;
}

.fm-js [data-reveal].on .fl-beam {
    animation: flBeam 6.4s var(--e-io) 1s infinite;
    transform-box: fill-box;
    transform-origin: bottom;
}

@keyframes flBeam {

    0%,
    100% {
        transform: scaleY(1);
        opacity: .34;
    }

    34%,
    58% {
        transform: scaleY(.34);
        opacity: .85;
    }
}

.fm-js [data-reveal].on .fl-tok {
    animation: flCarry 5.4s var(--e-io) 1.1s infinite;
}

.fm-js [data-reveal] .fl-seq {
    opacity: 0;
    transform: translateY(8px);
}

.fm-js [data-reveal].on .fl-seq {
    opacity: 1;
    transform: none;
    transition: opacity .5s var(--e), transform .6s var(--e);
}

.fm-js [data-reveal].on .fl-seq--1 {
    transition-delay: .12s;
}

.fm-js [data-reveal].on .fl-seq--2 {
    transition-delay: .24s;
}

.fm-js [data-reveal].on .fl-seq--3 {
    transition-delay: .36s;
}

.fm-js [data-reveal].on .fl-seq--4 {
    transition-delay: .48s;
}

.fm-js [data-reveal].on .fl-lit {
    animation: flLit 4.4s var(--e-io) 1s infinite;
}

.fm-js [data-reveal].on .fl-lit--1 {
    animation-delay: 1.2s;
}

.fm-js [data-reveal].on .fl-lit--2 {
    animation-delay: 1.4s;
}

.fm-js [data-reveal].on .fl-lit--3 {
    animation-delay: 1.6s;
}

@keyframes flLit {

    0%,
    100% {
        opacity: .36;
    }

    24%,
    46% {
        opacity: 1;
    }
}

.fl-halo {
    transform-box: fill-box;
    transform-origin: center;
}

.fm-js [data-reveal].on .fl-halo {
    animation: flHalo 3.6s var(--e-io) infinite;
}

@keyframes flHalo {

    0%,
    100% {
        opacity: .5;
        transform: scale(.92);
    }

    50% {
        opacity: 1;
        transform: scale(1.06);
    }
}

@media (prefers-reduced-motion: reduce) {

    .fl__art {
        transition: none;
    }

    .fm-js [data-reveal] .fl-seq {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .fm-js [data-reveal].on .fl-head,
    .fm-js [data-reveal].on .fl-beam,
    .fm-js [data-reveal].on .fl-tok,
    .fm-js [data-reveal].on .fl-lit,
    .fm-js [data-reveal].on .fl-halo {
        animation: none;
    }

    .fm-js [data-reveal].on .fl-tok {
        opacity: 1;
    }
}

.fl__screen-k {
    margin: clamp(1.2rem, 1.6vw, 1.6rem) 0 0;
    font-size: var(--t-body-s);
    line-height: 1.45;
    color: var(--ink-3);
    text-wrap: pretty;
}

.fl__screen-k b {
    display: block;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--acc-2);
    margin-bottom: .5rem;
}

/* ── the foot ────────────────────────────────────────────────────────────── */

.fl__foot {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: clamp(2.4rem, 4vw, 5rem);
    margin-top: clamp(3.4rem, 5vw, 5rem);
    padding-top: clamp(2.4rem, 3vw, 3rem);
    border-top: 1px solid var(--rule-warm);
}

.fl__swap-k {
    margin: 0 0 1.4rem;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--acc-2);
}

.fl__swap-l {
    display: flex;
    flex-wrap: wrap;
    gap: .8rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.fl__swap-l li {
    position: relative;
    padding: .6rem 1.2rem;
    background: var(--p-4);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-x);
    font-size: var(--t-body-s);
    color: var(--ink-3);
}

/* struck through, because the point is that they go away */
.fl__swap-l li::after {
    content: "";
    position: absolute;
    left: .8rem;
    right: .8rem;
    top: 50%;
    height: 1px;
    background: var(--acc);
    opacity: .6;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .5s var(--e);
    transition-delay: calc(var(--i, 0) * 90ms);
}

.fl-js .fl__swap.is-in .fl__swap-l li::after {
    transform: scaleX(1);
}

.fl__cta {
    display: flex;
    flex-wrap: wrap;
    gap: 1.6rem 2.6rem;
}

.fl-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .8rem;
    padding-bottom: .5rem;
    font-size: var(--t-body);
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
}

.fl-btn svg {
    width: 1.7rem;
    height: 1.7rem;
    flex: none;
    stroke-width: 1.5;
    transition: transform .4s var(--e);
}

.fl-btn::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: var(--rule-2);
    transform-origin: left;
    transition: transform .5s var(--e), background-color .4s var(--e);
}

.fl-btn:hover::after {
    background: var(--acc);
    transform: scaleY(2);
}

.fl-btn:hover svg {
    transform: translateX(3px);
}

.fl-btn--go {
    color: var(--acc-3);
    font-weight: 500;
}

.fl-btn--go::after {
    background: var(--acc-line);
}

.fl-btn--go:hover svg {
    transform: translate(3px, -3px);
}

/* ── narrow ──────────────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
    .fl__rail {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* the arc only reads across four; on two it just looks misaligned */
    .fl__screen:nth-child(2) .pl-plate,
    .fl__screen:nth-child(3) .pl-plate {
        transform: none;
    }

    .fl__screen:nth-child(2):hover .pl-plate,
    .fl__screen:nth-child(3):hover .pl-plate {
        transform: translateY(-8px);
    }
}

@media (max-width: 860px) {

    .fl__head,
    .fl__foot {
        grid-template-columns: 1fr;
        align-items: start;
    }

    .fl__hero>img {
        aspect-ratio: 16 / 11;
    }
}

@media (max-width: 520px) {
    .fl__rail {
        grid-template-columns: 1fr;
        gap: clamp(2.4rem, 5vw, 3rem);
    }
}

@media (prefers-reduced-motion: reduce) {

    .fl__badge i {
        animation: none;
    }

    .fl-js .fl__hero>img {
        transform: none;
    }

    .fl__screen .pl-plate,
    .fl__swap-l li::after {
        transition: none;
    }
}


/* ══════════════════════════════════════════════════════════════════════════
   05 · WORK
   The same plate as section 04, at half the size and two to a row. Two of the
   four have nothing real to show yet, so they get a typographic plate rather
   than a picture of a product that does not exist.
   ══════════════════════════════════════════════════════════════════════════ */

.wk-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(4rem, 6vw, 8rem) clamp(2.6rem, 4vw, 5rem);
    list-style: none;
    margin: clamp(3.4rem, 5vw, 5.4rem) 0 0;
    padding: 0;
}

/* the second column drops, so the eye travels diagonally rather than
   scanning a flat pair of rows */
.wk-item:nth-child(even) {
    margin-top: clamp(2.4rem, 5vw, 6rem);
}

.wk-item__shot {
    transition: transform .55s var(--e), box-shadow .55s var(--e);
}

.wk-item:hover .wk-item__shot {
    transform: translateY(-6px);
    box-shadow: var(--sh-3);
}

.wk-item__shot img {
    aspect-ratio: 1200 / 760;
    object-fit: cover;
}

/* The plate is a link on the cards that have a case study behind them, so the
   glass cursor takes over the whole image the way it does in section 06 --
   before this, only the small text link at the foot of the card was a zone and
   pointing at the artwork got you nothing. Quizzy and Data Manthan are
   deliberately left out: there is nowhere for them to go yet, and a pill that
   says "Read it" over something unclickable is a lie. */

.wk-item__link {
    display: block;
    border-radius: var(--r-l);
}

.wk-item__link:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 4px;
}

/* ── work that has more than one screen worth showing ─────────────────────
   The same reel section 06 runs, borrowed wholesale: one nine-second cycle
   with each frame lit for a third of it, handed over on a fade. Only the
   images after the first are taken out of flow -- the first one stays put and
   goes on setting the plate's height, so there is no aspect-ratio to keep in
   sync with the artwork. `inset` matches .pl-plate's own padding, which is
   what keeps the overlays inside the plate's rounded edge. */

/* Full bleed, the way section 06's cards run: the screen reaches the edge of
   the plate instead of floating on the sand, so .pl-plate's own padding and
   inner radius are dropped here. All three frames sit in one grid cell rather
   than being absolutely positioned -- matching the padding by hand meant
   re-deriving the containing block, and it came out 24px wide of the first
   frame. Stacked in a single cell they are the same box by construction. */
.wk-item__shot--reel {
    display: grid;
    padding: 0;
}

.wk-item__shot--reel img {
    grid-area: 1 / 1;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: calc(var(--r-l) - 1px);
    opacity: 0;
    transition: opacity .7s var(--e);
}

.wk-item__shot--reel img:first-child {
    opacity: 1;
}

.wk-item:hover .wk-item__shot--reel img,
.wk-item:focus-within .wk-item__shot--reel img {
    animation: csWalk 9s linear infinite;
}

.wk-item:hover .wk-item__shot--reel img:nth-child(2),
.wk-item:focus-within .wk-item__shot--reel img:nth-child(2) {
    animation-delay: -6s;
}

.wk-item:hover .wk-item__shot--reel img:nth-child(3),
.wk-item:focus-within .wk-item__shot--reel img:nth-child(3) {
    animation-delay: -3s;
}

/* the same tick, so it reads as a set of three rather than a glitch */
.wk-item__shot--reel::after {
    content: "";
    position: absolute;
    right: 1.6rem;
    bottom: 1.6rem;
    z-index: 2;
    width: 3.6rem;
    height: 2px;
    border-radius: 2px;
    background: rgba(255, 250, 240, .8);
    box-shadow: 0 0 0 1px rgba(40, 22, 8, .16), 0 1px 4px rgba(40, 22, 8, .3);
    opacity: 0;
    transform-origin: left;
    transition: opacity .4s var(--e);
}

.wk-item:hover .wk-item__shot--reel::after,
.wk-item:focus-within .wk-item__shot--reel::after {
    opacity: 1;
    animation: csTick 3s linear infinite;
}

@media (prefers-reduced-motion: reduce) {

    /* a card that flicks through three screens on its own is exactly what
       reduced motion is asking not to happen */
    .wk-item__shot--reel img {
        transition: none;
    }

    .wk-item:hover .wk-item__shot--reel img,
    .wk-item:focus-within .wk-item__shot--reel img,
    .wk-item:hover .wk-item__shot--reel::after,
    .wk-item:focus-within .wk-item__shot--reel::after {
        animation: none;
    }

    .wk-item:hover .wk-item__shot--reel::after,
    .wk-item:focus-within .wk-item__shot--reel::after {
        opacity: 0;
    }
}

/* ── the plate for work with nothing to show yet ─────────────────────────── */

.wk-item__shot--none {
    display: grid;
    align-content: center;
    justify-items: center;
    gap: 1rem;
    aspect-ratio: 1200 / 760;
    background:
        repeating-linear-gradient(-45deg,
            transparent 0 12px,
            rgba(93, 82, 75, .05) 12px 13px),
        var(--p-4);
}

.wk-none__k {
    font-family: var(--serif);
    font-size: clamp(2.6rem, 2.82vw, 3.32rem);
    font-weight: 450;
    letter-spacing: -.03em;
    color: var(--ink-3);
}

.wk-none__s {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--acc-2);
}

/* ── the entry beneath ───────────────────────────────────────────────────── */

.wk-item__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .8rem 1.4rem;
    margin: clamp(1.8rem, 2.4vw, 2.2rem) 0 0;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-4);
}

.wk-n {
    color: var(--acc-2);
}

.wk-state {
    padding: .45rem 1rem;
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-x);
    color: var(--ink-3);
}

.wk-state--live {
    background: var(--s-sand);
    border-color: var(--acc-line);
    color: var(--acc-3);
}

.wk-item__name {
    margin: 1.2rem 0 0;
    font-family: var(--serif);
    font-size: clamp(2.8rem, 2.82vw, 3.49rem);
    font-weight: 450;
    line-height: 1;
    letter-spacing: -.03em;
    color: var(--ink);
}

.wk-item__about {
    margin: 1.4rem 0 0;
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-3);
    max-width: 50ch;
    text-wrap: pretty;
}

.wk-item__tags {
    display: flex;
    flex-wrap: wrap;
    gap: .8rem;
    list-style: none;
    margin: 1.8rem 0 0;
    padding: 0;
}

.wk-item__tags li {
    padding: .6rem 1.2rem;
    background: var(--p-4);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-x);
    font-family: var(--mono);
    font-size: var(--t-xs);
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.wk-item__go {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .8rem;
    margin-top: 1.8rem;
    padding-bottom: .5rem;
    font-size: var(--t-body);
    color: var(--acc-3);
    font-weight: 500;
    text-decoration: none;
}

.wk-item__go svg {
    width: 1.7rem;
    height: 1.7rem;
    flex: none;
    stroke-width: 1.5;
    transition: transform .4s var(--e);
}

.wk-item__go::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: var(--acc-line);
    transform-origin: left;
    transition: transform .5s var(--e), background-color .4s var(--e);
}

.wk-item__go:hover::after {
    background: var(--acc);
    transform: scaleY(2);
}

.wk-item__go:hover svg {
    transform: translateX(3px);
}

/* ── narrow ──────────────────────────────────────────────────────────────── */

@media (max-width: 860px) {
    .wk-grid {
        grid-template-columns: 1fr;
        gap: clamp(4rem, 8vw, 6rem);
    }

    .wk-item:nth-child(even) {
        margin-top: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .wk-item__shot {
        transition: none;
    }
}


/* recovered: these belong to 06 but sat inside the old 05 block */


/* ══════════════════════════════════════════════════════════════════════════
   05 · CUSTOM BUILDS
   The second lane. The impact work is the lead, but most of what the studio
   ships is ordinary commercial work, and the site said so nowhere a person
   would read. This is also where the "50+ delivered" figure finally earns
   itself. Laid out as a ledger of rows rather than cards — the one layout
   the page does not already use.
   ══════════════════════════════════════════════════════════════════════════ */

.fm--builds {
    background: var(--g-lift);
}

/* ── who it was built for ────────────────────────────────────────────────── */

.bl-clients {
    display: flex;
    align-items: center;
    gap: clamp(1.6rem, 3vw, 3.4rem);
    padding: clamp(2.6rem, 3vw, 3.4rem) 0;
    border-bottom: 1px solid var(--rule-warm);
}

.bl-clients__k {
    flex: none;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-4);
    margin: 0;
}

/* the names run continuously; the edges dissolve rather than cutting off */
.bl-clients__vp {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.bl-clients__track {
    display: flex;
    width: max-content;
    animation: blRun var(--dur, 30s) linear infinite;
}

/* marquee() clones the set until the track is twice the viewport, then
   mirrors the whole thing — so -50% lands exactly on a repeat and the loop
   never shows a seam. These keyframes were removed with the old section-06
   rules by mistake, which left the track referencing an animation that did
   not exist: it simply sat still. */
@keyframes blRun {
    to {
        transform: translateX(-50%);
    }
}

.bl-clients__vp:hover .bl-clients__track {
    animation-play-state: paused;
}

.bl-clients__set {
    display: flex;
    align-items: baseline;
    gap: clamp(2.4rem, 4vw, 5rem);
    list-style: none;
    margin: 0;
    padding: 0 clamp(1.2rem, 2vw, 2.5rem) 0 0;
}

/* names, not logos — we do not have marks for these and a fake one is worse */
.bl-clients li {
    font-family: var(--serif);
    font-size: clamp(2rem, 1.66vw, 2.32rem);
    font-weight: 450;
    letter-spacing: -.02em;
    color: var(--ink);
    white-space: nowrap;
}

/* a mark between names so the run reads as a list, not a sentence */
.bl-clients li::after {
    content: "";
    display: inline-block;
    width: .5rem;
    height: .5rem;
    margin-left: clamp(2.4rem, 4vw, 5rem);
    border-radius: 50%;
    background: var(--acc-line);
    vertical-align: middle;
}

@media (prefers-reduced-motion: reduce) {

    .bl-clients__vp {
        overflow-x: auto;
        scrollbar-width: none;
    }

    .bl-clients__vp::-webkit-scrollbar {
        display: none;
    }

    .bl-clients__track {
        animation: none;
    }
}


@media (max-width: 640px) {

    .bl-clients {
        display: block;
    }

    .bl-clients__k {
        margin-bottom: 1.6rem;
    }
}


/* recovered: the crew rules a .cw- sweep took with the gallery */


/* ── the roster ──────────────────────────────────────────────────────────── */

.cw-roster {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(2.4rem, 3vw, 4rem);
    align-items: start;
}

/* every second print hangs lower, so the row reads as a wall not a shelf */
.cw-p:nth-child(even) {
    margin-top: clamp(2.4rem, 4.5vw, 6rem);
}

.cw-p {
    display: flex;
    flex-direction: column;
}

.cw-p__shot {
    position: relative;
    margin: 0 0 2.2rem;
    aspect-ratio: 4 / 5;
    overflow: hidden;
    background: linear-gradient(150deg, #F7E9D6, #EDD8BE);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-m);
    transition: border-color .5s var(--e), box-shadow .5s var(--e), transform .5s var(--e);
}

.cw-p__shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 20%;
    filter: saturate(.78) contrast(1.02);
    transform: scale(1);
    transition: filter .6s var(--e), transform .9s var(--e);
}

.cw-p:hover .cw-p__shot {
    border-color: var(--acc-line);
    box-shadow: var(--sh-2);
    transform: translateY(-6px);
}

.cw-p:hover .cw-p__shot img {
    filter: none;
    transform: scale(1.04);
}

.cw-p__n {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    color: var(--acc-2);
    margin: 0 0 1.2rem;
}

.cw-p__name {
    font-family: var(--serif);
    font-size: clamp(2.1rem, 1.49vw, 2.24rem);
    font-weight: 450;
    line-height: 1.05;
    letter-spacing: -.025em;
    color: var(--ink);
    text-wrap: balance;
    margin: 0 0 .9rem;
    transition: color .35s var(--e);
}

.cw-p:hover .cw-p__name {
    color: var(--acc-2);
}

.cw-p__role {
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--ink-4);
    margin: 0 0 1.6rem;
}

.cw-p__bio {
    font-size: var(--t-body-s);
    line-height: 1.6;
    color: var(--ink-3);
    text-wrap: pretty;
    margin: 0 0 1.8rem;
}

.cw-p__builds {
    display: grid;
    gap: .6rem;
    padding-top: 1.6rem;
    border-top: 1px solid var(--rule-warm);
    font-size: var(--t-body-s);
    line-height: 1.45;
    color: var(--ink-2);
    margin: 0 0 2.2rem;
}

.cw-p__builds span {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .15em;
    text-transform: uppercase;
    color: var(--ink-4);
}

/* pinned to the bottom so the four links form one line across the row */
.cw-p__link {
    align-self: flex-start;
    margin-top: auto;
    font-size: var(--t-sm);
    display: inline-flex;
    align-items: center;
    gap: .6em;
    font-family: var(--mono);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink);
    text-decoration: none;
    padding-bottom: .45em;
    background-image: linear-gradient(var(--acc-2), var(--acc-2));
    background-size: 0% 1px;
    background-position: 0 100%;
    background-repeat: no-repeat;
    transition: background-size .45s var(--e), color .3s var(--e);
}

.cw-p__link svg {
    width: 1.2em;
    height: 1.2em;
    stroke-width: 1.6;
    transition: transform .3s var(--e);
}

.cw-p__link:hover {
    color: var(--acc-2);
    background-size: 100% 1px;
}

.cw-p__link:hover svg {
    transform: translate(2px, -2px);
}


.cw-p__link:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {


    .cw-p__shot,
    .cw-p__shot img {
        transition: none;
    }
}


@media (max-width: 560px) {

    .cw-roster {
        grid-template-columns: 1fr;
    }

    .cw-p__shot {
        aspect-ratio: 5 / 4;
    }
}


/* ══════════════════════════════════════════════════════════════════════════
   06 · STUDIO
   A roster, not a selector. All four are on the page at once — hiding three
   people behind a click was hiding the whole point of a four-person studio.
   The row is staggered so it reads as a hung wall rather than a card row, and
   the shared fact (everyone is in one room in Ahmedabad) is stated once in
   the header instead of four times down the page.
   ══════════════════════════════════════════════════════════════════════════ */

.fm--crew {
    background: var(--g-stone);
}

.cw__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: 2.4rem clamp(3rem, 5vw, 7rem);
    padding-bottom: clamp(3rem, 4vw, 4.4rem);
    border-bottom: 1px solid var(--rule-warm);
    margin-bottom: clamp(4.5rem, 6vw, 7.5rem);
}

.cw__headline .fm-lede {
    max-width: 52ch;
}

/* said once, here, instead of on all four cards */
.cw__where {
    display: grid;
    gap: .7rem;
    justify-items: end;
    text-align: right;
    font-family: var(--serif);
    font-size: clamp(1.7rem, 1.16vw, 1.74rem);
    letter-spacing: -.01em;
    color: var(--ink);
    margin: 0;
}

.cw__where span {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--acc-2);
}

.cw__where i {
    font-style: normal;
    font-size: .72em;
    color: var(--ink-3);
}

/* ── responsive ──────────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
    .cw__head {
        grid-template-columns: 1fr;
        align-items: start;
    }

    .cw__where {
        justify-items: start;
        text-align: left;
    }

    .cw-roster {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: clamp(3rem, 5vw, 5rem);
    }

    .cw-p:nth-child(even) {
        margin-top: 0;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   07 · START
   What happens after you send runs as a rail across the top — it is a promise
   to everyone reading, not a footnote in a sidebar. Under it the form takes
   the wide column and the ways to reach a person directly sit beside it, so
   nobody has to fill in a form to get a phone number.
   ══════════════════════════════════════════════════════════════════════════ */

.fm--start {
    background: var(--g-warm);
}

/* ── what happens next ───────────────────────────────────────────────────── */

.st-flow {
    list-style: none;
    margin: 0 0 clamp(4.5rem, 6vw, 7.5rem);
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 2.6rem clamp(2.4rem, 3.4vw, 4.4rem);
}

.st-flow li {
    padding-top: 1.8rem;
    border-top: 1px solid var(--rule-warm);
}

.st-flow__n {
    display: block;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    color: var(--acc-2);
    margin-bottom: 1.4rem;
}

.st-flow h3 {
    font-family: var(--serif);
    font-size: clamp(1.8rem, 1.16vw, 1.83rem);
    font-weight: 450;
    line-height: 1.15;
    letter-spacing: -.015em;
    color: var(--ink);
    text-wrap: balance;
    margin: 0 0 .9rem;
}

.st-flow p {
    font-size: var(--t-body-s);
    line-height: 1.55;
    color: var(--ink-3);
    text-wrap: pretty;
    margin: 0;
}

/* ── the brief, and the ways round it ────────────────────────────────────── */

.st {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, .65fr);
    gap: clamp(2.4rem, 3.5vw, 5rem);
    align-items: start;
}

.st__side {
    display: grid;
    gap: clamp(1.8rem, 2.2vw, 2.6rem);
    position: sticky;
    top: 12rem;
}

.st-card {
    padding: clamp(2.4rem, 2.8vw, 3.2rem);
    background: var(--p-3);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-l);
}

.st-card__k {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--acc-2);
    margin: 0 0 2rem;
}

.st-lines {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
}

.st-lines li+li {
    border-top: 1px solid var(--rule-warm);
}

.st-lines a {
    display: grid;
    gap: .5rem;
    padding: 1.6rem 0;
    text-decoration: none;
}

.st-lines li:first-child a {
    padding-top: 0;
}

.st-lines li:last-child a {
    padding-bottom: 0;
}

.st-lines__t {
    font-family: var(--serif);
    font-size: clamp(1.7rem, 1.08vw, 1.66rem);
    letter-spacing: -.015em;
    line-height: 1.2;
    color: var(--ink);
    overflow-wrap: anywhere;
    transition: color .3s var(--e);
}

.st-lines__s {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .15em;
    text-transform: uppercase;
    color: var(--ink-4);
}

.st-lines a:hover .st-lines__t {
    color: var(--acc-2);
}

.st-lines a:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

.st-card--place address {
    font-style: normal;
    font-size: var(--t-body);
    line-height: 1.65;
    color: var(--ink-3);
    margin: 0 0 2.2rem;
}

.st-map {
    font-size: var(--t-sm);
    display: inline-flex;
    align-items: center;
    gap: .6em;
    font-family: var(--mono);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink);
    text-decoration: none;
    padding-bottom: .45em;
    background-image: linear-gradient(var(--acc-2), var(--acc-2));
    background-size: 0% 1px;
    background-position: 0 100%;
    background-repeat: no-repeat;
    transition: background-size .45s var(--e), color .3s var(--e);
}

.st-map svg {
    width: 1.2em;
    height: 1.2em;
    stroke-width: 1.6;
    transition: transform .3s var(--e);
}

.st-map:hover {
    color: var(--acc-2);
    background-size: 100% 1px;
}

.st-map:hover svg {
    transform: translate(2px, -2px);
}

.st-map:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

/* ── the form ────────────────────────────────────────────────────────────── */

.st__form {
    padding: clamp(2.8rem, 3.5vw, 4.8rem);
    background: var(--p);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-l);
    box-shadow: var(--sh-1);
}

.fm-fs {
    margin: 0 0 3.6rem;
    padding: 0;
    border: 0;
}

.fm-fs legend {
    display: flex;
    align-items: center;
    gap: 1rem;
    width: 100%;
    padding: 0 0 1.8rem;
    margin-bottom: 2.4rem;
    border-bottom: 1px solid var(--rule-warm);
    font-family: var(--mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.fm-fs legend i {
    font-style: normal;
    color: var(--acc-2);
}

.fm-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.8rem;
}

.fm-field {
    display: flex;
    flex-direction: column;
    gap: .8rem;
    margin: 0;
    min-width: 0;
}

.fm-field--full {
    grid-column: 1 / -1;
}

.fm-field label {
    font-size: var(--t-body-s);
    font-weight: 500;
    color: var(--ink-2);
    transition: color .25s var(--e);
}

.fm-field abbr {
    color: var(--acc-2);
    text-decoration: none;
    margin-left: .2em;
}

.st__form .form-control {
    width: 100%;
    padding: 1.2em 1.3em;
    font-family: inherit;
    font-size: var(--t-body);
    color: var(--ink);
    background: var(--p-2);
    border: 1px solid var(--rule-2);
    border-radius: var(--r-s);
    transition: border-color .25s var(--e), box-shadow .25s var(--e), background-color .25s var(--e);
}

.st__form .form-control::placeholder {
    color: rgba(109, 99, 91, .55);
}

.st__form .form-control:hover:not(:focus) {
    border-color: var(--acc-line);
}

.st__form .form-control:focus {
    outline: none;
    background: var(--p);
    border-color: var(--acc);
    box-shadow: 0 0 0 3px var(--acc-soft);
}

.st__form textarea.form-control {
    min-height: 14rem;
    resize: vertical;
    line-height: 1.6;
}

.fm-select {
    appearance: none;
    cursor: pointer;
    padding-right: 3.4em;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%238C6039' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 1.3em center;
}

/* Validation — warm brick, never stock red/green */
.st__form .form-control.is-invalid {
    border-color: #9B3B32;
    background: rgba(155, 59, 50, .035);
}

.st__form .form-control.is-invalid:focus {
    box-shadow: 0 0 0 3px rgba(155, 59, 50, .12);
}

.st__form .form-control.is-valid {
    border-color: #4F6B45;
}

/* contact.js marks the surrounding .form-group, so the label answers too */
.fm-field.has-error label {
    color: #8A342C;
}

/* Per-field error copy — collapsed to nothing until has-error fills it in,
   so the layout doesn't jump when a field passes validation. */
.fm-error {
    display: block;
    font-size: var(--t-nano, .78em);
    line-height: 1.4;
    color: #8A342C;
    min-height: 0;
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    transform: translateY(-2px);
    transition: max-height .25s var(--e), opacity .2s var(--e), transform .2s var(--e);
}

.fm-field.has-error .fm-error {
    max-height: 3em;
    opacity: 1;
    transform: translateY(0);
}

.fm-error:before {
    content: "⚠ ";
}

.fm-error:empty:before {
    content: "";
}

/* the widget lives in a frame of the form's own making, so the space is
   reserved before it loads and a failure is contained rather than a
   Cloudflare error card pasted into a cream form */
.fm-turnstile {
    display: grid;
    place-items: center;
    min-height: 8.4rem;
    margin: 2.4rem 0;
    padding: 1.2rem;
    background: var(--p-3);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-m);
}

.fm-turnstile__down {
    display: none;
    margin: 0;
    max-width: 46ch;
    text-align: center;
    font-size: var(--t-body-s);
    line-height: 1.5;
    color: var(--ink-3);
}

.fm-turnstile__down b {
    display: block;
    margin-bottom: .5rem;
    font-weight: 500;
    color: var(--ink);
}

.fm-turnstile__down a {
    color: var(--acc-2);
}

/* when it cannot load, say so in our own words and give a way round it —
   the token is still required to submit, so this explains rather than
   waves the check through */
.fm-turnstile.is-down .cf-turnstile {
    display: none;
}

.fm-turnstile.is-down .fm-turnstile__down {
    display: block;
}

.fm-submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .7em;
    width: 100%;
    padding: 1.4em 2em;
    border: 0;
    border-radius: 100px;
    background: var(--ink);
    color: var(--p);
    font-family: var(--mono);
    font-size: var(--t-md);
    letter-spacing: .06em;
    text-transform: uppercase;
    cursor: pointer;
    box-shadow: var(--sh-1);
    transition: background-color .3s var(--e), transform .3s var(--e), box-shadow .3s var(--e), opacity .3s var(--e);
}

.fm-submit svg {
    width: 1.2em;
    height: 1.2em;
    stroke-width: 1.6;
    transition: transform .3s var(--e);
}

.fm-submit:hover:not(:disabled) {
    background: var(--ink-2);
    transform: translateY(-2px);
    box-shadow: var(--sh-2);
}

.fm-submit:hover:not(:disabled) svg {
    transform: translateX(3px);
}

.fm-submit:active:not(:disabled) {
    transform: translateY(0) scale(.99);
}

.fm-submit:disabled {
    opacity: .38;
    cursor: not-allowed;
}

.fm-submit:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

.form-status {
    margin-top: 1.6rem;
    padding: 1.2em 1.4em;
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-s);
    background: var(--p-2);
    font-size: var(--t-body-s);
    line-height: 1.5;
    color: var(--ink-3);
}

.form-status:empty {
    display: none;
}

.form-status.is-error {
    border-color: rgba(155, 59, 50, .35);
    background: rgba(155, 59, 50, .05);
    color: #8A342C;
}

.form-status.is-success {
    border-color: rgba(79, 107, 69, .35);
    background: rgba(79, 107, 69, .06);
    color: #3B5135;
}

/* ── responsive ──────────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
    /* minmax(0,…), not 1fr: a bare 1fr track takes its minimum from the
       card's content, and the Turnstile widget is a fixed 300px iframe —
       which pushed the whole column past the viewport on small screens */
    .st {
        grid-template-columns: minmax(0, 1fr);
    }

    /* the direct lines come first — nobody should fill a form for a number */
    .st__side {
        order: -1;
        position: static;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 760px) {
    .st-flow {
        grid-template-columns: 1fr;
        gap: 2.2rem;
    }

    .st__side {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 560px) {
    .fm-grid {
        grid-template-columns: 1fr;
    }
}

/* ── small screens: the form has to fit, Turnstile included ──────────────── */

@media (max-width: 560px) {
    .st__form {
        padding: clamp(1.8rem, 5vw, 2.6rem);
    }

    /* the fieldset defaulted to min-width:min-content, which let the widest
       child set the floor for everything above it */
    .fm-fs,
    .st__form,
    .st__form form {
        min-width: 0;
    }
}

/* Turnstile renders a fixed 300px iframe with no responsive mode short of
   re-rendering it compact. Scaling the box it sits in keeps the widget
   usable and stops it dictating the page width. */
@media (max-width: 420px) {
    .fm-turnstile {
        overflow: hidden;
    }

    .fm-turnstile>* {
        transform: scale(.8);
        transform-origin: left top;
    }

    /* the scaled widget leaves a gap under it, so the box is pulled back in */
    .fm-turnstile {
        margin-bottom: .6rem;
    }
}

@media (max-width: 360px) {
    .fm-turnstile>* {
        transform: scale(.72);
    }
}


/* ══════════════════════════════════════════════════════════════════════════
   FOOTER
   A sign-off, not a link farm. The studio says what it does once, at size,
   with the one action that matters next to it; the lists underneath are kept
   to what someone actually leaves for. Nothing here points at a page that
   does not exist.
   ══════════════════════════════════════════════════════════════════════════ */

#site-footer {
    position: relative;
    z-index: 10;
    background: var(--p);
    color: var(--ink-2);
    padding: clamp(4rem, 5vw, 5.6rem) 0 clamp(2.4rem, 3vw, 3.2rem);
    border-top: 1px solid var(--rule-warm);
}

/* the sign-off and the lists sit side by side — stacked, the footer ran
   longer than the viewport it was closing */
.fm-foot {
    display: grid;
    grid-template-columns: minmax(0, .88fr) minmax(0, 1.12fr);
    gap: clamp(3rem, 3.6vw, 4rem) clamp(3rem, 5vw, 7rem);
    align-items: start;
}

/* ── the sign-off ────────────────────────────────────────────────────────── */

.ft-say {
    grid-column: 1;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 2rem;
}

.ft-mark {
    display: block;
    width: fit-content;
    border-radius: var(--r-x);
}

.ft-mark img {
    height: 30px;
    width: auto;
    display: block;
}

.ft-mark:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 6px;
}

.ft-say__big {
    font-family: var(--serif);
    font-size: clamp(2.6rem, 2.82vw, 3.65rem);
    font-weight: 450;
    line-height: 1.02;
    letter-spacing: -.035em;
    color: var(--ink);
    max-width: 18ch;
    text-wrap: balance;
    margin: clamp(1.8rem, 2vw, 2.4rem) 0 1.2rem;
}

.ft-say__small {
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-3);
    margin: 0;
}

/* the one thing worth doing from down here */
.ft-cta {
    justify-self: start;
    display: inline-flex;
    align-items: center;
    gap: .8em;
    padding: 1.35em 2.2em;
    border: 1px solid var(--ink);
    border-radius: 100px;
    background: var(--ink);
    font-family: var(--mono);
    font-size: var(--t-md);
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--p);
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .3s var(--e), border-color .3s var(--e), transform .3s var(--e), box-shadow .3s var(--e);
}

.ft-cta svg {
    width: 1.3em;
    height: 1.3em;
    stroke-width: 1.6;
    transition: transform .3s var(--e);
}

.ft-cta:hover {
    background: var(--ink-2);
    border-color: var(--ink-2);
    transform: translateY(-2px);
    box-shadow: var(--sh-2);
}

.ft-cta:hover svg {
    transform: translateX(3px);
}

.ft-cta:active {
    transform: translateY(0) scale(.99);
}

.ft-cta:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

/* ── the short lists ─────────────────────────────────────────────────────── */

.ft-cols {
    grid-column: 2;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.35fr);
    gap: clamp(2.4rem, 3vw, 3.4rem);
}

.fm-foot__h {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--acc-2);
    margin: 0 0 1.5rem;
}

.ft-col ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: .9rem;
}

.ft-col a {
    font-size: var(--t-body);
    line-height: 1.35;
    color: var(--ink-2);
    text-decoration: none;
    overflow-wrap: anywhere;
    transition: color .25s var(--e);
}

.ft-col a:hover {
    color: var(--acc-2);
}

.ft-col a:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
    border-radius: 2px;
}

/* leaving the site is marked, so nobody is surprised by a new tab */
.ft-out a::after {
    content: "↗";
    display: inline-block;
    margin-left: .45em;
    font-size: .85em;
    color: var(--ink-4);
    transition: transform .25s var(--e), color .25s var(--e);
}

.ft-out a:hover::after {
    color: var(--acc-2);
    transform: translate(2px, -2px);
}

.ft-col--reach address {
    font-style: normal;
    font-size: var(--t-body-s);
    line-height: 1.65;
    color: var(--ink-3);
    margin: 1.6rem 0 0;
    padding-top: 1.6rem;
    border-top: 1px solid var(--rule-warm);
}

/* ── the bottom rule ─────────────────────────────────────────────────────── */

.fm-foot__bottom {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 1.6rem;
    padding-top: clamp(2rem, 2.4vw, 2.4rem);
    border-top: 1px solid var(--rule-warm);
}

.fm-foot__bottom p {
    font-family: var(--mono);
    font-size: var(--t-md);
    letter-spacing: .08em;
    color: var(--ink-3);
    margin: 0;
}

.ft-top {
    display: inline-flex;
    align-items: center;
    gap: .7em;
    font-family: var(--mono);
    font-size: var(--t-md);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-2);
    text-decoration: none;
    transition: color .25s var(--e);
}

.ft-top svg {
    width: 1.4em;
    height: 1.4em;
    stroke-width: 1.6;
    transition: transform .3s var(--e);
}

.ft-top:hover {
    color: var(--acc-2);
}

.ft-top:hover svg {
    transform: translateY(-3px);
}

.ft-top:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

/* a live clock in the studio's own time — small, and true */
.ft-clock {
    display: inline-flex;
    align-items: center;
    gap: .8em;
    font-family: var(--mono);
    font-size: var(--t-md);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
    margin: 0;
}

.ft-clock i {
    width: .6rem;
    height: .6rem;
    border-radius: 50%;
    background: var(--acc);
    animation: ftPulse 3s var(--e-io) infinite;
}

@keyframes ftPulse {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: .25;
    }
}

.ft-clock time {
    font-variant-numeric: tabular-nums;
    color: var(--ink);
}

/* registered so the spotlight position can actually be animated — an
   unregistered custom property steps between keyframes instead of tweening */
@property --mx {
    syntax: '<percentage>';
    inherits: true;
    initial-value: 50%;
}

@property --my {
    syntax: '<percentage>';
    inherits: true;
    initial-value: 50%;
}

/* ── the sign-off wordmark ───────────────────────────────────────────────── */

.ft-word {
    --ft-dur: 4.2s;
    /* the size lives here so the headroom and the hop can be set in em
       against it — on the spans, em resolved against the inherited body
       size and every offset came out a tenth of what it should be */
    font-size: clamp(4.6rem, 12.8vw, 18.3rem);
    position: relative;
    margin-top: clamp(2.4rem, 3vw, 3.4rem);
    /* .70 sat the line box inside the glyphs and overflow:hidden then took
       the tops off the S, the T and the tittle on the i */
    padding: .2em var(--gut) 0;
    overflow: hidden;
    line-height: .86;
    text-align: center;
    user-select: none;
    pointer-events: auto;
}

.ft-word span {
    display: block;
    font-family: var(--serif);
    /* sized to span the measure — the name should reach both gutters */
    font-size: 1em;
    font-weight: 450;
    letter-spacing: -.045em;
    white-space: nowrap;
}

/* the ghost the name is cut from */
.ft-word__base {
    color: rgba(42, 24, 22, .10);
}

/* …and, where the browser can clip a gradient to the glyphs, it is struck in
   warm metal with a highlight that travels across the letters */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
    .ft-word__base {
        color: transparent;
        background-image: linear-gradient(94deg,
                rgba(166, 124, 82, .22) 0%,
                rgba(166, 124, 82, .22) 36%,
                rgba(214, 172, 116, .60) 44%,
                rgba(247, 226, 184, .95) 49%,
                #FFF6E2 50.5%,
                rgba(247, 226, 184, .95) 52%,
                rgba(214, 172, 116, .60) 57%,
                rgba(166, 124, 82, .22) 65%,
                rgba(166, 124, 82, .22) 100%);
        background-size: 260% 100%;
        background-position: 120% 0;
        -webkit-background-clip: text;
        background-clip: text;
        animation: ftShine var(--ft-dur) linear infinite;
    }
}

/* the first time it comes into view it sweeps once on its own, so the effect
   is never missed by someone who does not hover */
.ft-word.is-seen .ft-word__lit {
    opacity: 1;
    animation: ftGreet 1.5s var(--e) 1 both;
}

.ft-word.is-live .ft-word__lit {
    animation: none;
}

@keyframes ftGreet {
    0% {
        opacity: 0;
        --mx: -10%;
    }

    35% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        --mx: 110%;
    }
}

@keyframes ftShine {
    to {
        background-position: -60% 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .ft-word__base {
        animation: none;
        background-position: 50% 0;
    }
}

/* the lit copy, revealed only where the cursor is */
.ft-word__lit {
    position: absolute;
    inset: .2em var(--gut) 0;
    color: transparent;
    background-image: radial-gradient(circle at var(--mx, 50%) var(--my, 50%),
            #FFF6E2 0%,
            rgba(226, 186, 122, .92) 14%,
            rgba(166, 124, 82, .55) 26%,
            rgba(166, 124, 82, 0) 46%);
    -webkit-background-clip: text;
    background-clip: text;
    opacity: 0;
    transition: opacity .45s var(--e);
}

.ft-word.is-live .ft-word__lit {
    opacity: 1;
}

/* no cursor to follow — give the name a fixed warm wash instead */
@media (hover: none),
(pointer: coarse) {
    .ft-word__lit {
        opacity: 1;
        background-image: linear-gradient(100deg,
                rgba(166, 124, 82, 0) 8%,
                rgba(166, 124, 82, .55) 42%,
                rgba(166, 124, 82, 0) 76%);
    }
}

@media (prefers-reduced-motion: reduce) {
    .ft-word__lit {
        transition: none;
    }

    .ft-clock i {
        animation: none;
    }
}

/* ── responsive ──────────────────────────────────────────────────────────── */

@media (max-width: 860px) {
    .fm-foot {
        grid-template-columns: 1fr;
    }

    .ft-say,
    .ft-cols {
        grid-column: 1;
    }

    .ft-cols {
        padding-top: clamp(2.6rem, 3.2vw, 3.6rem);
        border-top: 1px solid var(--rule-warm);
    }

    .ft-cols {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: clamp(3rem, 5vw, 4rem);
    }

    .ft-col--reach {
        grid-column: 1 / -1;
    }

    .ft-col--reach address {
        margin-top: 1.6rem;
        padding-top: 1.6rem;
    }
}

@media (max-width: 380px) {
    .ft-cols {
        grid-template-columns: 1fr;
    }

    .ft-cta {
        width: 100%;
        justify-content: center;
    }

    .fm-foot__bottom {
        flex-direction: column;
        align-items: flex-start;
        gap: 2rem;
    }
}

/* Skip link */
.fm-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 999;
    padding: 1.2em 1.8em;
    background: var(--ink);
    color: var(--p);
    font-family: var(--mono);
    font-size: var(--t-md);
    border-radius: 0 0 var(--r-s) 0;
    text-decoration: none;
}

.fm-skip:focus {
    left: 0;
}

/* ── scroll cost ─────────────────────────────────────────────────────────────
   The page is ~21 screens. These three are long, static and self-contained, so
   the browser is allowed to skip their layout and paint until they are close.
   The intrinsic sizes keep the scrollbar honest. Sections that JS measures
   (the wall canvas, the board, the topology) are deliberately left out. */

#work {
    content-visibility: auto;
    contain-intrinsic-size: auto 2190px;
}

#builds {
    content-visibility: auto;
    contain-intrinsic-size: auto 2700px;
}

#team {
    content-visibility: auto;
    contain-intrinsic-size: auto 1390px;
}

/* ── the board, brought to life ──────────────────────────────────────────────
   The days no longer just switch colour: a highlight runs across each cell as
   it lights, in day order, so the sixty days read as a sweep rather than a
   flicker. Hovering a phase lifts its own days and dims the rest. */


/* hovering a phase key: its days rise and glow, the others recede */
.bd-grid.is-keyed .bd-day {
    transition:
        transform .45s var(--e) calc(var(--i) * 6ms),
        opacity .45s var(--e) calc(var(--i) * 6ms),
        box-shadow .45s var(--e) calc(var(--i) * 6ms);
}

.bd-grid.is-keyed .bd-day.is-keyed {
    transform: scale(1.18);
    box-shadow: 0 0 0 1px rgba(255, 246, 226, .35), 0 4px 12px rgba(0, 0, 0, .35);
}

@media (prefers-reduced-motion: reduce) {

    .bd-grid.is-lit .bd-day::after {
        animation: none;
    }

    .bd-grid.is-keyed .bd-day {
        transition: none;
    }
}

/* ── the wall, given some light ──────────────────────────────────────────────
   The cells were flat fills. Each one now has a soft gradient across it, a
   lit top edge where the light would catch, a deeper shadow to sit it off the
   paper, and a sheen that travels the card when you point at it. */

.pw-cell__in {
    background-image: linear-gradient(152deg,
            rgba(255, 252, 245, .55) 0%,
            rgba(255, 252, 245, 0) 42%,
            rgba(120, 82, 52, .07) 100%);
    box-shadow:
        0 1px 0 rgba(255, 252, 245, .55) inset,
        0 1px 2px rgba(93, 82, 75, .06),
        0 8px 22px -10px rgba(93, 82, 75, .22);
}

/* the sheen — a wide band that crosses the card on hover */
.pw-cell__in::after {
    content: "";
    position: absolute;
    inset: -40%;
    z-index: -1;
    background: linear-gradient(105deg,
            rgba(255, 250, 238, 0) 42%,
            rgba(255, 250, 238, .55) 50%,
            rgba(255, 250, 238, 0) 58%);
    transform: translateX(-70%);
    opacity: 0;
    transition: transform 1.05s var(--e), opacity .4s var(--e);
    pointer-events: none;
}

.pw-cell.is-hot .pw-cell__in {
    box-shadow:
        0 1px 0 rgba(255, 252, 245, .7) inset,
        0 2px 4px rgba(93, 82, 75, .08),
        0 22px 48px -18px rgba(93, 82, 75, .34);
}

.pw-cell.is-hot .pw-cell__in::after {
    transform: translateX(70%);
    opacity: 1;
}

/* the dark cell wants the light from the other side */
.pw-cell--fig .pw-cell__in {
    background-image: linear-gradient(152deg,
            rgba(255, 240, 214, .13) 0%,
            rgba(255, 240, 214, 0) 46%,
            rgba(0, 0, 0, .22) 100%);
    box-shadow:
        0 1px 0 rgba(255, 240, 214, .16) inset,
        0 10px 26px -12px rgba(0, 0, 0, .45);
}

.pw-cell--fig.is-hot .pw-cell__in {
    box-shadow:
        0 1px 0 rgba(255, 240, 214, .22) inset,
        0 24px 52px -18px rgba(0, 0, 0, .55);
}

.pw-cell--fig .pw-cell__in::after {
    background: linear-gradient(105deg,
            rgba(255, 240, 214, 0) 42%,
            rgba(255, 240, 214, .14) 50%,
            rgba(255, 240, 214, 0) 58%);
}

@media (prefers-reduced-motion: reduce) {
    .pw-cell__in::after {
        transition: none;
    }
}


/* ── 06 · pick what you need ─────────────────────────────────────────────────
   The ledger was a list you read top to bottom and forgot. Now choosing a row
   answers on the right: what you actually get, in three lines. The row you are
   on carries the fill and the arrow. */

.bl {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    gap: clamp(2.4rem, 4vw, 5rem);
    align-items: start;
}


@media (max-width: 900px) {
    .bl {
        grid-template-columns: 1fr;
    }
}


/* ══════════════════════════════════════════════════════════════════════════
   08 · QUESTIONS
   Plain answers, on the page rather than only in the schema — an answer engine
   quotes what a reader can see. Every panel is in the DOM and readable with
   JS off; the toggle only collapses them.
   ══════════════════════════════════════════════════════════════════════════ */

.fm--faq {
    background: var(--g-olive);
}

.fq {
    margin: clamp(3.4rem, 4.5vw, 5rem) 0 0;
    border-top: 1px solid var(--rule-warm);
}

.fq__i {
    border-bottom: 1px solid var(--rule-warm);
}

.fq__q {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 2rem;
    width: 100%;
    padding: clamp(2rem, 2.4vw, 2.6rem) 0;
    border: 0;
    background: none;
    text-align: left;
    cursor: pointer;
    font-family: var(--serif);
    font-size: clamp(1.9rem, 1.49vw, 1.99rem);
    font-weight: 450;
    line-height: 1.2;
    letter-spacing: -.025em;
    color: var(--ink);
    transition: color .3s var(--e);
}

.fq__q:hover {
    color: var(--acc-2);
}

.fq__q:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: -2px;
}

/* the marker: a plus that becomes a minus */
.fq__q i {
    position: relative;
    width: 2.2rem;
    height: 2.2rem;
    flex: none;
}

.fq__q i::before,
.fq__q i::after {
    content: "";
    position: absolute;
    inset: 50% 0 auto;
    height: 1.5px;
    background: var(--acc-2);
    transition: transform .4s var(--e);
}

.fq__q i::after {
    transform: rotate(90deg);
}

.fq__q[aria-expanded="true"] i::after {
    transform: rotate(0deg);
}

/* 0fr -> 1fr so it animates to auto height without measuring. The track has to
   stay a bare 0fr/1fr for the transition to interpolate — minmax() forms stall
   at the start value — so the automatic minimum is defeated the other way, by
   giving the grid item an inner wrapper that carries no padding of its own. */
.fq__a {
    display: grid;
    grid-template-rows: 0fr;
    margin: 0;
    transition: grid-template-rows .5s var(--e);
}

.fq__i:has([aria-expanded="true"]) .fq__a {
    grid-template-rows: 1fr;
}

.fq__a>div {
    overflow: hidden;
    min-height: 0;
}

.fq__a p {
    font-size: var(--t-body);
    line-height: 1.65;
    color: var(--ink-3);
    max-width: 68ch;
    text-wrap: pretty;
    margin: 0;
    padding-bottom: clamp(2rem, 2.4vw, 2.6rem);
}

.fq__a b {
    font-weight: 500;
    color: var(--ink);
}

/* with JS off nothing can toggle, so everything stays open and readable */
.no-js .fq__a {
    grid-template-rows: 1fr;
}

@media (prefers-reduced-motion: reduce) {

    .fq__a,
    .fq__q i::before,
    .fq__q i::after {
        transition: none;
    }
}

/* ── the wall, alive under the cursor ─────────────────────────────────────
   The sheen and the warm glow were doing the work on their own and read as
   soft. What was missing was something with an edge: a line of light that
   actually travels the border, and copy that shifts against the pointer so
   the card has depth rather than just brightness. */

/* ── pointing at a cell ───────────────────────────────────────────────────
   This used to trace a conic-gradient ring round the cell on hover. Masked
   to 1.5px it is a clever trick and it looked like a fault: the bright stop
   in the sweep reads as a hard line drawn down the edge nearest whatever is
   next to it, which is exactly what it was reported as. A cell that lifts,
   warms its edge and blooms its shadow says "this one" without drawing
   anything the reader has to explain to themselves.
   ───────────────────────────────────────────────────────────────────────── */

.pw-cell.is-hot {
    transform: translateY(-3px);
}

.pw-cell.is-hot .pw-cell__in {
    border-color: var(--acc-line);
    box-shadow:
        0 1px 0 rgba(255, 252, 245, .7) inset,
        0 2px 6px rgba(93, 82, 75, .07),
        0 22px 44px -18px rgba(93, 82, 75, .34);
}

/* ── the signal cell, under the pointer ───────────────────────────────────
   The panel is a picture of something being read, so pointing at it starts
   a read: a soft band travels down the blades, and the sector name under it
   changes at the pace of the sweep rather than its idle pace. */

.pw-scan {
    position: absolute;
    inset: 0 0 auto 0;
    z-index: 1;
    height: 34%;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(to bottom,
            rgba(255, 250, 240, 0) 0%,
            rgba(255, 250, 240, .34) 44%,
            rgba(255, 250, 240, .62) 52%,
            rgba(255, 250, 240, .28) 60%,
            rgba(255, 250, 240, 0) 100%);
    transform: translateY(-130%);
}

.pw-cell--signal.is-hot .pw-scan {
    animation: pwScan 2.3s var(--e-io) infinite;
}

@keyframes pwScan {
    0% {
        opacity: 0;
        transform: translateY(-130%);
    }

    12% {
        opacity: 1;
    }

    82% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        transform: translateY(330%);
    }
}

/* the readout keeps up with the sweep */
.pw-cell--signal.is-hot .pw-dot {
    animation-duration: .9s;
}

@media (prefers-reduced-motion: reduce) {

    .pw-cell.is-hot {
        transform: none;
    }

    .pw-cell--signal.is-hot .pw-scan {
        animation: none;
    }
}

/* copy drifts against the pointer — a few pixels is all it takes to read as
   depth, and it costs one transform */
/* :not(canvas):not(.pw-scan) matters. Both of those are full-bleed layers
   pinned to inset:0 — drifting them by a few pixels drags their edge off the
   card and leaves a hard line of bare ground down one side. Only the copy
   should move. */
.pw-cell__in>*:not(canvas):not(.pw-scan) {
    transition: transform .5s var(--e);
}

.pw-cell.is-hot .pw-cell__in>*:not(canvas):not(.pw-scan) {
    transform: translate3d(calc(var(--dx, 0) * -5px), calc(var(--dy, 0) * -5px), 0);
}

/* The canvas is the background of its own cell, so it leans the other way.
   The scale has to out-run the lean *and* the blur: at 1.06 the 9px drift
   walked the canvas edge exactly onto the card edge and the blur softened the
   last few pixels, which is the hard pale line that showed up under the
   pointer. 1.14 against a 5px lean leaves real headroom on every side. */
.pw-cell.is-hot .pw-canvas {
    transform: translate3d(calc(var(--dx, 0) * 5px), calc(var(--dy, 0) * 5px), 0) scale(1.14);
}

.pw-canvas {
    transition: transform .6s var(--e), filter .6s var(--e);
}

/* sharper under the cursor: the softness was hiding the panels entirely */
.pw-cell--signal.is-hot .pw-canvas {
    filter: blur(5px);
}

/* the sector the panel is naming, cycling underneath the label */
.pw-signal__now {
    display: inline-block;
    min-width: 12ch;
    color: var(--acc-3);
}

.pw-signal__now span {
    display: inline-block;
    animation: pwNow .5s var(--e);
}

@keyframes pwNow {
    from {
        opacity: 0;
        transform: translateY(.5em);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {

    .pw-cell.is-hot::after {
        animation: none;
    }

    .pw-cell.is-hot .pw-cell__in>*,
    .pw-cell.is-hot .pw-canvas {
        transform: none;
    }

    .pw-signal__now span {
        animation: none;
    }
}

/* ── the sector motifs ────────────────────────────────────────────────────
   The same lit isometric language as the capability cards, in the corner the
   open panel leaves free. These were 1px line drawings ghosted to 30% behind
   the copy — a drawing worth making is a drawing worth being able to see, so
   they are rendered and at full strength, and the copy keeps out of their
   column above 1180px rather than relying on them being faint.
   ───────────────────────────────────────────────────────────────────────── */

.sc-motif {
    position: absolute;
    right: clamp(1.4rem, 2.6vw, 3.4rem);
    top: clamp(1.4rem, 2.6vw, 3rem);
    z-index: 0;
    width: clamp(14rem, 21vw, 25rem);
    height: auto;
    pointer-events: none;
    opacity: 0;
    transform: translateY(12px) scale(.96);
    transition: opacity .7s var(--e) .1s, transform .85s var(--e) .1s;
}

.sc-panel.is-open .sc-motif {
    opacity: 1;
    transform: none;
}

/* the copy sits in front of it, and above the width where the drawing
   appears it keeps out of that column entirely */
.sc-content__in {
    position: relative;
    z-index: 1;
}

@media (min-width: 1281px) {

    /* the panel being measured has to reserve the drawing's column too, or
       the copy wraps wider than it ever will and the strip is sized for a
       sentence that does not exist */
    .sc-panel.is-open .sc-content__in,
    .sc-panel.is-measuring .sc-content__in {
        padding-right: clamp(15rem, 22vw, 27rem);
    }
}

/* the solids arrive in order — books stacking, columns raised, rows drawn */
.sc-seq {
    opacity: 0;
    transform: translateY(9px);
    transition: opacity .5s var(--e), transform .6s var(--e);
}

.sc-panel.is-open .sc-seq {
    opacity: 1;
    transform: none;
}

.sc-panel.is-open .sc-seq--0 {
    transition-delay: .28s;
}

.sc-panel.is-open .sc-seq--1 {
    transition-delay: .38s;
}

.sc-panel.is-open .sc-seq--2 {
    transition-delay: .48s;
}

.sc-panel.is-open .sc-seq--3 {
    transition-delay: .58s;
}

.sc-panel.is-open .sc-seq--4 {
    transition-delay: .68s;
}

.sc-panel.is-open .sc-seq--5 {
    transition-delay: .78s;
}

/* and the marks that are meant to read as live keep pulsing: a monitor
   trace, lit windows, a chart, a frieze picked out in the light */
.sc-panel.is-open .sc-lit {
    animation: scLit 4.6s var(--e-io) .9s infinite;
}

.sc-panel.is-open .sc-lit--1 {
    animation-delay: 1.1s;
}

.sc-panel.is-open .sc-lit--2 {
    animation-delay: 1.3s;
}

.sc-panel.is-open .sc-lit--3 {
    animation-delay: 1.5s;
}

.sc-panel.is-open .sc-lit--4 {
    animation-delay: 1.7s;
}

.sc-panel.is-open .sc-lit--5 {
    animation-delay: 1.9s;
}

.sc-panel.is-open .sc-lit--6 {
    animation-delay: 2.1s;
}

@keyframes scLit {

    0%,
    100% {
        opacity: .34;
    }

    24%,
    46% {
        opacity: 1;
    }
}

/* the gantry works its way along the line */
.sc-panel.is-open .sc-arm {
    animation: scArm 6s var(--e-io) 1s infinite;
}

@keyframes scArm {

    0%,
    100% {
        transform: translate(-19.05px, -11px);
    }

    46%,
    58% {
        transform: translate(19.05px, 11px);
    }
}

/* below this the copy fills the plate and the drawing would sit under the tags */
@media (max-width: 1280px) {
    .sc-motif {
        display: none;
    }

    /* a display:none subtree does not tick its animations, but saying so
       outright means nothing is left declared on a phone */
    .sc-panel.is-open .sc-lit,
    .sc-panel.is-open .sc-arm {
        animation: none;
    }
}

@media (prefers-reduced-motion: reduce) {

    .sc-motif,
    .sc-seq {
        transition: none;
    }

    .sc-panel.is-open .sc-lit,
    .sc-panel.is-open .sc-arm {
        animation: none;
    }

    .sc-lit {
        opacity: 1;
    }

    .sc-seq {
        opacity: 1;
        transform: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   06 · CUSTOM BUILDS — the ticker
   Six things on a track that runs by itself until someone takes hold of it.
   Deliberately not another accordion or another strip: the page already has
   both, and this lane needed to move differently from the impact work.
   ══════════════════════════════════════════════════════════════════════════ */

.cb {
    margin-top: clamp(3.4rem, 5vw, 5.4rem);
}

/* ── the foot: proof, then the way in ────────────────────────────────────── */

.cb-foot {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(2.6rem, 5vw, 6rem);
    align-items: end;
    margin-top: clamp(4rem, 6vw, 7rem);
    padding-top: clamp(2.6rem, 3.4vw, 3.4rem);
    border-top: 1px solid var(--rule-warm);
}

.cb-foot__count {
    display: flex;
    align-items: baseline;
    gap: 1.4rem;
    margin: 0 0 clamp(1.8rem, 2.4vw, 2.4rem);
}

.cb-foot__count b {
    display: inline-flex;
    align-items: baseline;
    font-family: var(--serif);
    font-size: clamp(4rem, 4.98vw, 5.81rem);
    font-weight: 450;
    line-height: .9;
    letter-spacing: -.04em;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.cb-foot__count b i {
    font-style: normal;
    font-size: .45em;
    color: var(--acc);
    margin-left: .1em;
}

.cb-foot__count>span {
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-4);
}

.cb-foot__p {
    margin: 0 0 clamp(1.8rem, 2.4vw, 2.2rem);
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-3);
    max-width: 46ch;
    text-wrap: pretty;
}

/* ── narrow ──────────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
    .cb-foot {
        grid-template-columns: 1fr;
        align-items: start;
    }
}

/* the two halves of the foot, each stacking its own way */
.cb-foot__proof,
.cb-foot__ask {
    min-width: 0;
}

/* ══════════════════════════════════════════════════════════════════════════
   06 · CUSTOM BUILDS — the brief
   A sentence the visitor assembles, that answers back and then fills in the
   contact form. The point is that choosing leads somewhere: this section is
   the only one on the page where the reader does something and the site
   does something in return.
   ══════════════════════════════════════════════════════════════════════════ */

.br {
    margin-top: clamp(3.4rem, 5vw, 5.4rem);
}

/* ── narrow ──────────────────────────────────────────────────────────────── */

@media (max-width: 900px) {}

/* On a phone the sheet spans the sentence rather than hanging off one word.
   It was `position: fixed` centred with translateX(-50%), which broke twice
   over: the drop-in animation sets its own `transform` and wiped the
   centring, and an ancestor transform meant `fixed` was not resolving
   against the viewport at all. Anchoring it to the line avoids both. */
@media (max-width: 560px) {}


/* ══════════════════════════════════════════════════════════════════════════
   RESPONSIVE REPAIRS
   Measured at 320 / 375 / 414 / 768 / 1024 / 1280 / 1440, not guessed at.
   ══════════════════════════════════════════════════════════════════════════ */

/* The .w-Ncol classes come from the original 1728px grid and resolve to fixed
   column maths, so at 320px .w-6col computed to 893px inside a 291px box and
   spilled 287px either side. Capping them keeps the centred hero text where
   it is without touching the hero's structure or its slide script. */
@media (max-width: 900px) {

    .w-3col,
    .w-4col,
    .w-5col,
    .w-6col,
    .w-7col,
    .w-8col {
        max-width: 100%;
    }
}

/* --t-xs is 10.5px, which is fine on a desktop label and too small to read
   comfortably on a phone. Every mono label on the site keys off this. */
@media (max-width: 560px) {
    :root {
        --t-xs: 1.15rem;
        --t-sm: 1.25rem;
    }
}

/* Text links were 18–20px tall — under the 24px minimum for a touch target.
   Padding the box rather than the type keeps the type size and rhythm. */
@media (max-width: 820px) {

    .ft-col a,
    .ft-top,
    .st-map,
    .cw-p__link,
    .fq__a a,
    .bl-clients a {
        display: inline-block;
        padding-block: .5rem;
    }}

@media (max-width: 560px) {

    /* the chapter numeral and the unit suffix are set in em off their parents,
       so the root bump above does not reach them */
    .fm-label i {
        font-size: 1.25rem;
    }

    .pw-fig__n i {
        font-size: .22em;
    }
}

/* The proof strip was holding three stats in fixed thirds beside the CTA,
   which at tablet width squeezed "Core SDGs" into a 31px column. It now
   stacks away from the CTA at 900 rather than 760, and the stats fall
   3 → 2 → 1 on their own, so no width leaves a label crushed. */
@media (max-width: 900px) {
    .pw-cell--proof .pw-cell__in {
        flex-direction: column;
        align-items: stretch;
    }

    .pw-mini {
        max-width: none;
        min-width: 0;
        grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
        gap: 1.6rem 2rem;
    }

    .pw-go {
        align-self: flex-start;
    }
}

/* the label bump reaches tablets too — a 10.5px mono label is no easier to
   read on a 768px tablet held at arm's length than on a phone */
@media (max-width: 820px) {
    :root {
        --t-xs: 1.15rem;
        --t-sm: 1.25rem;
    }

    .fm-label i {
        font-size: 1.25rem;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   02 · CAPABILITIES — the four ways in
   Four cards, each carrying a working drawing of its own subject under the
   copy rather than an icon above it: the sixty days as a schedule with a
   head running across it, the assistant as a loop with traffic on it, the
   operations lane as a queue routing to a person, the platform as a stack
   with a reading climbing it. Every drawing animates the thing it depicts,
   at the site's own stroke weight — technical plates, not clip art.

   The cards are 7/5 and 5/7 across twelve columns so the pair of rows steps
   rather than sitting as a flat 2×2, and the strip along the foot of each
   card says which stretch of the chain that way in covers, so the four still
   read as one system.
   ══════════════════════════════════════════════════════════════════════════ */

.ex {
    list-style: none;
    margin: clamp(3.4rem, 5vw, 5.4rem) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: clamp(2rem, 2.6vw, 3rem);
}

.ex__i {
    min-width: 0;
}

.ex__i--w {
    grid-column: span 7;
}

.ex__i--n {
    grid-column: span 5;
}

.ex__card {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: clamp(2.2rem, 2.8vw, 3.2rem);
    background: var(--p-3);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-l);
    box-shadow: var(--sh-1);
    transition: transform .6s var(--e), box-shadow .6s var(--e), border-color .6s var(--e);
}

.ex__i:hover .ex__card {
    transform: translateY(-4px);
    border-color: var(--acc-line);
    box-shadow: var(--sh-2);
}

.ex__n {
    display: flex;
    align-items: baseline;
    gap: 1rem;
    margin: 0;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--acc-2);
}

.ex__n i {
    font-style: normal;
    color: var(--ink-4);
}

.ex__ttl {
    margin: 1.2rem 0 0;
    font-family: var(--serif);
    font-size: clamp(2.3rem, 2.07vw, 2.82rem);
    font-weight: 450;
    line-height: 1.06;
    letter-spacing: -.03em;
    color: var(--ink);
    text-wrap: balance;
}

.ex__d {
    margin: 1.4rem 0 0;
    max-width: 52ch;
    font-size: var(--t-body-s);
    line-height: 1.6;
    color: var(--ink-3);
    text-wrap: pretty;
}

/* ── the scene ───────────────────────────────────────────────────────────
   These were 1px line drawings, and read as clip art however carefully the
   geometry was worked out. What makes a render look rendered is not detail,
   it is light: a warm key from the upper left, a *cool* fill in the shadows
   rather than more brown, a contact shadow where an object meets the ground,
   and a rim where a top edge catches the key. All of that is flat SVG —
   gradients and polygons, no bitmap, crisp at any size — so the four scenes
   cost about as much as the line drawings did.
   ───────────────────────────────────────────────────────────────────────── */

.ex__art {
    margin: clamp(2.4rem, 3vw, 3.2rem) 0 0;
    flex: none;
    padding: 0;
    /* the stage the scene stands in, lit from where the key is */
    background: radial-gradient(120% 96% at 26% 8%, #FBF3E4 0%, #F0E0C7 62%, #E6D2B2 100%);
    border: 1px solid rgba(93, 82, 75, .14);
    border-radius: var(--r-m);
    overflow: hidden;
    transition: box-shadow .6s var(--e), border-color .6s var(--e);
}

.ex__i:hover .ex__art {
    border-color: var(--acc-line);
    box-shadow: inset 0 1px 0 rgba(255, 252, 243, .7);
}

.ex__plate {
    display: block;
    width: 100%;
    height: auto;
    transition: transform .8s var(--e);
}

.ex__i:hover .ex__plate {
    transform: scale(1.022);
}

/* ── the scenes, running ──────────────────────────────────────────────────
   Each scene moves the way its own card reads, and no two move alike:

     01  a climb   — the marker hops three steps, each taller than the last,
                     and stops at the mast. An idea getting shipped.
     02  an orbit  — the assistant goes round the desk rather than sitting in
                     front of it: beside how someone already works.
     03  a flow    — work travels the line, is routed, and one item branches
                     out to the desk a person sits at.
     04  a convergence — three readings arrive from three directions and the
                     bar they land in grows.

   Every path is measured off the geometry it moves through: the keyframe
   offsets below are printed by the same script that projects the scene, so
   the marker lands on the step rather than near it.

   The static geometry builds itself once on reveal; only the moving parts
   loop, and nothing loops off-screen.
   ───────────────────────────────────────────────────────────────────────── */

.fm-js [data-reveal] .rs-step,
.fm-js [data-reveal] .rs-tier,
.fm-js [data-reveal] .rs-dev,
.fm-js [data-reveal] .rs-tray {
    opacity: 0;
    transform: translateY(16px);
}

.fm-js [data-reveal].on .rs-step,
.fm-js [data-reveal].on .rs-tier,
.fm-js [data-reveal].on .rs-dev,
.fm-js [data-reveal].on .rs-tray {
    opacity: 1;
    transform: none;
    transition: opacity .75s var(--e), transform .85s var(--e);
}

.fm-js [data-reveal].on .rs-step--1,
.fm-js [data-reveal].on .rs-tier--1,
.fm-js [data-reveal].on .rs-dev--1,
.fm-js [data-reveal].on .rs-tray--1 {
    transition-delay: .1s;
}

.fm-js [data-reveal].on .rs-step--2,
.fm-js [data-reveal].on .rs-tier--2,
.fm-js [data-reveal].on .rs-dev--2 {
    transition-delay: .2s;
}

.fm-js [data-reveal].on .rs-tier--3 {
    transition-delay: .3s;
}

/* the glow under whatever is live */
.rs-halo {
    transform-box: fill-box;
    transform-origin: center;
}

.fm-js [data-reveal].on .ex__plate--1 .rs-halo,
.fm-js [data-reveal].on .ex__plate--3 .rs-halo,
.fm-js [data-reveal].on .ex__plate--4 .rs-halo {
    animation: rsHalo 3.6s var(--e-io) infinite;
}

@keyframes rsHalo {

    0%,
    100% {
        opacity: .55;
        transform: scale(.92);
    }

    50% {
        opacity: 1;
        transform: scale(1.06);
    }
}

/* opacity only, so it can run alongside a keyframe that owns the transform */
@keyframes rsGlow {

    0%,
    100% {
        opacity: .5;
    }

    50% {
        opacity: 1;
    }
}

/* ── 01 · the climb ──────────────────────────────────────────────────────── */

.fm-js [data-reveal].on .rs-ball {
    animation: rsClimb 7.6s var(--e-io) 1s infinite;
}

/* ── 02 · the orbit ──────────────────────────────────────────────────────── */

.fm-js [data-reveal].on .rs-orb {
    animation: rsOrbit 15s linear 1s infinite;
}

.fm-js [data-reveal].on .ex__plate--2 .rs-halo {
    animation: rsOrbitHalo 15s linear 1s infinite, rsGlow 3.4s var(--e-io) infinite;
}

.fm-js [data-reveal].on .ex__plate--2 .rs-bar {
    animation: rsPip 15s var(--e-io) 1s infinite;
}

.fm-js [data-reveal].on .ex__plate--2 .rs-bar--1 {
    animation-delay: 1.6s;
}

.fm-js [data-reveal].on .ex__plate--2 .rs-bar--2 {
    animation-delay: 2.2s;
}

.fm-js [data-reveal].on .ex__plate--2 .rs-bar--3 {
    animation-delay: 2.8s;
}

.fm-js [data-reveal].on .ex__plate--2 .rs-bar--4 {
    animation-delay: 3.4s;
}

@keyframes rsPip {

    0%,
    100% {
        opacity: .35;
    }

    8%,
    18% {
        opacity: .95;
    }

    30% {
        opacity: .5;
    }
}

/* ── 03 · the flow ───────────────────────────────────────────────────────── */

/* four items on one 6.4s cycle, a quarter of it apart: the belt is never
   empty and nothing ever jumps back to the start in view */
.fm-js [data-reveal].on .ex__plate--3 .rs-q {
    animation: rsBelt 6.4s linear infinite;
}

.fm-js [data-reveal].on .ex__plate--3 .rs-q--1 {
    animation-delay: -4.8s;
}

.fm-js [data-reveal].on .ex__plate--3 .rs-q--2 {
    animation-delay: -3.2s;
}

.fm-js [data-reveal].on .ex__plate--3 .rs-q--3 {
    animation-delay: -1.6s;
}

/* all three outputs carry something, so the picture finishes */
.fm-js [data-reveal].on .ex__plate--3 .rs-out--0 {
    animation: rsOut0 6.4s var(--e-io) 1.1s infinite;
}

.fm-js [data-reveal].on .ex__plate--3 .rs-out--1 {
    animation: rsOut1 6.4s var(--e-io) 3.2s infinite;
}

.fm-js [data-reveal].on .ex__plate--3 .rs-out--2 {
    animation: rsOut2 6.4s var(--e-io) 5.1s infinite;
}

.fm-js [data-reveal].on .ex__plate--3 .rs-lane {
    stroke-dasharray: 5 5;
    animation: rsLane 1.9s linear infinite;
}

.fm-js [data-reveal].on .ex__plate--3 .rs-lane--2 {
    animation-duration: 1.4s;
}

@keyframes rsLane {
    to {
        stroke-dashoffset: -20;
    }
}

/* ── 04 · the convergence ────────────────────────────────────────────────── */

.fm-js [data-reveal].on .ex__plate--4 .rs-tok--0 {
    animation: rsConverge0 5.6s var(--e-io) 1.2s infinite;
}

.fm-js [data-reveal].on .ex__plate--4 .rs-tok--1 {
    animation: rsConverge1 5.6s var(--e-io) 1.9s infinite;
}

.fm-js [data-reveal].on .ex__plate--4 .rs-tok--2 {
    animation: rsConverge2 5.6s var(--e-io) 2.5s infinite;
}

/* the bar the readings land in. A vertical face projects world z straight
   onto screen y, so a plain scaleY is a true growth in the drawing's own
   space rather than a squash of it. */
.rs-fill {
    transform-box: fill-box;
    transform-origin: bottom;
}

.fm-js [data-reveal].on .rs-fill {
    animation: rsFill 5.6s var(--e-io) 1.2s infinite;
}

@keyframes rsFill {

    0%,
    46% {
        transform: scaleY(.28);
        opacity: .5;
    }

    64%,
    88% {
        transform: scaleY(1);
        opacity: .95;
    }

    100% {
        transform: scaleY(.28);
        opacity: .5;
    }
}

.fm-js [data-reveal].on .ex__plate--4 .rs-lane {
    stroke-dasharray: 4 4;
    animation: rsLane 2.2s linear infinite;
}

@keyframes flSense {
    0% {
        transform: translate(0.00px, 0.00px);
    }

    34% {
        transform: translate(0.00px, 20.00px);
    }

    58% {
        transform: translate(0.00px, 20.00px);
    }

    92% {
        transform: translate(0.00px, 0.00px);
    }

    100% {
        transform: translate(0.00px, 0.00px);
    }
}

@keyframes flCarry {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
    }

    12% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
    }

    44% {
        transform: translate(20.78px, 2.00px);
        opacity: 1;
    }

    76% {
        transform: translate(48.50px, 40.00px);
        opacity: 1;
    }

    86% {
        transform: translate(48.50px, 40.00px);
        opacity: 0;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
    }
}

@keyframes rsClimb {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }

    5% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
        animation-timing-function: linear;
    }

    11% {
        transform: translate(0.00px, 0.00px);
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    18% {
        transform: translate(14.64px, -14.17px);
        animation-timing-function: cubic-bezier(.58,0,.8,.34);
    }

    25% {
        transform: translate(30.40px, 7.15px);
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    28% {
        transform: translate(30.40px, 2.73px);
        animation-timing-function: cubic-bezier(.58,0,.8,.34);
    }

    31% {
        transform: translate(30.40px, 7.15px);
        animation-timing-function: linear;
    }

    38% {
        transform: translate(30.40px, 7.15px);
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    45% {
        transform: translate(43.91px, -7.67px);
        animation-timing-function: cubic-bezier(.58,0,.8,.34);
    }

    52% {
        transform: translate(57.42px, 12.35px);
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    55% {
        transform: translate(57.42px, 7.93px);
        animation-timing-function: cubic-bezier(.58,0,.8,.34);
    }

    58% {
        transform: translate(57.42px, 12.35px);
        animation-timing-function: linear;
    }

    65% {
        transform: translate(57.42px, 12.35px);
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    72% {
        transform: translate(70.93px, -2.47px);
        animation-timing-function: cubic-bezier(.58,0,.8,.34);
    }

    79% {
        transform: translate(84.44px, 17.55px);
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    82% {
        transform: translate(84.44px, 13.13px);
        animation-timing-function: cubic-bezier(.58,0,.8,.34);
    }

    85% {
        transform: translate(84.44px, 17.55px);
        opacity: 1;
        animation-timing-function: linear;
    }

    94% {
        transform: translate(84.44px, 17.55px);
        opacity: 1;
        animation-timing-function: linear;
    }

    98% {
        transform: translate(84.44px, 17.55px);
        opacity: 0;
        animation-timing-function: linear;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }
}

@keyframes rsOrbit {
    0.0% {
        transform: translate(0.00px, 0.00px);
        animation-timing-function: linear;
    }

    6.67% {
        transform: translate(-28.62px, 10.73px);
        animation-timing-function: linear;
    }

    13.33% {
        transform: translate(-62.32px, 13.81px);
        animation-timing-function: linear;
    }

    20.0% {
        transform: translate(-95.28px, 8.71px);
        animation-timing-function: linear;
    }

    26.67% {
        transform: translate(-121.79px, -3.69px);
        animation-timing-function: linear;
    }

    33.33% {
        transform: translate(-137.29px, -21.24px);
        animation-timing-function: linear;
    }

    40.0% {
        transform: translate(-139.07px, -40.91px);
        animation-timing-function: linear;
    }

    46.67% {
        transform: translate(-126.84px, -59.30px);
        animation-timing-function: linear;
    }

    53.33% {
        transform: translate(-102.72px, -73.23px);
        animation-timing-function: linear;
    }

    60.0% {
        transform: translate(-70.86px, -80.29px);
        animation-timing-function: linear;
    }

    66.67% {
        transform: translate(-36.79px, -79.26px);
        animation-timing-function: linear;
    }

    73.33% {
        transform: translate(-6.38px, -70.32px);
        animation-timing-function: linear;
    }

    80.0% {
        transform: translate(15.09px, -55.01px);
        animation-timing-function: linear;
    }

    86.67% {
        transform: translate(23.92px, -35.98px);
        animation-timing-function: linear;
    }

    93.33% {
        transform: translate(18.58px, -16.52px);
        animation-timing-function: linear;
    }

    100.0% {
        transform: translate(0.00px, -0.00px);
        animation-timing-function: linear;
    }
}

@keyframes rsOrbitHalo {
    0.0% {
        transform: translate(0.00px, 0.00px);
        animation-timing-function: linear;
    }

    6.67% {
        transform: translate(-28.62px, 10.73px);
        animation-timing-function: linear;
    }

    13.33% {
        transform: translate(-62.32px, 13.81px);
        animation-timing-function: linear;
    }

    20.0% {
        transform: translate(-95.28px, 8.71px);
        animation-timing-function: linear;
    }

    26.67% {
        transform: translate(-121.79px, -3.69px);
        animation-timing-function: linear;
    }

    33.33% {
        transform: translate(-137.29px, -21.24px);
        animation-timing-function: linear;
    }

    40.0% {
        transform: translate(-139.07px, -40.91px);
        animation-timing-function: linear;
    }

    46.67% {
        transform: translate(-126.84px, -59.30px);
        animation-timing-function: linear;
    }

    53.33% {
        transform: translate(-102.72px, -73.23px);
        animation-timing-function: linear;
    }

    60.0% {
        transform: translate(-70.86px, -80.29px);
        animation-timing-function: linear;
    }

    66.67% {
        transform: translate(-36.79px, -79.26px);
        animation-timing-function: linear;
    }

    73.33% {
        transform: translate(-6.38px, -70.32px);
        animation-timing-function: linear;
    }

    80.0% {
        transform: translate(15.09px, -55.01px);
        animation-timing-function: linear;
    }

    86.67% {
        transform: translate(23.92px, -35.98px);
        animation-timing-function: linear;
    }

    93.33% {
        transform: translate(18.58px, -16.52px);
        animation-timing-function: linear;
    }

    100.0% {
        transform: translate(0.00px, -0.00px);
        animation-timing-function: linear;
    }
}

@keyframes rsBelt {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }

    7% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
        animation-timing-function: linear;
    }

    62% {
        transform: translate(55.18px, 31.86px);
        opacity: 1;
        animation-timing-function: linear;
    }

    70% {
        transform: translate(55.18px, 31.86px);
        opacity: 0;
        animation-timing-function: linear;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }
}

@keyframes rsOut0 {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }

    10% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
        animation-timing-function: linear;
    }

    54% {
        transform: translate(11.24px, 6.49px);
        opacity: 1;
        animation-timing-function: linear;
    }

    84% {
        transform: translate(23.50px, 12.39px);
        opacity: 1;
        animation-timing-function: linear;
    }

    93% {
        transform: translate(23.50px, 12.39px);
        opacity: 0;
        animation-timing-function: linear;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }
}

@keyframes rsOut1 {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }

    10% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
        animation-timing-function: linear;
    }

    54% {
        transform: translate(11.24px, 6.49px);
        opacity: 1;
        animation-timing-function: linear;
    }

    84% {
        transform: translate(23.50px, 12.39px);
        opacity: 1;
        animation-timing-function: linear;
    }

    93% {
        transform: translate(23.50px, 12.39px);
        opacity: 0;
        animation-timing-function: linear;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }
}

@keyframes rsOut2 {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }

    10% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
        animation-timing-function: linear;
    }

    54% {
        transform: translate(11.24px, 6.49px);
        opacity: 1;
        animation-timing-function: linear;
    }

    84% {
        transform: translate(25.55px, 7.67px);
        opacity: 1;
        animation-timing-function: linear;
    }

    93% {
        transform: translate(25.55px, 7.67px);
        opacity: 0;
        animation-timing-function: linear;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }
}

@keyframes rsConverge0 {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }

    10% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    26% {
        transform: translate(0.00px, -11.70px);
        opacity: 1;
        animation-timing-function: linear;
    }

    68% {
        transform: translate(67.55px, 4.29px);
        opacity: 1;
        animation-timing-function: linear;
    }

    78% {
        transform: translate(67.55px, 4.29px);
        opacity: 0;
        animation-timing-function: linear;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }
}

@keyframes rsConverge1 {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }

    10% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    26% {
        transform: translate(0.00px, -11.70px);
        opacity: 1;
        animation-timing-function: linear;
    }

    68% {
        transform: translate(54.04px, -32.11px);
        opacity: 1;
        animation-timing-function: linear;
    }

    78% {
        transform: translate(54.04px, -32.11px);
        opacity: 0;
        animation-timing-function: linear;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }
}

@keyframes rsConverge2 {
    0% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }

    10% {
        transform: translate(0.00px, 0.00px);
        opacity: 1;
        animation-timing-function: cubic-bezier(.19,.72,.4,1);
    }

    26% {
        transform: translate(0.00px, -11.70px);
        opacity: 1;
        animation-timing-function: linear;
    }

    68% {
        transform: translate(-11.26px, -41.21px);
        opacity: 1;
        animation-timing-function: linear;
    }

    78% {
        transform: translate(-11.26px, -41.21px);
        opacity: 0;
        animation-timing-function: linear;
    }

    100% {
        transform: translate(0.00px, 0.00px);
        opacity: 0;
        animation-timing-function: linear;
    }
}

/* ── the chain strip ─────────────────────────────────────────────────────
   Pinned to the foot of the card: the four descriptions and scenes are
   different heights, and a strip that floats wherever the copy happens to
   end reads as four unrelated cards rather than one set. */

.ex__chain {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem 1.8rem;
    margin: clamp(1.8rem, 2.2vw, 2.2rem) 0 0;
    margin-top: auto;
    padding-top: clamp(1.4rem, 1.8vw, 1.8rem);
    border-top: 1px solid var(--rule);
}

.ex__chain span {
    position: relative;
    padding-left: 1.4rem;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ink-4);
}

.ex__chain span::before {
    content: "";
    position: absolute;
    left: 0;
    top: .42em;
    width: 6px;
    height: 6px;
    border: 1px solid var(--rule-2);
    border-radius: 50%;
}

.ex__chain span.is-in {
    color: var(--acc-2);
}

.ex__chain span.is-in::before {
    background: var(--acc-hot);
    border-color: var(--acc-hot);
}

/* ── narrow ──────────────────────────────────────────────────────────────── */

@media (max-width: 1000px) {

    .ex__i--w,
    .ex__i--n {
        grid-column: span 6;
    }
}

@media (max-width: 680px) {

    .ex__i--w,
    .ex__i--n {
        grid-column: span 12;
    }
}

@media (prefers-reduced-motion: reduce) {

    .ex__card,
    .ex__art,
    .ex__plate {
        transition: none;
    }

    /* a scene that has to move to make its point is not worth making someone
       ill over: the geometry stays, the motion stops, and every moving part
       is parked where it means something rather than where it started */
    .fm-js [data-reveal] .rs-step,
    .fm-js [data-reveal] .rs-tier,
    .fm-js [data-reveal] .rs-dev,
    .fm-js [data-reveal] .rs-tray {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .fm-js [data-reveal].on .rs-ball,
    .fm-js [data-reveal].on .rs-orb,
    .fm-js [data-reveal].on .rs-halo,
    .fm-js [data-reveal].on .ex__plate--2 .rs-halo,
    .fm-js [data-reveal].on .ex__plate--2 .rs-bar,
    .fm-js [data-reveal].on .ex__plate--3 .rs-q,
    .fm-js [data-reveal].on .ex__plate--3 .rs-out--0,
    .fm-js [data-reveal].on .ex__plate--3 .rs-out--1,
    .fm-js [data-reveal].on .ex__plate--3 .rs-out--2,
    .fm-js [data-reveal].on .ex__plate--3 .rs-lane,
    .fm-js [data-reveal].on .ex__plate--4 .rs-tok--0,
    .fm-js [data-reveal].on .ex__plate--4 .rs-tok--1,
    .fm-js [data-reveal].on .ex__plate--4 .rs-tok--2,
    .fm-js [data-reveal].on .ex__plate--4 .rs-lane,
    .fm-js [data-reveal].on .rs-fill {
        animation: none;
    }

    /* the climb ends at the top step, not at the bottom of it */
    .fm-js [data-reveal].on .rs-ball {
        transform: translate(84.44px, 17.55px);
    }

    .fm-js [data-reveal].on .rs-fill {
        transform: scaleY(1);
        opacity: .8;
    }

    .fm-js [data-reveal].on .ex__plate--4 .rs-tok--0,
    .fm-js [data-reveal].on .ex__plate--4 .rs-tok--1,
    .fm-js [data-reveal].on .ex__plate--4 .rs-tok--2 {
        opacity: 1;
    }
}

/* the way through to the full portfolio, at the foot of the impact work */
.wk-all {
    margin: clamp(3rem, 4vw, 4.4rem) 0 0;
    padding-top: clamp(2.2rem, 3vw, 2.8rem);
    border-top: 1px solid var(--rule-warm);
}

.wk-all a {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .9rem;
    padding-bottom: .5rem;
    font-family: var(--serif);
    font-size: clamp(1.9rem, 1.66vw, 1.99rem);
    letter-spacing: -.02em;
    color: var(--ink);
    text-decoration: none;
}

.wk-all svg {
    width: 1.9rem;
    height: 1.9rem;
    flex: none;
    stroke-width: 1.5;
    color: var(--acc);
    transition: transform .4s var(--e);
}

.wk-all a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: var(--rule-2);
    transform-origin: left;
    transition: transform .5s var(--e), background-color .4s var(--e);
}

.wk-all a:hover::after {
    background: var(--acc);
    transform: scaleY(2);
}

.wk-all a:hover svg {
    transform: translateX(5px);
}

@media (prefers-reduced-motion: reduce) {

    .wk-all a::after,
    .wk-all svg {
        transition: none;
    }
}

/* the two links a site collecting names and files is obliged to carry */
.ft-legal {
    display: flex;
    gap: 1.6rem;
    margin: 0;
}

.ft-legal a {
    color: var(--ink-4);
    text-decoration: none;
    transition: color .35s var(--e);
}

.ft-legal a:hover {
    color: var(--acc-2);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* ══════════════════════════════════════════════════════════════════════════
   DOCUMENT PAGES
   The privacy notice, the terms and the 404 share one shell so they cost a
   single cached stylesheet between them and cannot drift from the site the
   way the waitlist page did. Everything below is layout — the type, colour
   and rules all come from the tokens above.
   ══════════════════════════════════════════════════════════════════════════ */

.dp {
    background: var(--g-cream, #FEF9ED);
    color: var(--ink-2);
    font-family: var(--serif);
    margin: 0;
    -webkit-font-smoothing: antialiased;
}

.dp-head,
.dp-foot {
    max-width: var(--max);
    margin: 0 auto;
    padding: clamp(2rem, 3vw, 3rem) var(--gut);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1.2rem 2.4rem;
}

.dp-foot {
    border-top: 1px solid var(--rule);
    padding-bottom: clamp(3rem, 4vw, 4rem);
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-4);
}

.dp-foot a {
    color: var(--acc-2);
    text-decoration: none;
}

.dp-foot a:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.dp-brand {
    display: inline-flex;
    align-items: center;
    gap: 1rem;
    min-height: 44px;
    text-decoration: none;
}

/* the file is a 1001×156 wordmark that already reads "TECHSENTINALS", so it
   is sized by width and carries the name on its own — a 3rem box turned it
   into a 5px-tall smudge with the name repeated in a span beside it */
.dp-brand img {
    width: clamp(13rem, 15vw, 17rem);
    height: auto;
}

.dp-back {
    display: inline-flex;
    align-items: center;
    gap: .7rem;
    min-height: 44px;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--acc-2);
    text-decoration: none;
}

.dp-back svg {
    width: 1.4rem;
    height: 1.4rem;
    stroke-width: 1.6;
    transition: transform .4s var(--e);
}

.dp-back:hover svg {
    transform: translateX(-3px);
}

/* ── the sheet ───────────────────────────────────────────────────────────── */

.dp-main {
    max-width: var(--max);
    margin: 0 auto;
    padding: clamp(2rem, 4vw, 4rem) var(--gut) clamp(4rem, 6vw, 7rem);
}

.dp-title {
    margin: 0;
    max-width: 20ch;
    font-family: var(--serif);
    font-size: clamp(3.4rem, 4.48vw, 5.81rem);
    font-weight: 450;
    line-height: 1.02;
    letter-spacing: -.035em;
    color: var(--ink);
    text-wrap: balance;
}

.dp-title em {
    font-style: italic;
    color: var(--acc-2);
}

.dp-stamp {
    margin: clamp(1.8rem, 2.4vw, 2.4rem) 0 0;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--ink-4);
}

.dp-lede {
    margin: clamp(2rem, 2.6vw, 2.6rem) 0 0;
    max-width: 62ch;
    font-size: var(--t-lead);
    line-height: 1.55;
    color: var(--ink-3);
    text-wrap: pretty;
}

.dp-body {
    max-width: 68ch;
    margin-top: clamp(3.4rem, 5vw, 5.4rem);
}

/* On privacy/terms this is the whole page, section after section, and a
   narrow measure reads as an intentional document rhythm. On the team page
   it is one short paragraph tacked on after a wide two-column roster, and
   the same 68ch cap left it a slim column of text stranded on the left with
   the other half of the page empty beside it -- cramped rather than airy.
   Widened here, and the top rule/spacing loosened, so it reads as a distinct
   closing block rather than a leftover fragment of a different page type. */
.tm-list+.dp-body {
    max-width: none;
    margin-top: clamp(4.4rem, 6vw, 6.6rem);
}

.tm-list+.dp-body section {
    padding-top: clamp(3.4rem, 4.4vw, 4.6rem);
}

/* Address, email, phone, socials -- each its own row rather than folded into
   one sentence. The single-paragraph version read as a wall of text and,
   worse, ran the address, the email and the phone number together with no
   visual break between them at all on a phone. Same label/value language as
   .tm__facts above, so the page reads as one system rather than two. */
.tm-find {
    margin: 0;
    max-width: 62rem;
    display: grid;
    gap: 1.8rem;
}

.tm-find__row {
    display: grid;
    grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
    gap: .4rem clamp(1.4rem, 2vw, 2.4rem);
    padding-top: 1.8rem;
    border-top: 1px solid var(--rule);
}

.tm-find__row:first-child {
    padding-top: 0;
    border-top: 0;
}

.tm-find dt {
    margin: 0;
    font-family: var(--mono);
    font-size: var(--t-sm);
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.tm-find dd {
    margin: 0;
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-2);
}

.tm-find dd a {
    color: var(--acc-2);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.tm-find dd a+a {
    margin-left: 1.6rem;
}

@media screen and (max-width: 560px) {
    .tm-find__row {
        grid-template-columns: minmax(0, 1fr);
        gap: .5rem;
    }
}

.dp-body section {
    padding-top: clamp(2.6rem, 3.4vw, 3.4rem);
    border-top: 1px solid var(--rule);
}

.dp-body section+section {
    margin-top: clamp(2.6rem, 3.4vw, 3.4rem);
}

.dp-body h2 {
    margin: 0 0 1.4rem;
    font-family: var(--serif);
    font-size: clamp(2.2rem, 2.16vw, 2.66rem);
    font-weight: 450;
    line-height: 1.1;
    letter-spacing: -.03em;
    color: var(--ink);
}

.dp-body h3 {
    margin: 2.4rem 0 .8rem;
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--acc-2);
}

.dp-body p {
    margin: 0 0 1.4rem;
    font-size: var(--t-body);
    line-height: 1.65;
    color: var(--ink-3);
    text-wrap: pretty;
}

.dp-body p:last-child {
    margin-bottom: 0;
}

.dp-body ul {
    list-style: none;
    margin: 0 0 1.4rem;
    padding: 0;
}

.dp-body ul li {
    position: relative;
    padding: .5em 0 .5em 2.2rem;
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-3);
}

.dp-body ul li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 1.1em;
    width: 1.2rem;
    height: 1px;
    background: var(--acc-line);
}

.dp-body a {
    color: var(--acc-2);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.dp-body b {
    font-weight: 500;
    color: var(--ink);
}

/* ── the 404's ways on ───────────────────────────────────────────────────── */

.dp-ways {
    display: flex;
    flex-wrap: wrap;
    gap: 1.4rem 2.4rem;
    margin-top: clamp(3rem, 4vw, 4rem);
}

.dp-go {
    display: inline-flex;
    align-items: center;
    gap: 1rem;
    min-height: 44px;
    padding: 1.2rem 2.4rem;
    background: var(--ink);
    color: var(--p);
    border-radius: var(--r-x);
    font-size: var(--t-body);
    text-decoration: none;
    transition: background-color .4s var(--e), transform .4s var(--e);
}

.dp-go:hover {
    background: #3B2117;
    transform: translateY(-2px);
}

.dp-go--quiet {
    background: none;
    color: var(--acc-2);
    padding-left: 0;
    padding-right: 0;
}

.dp-go--quiet:hover {
    background: none;
    text-decoration: underline;
    text-underline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {

    .dp-back svg,
    .dp-go {
        transition: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   TAP TARGETS
   The text links on this page are underline-draw marks, so their hit area is
   the height of the text — 26 to 30px at 375px wide, against the 44px a thumb
   actually needs. On a coarse pointer they get the height without gaining a
   box: the padding is vertical only and the underline stays pinned to the
   text, so nothing about them looks different on a desktop or a phone.
   ══════════════════════════════════════════════════════════════════════════ */

@media (pointer: coarse) {

    .fl-btn,
    .wk-item__go,
    .cw-p__link,
    .st-map,
    .ft-mark,
    .wk-all a,
    .cs-all a,
    .ft-col a,
    .ft-out a,
    .ft-legal a,
    .ft-top,
    .pw-go {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }

    /* an inline link inside a sentence is exempt: giving it a 44px box would
       space out the paragraph it lives in. These are all standalone marks. */

    /* the hamburger's own box is 18×8; the thumb needs the whole corner */
    [menu-button] {
        min-width: 44px;
        min-height: 44px;
    }

    /* the wordmark is the way home from anywhere on the page */
    header a[aria-label="Home"] {
        min-height: 44px;
    }

    /* a tab in the sector strip and a phase key on the board are both
       pointer targets before they are anything else */
    .sc-spine__btn,
    .bd-key {
        min-height: 44px;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   THE OPEN CURSOR
   Over a piece of work the pointer becomes the invitation: a glass pill with
   the word on it, lit from behind in gold. Real glass rather than a flat
   chip — a blur of whatever is under it, a bright inner top edge and a dark
   inner bottom one, which is what makes a surface read as having thickness.
   It follows on a spring rather than snapping, and the native cursor is only
   hidden where the pill has actually taken over.
   ══════════════════════════════════════════════════════════════════════════ */

.op-cursor {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 60;
    display: grid;
    place-items: center;
    padding: 1.05em 1.9em;
    border-radius: 100px;
    pointer-events: none;
    opacity: 0;
    transform: translate3d(var(--ox, -100px), var(--oy, -100px), 0) translate(-50%, -50%) scale(.6);
    transition: opacity .3s var(--e), transform .45s var(--e);
    will-change: transform;

    font-family: var(--mono);
    font-size: 1.15rem;
    font-weight: 500;
    letter-spacing: .2em;
    text-transform: uppercase;
    white-space: nowrap;
    color: #FFF6E4;

    background: linear-gradient(150deg,
            rgba(255, 236, 199, .34) 0%,
            rgba(196, 138, 74, .28) 46%,
            rgba(120, 74, 30, .32) 100%);
    -webkit-backdrop-filter: blur(9px) saturate(150%);
    backdrop-filter: blur(9px) saturate(150%);
    box-shadow:
        inset 0 1px 0 rgba(255, 249, 236, .55),
        inset 0 -1px 0 rgba(70, 42, 18, .35),
        0 0 0 1px rgba(255, 240, 214, .22),
        0 10px 30px -8px rgba(60, 36, 14, .5),
        0 0 34px -6px rgba(214, 158, 84, .55);
    text-shadow: 0 1px 2px rgba(50, 28, 10, .5);
}

.op-cursor.is-on {
    opacity: 1;
    transform: translate3d(var(--ox, -100px), var(--oy, -100px), 0) translate(-50%, -50%) scale(1);
}

/* the shine crossing the glass */
.op-cursor::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(100deg,
            rgba(255, 250, 236, 0) 34%,
            rgba(255, 250, 236, .5) 48%,
            rgba(255, 250, 236, 0) 62%);
    background-size: 260% 100%;
    background-position: 130% 0;
}

.op-cursor.is-on::after {
    animation: opShine 2.8s linear infinite;
}

@keyframes opShine {
    to {
        background-position: -130% 0;
    }
}

/* only where the pill is standing in for it */
.op-live .cs__card,
.op-live .fl__screen,
.op-live [data-open-cursor] {
    cursor: none;
}

@media (prefers-reduced-motion: reduce) {

    .op-cursor {
        transition: opacity .2s linear;
    }

    .op-cursor.is-on::after {
        animation: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   06 · CUSTOM BUILDS — the cases
   Real client screens at the size they were designed to be looked at, then
   the numbers, then who the work was for. Earlier versions of this section
   were a tablist, a ticker, a typed sentence and six abstract plates — every
   one of them a description of the work rather than the work. The portfolio
   page still holds all fifteen; this shows six and links there.
   ══════════════════════════════════════════════════════════════════════════ */

.cs {
    list-style: none;
    margin: clamp(3.4rem, 5vw, 5.4rem) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(3rem, 4.5vw, 5.6rem) clamp(2.4rem, 3.5vw, 4rem);
}

.cs__i {
    min-width: 0;
}

/* the second of each pair drops, so the eye travels diagonally rather than
   scanning a flat two-by-three of boxes */
.cs__i:nth-child(even) {
    margin-top: clamp(2rem, 4vw, 5rem);
}

.cs__card {
    display: block;
    text-decoration: none;
    color: inherit;
}

.cs__card:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 6px;
    border-radius: var(--r-m);
}

/* ── the shot, and the three of them ──────────────────────────────────────
   Pointing at a case walks its screens: three stacked in the same frame,
   crossfading on a nine-second loop so each one holds long enough to be
   looked at. It runs on hover only — no timers, nothing cycling on a page
   nobody is pointing at — and the first frame is the one that shows when
   the pointer is elsewhere, so the card at rest is never mid-fade.
   ───────────────────────────────────────────────────────────────────────── */

.cs__shot {
    position: relative;
    margin: 0;
    overflow: hidden;
    background: var(--p-4);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-l);
    aspect-ratio: 16 / 9;
    transition: transform .6s var(--e), box-shadow .6s var(--e), border-color .6s var(--e);
}

.cs__shot img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: transform .9s var(--e), opacity .7s var(--e);
}

.cs__shot img:first-child {
    opacity: 1;
}

/* one nine-second cycle, each frame lit for a third of it and handed over
   with a fade rather than a cut */
.cs__card:hover .cs__shot img {
    animation: csWalk 9s linear infinite;
}

.cs__card:hover .cs__shot img:nth-child(2) {
    animation-delay: -6s;
}

.cs__card:hover .cs__shot img:nth-child(3) {
    animation-delay: -3s;
}

@keyframes csWalk {

    0%,
    26% {
        opacity: 1;
    }

    33%,
    93% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

/* the counter, so it reads as a set rather than a glitch */
.cs__shot::after {
    content: "";
    position: absolute;
    right: 1.4rem;
    bottom: 1.4rem;
    z-index: 2;
    width: 3.6rem;
    height: 2px;
    border-radius: 2px;
    background: rgba(255, 250, 240, .45);
    opacity: 0;
    transform-origin: left;
    transition: opacity .4s var(--e);
}

.cs__card:hover .cs__shot::after {
    opacity: 1;
    animation: csTick 3s linear infinite;
}

@keyframes csTick {
    from {
        transform: scaleX(.06);
    }

    to {
        transform: scaleX(1);
    }
}

.cs__card:hover .cs__shot {
    transform: translateY(-6px);
    border-color: var(--acc-line);
    box-shadow: var(--sh-3);
}

/* the screen pushes in a touch, so the plate reads as a window onto it */
.cs__card:hover .cs__shot img {
    transform: scale(1.04);
}

.cs__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem 1.6rem;
    margin: clamp(1.6rem, 2.2vw, 2rem) 0 0;
}

.cs__name {
    font-family: var(--serif);
    font-size: clamp(2.2rem, 2.07vw, 2.57rem);
    font-weight: 450;
    line-height: 1.05;
    letter-spacing: -.03em;
    color: var(--ink);
}

/* the one fact that separates these builds from each other, set as a mark
   rather than a filled pill */
.cs__chip {
    flex: none;
    padding: .5em .9em;
    border: 1px solid var(--acc-line);
    border-radius: var(--r-x);
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--acc-2);
    transition: background-color .5s var(--e), color .5s var(--e);
}

.cs__card:hover .cs__chip {
    background: rgba(166, 73, 26, .08);
    border-color: rgba(166, 73, 26, .44);
    color: var(--acc-hot);
}

.cs__line {
    margin: 1rem 0 0;
    max-width: 46ch;
    font-size: var(--t-body-s);
    line-height: 1.55;
    color: var(--ink-3);
    text-wrap: pretty;
}

/* ── the way through to all fifteen ──────────────────────────────────────── */

.cs-all {
    margin: clamp(3.4rem, 5vw, 5rem) 0 0;
}

.cs-all a {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .9rem;
    padding-bottom: .5rem;
    font-family: var(--serif);
    font-size: clamp(1.9rem, 1.66vw, 1.99rem);
    letter-spacing: -.02em;
    color: var(--ink);
    text-decoration: none;
}

.cs-all svg {
    width: 1.9rem;
    height: 1.9rem;
    flex: none;
    stroke-width: 1.5;
    color: var(--acc);
    transition: transform .4s var(--e);
}

.cs-all a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: var(--rule-2);
    transform-origin: left;
    transition: transform .5s var(--e), background-color .4s var(--e);
}

.cs-all a:hover::after {
    background: var(--acc);
    transform: scaleY(2);
}

.cs-all a:hover svg {
    transform: translateX(5px);
}

/* ══════════════════════════════════════════════════════════════════════════
   06 · the tally
   Four figures on their own rules. They count up once, when the block is
   reached — the same counter the rest of the page uses.
   ══════════════════════════════════════════════════════════════════════════ */

.tl {
    margin-top: clamp(5rem, 8vw, 9rem);
}

.tl__k {
    margin: 0 0 clamp(2.4rem, 3.4vw, 3.4rem);
    font-family: var(--mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--ink-4);
}

.tl__grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(2rem, 3vw, 3.4rem);
    margin: 0;
}

.tl__cell {
    min-width: 0;
    padding-top: clamp(1.6rem, 2.2vw, 2.2rem);
    border-top: 1px solid var(--rule-warm);
}

.tl__cell dt {
    display: flex;
    align-items: baseline;
    font-family: var(--serif);
    font-size: clamp(4rem, 4.65vw, 5.98rem);
    font-weight: 450;
    line-height: .88;
    letter-spacing: -.045em;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.tl__cell dt i {
    font-style: normal;
    font-size: .42em;
    color: var(--acc-hot);
    margin-left: .06em;
}

.tl__cell dd {
    margin: clamp(1.2rem, 1.6vw, 1.6rem) 0 0;
    max-width: 22ch;
    font-size: var(--t-body-s);
    line-height: 1.5;
    color: var(--ink-3);
    text-wrap: pretty;
}

/* ── narrow ──────────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
    .tl__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 680px) {
    .cs {
        grid-template-columns: 1fr;
    }

    .cs__i:nth-child(even) {
        margin-top: 0;
    }
}

@media (max-width: 460px) {
    .tl__grid {
        grid-template-columns: 1fr;
    }
}

@media (prefers-reduced-motion: reduce) {

    .cs__shot,
    .cs__shot img,
    .cs__shot::after,
    .cs__chip,
    .cs-all a::after,
    .cs-all svg {
        transition: none;
    }

    .cs__card:hover .cs__shot img {
        transform: none;
    }

    /* a card that flicks through three screens on its own is exactly what
       reduced motion is asking not to happen */
    .cs__card:hover .cs__shot img,
    .cs__card:hover .cs__shot::after {
        animation: none;
    }

    .cs__card:hover .cs__shot::after {
        opacity: 0;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   FORM SUCCESS — the creature turns up when someone actually sends something
   Same character as the delivery board, one pose only. Every gradient id in it
   carries an sx prefix so it can share a page with the board's copy without
   two elements answering to the same name.
   ══════════════════════════════════════════════════════════════════════════ */

.sx-done[hidden] {
    display: none;
}

.sx-done {
    display: grid;
    justify-items: center;
    text-align: center;
    padding: clamp(2.4rem, 4vw, 4rem) clamp(1.6rem, 3vw, 3rem) clamp(3rem, 4vw, 4rem);
}

.sx-pet {
    width: clamp(8.4rem, 11vw, 11rem);
    /* margin-inline, not text-align: the waitlist page centres its success
       panel with text-align, which does nothing for a block of a set width */
    margin: 1.4rem auto 0;
    animation: sxLand .85s cubic-bezier(.2, .9, .3, 1.35) .12s both;
}

.sx-pet__svg {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
}

/* it arrives, overshoots, settles -- then keeps breathing so the panel is
   never quite still */
@keyframes sxLand {
    0% {
        opacity: 0;
        transform: translateY(16px) scale(.55);
    }

    58% {
        opacity: 1;
        transform: translateY(-6px) scale(1.08);
    }

    100% {
        opacity: 1;
        transform: none;
    }
}

.sx-pet__svg {
    animation: sxBreathe 3.6s var(--e-io, ease-in-out) 1s infinite;
    transform-origin: 50% 94%;
}

@keyframes sxBreathe {

    0%,
    100% {
        transform: scale(1, 1);
    }

    50% {
        transform: scale(1.02, .98);
    }
}

.sx-star {
    transform-box: fill-box;
    transform-origin: 50% 50%;
    opacity: 0;
}

.sx-star--a {
    animation: sxPop 2.6s ease-in-out .7s infinite;
}

.sx-star--b {
    animation: sxPop 2.6s ease-in-out 1.05s infinite;
}

.sx-star--c {
    animation: sxPop 2.6s ease-in-out 1.35s infinite;
}

@keyframes sxPop {

    0%,
    62%,
    100% {
        opacity: 0;
        transform: scale(.3) rotate(-30deg);
    }

    18% {
        opacity: 1;
        transform: scale(1.12) rotate(8deg);
    }

    40% {
        opacity: .55;
        transform: scale(.95) rotate(20deg);
    }
}

/* the thought, above its head, tail pointing down at it */
.sx-say {
    position: relative;
    width: max-content;
    max-width: 26rem;
    margin: 0 auto 1.9rem;
    padding: 1.05rem 1.5rem;
    border-radius: 1.9rem;

    font-family: var(--mono, ui-monospace, monospace);
    font-size: 1.25rem;
    line-height: 1.42;
    text-align: center;
    text-wrap: balance;
    color: #33231A;

    background: linear-gradient(168deg, #FFFBF2 0%, #FBF3E2 62%, #F5E9D3 100%);
    box-shadow:
        0 0 0 1px rgba(150, 116, 74, .22),
        0 2px 0 rgba(255, 255, 255, .7) inset,
        0 -7px 12px -8px rgba(120, 86, 48, .38) inset,
        0 12px 26px -14px rgba(18, 8, 2, .45);

    animation: sxSay .5s cubic-bezier(.18, .96, .3, 1.28) .5s both;
}

.sx-say::before,
.sx-say::after {
    content: "";
    position: absolute;
    left: 50%;
    border-radius: 50%;
    background: linear-gradient(168deg, #FDF7EA, #F4E7D0);
    box-shadow: 0 0 0 1px rgba(150, 116, 74, .2);
}

.sx-say::before {
    width: 1.05rem;
    height: 1.05rem;
    bottom: -1.25rem;
    margin-left: -.525rem;
}

.sx-say::after {
    width: .62rem;
    height: .62rem;
    bottom: -2.4rem;
    margin-left: -.31rem;
}

@keyframes sxSay {
    from {
        opacity: 0;
        transform: translateY(8px) scale(.8) rotate(-1.4deg);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {

    .sx-pet,
    .sx-pet__svg,
    .sx-say,
    .sx-star {
        animation: none;
    }

    .sx-star {
        opacity: .9;
    }
}

.sx-done__t {
    margin: 2.6rem 0 0;
    font-family: var(--serif);
    font-size: clamp(2.4rem, 2.16vw, 2.66rem);
    font-weight: 400;
    letter-spacing: -.02em;
    color: var(--ink);
}

.sx-done__d {
    max-width: 42rem;
    margin: 1.2rem 0 0;
    font-size: var(--t-body);
    line-height: 1.6;
    color: var(--ink-2);
}

.sx-done__d a {
    color: var(--acc-2);
    text-decoration: underline;
    text-underline-offset: .25em;
}


/* ══════════════════════════════════════════════════════════════════════════
   MOBILE MENU PANEL
   The template's panel was built to fill the screen — 100dvh of sheet for six
   links, so it reads as a blank block with the words stranded at the top. It
   is sized to its contents here instead, and the waitlist sits at the foot of
   the list with a rule above it, the way the desktop bar carries it.
   ══════════════════════════════════════════════════════════════════════════ */

@media screen and (max-width: 600px) {

    [menu-panel] {
        height: auto !important;
    }

    [menu-panel] [inner-panel] {
        height: auto !important;
        padding-top: 7.4rem !important;
        padding-bottom: 3.2rem !important;
        border-radius: 0 0 2rem 2rem;
    }

    /* The bar was 93px of phone: 24px of padding either side of a 44px row,
       which is a lot of furniture to carry down the page. The 44px is the tap
       target on the logo and stays; the padding does not need to be that
       generous at this width, and the wordmark can lose a few pixels with it. */
    [main-nav]>header {
        padding-top: 1.1rem !important;
        padding-bottom: 1.1rem !important;
    }

    [main-nav]>header a[aria-label="Home"] img {
        height: 27px !important;
    }

    /* the template nests five wrappers between the sheet and the list, each
       carrying a desktop column width. On a phone the list is the panel, so
       every one of them is released to the full sheet. */
    [menu-panel] [inner-panel]>div,
    [menu-panel] [inner-panel]>div>div,
    [menu-panel] [data-lenis-prevent],
    [menu-panel] [data-lenis-prevent]>div {
        width: 100% !important;
        max-width: none !important;
        height: auto !important;
    }

    [menu-panel] [data-lenis-prevent] {
        overflow: visible !important;
        gap: 2.8rem;
    }

    #menu-panel-list {
        display: flex;
        flex-direction: column;
        gap: .2em;
    }

    #menu-panel-list .menu-item a {
        display: block;
        padding: .12em 0;
        transition: color .35s var(--e), transform .35s var(--e);
    }

    #menu-panel-list .menu-item a:active {
        transform: translateX(4px);
    }

    #menu-panel-list .menu-item--go {
        margin-top: .5em;
        padding-top: .55em;
        border-top: 1px solid var(--rule-warm, rgba(93, 82, 75, .18));
    }

    #menu-panel-list .menu-item--go a {
        color: var(--acc, #A67C52);
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   TEAM PAGE
   /team/ exists because a homepage is about a studio, not about a person.
   Someone searching a name needs a page that is actually about that name,
   with a photo, a role, a bio and links on it. Built on the .dp-* document
   shell so it inherits the type, measure and rules already set there.
   ══════════════════════════════════════════════════════════════════════════ */

.dp-crumb {
    /* has to be the same box as .dp-main, or the trail hangs in mid-air
       somewhere to the right of the title it belongs to */
    max-width: var(--max);
    margin: 0 auto;
    padding: 0 var(--gut);
    font-family: var(--mono);
    font-size: var(--t-sm);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.dp-crumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: .8rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.dp-crumb li+li::before {
    content: "/";
    margin-right: .8rem;
    opacity: .5;
}

.dp-crumb a {
    color: var(--ink-3);
    text-decoration: none;
    border-bottom: 1px solid var(--rule-warm);
}

.dp-crumb a:hover {
    color: var(--acc-2);
}

.tm-list {
    /* .dp-main runs to 1400px so a legal document's rules span the page; a
       roster needs a measure, and 96rem keeps the whitespace either side of
       it even rather than pooling on the right */
    max-width: 96rem;
    margin: clamp(4rem, 6vw, 6.5rem) 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: clamp(3.4rem, 5vw, 5.4rem);
}

.tm {
    display: grid;
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
    gap: clamp(2rem, 3.4vw, 3.6rem);
    align-items: start;
    padding-top: clamp(3.4rem, 5vw, 5.4rem);
    border-top: 1px solid var(--rule-warm);
}

.tm-list>.tm:first-child {
    padding-top: 0;
    border-top: 0;
}

.tm__shot {
    margin: 0;
    overflow: hidden;
    background: var(--p-4);
    border: 1px solid var(--rule-warm);
    border-radius: var(--r-l);
    box-shadow: var(--sh-1);
}

.tm__shot img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 5;
    object-fit: cover;
}

.tm__name {
    margin: 0;
    font-family: var(--serif);
    font-size: clamp(2.6rem, 2.49vw, 2.99rem);
    font-weight: 400;
    letter-spacing: -.022em;
    line-height: 1.06;
    color: var(--ink);
}

.tm__role {
    margin: .9rem 0 0;
    font-family: var(--mono);
    font-size: var(--t-sm);
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--acc-2);
}

.tm__bio {
    margin: 1.8rem 0 0;
    max-width: 46rem;
    font-size: var(--t-body);
    line-height: 1.62;
    color: var(--ink-2);
}

.tm__facts {
    margin: 2.2rem 0 0;
    display: grid;
    grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
    gap: .8rem clamp(1.4rem, 2vw, 2.4rem);
    max-width: 50rem;
    font-size: var(--t-sm-2, 1.4rem);
    line-height: 1.5;
}

.tm__facts dt {
    font-family: var(--mono);
    font-size: var(--t-sm);
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.tm__facts dd {
    margin: 0;
    color: var(--ink-2);
}

.tm__links {
    display: flex;
    flex-wrap: wrap;
    gap: 1.8rem;
    margin: 2.2rem 0 0;
}

.tm__links a {
    font-family: var(--mono);
    font-size: var(--t-sm);
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--acc-2);
    text-decoration: none;
    border-bottom: 1px solid var(--acc-line);
    padding-bottom: .3em;
    transition: border-color .35s var(--e), color .35s var(--e);
}

.tm__links a:hover {
    color: var(--ink);
    border-color: var(--ink);
}

@media screen and (max-width: 720px) {
    .tm {
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
    }

    .tm__shot {
        max-width: 24rem;
    }

    .tm__facts {
        grid-template-columns: minmax(0, 1fr);
        gap: .3rem;
    }

    .tm__facts dd {
        margin-bottom: 1.2rem;
    }
}

/* a route out of the studio section to the page that is actually about the
   four of them */
.cw-more {
    margin: clamp(3.4rem, 4.5vw, 5rem) 0 0;
}

.cw-more a {
    display: inline-flex;
    align-items: center;
    gap: .8rem;
    font-family: var(--mono);
    font-size: var(--t-sm);
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--acc-2);
    text-decoration: none;
    padding-bottom: .4em;
    border-bottom: 1px solid var(--acc-line);
    transition: color .35s var(--e), border-color .35s var(--e);
}

.cw-more a:hover {
    color: var(--ink);
    border-color: var(--ink);
}

.cw-more svg {
    width: 1.6rem;
    height: 1.6rem;
    transition: transform .4s var(--e);
}

.cw-more a:hover svg {
    transform: translateX(4px);
}
