/* ============================================================================
   LoneStarLower — design tokens
   ----------------------------------------------------------------------------
   Single source of truth for color, type, spacing, radius, and motion,
   consumed by both app/ (React SPA) and site/ (static content, built in a
   later prompt). Nothing outside this file defines a color, font size,
   spacing value, or radius — shared/tokens/lint.js fails the build on any
   value it finds outside here.

   PROVENANCE: values were extracted from the real app/protest-app.jsx demo,
   not invented, and reconciled against shared/DESIGN_SYSTEM.md's illustrative
   brief. Where they disagreed, the demo won — except the four corrections in
   the brief's §7, which are deliberate and documented inline below. Every
   token that has no demo equivalent (i.e. is genuinely new) is marked NEW
   with its justification. Full reconciliation table: shared/tokens/README.md.

   Named by ROLE, never by appearance — "surface-raised", not "off-white" —
   so a palette change never requires a find/replace of every reference.
============================================================================ */

/* ---------------------------------------------------------------------------
   Fonts — self-hosted, latin-subset, no CDN (DESIGN_SYSTEM.md §8).
   The demo loaded these from a Google Fonts CDN @import; that's the one
   demo behavior this file deliberately does NOT carry forward, because §8
   is explicit ("No font CDN") and CDN loading is a performance regression,
   not an aesthetic choice. Archivo ships as a single variable-weight file
   (400-800 in one 34KB woff2) — Google serves it that way already, so
   self-hosting it as one file rather than five is not a regression, it's
   strictly less payload than static per-weight files would be. Space Mono
   has no variable axis on Google Fonts, hence two static files.
--------------------------------------------------------------------------- */
@font-face {
  font-family: "Archivo";
  src: url("./fonts/archivo-variable-latin.woff2") format("woff2-variations"),
       url("./fonts/archivo-variable-latin.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Space Mono";
  src: url("./fonts/space-mono-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Space Mono";
  src: url("./fonts/space-mono-700-latin.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ==========================================================================
     COLOR — raw palette (role-named, not appearance-named)
  ========================================================================== */

  /* Surfaces */
  --surface-canvas: #F4F5F1;   /* demo `paper` — page background, warm greige */
  --surface-raised: #FBFCFA;   /* demo `card` — cards, the app frame */
  --surface-sunken: #ECEDE7;   /* NEW: no demo equivalent existed (no data tables
                                   yet in a single-screen app). Derived by
                                   interpolating between surface-canvas and
                                   border-default, same warm-greige family, for
                                   table zebra rows and inset blocks (Task 4). */

  /* Ink (text) — the demo has two tiers (ink/inkSoft); the brief's component
     vocabulary (attribution blocks, mono labels on data tables) needs a third,
     distinct from body-supporting prose. See ink-muted below. */
  --ink-primary: #16202B;      /* demo `ink` — headlines, body */
  --ink-secondary: #59636E;    /* demo `inkSoft` — supporting prose */
  --ink-muted: #67717C;        /* NEW: split out of inkSoft's overloaded dual
                                   role (prose vs. metadata). The brief's own
                                   illustrative value (#8A8F93) measures ~3.1:1
                                   against surface-canvas — fails WCAG AA for
                                   normal text, and §3 requires attribution to
                                   be legible with "deliberate presence," not
                                   decorative grey. This is the lightest value
                                   in the same hue ramp as ink-secondary that
                                   still clears 4.5:1 on both surface-canvas and
                                   surface-raised — see contrast_check.py. */

  /* Brand */
  --brand-primary: #0E6E4E;         /* demo `green` — wins outright over the
                                        brief's illustrative #2F6B4F: real value,
                                        darker and more saturated. */
  --brand-primary-hover: #0C5E42;   /* NEW: demo had no distinct hover state —
                                        derived by darkening brand-primary ~15%,
                                        the standard "held" step. */
  --accent-soft: #EAF3ED;           /* demo `greenWash` — chip backgrounds */
  --brand-primary-on-dark: #12915F; /* NEW (app retrofit, DESIGN_SYSTEM.md §9):
                                        demo `greenBright` — brand-primary itself
                                        measures only 2.63:1 against ink-primary,
                                        fails AA even at large-text size; this
                                        value measures 4.11:1 and is the ONLY
                                        approved green for text on a dark/ink
                                        surface (Reveal's hero figure). Never use
                                        brand-primary for text on ink-primary. */

  /* Borders */
  --border-default: #E1E5DD;   /* demo `line` */
  --border-strong: #CDD3C8;    /* demo `lineHard` — used ONLY for border/
                                   emphasis now. The demo also reused this
                                   value as the disabled-CTA background; that
                                   collision is exactly the §7.1 correction —
                                   see --state-disabled below. */

  /* State */
  --state-disabled-bg: #BFC7BE;   /* NEW: the brief's illustrative value,
                                      adopted because no demo value existed for
                                      this role separately from border-strong —
                                      see the border-strong note above. */
  --state-disabled-fg: var(--ink-secondary); /* was `#fff` on the old shared
                                      lineHard background in the demo, which
                                      measured 1.53:1 — nearly invisible. WCAG
                                      1.4.3 exempts disabled controls from the
                                      AA floor, but "exempt" isn't the bar; see
                                      contrast_check.py for the before/after. */
  --state-error: #B5432E;          /* demo `brick` */
  --state-error-soft: #F6ECE8;     /* demo `brickWash` */
  --state-error-border: #E6CFC6;   /* demo's brickWash border variant (seen on
                                       the self-reported-value note in Reveal) */
  --accent-gold: #A87C3D;          /* demo `gold` — disclaimer left-border accent */
  --accent-soft-border: #CDE6D8;   /* NEW (app retrofit): demo reused this exact
                                       value twice (NoCase panel, accent Stat
                                       card) as a border a shade more saturated
                                       than accent-soft's fill — a real, reused
                                       role ("positive/success border"), not a
                                       one-off. */

  /* Reveal's hero card (dark, ink-primary background) is the app's only
     dark surface — none of the light-surface ink/border tokens above are
     legible on it. NEW namespace, all justified by the app retrofit: every
     value below is the demo's own, just named by role instead of left as a
     literal. Two near-identical demo greys (#9aa6ad and #8f9aa1, a few RGB
     units apart) collapse into one (--ink-on-dark-soft) per DESIGN_SYSTEM.md
     §10's "collapse near-duplicate greys" instruction. */
  --ink-on-dark: #FFFFFF;          /* primary text/elements on ink-primary */
  --ink-on-dark-soft: #9aa6ad;     /* secondary labels/captions on ink-primary
                                       (also covers demo's #8f9aa1 — collapsed) */
  --ink-on-dark-strike: #B8C1C7;   /* struck-through de-emphasis (old value) */
  --border-on-dark: #33404a;       /* hairline borders on ink-primary (the
                                       distance pill) */
  --track-on-dark: #2b3742;        /* progress-track base on ink-primary */

  /* ==========================================================================
     COLOR — semantic aliases (components reference these, never raw palette)
  ========================================================================== */
  --cta-bg: var(--brand-primary);
  --cta-bg-hover: var(--brand-primary-hover);
  --cta-fg: #FFFFFF;
  --cta-bg-secondary: var(--ink-primary);   /* lower-emphasis actions — this was
                                                the demo's default CTA tone; see
                                                README §7.1 for why the primary
                                                CTA is standardized on green now */
  --cta-disabled-bg: var(--state-disabled-bg);
  --cta-disabled-fg: var(--state-disabled-fg);
  --attribution-fg: var(--ink-muted);
  --focus-ring: var(--brand-primary);

  /* ==========================================================================
     TYPE
  ========================================================================== */
  --font-display: "Archivo", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-mono: "Space Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  /* No third family. The demo used Inter for body/UI text — the brief is
     explicit ("Two families, no third") and separately requires body prose to
     be "the display family at regular weight, not mono" (§4), so Inter is
     retired in the token system: body text uses --font-display at
     --weight-regular. This changes app/protest-app.jsx's actual font stack —
     that swap happens in the app-retrofit prompt (§9), not here; this file
     only defines what the token *should* be. */

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --weight-black: 800;

  /* Fluid scale, ~1.25 ratio, clamp()'d between a small and a roomy viewport.
     text-base is deliberately larger than the demo's app-UI body text (13.5px)
     — content pages are reading pages (brief §4: "17–18px... these are
     reading pages"), the app's own compact UI text is a separate, smaller
     concern the retrofit prompt reconciles. */
  --text-xs: clamp(0.6875rem, 0.66rem + 0.12vw, 0.75rem);    /* 11–12px: attribution */
  --text-sm: clamp(0.75rem, 0.72rem + 0.15vw, 0.8125rem);    /* 12–13px: labels, chips */
  --text-base: clamp(1rem, 0.94rem + 0.3vw, 1.125rem);       /* 16–18px: body */
  --text-lg: clamp(1.125rem, 1.06rem + 0.35vw, 1.3125rem);   /* 18–21px: lede */
  --text-xl: clamp(1.375rem, 1.28rem + 0.5vw, 1.625rem);     /* 22–26px: h3 */
  --text-2xl: clamp(1.75rem, 1.58rem + 0.9vw, 2.125rem);     /* 28–34px: h2 */
  --text-3xl: clamp(2.125rem, 1.85rem + 1.4vw, 2.75rem);     /* 34–44px: h1 */
  --text-4xl: clamp(2.5rem, 2.05rem + 2.3vw, 3.5rem);        /* 40–56px: hero / big stat numeral */

  --leading-tight: 1.15;   /* display headlines, 1.1–1.2 per brief */
  --leading-normal: 1.6;   /* body */

  /* Letter-spacing / tracking — not one of §4's five named categories, but
     lint.py's own hardcoded-value rule doesn't distinguish "categorized" from
     "real repeated value" (DESIGN_SYSTEM.md §10's actual invariant: "every
     raw value lives in tokens.css and nowhere else"). NEW (app retrofit):
     the 6 distinct values already in use across components.css (P0.5) and
     the app — negative tracking tightens display headlines/numerals, positive
     tracking widens uppercase mono labels. */
  --tracking-tight: -0.01em;      /* CTA label, h4 */
  --tracking-tighter: -0.02em;    /* wordmark, stat numerals */
  --tracking-tightest: -0.025em;  /* h1/h2/h3 */
  --tracking-display: -0.03em;    /* hero numerals ($39, the reveal figure) */
  --tracking-wide: 0.04em;        /* mono meta caps (step counter, field labels) */
  --tracking-wider: 0.05em;       /* mono uppercase labels (Label/.lsl-label) */

  --measure-prose: 70ch;   /* 68–72ch per brief */
  --min-touch-target: 2.75rem;  /* 44px — WCAG 2.5.5 floor (DESIGN_SYSTEM.md §8),
                                    an external compliance constant rather than a
                                    design decision, but tokenized anyway since it
                                    recurs (inputs, buttons) and the lint rule
                                    treats any bare px value the same regardless
                                    of its reason for existing. */

  /* ==========================================================================
     TYPE — app-compact scale (App retrofit, DESIGN_SYSTEM.md §9)

     The scale above is tuned for content pages (see --text-base's comment:
     "larger than the demo's app-UI body text"). The app is a fixed ~400px-
     wide card, not a reading page, and its own inventory turned up 21
     distinct ad hoc font sizes (9 through 40px) — the same "near-duplicate
     sizes" drift DESIGN_SYSTEM.md's extraction table already flagged for the
     content scale. These 12 steps collapse that 21 down by role, FIXED px
     (not fluid clamp()) because the card doesn't meaningfully respond to
     viewport width the way a content page does. Every step is named for
     its role in the card, not "small/medium/large".
  ========================================================================== */
  --text-app-2xs: 0.594rem;   /* 9.5px  — micro badges (dist pill, chart ticks) */
  --text-app-xs: 0.656rem;    /* 10.5px — mono meta (header CAD tag, step counter, Label) */
  --text-app-sm: 0.719rem;    /* 11.5px — footnotes, disclosure asides */
  --text-app-base: 0.781rem;  /* 12.5px — captions, secondary buttons, tab labels */
  --text-app-md: 0.844rem;    /* 13.5px — body paragraphs, notice/banner text */
  --text-app-lg: 0.906rem;    /* 14.5px — inputs, form titles */
  --text-app-xl: 0.969rem;    /* 15.5px — wordmark, CTA label, old-value strike */
  --text-app-2xl: 1.125rem;   /* 18px   — Confirm headline, stat numerals, icons */
  --text-app-3xl: 1.375rem;   /* 22px   — nav chevron */
  --text-app-4xl: 1.5625rem;  /* 25px   — H1 (the card's one headline per screen) */
  --text-app-5xl: 2.125rem;   /* 34px   — Unlock's $39 price */
  --text-app-6xl: 2.5rem;     /* 40px   — Reveal's hero defensible-value figure */

  /* ==========================================================================
     EFFECTS — shadow. Not one of §4's five categories (color/type/spacing/
     radius/motion); the app has exactly one real shadow (the card frame) and
     it's worth a token anyway rather than a lint-exempt literal, since "every
     raw value lives in tokens.css" is the actual invariant this file exists
     to hold. NEW, single use. Its rgba channel is ink-primary's own RGB
     (22,32,43) at 28% — not a coincidence, the demo derived it that way.
  ========================================================================== */
  --shadow-card: 0 18px 50px -20px rgba(22, 32, 43, 0.28);

  /* ==========================================================================
     PRINT — the filed documents (letter + Form 50-132) must render as a
     neutral black-on-white formal filing, not branded UI; an appraisal
     review board receiving a brand-green legal letter reads as unserious.
     This is a deliberately SEPARATE palette/font namespace from the app's
     brand tokens above, used only by LetterDoc/FormDoc's print output (see
     app/protest-app.jsx's docBase). Collapses the demo's 7 raw print greys
     (#000/#333/#444/#999/#eee/#f4f4f4/#fff) into 6 — #333 and #444 were
     genuinely redundant (both used once, both "secondary print text") and
     collapse into one; the rest are distinct roles (rule vs. zebra vs.
     inset-tint vs. page bg) kept separate. NEW, justified per DESIGN_SYSTEM.md
     §10 exactly like the app-compact scale above.
  ========================================================================== */
  --print-ink: #000000;
  --print-ink-soft: #444444;
  --print-rule: #999999;
  --print-surface-zebra: #EEEEEE;
  --print-surface-tint: #F4F4F4;
  --print-bg: #FFFFFF;
  --font-print-serif: "Times New Roman", Georgia, serif;   /* the letter */
  --font-print-sans: Arial, sans-serif;                     /* Exhibit A / Form 50-132 */

  /* ==========================================================================
     SPACING — 4px base
  ========================================================================== */
  --space-1: 0.25rem;   /* 4px */
  --space-2: 0.5rem;    /* 8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-5: 1.5rem;    /* 24px */
  --space-6: 2rem;      /* 32px */
  --space-7: 3rem;      /* 48px */
  --space-8: 4rem;      /* 64px */
  --space-9: 6rem;      /* 96px */

  /* ==========================================================================
     RADIUS — one family, no mixing. The demo used eight different ad hoc
     values (7/9/10/13/14/16/20/26px); every one collapses into exactly one
     of these three per DESIGN_SYSTEM.md §4 ("One family, no mixing").
  ========================================================================== */
  --radius-sm: 0.5rem;      /* 8px — inputs, chips */
  --radius-md: 0.75rem;     /* 12px — cards */
  --radius-pill: 999px;     /* chips only */

  /* ==========================================================================
     MOTION — state transitions only. No entrance animation, no counters (the
     demo's `riseIn` fade-in and `useCountTo` number-count-up both violate
     this directly — see shared/tokens/README.md; removing them from the app
     is in scope for the retrofit prompt, not this token file).
  ========================================================================== */
  --motion-fast: 120ms;
  --motion-base: 160ms;
  --motion-slow: 180ms;
  --motion-ease: cubic-bezier(0, 0, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: 0ms;
    --motion-base: 0ms;
    --motion-slow: 0ms;
  }
}
