/*
 * Pellmarsh — design tokens. Every colour, font, size, weight, leading, space, radius,
 * duration, easing, filter, scale 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.
 *
 * Palette: CUT CHARTREUSE + SPRAY WHITE + OLIVE-SOOT. The chartreuse is a FIELD (hero
 * panel, houses label) as well as the cut line; the dark is the colour of real grime.
 *
 * Distinctness, CIEDE2000 (art/pellmarsh/delta-e.py, run 2026-10-02 against every --s-* hex
 * of the 17 other sites, and key-to-key against each site's ground / dark / accent):
 *   chartreuse  #d6dc50  nearest key: vantrell --s-lime #c6ff00 ........ ΔE 10.7
 *                        (moved from the draft #d3e54a, which was ΔE 7.7 from Vantrell's lime)
 *                        any token: vantrell --s-lime-hover #d6ff4a ...... ΔE 9.0 (a hover state, not a key)
 *   olive-soot  #2a280c  nearest key: vesperwood --s-ink #2b2118 ......... ΔE 11.0
 *                        (moved from the draft #23251e, ΔE 4.3 from Varrow charcoal)
 *   spray white #f6f9e6  nearest key: caldermoor --s-chalk #e1e7d6 ....... ΔE 4.1
 *                        Halberd & Stone concrete #e9e7e2 ................... ΔE 7.5
 *                        EXCEPTION, raised in PAIR-NOTES: no reading white clears ΔE 10 from
 *                        the nine near-white grounds already in the set (best possible ~9.8
 *                        is a visible lime tint). It carries a faint chartreuse cast so it
 *                        belongs to this palette, and it never appears without the field.
 *
 * Contrast, measured (WCAG 2.x, sRGB):
 *   olive-soot on chartreuse ......... 10.10:1  (hero headline, tapped plan zones, submit text)
 *   olive-soot on spray white ........ 13.94:1  (body)
 *   spray white on olive-soot ........ 13.94:1  (docked panels)
 *   wet slate #58573f on spray white ..  6.88:1  (secondary text)
 *   wet slate on chartreuse ...........  4.99:1  (secondary text on the field — body size min)
 *   slate graphic #8a8a70 on spray white 3.30:1  (rules, gauge ticks, plan hairlines: graphics only)
 *   chartreuse on spray white .........  1.38:1  FAILS — never text, never a lone rule on white;
 *                                                  the cut line on white always has its soot edge
 *   chartreuse on olive-soot .......... 10.10:1  (the cut line / needles / focus on dark)
 */
/* Fonts: latin-subset variable WOFF2 (sources + SHA-256 in BRIEF.md; OFL texts beside them).
   Preload ONLY Epilogue (the first-frame headline). */
