/*
 * Lumenbay — design tokens. Every colour, font, size, weight, leading, space, radius, duration,
 * easing, delay, scale, filter and breakpoint on the site lives here; site.css and site.js only
 * reference them. Prefix --s- (the gallery's tokens are also loaded, for the concept ribbon).
 * One definition per property; var() takes one argument; tokens always inside a selector.
 *
 * TWO ROOMS: the tunnel half (deep bay ultramarine, kinetic) and the studio half (bay-foam, slow).
 *
 * DISTINCTNESS (CIEDE2000, art/lumenbay/deltae.py, 2026-10-02; rule: a key colour < 10 from another
 * site's key colour must move). Key colours and their nearest neighbour KEY:
 *   deep bay #1c1e9e (tunnel field) .... saltmere #1c2427 18.2 · ostrander #1c2335 18.8 · corvane #16132a 21.7 · nightweave #07080f > 21
 *   bay ultramarine #2c2fd8 (accent) ... EPE azure #0f62fe 15.0 · saltmere 23.6
 *   bay-foam #dadcff (light ground) .... ashgrove #d9e1e9 11.3 · nightweave #f3f4f8 12.6 · fernhallow 14.9
 *     (the first draft's foam #f4f5fa was dE 0.5 from Nightweave's #f3f4f8: moved to a periwinkle foam)
 *   bay ink #1b1d5c (studio text) ...... ostrander #1c2335 11.8 · corvane #16132a 12.1
 *     (the draft's paint black #1a1b22 was dE 3.5 from Halberd's #1b1c1e: moved to a blue-black ink)
 *   Text-on-dark foam #eceeff is a TEXT colour, not a ground (nightweave text #f3f4f8 at dE ~7; not a key).
 *   Rinse cyan / wax magenta are stage LIGHT colours only (bars, bands, the lane marker glow), never text.
 *
 * ROOMS (revision 2026-10-02, review: ~10,000 px of one ultramarine): saturated bay is now ONLY the tunnel half
 * (hero scrim, tunnel, lane) and the hours board. Memberships + Join = bay-foam #dadcff (the tag objects rhyme
 * across opening and close); Visit = the near-white #eceeff room framing the ultramarine board; footer bay-night.
 * r3 (review 7.9: ~6,000 px of near-identical periwinkle/near-white after the tunnel): the Detail studio becomes
 * THE QUIETER DARK ROOM on bay-night #121360 (nearest key colour: ostrander-quill #1c2335 dE 13.6, corvane #16132a
 * 14.0), with a raised panel #1b1e78 for the slot picker. Order now: dark · dark · light · photo · DARK · near-white ·
 * light · dark. Studio pairs (measured): foam-text on bay-night 14.16, mist 8.80, mist-hi 9.92, rinse focus 9.60,
 * error-dark 10.84; on the panel: foam-text 12.13, mist 7.54, rinse 8.22, error-dark 9.29; bay-night on foam-text
 * (selected chip / solid button) 14.16.
 *   #eceeff as a GROUND: nearest corvane frame-edge #eceaf2 3.9 (a hairline, not a ground), nightweave text/btn-bg
 *   #f3f4f8 5.8 (text, not a ground; Nightweave's ground is midnight). Every near-white tested (17 candidates,
 *   L* 93-97) sits within 6.4 of some other site's near-white: at that lightness CIEDE2000 cannot separate tints by
 *   10, so the near-white is confined to ONE room whose identity is the ultramarine board on it.
 *   #fafaff tag paper is an object colour (stickers), not a ground.
 *
 * CONTRAST (WCAG 2.x, measured):
 *   foam-text #eceeff on deep bay #1c1e9e ..... 10.55:1     on bay #2c2fd8 ......... 7.28:1
 *   mist #b9bce0 on deep bay .................. 6.56:1      on bay ................. 4.52:1 (use mist-hi there)
 *   mist-hi #c4c7f0 on bay #2c2fd8 ............ 5.10:1
 *   ink #1b1d5c on bay-foam #dadcff ........... 11.38:1     on foam-hi #eceeff ..... 13.25:1
 *   ink-muted #44468f on bay-foam ............. 6.22:1
 *   bay #2c2fd8 on bay-foam ................... 6.25:1 (links, outlined button on light, focus on light)
 *   deep bay on bay-foam ...................... 9.06:1
 *   rinse cyan #5fd6f0 on deep bay ............ 7.15:1 (focus ring on dark — non-text 3:1 needed)
 *   wax magenta #f06fb4 on deep bay ........... 4.42:1 (decorative light only; NEVER text)
 *   rinse cyan on bay-night #121360 ............ 9.60:1      foam-text on bay-night ... 14.16:1
 *   ink-muted #44468f on foam-hi #eceeff ..... 7.24:1      bay on foam-hi ......... 7.28:1
 *   on tag paper #fafaff: ink 14.66 · ink-muted 8.01 · bay 8.06 · error-light 9.01
 *   NEVER bay #2c2fd8 text on deep bay (1.45:1).
 * Over photographs, text sits on the hero scrim only — ratios measured on real pixels at 390 and
 * 1440 are in art/lumenbay/PAIR-NOTES.md.
 */
