/* FenceCalc Pro — v2 design-system tokens, ported to this repo's convention.
 *
 * **Source of truth is the design bundle's `tokens/*.css`, not the handover prose.** Every
 * value below was read from `tokens/colors.css`, `tokens/typography.css` and `tokens/layout.css`
 * inside `FenceCalc Pro Design System (1).zip`. Where the prose and the token files disagreed,
 * the token files won — see the two notes marked CORRECTION.
 *
 * **It is wired into the four `ui/v2` screens and the component harness — not into the running
 * app.** The "not wired into anything" this paragraph used to open with was true when the file
 * landed and stopped being true when the v2 screens started linking it; corrected 2026-08-17
 * while proving phase 0, which is also what made phase 0's "port the design tokens" item
 * already-done rather than outstanding.
 *
 * `ui/app.css` is still untouched and the running app still uses its own `:root`. Adopting
 * these there is a palette decision and the UI hold is on.
 *
 * Namespace: every custom property keeps the bundle's `--fc-` / `--field-` prefix so a value
 * can be traced back to the design system by name alone, and so nothing here can collide with
 * an existing token in `app.css` if the two ever load on one page.
 */

:root {
  /* ── Ground ──────────────────────────────────────────────────────────── */
  --fc-paper: #FAFAF8;        /* app background — warm off-white */
  --fc-well:  #F7F6F2;        /* recessed panels, supplier tiles */
  --fc-calc:  #F4F3EF;        /* engine-calculated value wells */
  --fc-white: #FFFFFF;

  /* ── Ink & marine spine ──────────────────────────────────────────────── */
  --fc-ink:          #1C242B; /* body text */
  --fc-marine:       #173B53; /* primary — sidebar, buttons, headers */
  --fc-marine-hover: #102B3E;
  --fc-marine-deep:  #0E2635; /* pressed / darkest */
  --fc-sky:          #9FE0F0; /* accent on dark (heritage ice, brightened) */
  --fc-sky-soft:     #CFE8F2; /* selection, info tint */

  /* ── Text ramp on light ──────────────────────────────────────────────── */
  --fc-steel: #5E6B75;        /* secondary */
  --fc-mute:  #8B8779;        /* warm muted labels/meta */
  --fc-faint: #A9A499;        /* faintest */

  /* ── Semantic triples ────────────────────────────────────────────────── */
  --fc-green: #0F6A43;  --fc-green-tint: #E4F3EA;
  --fc-red:   #B3401F;  --fc-red-tint:   #FCF1ED;  --fc-red-line:   #E8B4A4;
  --fc-info:  #1E6E96;  --fc-info-tint:  #E9F3F8;

  /* CORRECTION 1 — the amber triple is the NOTICE colour, not the override colour.
     `tokens/colors.css` labels this line `/* override *\/` in its own comment, and
     DESIGN_HANDOVER r1 §5 repeated that label. **Both are wrong**, and r2 corrects it:
     this triple is badges, banners and weekend banding. The field-override state is the
     separate `--field-override-*` pair below. Conflating them puts a notice colour on a
     money cell — and the override tint is the one field state where a wrong colour hides
     that a figure was typed over. */
  --fc-amber: #8A5A16;  --fc-amber-tint: #FCF3E2;  --fc-amber-line: #EAD7AE;

  /* ── Lines ───────────────────────────────────────────────────────────── */
  --fc-line:         #E9E7E1; /* card borders, rules */
  --fc-line-soft:    #F1EFEA; /* row separators */
  --fc-line-strong:  #D9D6CE; /* input borders */
  --fc-line-on-dark: rgba(255, 255, 255, 0.12);

  /* ── On-dark text (marine surfaces) ──────────────────────────────────── */
  --fc-mist:        #A5B9C7;  /* nav resting, captions */
  --fc-mist-strong: #C6D4DE;

  /* ── The four ways a value exists ────────────────────────────────────────
     This is the load-bearing set. An estimator scans for colour to find what they can
     change, and that scan must never mislead. Verified against BOTH `tokens/colors.css`
     and `components/forms/Field.jsx`, which agree exactly. */
  --field-input-bg:     #FFFFFF;              /* you enter */
  --field-input-border: var(--fc-line-strong);
  --field-calc-bg:      var(--fc-calc);       /* engine calculates (ƒ), read-only */
  --field-override-bg:     #FFFDF6;           /* override active */
  --field-override-border: #D9A441;
  --field-attention-bg:     #FCF4F1;          /* needs attention */
  --field-attention-border: #DC9F8C;

  /* CORRECTION 2 — the attention FIELD state is not the semantic red triple.
     Field.jsx uses bg #FCF4F1 / border #DC9F8C, while the semantic red is
     #B3401F/#FCF1ED/#E8B4A4. The dot on an attention field is the semantic red #B3401F
     even though its border is #DC9F8C. Same two-sets shape as the amber pair above. */
  --field-override-dot:  #D9A441;
  --field-attention-dot: #B3401F;

  /* ── The costing sheet's input is a DIFFERENT input, and v2 had only one ──────
     `Field.jsx` and `CostSheet.jsx` disagree deliberately. A form field sits on the paper
     ground with a label beside it, so white on `--fc-line-strong` is enough to say "you
     type here". A costing-sheet cell has **no label and no room for one** — it is one of
     sixty in a dense grid — so there the tint *is* the label, and the design fills it blue:
     `background #FBFDFE`, `border #9FC2D8`.

     ⚠ **v2 pointed the sheet at `--field-input-bg` (white) and the blue vanished.** Three
     sources say blue independently: `CostSheet.jsx`'s `live` style, whose own footer sentence
     reads *"Blue cells are inputs; every other figure recalculates as you type"*;
     `engine/costing_sheet.py`'s docstring, *"NUMBER / TEXT a real input, pale blue #F7FBFC …
     the blue/tan distinction is load-bearing — an estimator scanning for 'what can I change?'
     is scanning for colour"*; and Classic's `--input`, which has carried it since day one.
     One token serving two components that the design gives different values — the same shape
     as `--pad-card` serving `.fc-card` and `.fc-dark`, found earlier in this pass. */
  --sheet-input-bg:     #FBFDFE;
  --sheet-input-border: #9FC2D8;

  /* ── Semantic aliases (the bundle's own) ─────────────────────────────── */
  --text-body:      var(--fc-ink);
  --text-secondary: var(--fc-steel);
  --text-muted:     var(--fc-mute);
  --text-heading:   var(--fc-ink);
  --surface-app:    var(--fc-paper);
  --surface-card:   var(--fc-white);
  --surface-dark:   var(--fc-marine);
  --action-primary:       var(--fc-marine);
  --action-primary-hover: var(--fc-marine-hover);
  --accent:          var(--fc-sky);
  --ok:              var(--fc-green);
  --warn:            var(--fc-amber);
  --danger:          var(--fc-red);
  --focus-ring:      var(--fc-marine);
  --focus-ring-dark: var(--fc-sky);
  --selection:       var(--fc-sky-soft);

  /* ── The site plan ───────────────────────────────────────────────────────
     ⚠ **These were missing entirely, and the failure was invisible.** `ui/v2/site_markup.js`
     reads them through `token()`, whose fallback is `|| "#C0392B"` — so every pin on the
     FenceCalc Pro plan drew in the same red, a corner indistinguishable from a double gate
     from a PA gate, and the run being traced the same colour as a finished one. **The screen
     rendered, nothing errored, and the legend beside it named four things that all looked
     identical.** `ui/app.css` has carried the palette since the plan was built; only Classic
     linked it.

     Named by role rather than by hue, and the reasoning is `app.css`'s own: `--pin-corner` and
     a delete affordance are the same red today and mean opposite things, so they get separate
     names and the day one moves the other stays put. **Kept the same values as `app.css`** —
     two interfaces drawing one plan must not colour it two ways. */
  --pin-corner:    #C0392B;
  --pin-dg:        #C9A227;
  --pin-pa:        var(--fc-marine);
  --pin-condition: var(--fc-amber);
  /* ⚠ **Its own green, deliberately not `var(--fc-green)`.** That is `--plan-trace`, and a
     pin drawn in the colour of the line it sits on is this screen's own founding defect
     wearing a different hue — six tokens once resolved empty and every pin and trace drew
     the same red. The workbook says 🟢 Green (`Input_Quote!M20`); which green is ours, and
     it has to survive being dropped on top of a traced run. */
  --pin-access:    #1E9E5A;
  --plan-trace:          var(--fc-green);
  --plan-trace-idle:     #7FA99B;
  --plan-trace-excluded: #A9B2B5;

  /* ── Type ────────────────────────────────────────────────────────────────
     Two faces. Both vendored under `ui/vendor/` — see `fonts-v2.css`. The bundle's own
     `tokens/fonts.css` @imports the Google CDN; that is mockup convenience and must not
     ship (DESIGN_HANDOVER r2 §6). */
  --font-body:    'Hanken Grotesk', sans-serif;
  --font-mono:    'JetBrains Mono', monospace;
  --font-display: 'Hanken Grotesk', sans-serif;  /* display = heavier weights of the body face */

  --text-base:   14px;
  --text-lead:   15px;
  --text-detail: 13.5px;
  --text-meta:   12.5px;
  --text-fine:   11.5px;
  --leading-body: 1.5;

  /* Sentence case throughout — v2 drops the all-caps display face. */
  --h1: 800 30px/1.1  'Hanken Grotesk', sans-serif;
  --h2: 700 19px/1.25 'Hanken Grotesk', sans-serif;
  --h3: 700 16px/1.3  'Hanken Grotesk', sans-serif;
  --tracking-h1: -0.015em;
  --tracking-h2: -0.01em;
  --label:    600 12px/1.3 'Hanken Grotesk', sans-serif;
  --overline: 700 11px/1.3 'Hanken Grotesk', sans-serif;
  --track-overline: 0.06em;
  /* The kit's other uppercase tracking, and the more common one — 13 uses across the screens
     against `--track-overline`'s six. Table heads, job-strip labels and item-code chips are
     all 0.05em. Two real values in the design, so two tokens: spending one on the other
     would be a token that names the wrong thing, which reads as compliance. */
  --track-caps: 0.05em;
  --numeric: 'JetBrains Mono', monospace;   /* always tabular-nums, right-aligned */

  /* ── Layout & elevation ──────────────────────────────────────────────── */
  --radius-card:    12px;
  /* A document, not a card. `ClientQuote.jsx` sets the printed quote to 4px — paper has
     near-square corners, and 12px is what makes a quote read as one more app panel. */
  --radius-doc:     4px;
  --radius-control: 10px;
  --radius-chip:    12px;   /* 999px for status pills */
  --radius-badge:   8px;
  --shadow-rest:  0 1px 3px rgba(28, 36, 43, 0.05);
  --shadow-float: 0 8px 24px -12px rgba(23, 43, 58, 0.22);
  --sidebar-w: 236px;
  --topbar-h:  58px;
  /* ⚠ **The offset anything sticky inside a screen uses to clear the top bar.**
     `Layout, Responsive & Print.md` (22 Aug): *"`top: 78px` appears on six screens and it is not
     arbitrary — it clears the sticky top bar. Define 78px once as a token. Six hard-coded copies
     of a value derived from another element's height is the same shape as the `1180 × 700`
     canvas figure the platform found written in three places and pinned to none."*

     ⚠ **It is NOT `--topbar-h` and must not be collapsed into it.** The bar is 58px; this is 78.
     The 20px difference is the gap a sticky panel leaves under it, and the design's own third
     copy of this figure — Projects' scroll offset — is **86px**, spelled differently again. Two
     of the three are ours to own; the third is not built. **One name per figure, and this figure
     is "how far down a sticky panel starts", not "how tall the bar is".** */
  --sticky-top: 78px;
  /* ⚠ **Split into its horizontal component for the same reason `--pad-card-x` above is** —
     `--pad-card-sm`'s note reads *"the card's head band is full-bleed and has to negate the
     body's padding, which a shorthand cannot do."* `.jt-scroll` has to negate exactly this
     one, and a shorthand cannot be read a component at a time in CSS either.
     ⚠ **The composed value is byte-identical to `tokens/layout.css`'s `30px 32px 90px`** and
     `tests/test_design_tokens.py` resolves `var()` before comparing, which is what makes the
     split legal rather than a divergence. */
  --pad-screen-x: 32px;
  --pad-screen: 30px var(--pad-screen-x) 90px;
  --max-content:      1080px;
  --max-content-wide: 1240px;
  --gap-card: 16px;  --gap-grid: 14px;  --gap-chip: 9px;
  /* ⚠ **One token served two components the design gives different values, and the card lost.**
     `Card.jsx` renders `16px 18px`; `DarkPanel.jsx` renders `24px 26px`. Both `.fc-card` and
     `.fc-dark` read `--pad-card`, so **every ordinary card on every v2 screen carried the dark
     panel's padding** — 50% more vertical and 44% more horizontal than the design.

     ⚠ **My first fix on 20 Aug was wrong and the design system's own `tokens/layout.css`
     caught it.** I redefined `--pad-card` to `16px 18px`. The design defines it as `24px 26px`
     — the roomy one — and already ships `--pad-card-sm: 16px 18px` for the card. **The names
     were right and the wiring was wrong**: nothing needed a new value, `.fc-card` needed to
     read the token that already held it. Redefining a shared name to mean something else is
     how two systems that agree end up disagreeing, which is the exact failure this file exists
     to prevent. Both names now match `tokens/layout.css` value-for-value, and
     `tests/test_design_tokens.py::TestTheTokensMatchTheDesignSystem` pins all 89 of them.

     `--pad-panel` is retained as the name `.fc-dark` reads, aliased to `--pad-card`: the
     component is a panel and calling it one at the point of use is worth a line. */
  /* Split, because `Card.jsx`'s head band is full-bleed inside the padded body and has to
     cancel the body's padding exactly. A shorthand cannot be negated. */
  --pad-card-y: 16px;     --pad-card-x: 18px;
  --pad-card:    24px 26px;                    /* tokens/layout.css — the roomy one */
  --pad-card-sm: var(--pad-card-y) var(--pad-card-x);   /* tokens/layout.css — Card.jsx's */
  --pad-panel:   var(--pad-card);              /* DarkPanel.jsx, named for what reads it */
  --pad-card-head: 13px 18px;                  /* Card.jsx's head band */
  --pad-cell: 12px 18px;  --pad-th: 11px 18px;
}