@font-face {
    font-family: "Epilogue";
    src: url("fonts/epilogue-latin-wght-normal.woff2") format("woff2-variations"), url("fonts/epilogue-latin-wght-normal.woff2") format("woff2");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Karla";
    src: url("fonts/karla-latin-wght-normal.woff2") format("woff2-variations"), url("fonts/karla-latin-wght-normal.woff2") format("woff2");
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
}
:root {
    /* ---- Palette --------------------------------------------------------------- */
    --s-chartreuse: #d6dc50;       /* the cut line, the hero panel, tapped plan zones + submit, gauge needles */
    --s-chartreuse-deep: #c4ca3e;  /* pressed / hatch on the field (graphic, never text) */
    --s-spray: #f6f9e6;            /* spray white — the reading ground */
    --s-spray-2: #eceed6;          /* a step down for panels and the stage mat on spray white */
    --s-soot: #2a280c;             /* olive-soot — text, docked panels, the tile-button shadow */
    --s-soot-2: #3a381c;           /* a lift for surfaces on soot */
    --s-slate: #58573f;            /* wet slate — secondary text (AA on spray and on chartreuse) */
    --s-slate-graphic: #8a8a70;    /* rules, ticks, hairlines — graphics only */
    --s-rule-light: #2a280c26;     /* hairlines on spray white */
    --s-rule-dark: #f6f9e62e;      /* hairlines on soot */
    --s-hatch: #2a280c;            /* site-plan selected-zone hatch stroke */
    --s-error: #8a2a12;            /* form error text on spray (8.10:1) and on chartreuse (5.87:1) */
    --s-scrim: #2a280cb8;          /* olive-soot chip behind any word that must sit on a photo */
    --s-panel-muted: #cfd0b6;      /* secondary text on soot panels (engineer; 9.49:1 on olive-soot) */
    --s-zone-hover: #2a280c1f;     /* site-plan zone under the pointer (graphic) */
    --s-water: #2a280c1a;          /* the plan's pool water: a tint, never pool blue */

    /* Roles (use these in site.css; the palette above is the source) */
    --s-bg: var(--s-spray);
    --s-surface: var(--s-spray-2);
    --s-text: var(--s-soot);
    --s-muted: var(--s-slate);
    --s-accent: var(--s-chartreuse);
    --s-accent-ink: var(--s-soot);
    --s-rule: var(--s-rule-light);
    --s-field: var(--s-chartreuse);
    --s-field-ink: var(--s-soot);
    --s-panel: var(--s-soot);
    --s-panel-ink: var(--s-spray);
    --s-focus-light: var(--s-soot);      /* focus ring on spray / chartreuse */
    --s-focus-dark: var(--s-chartreuse); /* focus ring on soot and on photos (with soot halo) */

    /* The PAVER-TILE button: spray-white fill, soot text, hard soot offset shadow,
       presses into its shadow on :active. Radius ~10px — never a pill. */
    --s-btn-bg: var(--s-spray);
    --s-btn-bg-hover: #ffffff;
    --s-btn-ink: var(--s-soot);
    --s-btn-edge: 2px;
    --s-btn-radius: 10px;
    --s-btn-shadow-x: 4px;
    --s-btn-shadow-y: 4px;
    --s-btn-h: 56px;
    --s-btn-pad-x: 26px;

    /* ---- Type ------------------------------------------------------------------ */
    --s-font-display: "Epilogue", system-ui, -apple-system, "Segoe UI", sans-serif;
    --s-font-body: "Karla", system-ui, -apple-system, "Segoe UI", sans-serif;
    --s-font-figure: var(--s-font-display);  /* gauge + timeline numbers, tabular */
    --s-numeric: tabular-nums;

    --s-weight-display: 800;
    --s-weight-heavy: 800;
    --s-weight-semi: 700;
    --s-weight-strong: 700;
    --s-weight-regular: 400;

    --s-step-hero: clamp(3.375rem, 1.75rem + 6.6vw, 7.5rem);   /* 54px at 390 → 120px at 1440 */
    --s-step-h2: clamp(2.5rem, 1.3rem + 4.6vw, 4.5rem);         /* section words: 40 → 72px */
    --s-step-h3: clamp(1.375rem, 1.15rem + 0.9vw, 1.875rem);
    --s-step-figure: clamp(1.75rem, 8.5cqi, 3.25rem);          /* gauge readout, sized to its dial column (container units) so the longest value stays on one line */
    --s-step-tab: clamp(1.25rem, 1.05rem + 0.8vw, 1.75rem);     /* hero surface tabs */
    --s-step-lede: clamp(1.125rem, 1.02rem + 0.45vw, 1.375rem);
    --s-step-body: clamp(1.0625rem, 0.92rem + 0.55vw, 1.3125rem); /* 17px phone → 21px at 1440: body never reads as small print beside the bold display type (review r3) */
    --s-step-caption: clamp(0.9375rem, 0.82rem + 0.3vw, 1.0625rem);    /* Karla 700 captions: 15px phone → 17px desktop, never letter-spaced micro-kickers */
    --s-step-statement: clamp(1.75rem, 0.6rem + 2.9vw, 3.5rem);  /* a section statement set to carry a half-frame on its own (houses, review r3) */
    --s-measure-statement: 18ch;
    --s-step-small: 0.875rem;       /* floor for any readable text */
    --s-step-logo: 1.375rem;
    --s-step-kicker: 0.9375rem;     /* template only */
    --s-step-input: 1rem;           /* 16px: stops iOS focus-zoom */

    --s-leading-solid: 0.92;        /* hero lines */
    --s-leading-display: 0.98;
    --s-leading-heading: 1.08;
    --s-leading-body: 1.55;
    --s-leading-caption: 1.35;

    --s-track-display: -0.035em;    /* Epilogue 800, tight */
    --s-track-heading: -0.025em;
    --s-track-logo: -0.02em;
    --s-track-kicker: 0em;          /* no tracked micro-labels anywhere */
    --s-measure: 62ch;
    --s-measure-narrow: 40ch;

    /* ---- Space ----------------------------------------------------------------- */
    --s-gutter: clamp(16px, 4.4vw, 64px);
    --s-section: clamp(88px, 11vw, 168px);
    --s-section-tight: clamp(56px, 7vw, 104px);
    --s-space-2xs: 4px;
    --s-space-xs: 8px;
    --s-space-s: 16px;
    --s-space-m: 24px;
    --s-space-l: 40px;
    --s-space-xl: clamp(48px, 6vw, 88px);
    --s-max: 1280px;
    --s-max-wide: 1520px;
    --s-radius: 10px;               /* the ONE radius: tile button, panels, inputs, pool tiles */
    --s-radius-s: 6px;

    /* ---- Chrome ---------------------------------------------------------------- */
    --s-ribbon-h: 34px;             /* shared/ribbon.css height; offset sticky UI by it */
    --s-nav-h: 68px;
    --s-nav-h-mobile: 58px;
    --s-tap: 44px;                  /* minimum touch target */
    --s-hairline: 1px;
    --s-focus-ring: 3px;
    --s-focus-offset: 3px;

    /* ---- The cut line (the ONE motif: hero, reveal grip, timeline axis, closing) -- */
    --s-cut-w: 6px;                 /* stroke width of the chartreuse line */
    --s-cut-edge: 2px;              /* soot edge either side of the line wherever it crosses a light ground */
    --s-cut-grip: 56px;             /* nozzle-shaped grip, visible size */
    --s-cut-hit: 56px;              /* drag hit area (≥ 48px) */
    --s-hero-split: 45%;            /* desktop: chartreuse panel width at the top edge… (engineer: 40% clipped the 120px headline) */
    --s-hero-split-foot: 57%;       /* …and at the bottom edge — the diagonal (the only one on the site) */
    --s-hero-photo-h-p: 42%;        /* phone: photo height of the first screen (engineer: 55% pushed the tile button below the fold at 390x844) */
    --s-hero-pos: 50% 50%;          /* hero photo object-position (crop is already art-directed) */
    --s-hero-pos-p: 50% 0%;        /* engineer: top-anchored so the real line exits the photo low enough to run on into the panel */

    /* ---- Photographs ----------------------------------------------------------- */
    --s-stage-ratio: 5 / 4;         /* reveal stage, desktop (all three stage crops are 5:4) */
    --s-stage-ratio-p: 4 / 5;       /* reveal stage, phone (all three phone crops are 4:5) */
    --s-strip-ratio: 12 / 5;        /* houses cinemascope strip (house-*.avif is 2.4:1) */
    --s-full-ratio-p: 4 / 5;        /* phone crops of the full-bleed photos */
    --s-pave-pos: 50% 50%;
    --s-pool-pos: 50% 60%;          /* keeps the waterline + deck on 16:9 at wide viewports */
    --s-house-pos: 50% 65%;         /* AD r3 re-cut: clapboard + corner board, kept clear of the sky corner */

    /* ---- Gauges (houses) ------------------------------------------------------- */
    --s-gauge-size: clamp(300px, 36vw, 500px);   /* engineer, review r2: dials carry the section (360–400 at 1440) */
    --s-gauge-stroke: 10px;
    --s-gauge-sweep: 240deg;        /* dial arc; 0 PSI at -120deg, scale max at +120deg */
    --s-gauge-start: -120deg;

    /* ---- Motion: purposeful, tactile, one-shot ------------------------------- */
    --s-ease-cut: cubic-bezier(0.65, 0, 0.35, 1);       /* the stroke drawing along the diagonal */
    --s-ease-settle: cubic-bezier(0.34, 1.36, 0.64, 1); /* needles: slight overshoot, then settle */
    --s-ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
    --s-ease: var(--s-ease-out);
    --s-dur-ui: 180ms;              /* hover, press, colour */
    --s-dur: 400ms;
    --s-dur-cut: 1400ms;            /* hero stroke draw */
    --s-dur-photo: 2400ms;          /* hero photo 1.0 → 1.04 */
    --s-dur-teach: 1600ms;          /* reveal teach sweep, once */
    --s-dur-needle: 1200ms;
    --s-dur-tile: 420ms;            /* each pool tile setting down */
    --s-dur-swap: 360ms;            /* reveal surface swap (crossfade) */
    --s-delay-teach: 500ms;
    --s-stagger-tile: 110ms;
    --s-scale-photo: 1.04;
    --s-parallax: 3%;               /* pavements swirl drift */
    --s-tile-drop: 14px;            /* pool tiles set down from this height */
    --s-press: 4px;                 /* tile button travels into its shadow */
    --s-reveal-start: 50;           /* % — the finished first frame of the reveal */
    --s-teach-from: 22;             /* % — the teach sweep runs from here to --s-reveal-start */
    --s-key-step: 5;                /* % per arrow key; PageUp/PageDown = 2× */

    /* ---- Breakpoints (JS reads these; CSS uses the same numbers) -------------- */
    --s-bp-tablet: 768px;
    --s-bp-desktop: 1024px;
    --s-bp-wide: 1280px;
}

