/* ==========================================================================
   tokens.css — the design brief, compiled.

   Values below are taken verbatim from the approved brief
   (runs/pro-landscapers-fargo-nd/brief.md §3.3, §2.6-2.8, §5.3). Nothing here
   is improvised; every token traces to a brief line or is flagged as a
   Builder-added house alias, argued below.
   ========================================================================== */

:root {
  --scheme: light;

  /* --- ground + ink (brief §3.3) ----------------------------------------- */
  --color-bg:        #F7F3EA;  /* prairie cream — L 0.8982 */
  --color-surface:   #EDE6D6;  /* deeper cream — card/plate ground */
  --color-ink:       #2B2A26;  /* warm near-black — L 0.0231 */
  --color-ink-muted: #656058;  /* muted warm grey — L 0.1184 */
  --color-rule:      #E2D9C4;  /* decorative hairline between index rows */

  /* --- accent — PRAIRIE-SKY. Dominant hue. Text-safe only at large sizes. */
  --color-accent:      #5C7F94; /* hsl(200.0°, 26.7%, 49.0%). 3.86:1 on bg — LARGE TEXT / decorative only, >=24px (brief §4.1 F3) */
  --color-cta-fill:    #3F5C6E; /* prairie-sky, deep cut — CTA fill only. 5.44:1 as text on bg; 7.07:1 for white text on this fill (F4/F5) */
  --color-accent-ink:  #FFFFFF; /* text ON --color-cta-fill */

  /* --- secondary — the vertical's semantic anchor, carried by IMAGERY only, never the dominant hue (brief §3.2) --- */
  --color-shelter: #5C7A52; /* shelterbelt-green — the hero's tree silhouettes and the outdoor-room index's dot marks. NEVER body text; graphic fill only (R4) */

  /* --- hero atmosphere fallback (shown before the generated plate loads, or if it fails) --- */
  --color-atmosphere-top:    #D9E6EC;
  --color-atmosphere-mid:    #E9E2CC;
  --color-atmosphere-bottom: #F2ECDB;

  /* House-required structural aliases (consumed by base.css). Brief §4.2 N2
     validates --color-ink at 12.97:1 on bg as the focus-ring pairing, so the
     alias below is that same value, not a new colour. */
  --color-border: #E2D9C4;   /* = --color-rule (brief §3.3); hairlines, field borders */
  --color-focus:  #2B2A26;   /* = --color-ink (brief §4.2 N2, 12.97:1) */
  --color-selection-bg:   #3F5C6E; /* = --color-cta-fill */
  --color-selection-ink:  #FFFFFF;

  /* --- type (brief §2.6) --------------------------------------------------- */
  --font-display:        'Jost 500', 'Jost Fallback', 'Century Gothic', 'Futura', sans-serif;
  --font-display-strong: 'Jost 600', 'Jost Fallback', 'Century Gothic', 'Futura', sans-serif;
  --font-body:            'Hanken Grotesk 400', 'Hanken Grotesk Fallback', 'Helvetica Neue', Arial, sans-serif;
  --font-body-strong:     'Hanken Grotesk 600', 'Hanken Grotesk Fallback', 'Helvetica Neue', Arial, sans-serif;

  /* House-required weight tokens (spec §3), matching brief §2.7's roles.
     R7: 700 is never requested against Hanken Grotesk; only 400/600 load. */
  --font-weight-body: 400;
  --font-weight-body-strong: 600;
  --font-weight-display: 500;
  --font-weight-display-strong: 600;

  /* --- fluid scale (brief §2.8) ---------------------------------------------------- */
  --text-display: clamp(2rem, 1.516rem + 2.066vw, 3.375rem);
  --text-h2:      clamp(1.25rem, 1.074rem + 0.751vw, 1.75rem);
  --text-lead:    clamp(1rem, 0.956rem + 0.188vw, 1.125rem);
  --text-body:    1rem;
  --text-eyebrow: 0.75rem;
  --text-micro:   0.6875rem;

  /* House alias: base.css/site.css read --text-small for form labels/hints
     and small nav/footer copy. Brief §2.8 does not name a distinct step for
     this role; set to the house's usual small step (unchanged value used on
     every prior registry row's own --text-small), not a new size decision. */
  --text-small: 0.875rem;

  --leading-tight: 1.2;   /* h1, h2, display-strong — brief §2.8 */
  --leading-body:  1.6;   /* lead, body, room glosses — brief §2.8 */
  /* House alias: base.css/site.css read --leading-snug for buttons/chips
     line-height. Brief §2.8 names tight/body only; carried at the house's
     usual value (unchanged mechanical default, not a new type decision). */
  --leading-snug:  1.35;
  --tracking-caps: 0.14em; /* eyebrow, section kickers — brief §2.8 */
  /* House alias: base.css reads --tracking-tight for heading letter-spacing.
     Brief §2.8 states no negative tracking anywhere on this site, so this
     resolves to zero rather than being left undefined. */
  --tracking-tight: 0em;

  /* --- space — the house scale (brief §3.3) -------------------------------------------- */
  --space-3xs: 0.25rem; --space-2xs: 0.5rem;  --space-xs: 0.75rem;
  --space-sm:  1rem;    --space-md:  1.5rem;  --space-lg: 2.5rem;
  --space-xl:  4rem;    --space-2xl: 6rem;
  /* House alias: site.css's textarea min-height reads --space-3xl, the same
     house scale step every prior registry row carries; brief §3.3 did not
     need to restate it because nothing else on this site calls it. */
  --space-3xl: 9rem;

  /* design-rules §7.1's ONE inter-section token. Two call sites only:
     .section's padding-block, and .hero's padding-block-end. */
  --section-gap: var(--space-xl);   /* 64px, fixed, at every width */

  /* --- layout (brief §3.3) --------------------------------------------------------- */
  --layout-container:     72rem;
  --layout-measure:       58ch;
  --layout-gutter:        clamp(1.25rem, 6vw, 3rem);
  --layout-tap-min:       44px;
  --layout-header-height: calc(var(--layout-tap-min) + var(--space-xs));  /* 56px min */

  /* --- the hero atmosphere field (brief §3.3, §5.3) ----------------------------------- */
  --hero-inset-top: 20px;  /* .hero__card padding-block-start — bespoke, argued, brief §3.3 */
  --hero-h1-gap:    18px;  /* h1 margin-block-end — bespoke, argued */
  --cta-height:     52px;
  --field-height:   210px; /* fixed at <45rem; scales at wider widths, brief §5.3 */
  --hero-field-inline: min(26rem, 42vw); /* brief §5.3's two-column field width, >=45rem only */
  /* Bespoke, argued (same status as --hero-inset-top/--hero-h1-gap above):
     the shelterbelt silhouette's own rendered height, sized by eye against
     --field-height (210/320/300px across breakpoints) so the row reads
     clearly at every size without crowding the teaser strip beneath it
     (brief §8's "legible, sharply-rendered foreground layer"). Width follows
     the symbol's own 32:48 viewBox ratio via CSS aspect-ratio, not a second
     token. */
  --shelterbelt-tree-h: 56px;
  /* Bespoke, argued: §II's outdoor-room index row name column, >=40em only
     (same status/pattern as 3-elements-landscaping-asheville-nc's own
     --pillar-row-name-col for an identical editorial-index layout). */
  --rooms-name-col: 12rem;

  /* --- radius + border. NO PILL TOKEN EXISTS ON THE CTA (brief §3.3). -------------------- */
  --radius-cta: 26px;   /* the tile's own rounded CTA — a rounded rectangle, kept as specified */
  --radius-chip: 14px;
  /* House alias: base.css's :focus-visible ring reads --radius-sm. Brief
     §3.3 doesn't name this role; sized down from --radius-chip to match the
     site's own rounded language. */
  --radius-sm: 6px;
  --border-hairline: 1px; --border-style: solid;
  /* House alias: base.css's :focus-visible outline-width reads --border-thick.
     Brief §3.3 does not restate it; house default (3px) carried unchanged. */
  --border-thick: 3px;

  /* --- motion (brief §3.3, §8) ------------------------------------------------------------ */
  --duration-fast: 380ms;
  /* House aliases: base.css's reveal system reads --duration-base/--duration-slow
     and --ease-out. Brief §8's one-shot reveal is 380ms regardless of which
     alias reaches it (the same convention every prior registry row uses). */
  --duration-base: 380ms;
  --duration-slow: 380ms;
  --ease-standard: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);

  /* Reveal geometry — house alias consumed by base.css's [data-reveal] rules. */
  --reveal-shift: 8px; /* --space-2xs, brief §8's one-shot fade-and-rise distance */
  --reveal-stagger: 90ms; /* house default, unchanged mechanical constant */

  /* Shelterbelt sway — brief §3.3, §8. Four periods sharing no small common
     factor; two amplitudes (the "sway1"/"sway2" keyframe pair brief §8
     describes: Trees 1 and 3 sway +/-1.4deg, Trees 2 and 4 sway +/-1.1deg). */
  --sway-1a: 7.5s;  --sway-1b: 6.9s;   /* the two "sway1" keyframe periods, staggered */
  --sway-2a: 8.8s;  --sway-2b: 9.6s;   /* the two "sway2" keyframe periods, staggered */
  --sway-amplitude:   1.4deg; /* Trees 1 and 3 (brief §8) */
  --sway-amplitude-2: 1.1deg; /* Trees 2 and 4 (brief §8) — Builder-added token,
                                  transcribing the brief's own second stated
                                  amplitude rather than inventing a new value */
  /* Per-tree animation-delay, transcribing brief §8's own stated offsets
     ("0.4s offset start" / "0.8s offset start") verbatim. */
  --sway-delay-1: 0s;
  --sway-delay-2: 0s;
  --sway-delay-3: 0.4s;
  --sway-delay-4: 0.8s;

  /* --- z layers (brief §3.3) -------------------------------------------------------- */
  --z-atmosphere: 0; --z-card: 1; --z-field: 1; --z-header: 100; --z-skip-link: 300;
  /* House aliases, unused by this brief's archetype (no full-screen nav panel). */
  --z-base: 0; --z-nav-panel: 200;
}