@font-face {
    font-family: "LB Unbounded";
    src: url("fonts/unbounded-latin-wght.woff2") format("woff2-variations"), url("fonts/unbounded-latin-wght.woff2") format("woff2");
    font-weight: 500 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "LB Hanken";
    src: url("fonts/hanken-latin-wght.woff2") format("woff2-variations"), url("fonts/hanken-latin-wght.woff2") format("woff2");
    font-weight: 400 600;
    font-style: normal;
    font-display: swap;
}

:root {
    /* ---- Palette ---------------------------------------------------------------------------- */
    --s-deep-bay: #1c1e9e;        /* tunnel-half field */
    --s-bay: #2c2fd8;             /* membership + closing fields; outlined button and links on light */
    --s-bay-night: #121360;       /* the lane band under the tunnel track, nav backdrop on dark */
    --s-foam-text: #eceeff;       /* type on dark; the foam-filled button; the tag's paper */
    --s-foam-hi: #eceeff;         /* raised panels on the light half (slot picker); the VISIT room's ground (revision) */
    --s-tag-paper: #fafaff;       /* windshield-tag sticker paper on the light rooms (an object, not a ground) */
    --s-bay-foam: #dadcff;        /* studio-half ground */
    --s-mist: #b9bce0;            /* secondary text on deep bay */
    --s-mist-hi: #c4c7f0;         /* secondary text on bay */
    --s-ink: #1b1d5c;             /* studio text */
    --s-ink-muted: #44468f;       /* secondary text on the light half */
    --s-rinse: #5fd6f0;           /* stage light: rinse cyan (decorative, focus on dark) */
    --s-wax: #f06fb4;             /* stage light: wax magenta (decorative only) */
    --s-mist-light: #9fe8ff;      /* stage light: pre-soak mist (decorative only) */
    --s-seal-light: #8f8cff;      /* stage light: sealant violet-blue (decorative only) */
    --s-dry-light: #ffffff;       /* stage light: dryer white (decorative only) */
    --s-error-dark: #ffc2d8;      /* form error text on bay 5.57:1 / deep bay 8.08:1 */
    --s-error-light: #8a1240;     /* form error text on bay-foam 6.99:1 / foam-hi 8.14:1 */
    --s-rule-dark: #eceeff2e;     /* hairlines on dark */
    --s-rule-light: #1b1d5c29;    /* hairlines on light */
    --s-bar-off: #eceeff1f;       /* an unlit arch bar */
    --s-dash: #eceeff73;          /* the lane's dashed centre line */
    --s-veil: #121360e0;          /* solid-ish panel over a photo (phone sticky lane bar) */
    --s-veil-soft: #12136099;     /* nav backdrop once scrolled */
    --s-shadow-ink: #0b0c3a;      /* the tag's drop shadow colour */

    /* Roles (site.css uses these; the palette above is the source) */
    --s-bg-dark: var(--s-deep-bay);
    --s-bg-field: var(--s-bay);
    --s-bg-light: var(--s-bay-foam);      /* light room ground (memberships/join alias it) */
    --s-bg-studio: var(--s-bay-night);    /* r3: the studio is the quieter DARK room */
    --s-studio-panel: #1b1e78;            /* r3: raised slot-picker panel on the dark studio (foam-text 12.13:1) */
    --s-bg-members: var(--s-bay-foam);    /* revision: memberships moved off saturated bay onto the light room */
    --s-bg-join: var(--s-bay-foam);       /* revision: the closing tag on the light room (rhymes with memberships) */
    --s-bg-visit: var(--s-foam-hi);       /* revision: the near-white room, framing the ultramarine hours board */
    --s-text-on-dark: var(--s-foam-text);
    --s-text-on-light: var(--s-ink);
    --s-muted-on-dark: var(--s-mist);
    --s-muted-on-field: var(--s-mist-hi);
    --s-muted-on-light: var(--s-ink-muted);
    --s-focus-dark: var(--s-rinse);
    --s-focus-light: var(--s-bay);
    --s-link-light: var(--s-bay);
    --s-btn-fill: var(--s-foam-text);     /* primary TAG button on dark: foam fill, deep-bay text (10.55:1) */
    --s-btn-fill-text: var(--s-deep-bay);
    --s-btn-fill-hover: #ffffff;
    --s-btn-line: var(--s-foam-text);     /* secondary TAG button on dark: foam outline + text */
    --s-btn-line-fill: #121360cc;         /* secondary TAG button over a photo: bay-night fill behind the outline (foam text measured 9.94:1 worst decile at 1440) */
    --s-btn-line-light: var(--s-bay);     /* secondary TAG button on light: bay outline + text (6.25:1) */
    --s-focus-halo: var(--s-bay-night);   /* a second ring outside the rinse focus ring when it sits on a photo */
    --s-btn-solid-light: var(--s-bay);    /* primary TAG button on light: bay fill, foam text (7.28:1) */

    /* Stage lights (content.php tunnel.stages[].light → --s-light-<light>) */
    --s-light-mist: var(--s-mist-light);
    --s-light-wax: var(--s-wax);
    --s-light-rinse: var(--s-rinse);
    --s-light-seal: var(--s-seal-light);
    --s-light-dry: var(--s-dry-light);

    /* Tier colour bands (content.php memberships.tiers[].band → --s-band-<band>) */
    --s-band-rinse: var(--s-rinse);
    --s-band-shine: var(--s-mist);
    --s-band-lumen: var(--s-wax);

    /* ---- Type ------------------------------------------------------------------------------- */
    --s-font-display: "LB Unbounded", "Arial Black", system-ui, sans-serif;   /* headlines, stage names, hours numerals, tag — never paragraphs */
    --s-font-body: "LB Hanken", system-ui, -apple-system, "Segoe UI", sans-serif;  /* digits are tabular by default (all 560 units) */

    --s-weight-display: 600;
    --s-weight-display-light: 500;
    --s-weight-display-heavy: 700;
    --s-weight-body: 400;
    --s-weight-semi: 600;

    --s-step-hero: clamp(3rem, 1.514rem + 6.095vw, 7rem);        /* 48px at 390 → 112px at 1440 */
    --s-step-stage: clamp(2rem, 1.443rem + 2.286vw, 3.5rem);     /* stage names: 32 → 56 */
    --s-step-h2: clamp(1.875rem, 1.362rem + 2.095vw, 3.25rem);   /* 30 → 52 */
    --s-step-h3: clamp(1.25rem, 1.11rem + 0.57vw, 1.625rem);     /* 20 → 26 */
    --s-step-numeral: clamp(2.25rem, 1.413rem + 3.43vw, 4.5rem); /* tier price, tag tier: 36 → 72 */
    --s-step-tag-name: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem);   /* name on the windshield tag */
    --s-step-interlude: clamp(1.75rem, 1.2rem + 2.3vw, 3.5rem);  /* the one line over the beading macro */
    --s-step-lede: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);      /* 17 → 20 */
    --s-step-body: clamp(1.0625rem, 0.95rem + 0.4vw, 1.25rem);   /* 17px phone → 20px desktop (review r3: body never reads as fine print) */
    --s-step-small: clamp(0.9375rem, 0.86rem + 0.25vw, 1.0625rem); /* 15px phone → 17px desktop — the smallest size that may carry muted text */
    --s-step-label: clamp(0.8125rem, 0.76rem + 0.18vw, 0.9375rem); /* 13 → 15px Hanken 600 labels */
    --s-step-logo: 1.0625rem;

    --s-leading-display: 1;
    --s-leading-tight: 1.12;
    --s-leading-snug: 1.3;
    --s-leading-body: 1.55;

    --s-track-display: -0.02em;
    --s-track-hero: -0.03em;
    --s-track-label: 0.06em;
    --s-track-logo: 0.14em;
    --s-track-numeral: -0.01em;

    --s-measure: 34em;             /* body copy */
    --s-measure-narrow: 26em;      /* stage notes, tag intro */
    --s-measure-hero: 13ch;        /* hero headline lines */

    /* ---- Space ------------------------------------------------------------------------------ */
    --s-space-3xs: 0.25rem;
    --s-space-2xs: 0.5rem;
    --s-space-xs: 0.75rem;
    --s-space-s: 1rem;
    --s-space-m: 1.5rem;
    --s-space-l: 2.25rem;
    --s-space-xl: 3.5rem;
    --s-space-2xl: 5rem;
    --s-space-3xl: 7.5rem;
    --s-gutter: clamp(16px, 4vw, 56px);
    --s-section: clamp(72px, 9vw, 144px);
    --s-section-seam: clamp(40px, 4.5vw, 72px);   /* a room's foot where the next room brings its own --s-section top (no doubled band) */
    --s-max: 1280px;
    --s-max-text: 720px;
    --s-ribbon-h: 34px;            /* shared/ribbon.css: 12px mono + 8px padding; JS should measure if it wraps */
    --s-nav-h: 64px;
    --s-tap: 48px;                 /* minimum touch target (chips, dots, logo, phone/email) */

    /* ---- Shapes ----------------------------------------------------------------------------- */
    /* TAG button: a windshield-tag shape, never a stadium. Radius well under half the height. */
    --s-tag-h: 56px;
    --s-tag-radius: 17px;
    --s-tag-pad-x: 1.625rem;
    --s-tag-hole: 9px;             /* punched hole near the left end */
    --s-tag-hole-inset: 14px;
    --s-tag-strip: 3px;            /* thin stage-light strip along the top edge */
    --s-tag-border: 1.5px;
    /* The windshield TAG object (tiers, closing builder) */
    --s-ticket-radius: 28px;       /* rounded top of the tag object */
    --s-ticket-radius-foot: 10px;
    --s-ticket-adhesive: 18px;     /* adhesive strip height at the top */
    --s-ticket-w: 256px;
    --s-ticket-w-big: 420px;
    --s-ticket-band: 14px;         /* tier colour band */
    --s-ticket-fan: 4deg;          /* fanned tiers: rotation step (revision: 7deg swung the outer tags' feet under the centre tag's CTA) */
    --s-ticket-lift: -18px;        /* the selected tier comes forward */
    --s-ticket-scale: 1.04;
    --s-radius-panel: 14px;
    --s-radius-chip: 12px;
    --s-bar-h: 4px;                /* arch light bars */
    --s-bar-gap: 10px;
    --s-dot: 8px;                  /* phone: the five bars become dots */
    --s-lane-h: 132px;             /* the lane band under the tunnel track (desktop) */
    --s-lane-h-phone: 72px;        /* sticky lane bar on phones */
    --s-lane-dash: 18px;
    --s-lane-dash-gap: 14px;
    --s-marker-w: 54px;            /* car marker SVG */
    --s-focus-w: 3px;
    --s-focus-offset: 3px;
    --s-shadow-tag: 0 18px 40px -16px var(--s-shadow-ink);
    --s-shadow-ticket: 0 30px 60px -24px var(--s-shadow-ink);
    --s-glow-bar: 0 0 18px 2px;    /* + the stage light colour, set in site.css */

    /* ---- Photographs ------------------------------------------------------------------------ */
    /* Banded on desktop: light over the open arch (the spray stays visible), heaviest at 36–45% where
       the lede crosses the car's roof, gone by 64%. Measured worst-decile ratios in PAIR-NOTES. */
    /* design pass: a deeper bay (#14158a) at lower opacity keeps the arch structure and spray readable instead of a
       flat lavender veil, and the tail eases out over 43-67% so there is no density step across the roof.
       Measured on the live 1440 render (text hidden): headline 8.23 / 6.44, lede 5.73 worst-decile. */
    /* r3 (manager review 7.9: "the whole frame is ultramarine, it reads cold night"): the photo is now graded
       near-neutral (art/lumenbay/grade.sh post "neutral"), and the bay-night ink is CONFINED to two bands —
       desktop: a top-left ellipse behind the headline + buttons and the foot band behind lede + open-now; the
       middle of the frame (the foamed car, the spray, the bay window) carries no scrim at all. Phone: a top band
       behind bars + headline + lede that is gone by 46%, then the foot band. Ratios + rendered b*: PAIR-NOTES r3. */
    --s-scrim-hero: linear-gradient(180deg, #121360d9 0%, #121360c7 25%, #12136000 31%), radial-gradient(ellipse 42% 54% at 0% 22%, #121360d9 0%, #121360cc 60%, #12136000 100%);
    --s-scrim-hero-phone: linear-gradient(180deg, #121360e0 0%, #121360cc 26%, #12136066 38%, #12136000 46%);
    --s-scrim-foot: linear-gradient(0deg, #121360e6 0%, #12136000 100%);   /* under the open-now strip; 160px tall (--s-scrim-foot-h) */
    --s-scrim-foot-h: 160px;
    --s-scrim-foot-h-hero: 240px;   /* engineer: desktop hero foot carries the lede AND the open-now strip (lede moved onto this scrim, review polish) */
    --s-scrim-interlude: linear-gradient(180deg, #12136000 40%, #121360cc 100%);
    --s-hero-pos: 50% 50%;         /* desktop file is already 16:10; the arch must stay at the top */
    --s-hero-pos-phone: 50% 100%;  /* phone (r6, art director): the phone master carries +600px of ceiling ABOVE the arch; anchoring the
                                      foot crops that band away on short boxes (Safari svh ~0.66) and shows it only on tall ones (0.51),
                                      so the car sits under the lede with both headlights at every phone height */
    --s-photo-scale-from: 1;
    --s-photo-scale-to: 1.05;
    --s-parallax: 4%;

    /* ---- Motion ----------------------------------------------------------------------------- */
    --s-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --s-ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
    --s-ease-soft: cubic-bezier(0.25, 0.1, 0.25, 1);
    --s-ease-gsap-out: power3.out;     /* GSAP names, read by site.js */
    --s-ease-gsap-inout: power2.inOut;
    --s-ease-gsap-slow: sine.inOut;
    --s-dur-fast: 180ms;
    --s-dur-base: 320ms;
    --s-dur-lift: 420ms;           /* tier tag lifts forward */
    --s-dur-bar: 520ms;            /* one arch bar ignites */
    --s-stagger-bar: 120ms;        /* bars ignite in sequence */
    --s-delay-bars: 250ms;
    --s-dur-hero-scale: 2400ms;
    --s-dur-theme: 700ms;          /* dark → light room change (class toggle + transition) */
    --s-dur-fan: 900ms;
    --s-stagger-fan: 90ms;
    --s-dur-studio-fade: 1100ms;   /* the studio slows down */
    --s-dur-sweep: 1400ms;         /* the one light sweep across the activated tag */
    --s-delay-announce: 700ms;     /* debounce for the tag's polite aria-live updates */
    --s-tunnel-scroll: 4;          /* pinned track length, in viewport widths of scroll */
    --s-open-check: 60000ms;       /* re-check open-now once a minute */

    /* ---- Layers ----------------------------------------------------------------------------- */
    --s-z-nav: 50;
    --s-z-sheet: 60;
    --s-z-lane: 40;

    /* ---- Breakpoints (site.js reads these; CSS media queries repeat the number) -------------- */
    --s-bp-tablet: 720px;
    --s-bp-desktop: 1024px;
    --s-bp-wide: 1280px;
}

/* ---- Front-end engineer's tokens (layout + behaviour; palette and photo values stay above) ---- */
:root {
    /* Media queries for <picture> sources (index.php) and site.js. CSS @media repeats the numbers. */
    --s-mq-phone: (max-width: 719.98px);
    --s-mq-desktop: (min-width: 1024px);
    --s-mq-tablet: (min-width: 720px);

    /* Per-element hooks: set inline on an element to pick a stage light / tier band (default here). */
    --s-tick-at: 0;                /* lane tick position (set inline per tick) */
    --s-lane-p: 1;                 /* lane progress 0..1 (site.js sets it; 1 = complete, the no-JS state) */
    --s-fan-i: 0;                  /* tier index around the centre (-1, 0, 1), set inline */
    --s-veil-light: #dadcffe6;     /* nav backdrop over the light rooms (bay-foam at 90%) */
    --s-adhesive: #9fe8ff4d;       /* the tag's adhesive strip (pre-soak mist at 30%) */
    --s-glow-r: 10px;
    --s-bar-dim: 0.4;              /* a passed arch bar in the tunnel */
    --s-step-board: clamp(1.75rem, 1.2rem + 2.2vw, 3rem);  /* hours-board numerals */
    --s-hairline: 1px;
    --s-border: 1.5px;
    --s-bar-light: var(--s-light-dry);
    --s-tag-band: var(--s-band-shine);

    /* Chrome */
    --s-nav-pad-y: 0.75rem;
    --s-nav-link-gap: 1.75rem;
    --s-nav-veil-blur: blur(12px);
    --s-btn-pad-sm-x: 1.125rem;
    --s-tag-h-sm: 44px;            /* the nav's Join tag (still a tag: radius stays well under half) */
    --s-tag-radius-sm: 13px;
    --s-tag-hole-sm: 7px;
    --s-tag-hole-inset-sm: 11px;
    --s-tag-strip-inset: 22%;      /* the top light strip starts/stops this far from the ends */
    --s-tag-press: translateY(1px);
    --s-tag-hover: translateY(-2px);
    --s-strip-grad: linear-gradient(90deg, var(--s-mist-light), var(--s-rinse), var(--s-seal-light), var(--s-wax));

    /* Hero */
    --s-hero-min: 560px;
    --s-hero-top: 1rem;            /* gap under the nav before the arch bars */
    --s-hero-bars-w: min(720px, 72vw);
    --s-hero-bars-w-phone: 7.5rem;
    --s-hero-stack-gap: 1.125rem;
    --s-hero-btn-gap: 0.875rem;
    --s-hero-lede-w: 42em;
    --s-hero-lede-w-wide: 28em;   /* revision: the left-aligned lede keeps to the scrimmed side */
    --s-open-h: 52px;              /* the open-now strip */
    --s-open-dot: 9px;
    --s-step-hero-phone: 2.5rem;   /* "Three minutes" in Unbounded is wide: 40px fits 358px of text width */

    /* Tunnel */
    --s-tunnel-head-h: 64px;
    --s-tunnel-frame-ratio: 1.2;   /* 6:5 frames */
    --s-lane-cols: minmax(0, 0.9fr) minmax(0, 1.6fr);   /* stage now · what it does (r4: the elapsed clock is gone; the arch bars carry progress) */
    --s-bar-h-tunnel: 8px;         /* the overhead arch bars in the tunnel: thick enough to read as the progress readout */
    --s-lane-bars-w-phone: 6.5rem; /* the arch bars inside the phone's sticky lane bar */
    --s-lane-cover: 8px;           /* the sticky lane's opaque ground continues this far below its edge */
    --s-lane-live-h: var(--s-lane-h-phone);   /* site.js sets the measured bar height on the tunnel (stage scroll-margin) */
    --s-lane-track-h: 22px;
    --s-lane-tick: 2px;
    --s-stage-cap-pad: 1.25rem;
    --s-stage-ratio-phone: 4 / 5;
    --s-stage-ratio: 6 / 5;
    --s-frame-scrim: linear-gradient(180deg, #12136000 45%, #121360eb 100%);   /* foot of each tunnel frame, under its caption */
    --s-frame-dim: 0.72;           /* frames the car is not in */
    --s-frame-cap-dim: 0.6;
    --s-dur-stage-dim: 500ms;
    --s-lane-progress-h: 3px;

    /* Memberships */
    --s-fan-gap: 2.25rem;          /* space between fanned tags: clears the 4deg swing at the foot (~25px) + the selected scale + the focus ring */
    --s-fan-drop: 1.25rem;         /* outer tags sit lower, like hung on a rail */
    --s-ticket-h: 360px;
    --s-ticket-hole: 22px;
    --s-ticket-pad: 1.5rem;
    --s-carousel-peek: 16%;
    --s-check-mark: 22px;
    --s-check-cols: repeat(2, minmax(0, 1fr));
    /* comparison board (memberships, review r3) */
    --s-compare-item-col: 40%;       /* the arch names column; the three tag columns share the rest */
    --s-compare-item-col-phone: 44%;
    --s-compare-item-col-narrow: 46%;  /* phones under 480px: arch names get half the board, so none wraps past two lines */
    --s-compare-band-w-phone: 32px;
    --s-compare-head-h: 132px;
    --s-compare-band-w: 56px;        /* the tier's colour band, as on the tag object */
    --s-compare-dash: 18px;          /* "not in this plan" mark */
    --s-compare-dash-o: 0.55;
    --s-compare-glow: 4px;           /* a rinse-light halo round ticks in the lit column */
    --s-compare-glow-c: #5fd6f055;
    --s-compare-rule-lit: #eceeff2e;

    /* Interlude */
    --s-interlude-h: 78svh;
    --s-interlude-h-phone: 62svh;

    /* Studio */
    --s-studio-cols: minmax(0, 5fr) minmax(0, 3fr) minmax(0, 6fr);
    /* round 5: the lit price board */
    --s-pricebd-cols: minmax(0, 0.72fr) minmax(0, 1.6fr);
    --s-pricebd-photo-ratio: 16 / 10;
    --s-menu-cols: minmax(0, 1.5fr) minmax(10rem, 1fr) auto;
    --s-menu-cols-phone: minmax(0, 1fr) auto;
    --s-menu-bar-h: 6px;
    --s-menu-bar-max: 11rem;
    --s-menu-hover: #ffffff0d;
    --s-step-price: clamp(1.5rem, 1.2rem + 1.1vw, 2.25rem);
    --s-daylight-h: 3px;
    --s-daylight-glow: 28px;
    --s-daylight-glow-spread: 6px;
    --s-daylight-haze: #ffffff40;
    --s-shadow-board: 0 30px 80px -30px #05062a;
    --s-studio-stagger: 2.5rem;
    --s-menu-at: 0.2;             /* share of the price board on screen before its bars fill */
    --s-dur-clip: 1400ms;          /* the price board bay-time bars fill */
    --s-pricebd-zoom: 1.08;        /* the polisher photo settles from this close-up as the board arrives */
    --s-studio-rise: 24px;
    --s-leader: 2px;               /* dot leader in the detail menu */
    --s-chip-min: 48px;
    --s-time-cols: repeat(4, minmax(0, 1fr));
    --s-time-cols-phone: repeat(2, minmax(0, 1fr));

    /* Visit */
    --s-visit-cols: minmax(0, 6fr) minmax(0, 6fr);   /* revision: the plan reads at full column width */
    --s-board-row-pad: 0.875rem;
    --s-board-today-bar: 6px;
    --s-plan-stroke: 3px;
    --s-plan-dash: 10 9;
    --s-plan-pin: 15px;
    --s-plan-line: 2;             /* plan outlines (SVG user units) */
    --s-plan-arch: 4;             /* tunnel arch ticks */
    --s-plan-band: 26;            /* the lane band, same language as the tunnel's lane */
    --s-plan-pin-ring: 3;
    --s-plan-name: 17px;          /* studio name inside the building (SVG px at the 600-unit viewBox) */
    --s-plan-sub: 11px;

    /* Join */
    --s-join-form-w: 640px;
    --s-tag-stamp-rot: -9deg;
    --s-sweep: linear-gradient(105deg, transparent 30%, var(--s-foam-text) 48%, var(--s-mist-light) 52%, transparent 70%);
    --s-sweep-from: translateX(-120%);
    --s-sweep-to: translateX(120%);
    --s-vehicle-icon-w: 64px;
    --s-dur-tag-update: 260ms;
}

/* r3: the Detail studio is a DARK room. The light-room role tokens it consumes are re-pointed here, inside the
   section's selector, so every studio rule (menu, chips, fields, focus, errors) flips with no per-rule duplication. */
.lb-studio {
    --s-ink: var(--s-foam-text);
    --s-ink-muted: var(--s-mist);
    --s-rule-light: var(--s-rule-dark);
    --s-focus-light: var(--s-focus-dark);
    --s-error-light: var(--s-error-dark);
    --s-bay-foam: var(--s-bay-night);      /* field wells sink into the room */
    --s-foam-hi: var(--s-studio-panel);    /* the slot-picker panel rises out of it */
    --s-btn-solid-light: var(--s-btn-fill);
    --s-studio-accent: var(--s-mist-hi);   /* menu prices, the close button (9.92:1 on bay-night, 8.50 on the panel) */
}