/* ---- Engineer's layout tokens (front-end, 2026-10-02) ------------------------------
   Layout-only values site.css / site.js need beyond the art director's set above.
   Media queries are read by index.php (picture sources) and site.js (matchMedia). */
:root {
    --s-mq-phone: (max-width: 767px);
    --s-mq-wide: (min-width: 768px);
    --s-mq-desk: (min-width: 1024px);
    --s-mq-nav: (min-width: 1200px);       /* section links inline in the nav from here */

    --s-z-photo: 1;
    --s-z-panel: 2;
    --s-z-line: 3;
    --s-z-copy: 4;
    --s-z-grip: 5;
    --s-z-sticky: 20;
    --s-z-nav: 50;

    /* Arrival */
    --s-hero-min-h: 640px;
    --s-hero-min-h-p: 600px;
    --s-hero-pad-top-p: 28px;
    --s-hero-copy-w: 36rem;
    --s-hero-pad-top: clamp(32px, 9vh, 104px);
    --s-hero-edge-p-left: 66%;             /* phone (no JS): panel BOTTOM edge at the left (of hero height)… */
    --s-hero-edge-p-right: 58%;            /* ...and at the right: rising, like the real line */
    --s-tab-gap: 6px;
    --s-tab-h: 52px;
    --s-tab-pad-x: 18px;
    --s-tab-lean: 14px;                    /* hero surface tabs lean on the clean edge */
    --s-tab-rule: 3px;                     /* underline of the hero surface tabs */
    --s-tab-rule-w: 2px;                   /* outline + dividers of the hero segmented control */
    /* Arrival, revision 2: ONE line. site.js places the photo so its real grime line clears the copy by
       a band, then cuts the panel along that same line (desktop: panel above-left of it, bent once up to
       the top edge; phone: panel below it, bent once down to the right edge). */
    --s-hero-line-band: 44px;              /* stroke-free band between the copy and the line, desktop */
    --s-hero-under-gap: 16px;       /* desktop: px between the surface tabs and the proof caption under the line */
    --s-hero-line-band-p: 22px;            /* …and above the H1 on phone */
    --s-hero-clean-p: 0.45;                /* round 5: phone — where the real line falls in the photo under the copy (share of its height) */
    --s-hero-lean: 0.18;                   /* desktop: the panel's one bend (x per y) up to the top edge */
    --s-hero-edge-gap: 48px;               /* desktop: that bend clears the copy's right side by this */

    /* Nav */
    --s-nav-btn-h: 44px;
    --s-nav-btn-pad-x: 16px;
    --s-nav-gap: clamp(14px, 1.6vw, 28px);
    --s-sheet-max: 32rem;

    /* The difference */
    --s-stage-col: minmax(0, 1.6fr);
    --s-console-col: minmax(18rem, 1fr);
    --s-seg-h: 52px;
    --s-seg-pad: 4px;
    --s-note-dot: 14px;
    --s-chip-max: 17rem;
    --s-grip-nozzle: 18px;                 /* the nozzle tip under the grip disc */
    --s-track-dash: 2 7;                   /* the line ahead of the marker: dashed soot */
    --s-chip-offset: 18px;

    /* Houses */
    --s-strip-max-h: 62vh;
    --s-strip-label-w: 46rem;              /* the chartreuse headline label inside the strip */
    --s-gauge-needle-w: 4px;
    --s-gauge-hub: 9px;
    --s-gauge-tick: 2px;
    --s-gauge-num: 10px;                   /* dial numerals, in SVG user units */

    /* Pavements / Pools */
    --s-pave-h: min(100svh, 66.66vw);
    --s-pave-panel-w: 44rem;               /* wide + short, so it reads docked to the ground (r2) */
    --s-step-panel: clamp(2.25rem, 1.5rem + 2.2vw, 3.25rem);   /* titles set inside docked panels */
    --s-pool-h: min(88svh, 56.25vw);
    --s-tile-size: clamp(7rem, 8.5vw, 8.5rem);    /* coping tiles: a narrow course, not cards */
    --s-coping-pad: 12px;                  /* the coping strip: slab margin above the tiles */
    --s-coping-joint: 6px;                 /* joint between coping tiles */
    --s-pools-title-w: 14ch;

    /* How we work */
    --s-axis-gap: 34px;                    /* steps sit this far below the axis */
    --s-node: 22px;

    /* Free site visit */
    --s-plan-ratio: 4 / 3;
    --s-step-visit: clamp(2.75rem, 1.2rem + 6vw, 6.5rem);   /* the closing statement, across the cream ground */
    --s-visit-title-w: 16ch;
    --s-lot-dash: 6 5;                     /* the plan's lot boundary */
    --s-detail-ratio: 4 / 3;               /* how-we-work detail photo (detail-*.avif is 4:3) */
    --s-plan-line: 1.5px;
    --s-plan-zone-line: 2px;
    --s-plan-max-p: 20rem;

    /* The clean edge carried through the page (round 5): one diagonal per section boundary,
       the hero's line continued; a clean pass sweeps each photograph the first time it is seen. */
    --s-edge-rise: clamp(36px, 6vw, 96px);        /* height of the diagonal across the full width */
    --s-edge-inset: 5px;                          /* half the stroke, so the line sits inside a clipped edge */
    --s-edge-skew: -12deg;                        /* list bullets: a short cut */
    --s-pass-skew: -18deg;                        /* the pass slab's leading edge */
    --s-dur-pass: 1100ms;
    --s-pass-at: 0.25;                            /* share of a photo on screen before its pass runs */
    --s-label-lean: 56px;                         /* chartreuse labels and docked panels end on the diagonal */
    --s-board-notch: 56px;                        /* the gauge board's cut corner */
    --s-gauge-plate-r: 28px;
    --s-bezel: #5d5b3c;                           /* machined bezel ring on the plate (graphic) */
    --s-plate-shade: #0000004d;                   /* inner shade at the plate's top */
    --s-plate-lip: #f6f9e61a;                     /* light lip under the plate */
    --s-glass: #f6f9e60a;                         /* glass highlight over the dial face */
    --s-dur-squeeze: 260ms;                       /* needle to the top of its range while the trigger is held */
    --s-dur-flutter: 140ms;                       /* a live gauge never sits perfectly still */
    --s-flutter: 0.7deg;
    --s-houses-intro-col: minmax(18rem, 1fr);
    --s-pools-photo-w: 56vw;
    --s-pools-photo-col: 56vw;
    --s-pools-lean: clamp(60px, 8vw, 140px);
    --s-tile-min: 10rem;
    --s-field-h: 52px;
    --s-check: 26px;
}