/* --------------------------------------------------------------------------
   @font-face — self-hosted woff2, latin subset, font-display: swap.

   Jost 500/600 and Hanken Grotesk 400/600, SIL OFL 1.1 (assets/fonts/OFL.txt).
   Every face is subset to the house declared safe range (house-tech-spec §8)
   and declares that exact range in unicode-range — identical on all four
   files, measured directly against the shipped woff2 with fontTools (not
   assumed): all four faces are MISSING the same six codepoints from the
   declared range — U+2010, U+2011, U+2012, U+2015, U+2032, U+2033 — a fully
   SYMMETRIC gap (every face lacks exactly the same six), so a page rendering
   any of them falls to the metrics-matched fallback consistently across every
   face, never mid-sentence in two different faces (house-tech-spec §8's own
   disclosure rule). This site's copy (copy.md, verbatim, every page) never
   uses any of the six, so the gap is not exercised by any shipped string.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Jost 500';
  src: url('../assets/fonts/jost-500-latin.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0, U+00A9, U+00AE, U+2122, U+00B0, U+00B7,
    U+00BF, U+00C0-00FF, U+2010-2015, U+2018-201A, U+201C-201E, U+2026, U+2032-2033;
}

@font-face {
  font-family: 'Jost 600';
  src: url('../assets/fonts/jost-600-latin.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0, U+00A9, U+00AE, U+2122, U+00B0, U+00B7,
    U+00BF, U+00C0-00FF, U+2010-2015, U+2018-201A, U+201C-201E, U+2026, U+2032-2033;
}

@font-face {
  font-family: 'Hanken Grotesk 400';
  src: url('../assets/fonts/hanken-grotesk-400-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0, U+00A9, U+00AE, U+2122, U+00B0, U+00B7,
    U+00BF, U+00C0-00FF, U+2010-2015, U+2018-201A, U+201C-201E, U+2026, U+2032-2033;
}

@font-face {
  font-family: 'Hanken Grotesk 600';
  src: url('../assets/fonts/hanken-grotesk-600-latin.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0, U+00A9, U+00AE, U+2122, U+00B0, U+00B7,
    U+00BF, U+00C0-00FF, U+2010-2015, U+2018-201A, U+201C-201E, U+2026, U+2032-2033;
}

/* --------------------------------------------------------------------------
   Metrics-matched fallbacks (house-tech-spec §7/§8, brief §2.4). Full
   derivation and the Jost-fallback escalation reasoning are in README.md —
   kept out of this shipped file to hold the CSS budget (spec §7).

   Hanken Grotesk Fallback — MEASURED (scripts/font-metrics.mjs, 2026-08-30)
   against the real hanken-grotesk-400-latin.woff2 and this environment's own
   installed Liberation Sans (verified clone of Arial: ascent/descent/lineGap/
   unitsPerEm match Arial's published figures exactly). size-adjust 101.56%,
   ascent-override 98.47%, descent-override 29.84%, line-gap-override 0%.

   Jost Fallback — ESCALATED, not fabricated. Brief §2.4 names Century
   Gothic/Futura, which are absent from every metrics source this session
   could reach (not installed here; absent from @capsizecss/metrics and from
   fontaine's own bundled dataset; no published OS/2 table found). Shipped
   below WITHOUT override properties rather than with invented numbers — see
   README.md and the Builder's handoff report for the full reasoning. */

@font-face {
  font-family: 'Hanken Grotesk Fallback';
  src: local('Helvetica Neue'), local('Arial'), local('Liberation Sans');
  size-adjust: 101.56%;
  ascent-override: 98.47%;
  descent-override: 29.84%;
  line-gap-override: 0%;
}

/* ESCALATED — see the long comment above. No override properties: shipping
   fabricated numbers against an unmeasured pair of proprietary fonts is a
   worse defect than an honest, disclosed gap (CLAUDE.md's fabrication wall,
   applied to font metrics the same way it applies to business facts). */
@font-face {
  font-family: 'Jost Fallback';
  src: local('Century Gothic'), local('Futura');
}

/* --------------------------------------------------------------------------
   Breakpoint-conditional token override — brief §5.3's own two breakpoints
   (45rem / 64rem), not the house's generic 48em/64em (base.css). Media-query
   conditions cannot read custom properties, so the breakpoint VALUE is the
   one house-documented literal exemption; the property itself stays a token,
   redeclared at :root.
   -------------------------------------------------------------------------- */
@media (min-width: 45rem) {
  :root { --field-height: 320px; }
}

@media (min-width: 64rem) {
  :root { --field-height: 300px; }
}
