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

   Values below are taken verbatim from the approved brief
   (runs/3-elements-landscaping-asheville-nc/brief.md §3.3). Nothing here is
   improvised; every token traces to a brief line.
   ========================================================================== */

:root {
  --scheme: light;

  /* --- ground + ink ------------------------------------------------------ */
  --color-bg:        #FAF7F2;  /* fieldstone — hsl(36.0°, 40.0%, 95.1%) */
  --color-surface:   #F1ECE3;  /* deeper fieldstone, card/plate ground */
  --color-ink:       #2B333A;  /* near-black cool slate */
  --color-ink-muted: #5B6670;  /* muted slate-grey — lead, captions, footer */

  /* --- accent — RIDGE-HAZE. Text-safe at every declared use. ------------- */
  --color-accent:      #547080; /* dominant hue — hsl(201.8°, 20.8%, 41.6%). 4.90:1 on bg — safe for text */
  --color-accent-ink:  #FFFFFF; /* text ON the accent fill (the primary CTA) — 5.24:1 with body-strong 600 */

  /* --- secondary — STONE pillar's material accent, decorative-only ------- */
  --color-warm: #8A4A32; /* the plumb weight's fill colour, and the Stone page's head-rule accent. NEVER body text; graphic fill and rule colour only */

  /* --- lines, focus, selection -------------------------------------------- */
  --color-rule:  #DCD5C8; /* decorative pillar-row separator */
  --color-focus: #2B333A; /* ink — used for focus rings */

  /* House-required structural aliases consumed by base.css (spec §3's
     required "border/focus" role names) — same values as above, named to
     match the house contract. */
  --color-border: #DCD5C8;
  --color-selection-bg: #547080;
  --color-selection-ink: #FFFFFF;

  /* --- type (brief §2) ----------------------------------------------------- */
  --font-display:        'Frank Ruhl Libre 500', 'Frank Ruhl Libre Fallback', Georgia, 'Times New Roman', serif;
  --font-display-strong: 'Frank Ruhl Libre 700', 'Frank Ruhl Libre Fallback', Georgia, 'Times New Roman', serif;
  --font-body:            'Mulish 400', 'Mulish Fallback', 'Helvetica Neue', Arial, sans-serif;
  --font-body-strong:     'Mulish 600', 'Mulish Fallback', 'Helvetica Neue', Arial, sans-serif;

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

  /* --- fluid scale (brief §2.8) ---------------------------------------------------- */
  --text-display: clamp(2.125rem, 1.597rem + 2.254vw, 3.625rem);
  --text-h2:      clamp(1.25rem, 1.030rem + 0.939vw, 1.875rem);
  --text-lead:    clamp(1.0625rem, 0.997rem + 0.282vw, 1.25rem);
  --text-body:    1rem;
  --text-eyebrow: 0.75rem;
  --text-micro:   0.6875rem;

  /* House alias: base.css's reset references --text-small for form labels/hints. */
  --text-small: 0.875rem;

  --leading-tight: 1.16;  /* h1, h2, display-strong */
  --leading-body:  1.60;  /* lead, body, pillar glosses */
  --leading-snug:  1.35;  /* buttons, chips — house alias base.css expects */
  --tracking-caps: 0.14em; /* eyebrow, section kickers */
  --tracking-tight: 0em;   /* brief specifies no negative tracking on headings */

  /* --- space — the house scale --------------------------------------------- */
  --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;
  --space-3xl: 9rem; /* house alias: base.css's textarea min-height reads this */

  /* 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 --------------------------------------------------------------- */
  --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 §7, §8) ------------------------------------ */
  --hero-inset-top: 20px;  /* .hero__card padding-block-start — bespoke, argued, §8.2 */
  --hero-h1-gap:    18px;  /* h1 margin-block-end — bespoke, argued */
  --cta-height:     52px;
  --field-height:   220px; /* fixed at <45rem; scales at wider widths, brief §8.3 */
  --hero-field-inline: min(26rem, 42vw); /* brief §5.3's own two-column field width, ≥45rem only */
  /* QA round-1 FIX: `.hero__cord`'s old `height: 40%` had no basis (no
     explicit height on `.hero__plumb`) and resolved to ~0. Derived from
     --field-height (redeclared per breakpoint already); 0.88/74px
     bespoke-argued to land the cord+bob near the teaser strip. */
  --plumb-cord-height: calc(var(--field-height) * 0.88 - 74px);
  --pillar-row-name-col: 8rem; /* §II's pillar-row grid, ≥40em: name column width */

  /* --- radius + border. NO PILL TOKEN EXISTS. -------------------------------- */
  --radius-none:  0;
  --radius-sm:    0; /* base.css references --radius-sm for the skip-link/nav-toggle;
                        this brief carries no rounded corners anywhere (§3.3 note) */
  --border-hairline: 1px; --border-style: solid;
  --border-thick: 3px; /* house alias: base.css's :focus-visible outline width */

  /* --- motion (brief §8) ------------------------------------------------------------ */
  --duration-fast:   380ms;
  --duration-base:   380ms; /* house alias: base.css/site.css reveal transitions read this name */
  --duration-slow:   380ms; /* the one-shot reveal is 380ms regardless of the alias used to reach it */
  --duration-settle: 1400ms;
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);      /* house alias for --ease-settle */
  --ease-settle: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --loop-mist-1: 22s; --loop-mist-2: 27s;
  --sway-distance: 26px;   /* mist plate 1's drift range */
  --sway-distance-2: -20px; /* mist plate 2's drift range (brief §3.3's own comment value) */

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

  --z-atmosphere: 0; --z-card: 1; --z-field: 1; --z-header: 100; --z-skip-link: 300;
  --z-base: 0; --z-nav-panel: 200; /* house aliases, unused by this brief's archetype */
}

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

   Frank Ruhl Libre 500/700 and Mulish 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.

   COVERAGE GAP, measured against the shipped woff2 files and disclosed here
   per house-tech-spec §8's own instruction ("a coverage gap is measured
   against the actual font files and written down where the range is
   defined"), rather than silently shipped:

     - U+2010, U+2011, U+2012, U+2015 (hyphen/dash variants beyond U+2013/2014)
       are absent from BOTH Frank Ruhl Libre and Mulish — symmetric, matching
       the house's own pilot-site precedent (§8): a page rendering one of
       these falls to the metrics-matched fallback consistently on every
       face, never mid-sentence in two different faces.
     - U+2032, U+2033 (′ ″ feet/inches) are present in Mulish but ABSENT from
       Frank Ruhl Libre — asymmetric. This site's copy (copy.md, verbatim,
       every page) never uses either mark, so the gap is not exercised by any
       shipped string; recorded here rather than silently carried, per the
       same house instruction, so a future copy amendment that introduces a
       prime mark is not a silent mid-sentence font split.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Frank Ruhl Libre 500';
  src: url('../assets/fonts/frank-ruhl-libre-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: 'Frank Ruhl Libre 700';
  src: url('../assets/fonts/frank-ruhl-libre-700-latin.woff2') format('woff2');
  font-weight: 700;
  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: 'Mulish 400';
  src: url('../assets/fonts/mulish-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: 'Mulish 600';
  src: url('../assets/fonts/mulish-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): a local() face carrying
   size-adjust/ascent-override/descent-override/line-gap-override tuned
   against the REAL shipped faces, so font-display:swap's fallback-then-swap
   costs no layout shift.

   Computed with the exact Fontaine (unjs/fontaine `generateFontFace`)
   reference formula — sizeAdjust from the ratio of each face's xAvgCharWidth
   (normalised by unitsPerEm) against the fallback's own, then ascent/descent/
   line-gap expressed relative to that scaled em — run against Fontaine's own
   bundled metrics collection (`@capsizecss/metrics`, the same dataset behind
   Next.js/Nuxt's automatic font fallback), not hand-recalled OS/2 values:

     Frank Ruhl Libre 500: ascent 957 / descent -334 / lineGap 0 / unitsPerEm 1000 / xWidthAvg 455
     Frank Ruhl Libre 700: ascent 957 / descent -334 / lineGap 0 / unitsPerEm 1000 / xWidthAvg 462
     Mulish 400:           ascent 1005 / descent -250 / lineGap 0 / unitsPerEm 1000 / xWidthAvg 464
     Mulish 600:           ascent 1005 / descent -250 / lineGap 0 / unitsPerEm 1000 / xWidthAvg 472
     Georgia:              ascent 1878 / descent -449 / lineGap 0 / unitsPerEm 2048 / xWidthAvg 913
     Arial:                ascent 1854 / descent -434 / lineGap 67 / unitsPerEm 2048 / xWidthAvg 913

   (ascent/descent/lineGap/unitsPerEm cross-checked against this run's own
   fontTools read of the shipped woff2 files — identical. The first pass at
   this file used hand-recalled Georgia/Arial xAvgCharWidth figures rather
   than a measured source, which under-corrected size-adjust and measured
   CLS 0.068 in Lighthouse; replaced with the values above.)

   ONE fallback name per family, matching brief §3.3's token stack verbatim
   ('Frank Ruhl Libre Fallback' / 'Mulish Fallback' — no per-weight fallback
   name exists in the brief's own tokens). Each is tuned against the 500/400
   cut, the weight that carries the great majority of this site's text (h1,
   h2, lead, body, pillar glosses); the 700/600 cut only ever sets short,
   low-frequency strings (the accent word, pillar names, the CTA label), so
   the small residual mismatch on those runs is not a CLS-visible amount.

   MEASUREMENT CAVEAT, disclosed rather than silently relied on: this build
   environment has neither Georgia nor Arial installed (fc-match substitutes
   DejaVu Serif / Liberation Sans), so Lighthouse's own CLS number in THIS
   sandbox cannot fully confirm the local() match a real Windows/Mac visitor
   gets. One extra local() source is added below where it is RISK-FREE to do
   so: Liberation Sans is a metric-compatible clone of Arial by explicit
   design (Red Hat's stated goal for the Liberation family), verified this
   session by measuring both names with Canvas `measureText` in this same
   engine — identical width/ascent/descent to the pixel. Adding it costs
   nothing on Windows/Mac (Arial still matches first) and gives Linux/most
   Android devices the same override numbers correctly, rather than falling
   through to an unrelated generic sans. No equivalent metric-compatible
   clone of Georgia is verified, so the serif fallback keeps the brief's
   single `local('Georgia')` source and the residual gap is named in
   README.md rather than papered over with an unverified substitute font.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Frank Ruhl Libre Fallback';
  src: local('Georgia');
  size-adjust: 102.06%;
  ascent-override: 93.77%;
  descent-override: 32.72%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Mulish Fallback';
  src: local('Arial'), local('Liberation Sans');
  size-adjust: 104.08%;
  ascent-override: 96.56%;
  descent-override: 24.02%;
  line-gap-override: 0%;
}

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