/* WantNot design tokens — single import root for all dashboard pages.
 *
 * Pages link this BEFORE palette.css and their own <style>:
 *   <link rel="stylesheet" href="tokens.css">
 *   <link rel="stylesheet" href="palette.css">
 * Later rules win, so per-page :root values still override these where a page
 * has not been migrated yet; new code should use the tokens directly.
 *
 * Kind colours (--k1…--k7) are deliberately ABSENT here. They live in
 * dashboard/palette.css, generated from shared/skus.json via
 * tools/generate_frontend_catalog.py — never hand-edit that file, and never
 * redeclare --kN inline except the .doc print pin in dashboard.html (which
 * keeps literals so the report prints identically in both themes).
 *
 * --paper is Audit Paper (#FFFFFF), --wash is Slate Wash (#EEF1F4).
 * Light is the default; dark mirrors brand/BRAND.md + palette.css dark ramp.
 */
:root{
  --paper:#FFFFFF; --wash:#EEF1F4;
  /* P1-B: --page IS the wash (Slate Wash #EEF1F4); surfaces that must print
     identically in both themes keep the same hex as a literal inside the
     .doc pin in dashboard.html (print immunity per DECISIONS.md:3). */
  --page:#EEF1F4; --card:#FFFFFF; --card-2:#F7F9FC;
  --line:#E4E9F0; --line-2:#EFF2F7;
  --ink:#0C1017; --ink-2:#4C5765; --ink-3:#8A94A4;
  --keep:#1A212C; --hot:#FF4D2E; --good:#12A56B;
  /* #127 direction 2: the brand hues above stay intact for fills and
     decoration. Text on --page/--card/--card-2 uses the darker text-only
     variants below (each clears 4.5:1 on all three surfaces). */
  --ink-3-text:#646E7E; --hot-text:#D62405; --good-text:#007E44;
  --focus:#FF4D2E;
  --display:'Archivo',system-ui,sans-serif;
  --ui:'Instrument Sans',system-ui,sans-serif;
  --r:16px; --r-sm:10px;
  --shadow:0 1px 2px rgba(12,16,23,.08),0 8px 28px -14px rgba(12,16,23,.18);
  --shadow-lift:0 2px 6px rgba(12,16,23,.10),0 18px 46px -18px rgba(12,16,23,.28);
  --lift:0 2px 8px rgba(12,16,23,.10),0 24px 56px -22px rgba(12,16,23,.30);
  /* Ledger rows (P0-B composes these): row padding + WCAG 2.2 AA target floor. */
  --ledger-row-pad:12px 18px; --target-min:24px;
  /* Hatch overlays: pattern + label carry meaning alongside colour, and survive
     grayscale print. Composed over kind fills (background: <hatch>, var(--kN)). */
  --hatch-none:none;
  --hatch-diagonal:repeating-linear-gradient(45deg,transparent 0 4px,rgba(12,16,23,.30) 4px 5px);
  --hatch-diagonal-rev:repeating-linear-gradient(-45deg,transparent 0 4px,rgba(12,16,23,.30) 4px 5px);
  --hatch-horizontal:repeating-linear-gradient(0deg,transparent 0 3px,rgba(12,16,23,.30) 3px 4px);
  --hatch-vertical:repeating-linear-gradient(90deg,transparent 0 3px,rgba(12,16,23,.30) 3px 4px);
  --hatch-dots:radial-gradient(rgba(12,16,23,.35) 1px,transparent 1.5px);
  /* P0-B triage encoding: one distinct hatch per kind (k1…k7 index the ORDER
     from kinds.js, not a colour), plus the absorbed hatch. Every kind swatch
     renders colour fill + hatch overlay + adjacent kLabel() text, so pattern
     and label survive achromatopsia simulation and grayscale print where hue
     alone collapses. Pages apply these via a data-hatch="kN" ::after overlay
     (see dashboard.html) so the inline background:var(--kN) fill is untouched.
     --hatch-k5 is dots and needs background-size:5px 5px at the use site. */
  --hatch-k1:repeating-linear-gradient(45deg,transparent 0 3px,rgba(12,16,23,.32) 3px 4px);
  --hatch-k2:repeating-linear-gradient(-45deg,transparent 0 3px,rgba(12,16,23,.32) 3px 4px);
  --hatch-k3:repeating-linear-gradient(90deg,transparent 0 4px,rgba(12,16,23,.32) 4px 5px);
  --hatch-k4:repeating-linear-gradient(0deg,transparent 0 4px,rgba(12,16,23,.32) 4px 5px);
  --hatch-k5:radial-gradient(rgba(12,16,23,.38) 1px,transparent 1.6px);
  --hatch-k6:repeating-linear-gradient(45deg,transparent 0 5px,rgba(12,16,23,.32) 5px 6px),repeating-linear-gradient(-45deg,transparent 0 5px,rgba(12,16,23,.32) 5px 6px);
  --hatch-k7:repeating-linear-gradient(45deg,transparent 0 7px,rgba(12,16,23,.28) 7px 8px);
  --hatch-absorbed:repeating-linear-gradient(-45deg,transparent 0 5px,rgba(12,16,23,.25) 5px 6px);
}
@media (prefers-color-scheme:dark){
  :root{
    --paper:#12161D; --wash:#090B0F;
    --page:#090B0F; --card:#12161D; --card-2:#171C25;
    --line:#232A35; --line-2:#1B212B;
    --ink:#EDF1F7; --ink-2:#A3AEBC; --ink-3:#6C7684;
    --keep:#DDE4EC; --hot:#FF6647; --good:#2FCE8E;
    /* #127 direction 2: dark brand hues are already text-safe except --ink-3,
       so --hot-text/--good-text match the brand while --ink-3-text is the
       lighter, AA-passing variant (4.75:1+ on page, card and card-2). */
    --ink-3-text:#7E8894; --hot-text:#FF6647; --good-text:#2FCE8E;
    --focus:#FF6647;
    --shadow:0 1px 2px rgba(0,0,0,.4),0 8px 28px -14px rgba(0,0,0,.7);
    --shadow-lift:0 2px 6px rgba(0,0,0,.5),0 18px 46px -18px rgba(0,0,0,.85);
    --lift:0 2px 8px rgba(0,0,0,.5),0 24px 56px -22px rgba(0,0,0,.9);
    --hatch-diagonal:repeating-linear-gradient(45deg,transparent 0 4px,rgba(221,228,236,.30) 4px 5px);
    --hatch-diagonal-rev:repeating-linear-gradient(-45deg,transparent 0 4px,rgba(221,228,236,.30) 4px 5px);
    --hatch-horizontal:repeating-linear-gradient(0deg,transparent 0 3px,rgba(221,228,236,.30) 3px 4px);
    --hatch-vertical:repeating-linear-gradient(90deg,transparent 0 3px,rgba(221,228,236,.30) 3px 4px);
    --hatch-dots:radial-gradient(rgba(221,228,236,.35) 1px,transparent 1.5px);
    --hatch-k1:repeating-linear-gradient(45deg,transparent 0 3px,rgba(221,228,236,.32) 3px 4px);
    --hatch-k2:repeating-linear-gradient(-45deg,transparent 0 3px,rgba(221,228,236,.32) 3px 4px);
    --hatch-k3:repeating-linear-gradient(90deg,transparent 0 4px,rgba(221,228,236,.32) 4px 5px);
    --hatch-k4:repeating-linear-gradient(0deg,transparent 0 4px,rgba(221,228,236,.32) 4px 5px);
    --hatch-k5:radial-gradient(rgba(221,228,236,.38) 1px,transparent 1.6px);
    --hatch-k6:repeating-linear-gradient(45deg,transparent 0 5px,rgba(221,228,236,.32) 5px 6px),repeating-linear-gradient(-45deg,transparent 0 5px,rgba(221,228,236,.32) 5px 6px);
    --hatch-k7:repeating-linear-gradient(45deg,transparent 0 7px,rgba(221,228,236,.28) 7px 8px);
    --hatch-absorbed:repeating-linear-gradient(-45deg,transparent 0 5px,rgba(221,228,236,.25) 5px 6px);
  }
}
/* Triage targets (P0-B): every interactive triage element (legend chips, keys,
   filter chips, copilot hints, group heads) measures at least 24px per
   WCAG 2.2 AA §2.5.8. Pages meet this with padding, never font-size, and keep
   their own geometry; this class is the audit floor for new controls. */
.triage-target{min-height:var(--target-min);min-width:var(--target-min)}
/* Forced colours: patterns flatten, so swatches keep a border and the always-
   rendered text label carries the meaning on its own. */
@media (forced-colors:active){
  .sw[data-hatch],.spendbar .seg[data-hatch],.bar .seg-w[data-hatch]{border:1px solid CanvasText}
}
/* Money in columns must not jitter between renders. */
.tabular{font-variant-numeric:tabular-nums}
/* P3 motion budget + focus (final polish, smallest blast radius).
 *
 * Exactly one orchestrated load sequence exists: index.html hero (bar draw
 * → waste lift → figure count-up, once, per brand/BRAND.md Motion). Every
 * other page loads still — no per-page bespoke timelines, no scroll-timeline
 * progress/head effects (deleted from all six pages).
 *
 * All remaining motion answers user action (hover/focus/active) inside
 * 120–150ms. Carve pin/hover is transform/opacity/filter only with
 * isolation:isolate retained at the use site — zero layout shift. Pages
 * reference --dur-carve/--dur-response so timing stays centralised here. */
:root{
  --dur-response:140ms;
  --dur-carve:150ms;
  --ease-response:cubic-bezier(.3,.9,.4,1);
}
/* Focus base: every interactive element gets a visible ring from --focus.
 * Specificity is :where() (zero), so per-page rules keep their own offsets
 * and carve colours. Text inputs keep their custom glow (out of this
 * selector); file/select/checkbox controls are covered. */
:where(a,button,summary,[tabindex],[role="button"],select,input[type="file"],input[type="checkbox"],input[type="radio"]):focus-visible{
  outline:2px solid var(--focus);outline-color:var(--focus,#FF4D2E);outline-offset:2px;
}
@media (forced-colors:active){
  :where(a,button,summary,[tabindex],[role="button"],select,input[type="file"],input[type="checkbox"],input[type="radio"]):focus-visible{
    outline-color:Highlight;
  }
}
/* Instant fallback everywhere, including the home sequence: durations
 * collapse to ~zero so content paints at its final state; smooth scroll off.
 * (Pages keep their own reduce blocks as a second layer; this one covers all
 * six, including pages with no page-level block.) */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
  html{scroll-behavior:auto}
}
/* ── skeleton placeholders (issue #81) ───────────────────────────────
   Layout-matched grey blocks shown while a fetch is in flight, so a page does
   not flash bare "Loading…" text and the content does not jump when data
   lands. Views compose these primitives in JS; only the primitives live here.
   A skeleton root carries aria-busy="true" and is replaced wholesale by the
   real render, so the flag never outlives the load. Reuse layout shells
   (.hero, .panel) for final dimensions, but never the data/state classes the
   smoke suite counts (.row, .empty). The shimmer is decorative only: the
   global kill-switch above already stops it, and the explicit block below
   leaves a static block under prefers-reduced-motion. */
.sk{position:relative;overflow:hidden;background:var(--line);border-radius:6px}
.sk::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--ink) 8%,transparent),transparent);
  animation:sk-shimmer 1.4s ease-in-out infinite}
@keyframes sk-shimmer{to{transform:translateX(100%)}}
.sk-line{height:11px;margin:9px 0}
.sk-line.sm{height:8px}
.sk-line.lg{height:22px;margin:11px 0}
/* .xl tracks .hero-figure's clamp so the figure block stays put at any width. */
.sk-line.xl{height:clamp(40px,7.5vw,68px);margin:6px 0 14px}
.sk-w20{width:20%}.sk-w30{width:30%}.sk-w40{width:40%}.sk-w50{width:50%}
.sk-w60{width:60%}.sk-w75{width:75%}.sk-w100{width:100%}
.sk-bar{height:58px;border-radius:12px;margin-top:6px}
.sk-block{border-radius:var(--r-sm)}
/* A row mirrors .ledger .row / tbody geometry so the swap does not jump. */
.sk-row{display:flex;align-items:center;gap:14px;padding:12px 18px;border-bottom:1px solid var(--line-2)}
.sk-row:last-child{border-bottom:none}
.sk-row > .sk{flex:1;margin:0}
.sk-row > .sk.sk-fixed{flex:none;width:96px}
.sk-stat{display:flex;gap:34px;flex-wrap:wrap;margin-top:24px}
.sk-stat > .sk{width:110px;height:38px}
.sk-table > .sk-row{padding:13px 22px}
/* Screen-reader-only label (e.g. the "Authenticating…" state a skeleton
   replaces): the visible flash goes, the announcement stays. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
@media (prefers-reduced-motion:reduce){
  .sk::after{display:none}
}
/* Print mirror (P2-A): paper never inherits the dark theme. The .doc report
   in dashboard.html pins the same light literals (print immunity per
   DECISIONS.md:3); this block keeps every other var() consumer — hatch
   overlays, focus ring, ledger rows — on the light ramp when printing from
   dark mode, so Letter PDFs from either theme are equivalent. Same hexes as
   :root above; keep in step by hand. */
@media print{
  :root{
    --paper:#FFFFFF; --wash:#EEF1F4;
    --page:#EEF1F4; --card:#FFFFFF; --card-2:#F7F9FC;
    --line:#E4E9F0; --line-2:#EFF2F7;
    --ink:#0C1017; --ink-2:#4C5765; --ink-3:#8A94A4;
    --keep:#1A212C; --hot:#FF4D2E; --good:#12A56B;
    --ink-3-text:#646E7E; --hot-text:#D62405; --good-text:#007E44;
    --focus:#FF4D2E;
    --hatch-diagonal:repeating-linear-gradient(45deg,transparent 0 4px,rgba(12,16,23,.30) 4px 5px);
    --hatch-diagonal-rev:repeating-linear-gradient(-45deg,transparent 0 4px,rgba(12,16,23,.30) 4px 5px);
    --hatch-horizontal:repeating-linear-gradient(0deg,transparent 0 3px,rgba(12,16,23,.30) 3px 4px);
    --hatch-vertical:repeating-linear-gradient(90deg,transparent 0 3px,rgba(12,16,23,.30) 3px 4px);
    --hatch-dots:radial-gradient(rgba(12,16,23,.35) 1px,transparent 1.5px);
    --hatch-k1:repeating-linear-gradient(45deg,transparent 0 3px,rgba(12,16,23,.32) 3px 4px);
    --hatch-k2:repeating-linear-gradient(-45deg,transparent 0 3px,rgba(12,16,23,.32) 3px 4px);
    --hatch-k3:repeating-linear-gradient(90deg,transparent 0 4px,rgba(12,16,23,.32) 4px 5px);
    --hatch-k4:repeating-linear-gradient(0deg,transparent 0 4px,rgba(12,16,23,.32) 4px 5px);
    --hatch-k5:radial-gradient(rgba(12,16,23,.38) 1px,transparent 1.6px);
    --hatch-k6:repeating-linear-gradient(45deg,transparent 0 5px,rgba(12,16,23,.32) 5px 6px),repeating-linear-gradient(-45deg,transparent 0 5px,rgba(12,16,23,.32) 5px 6px);
    --hatch-k7:repeating-linear-gradient(45deg,transparent 0 7px,rgba(12,16,23,.28) 7px 8px);
    --hatch-absorbed:repeating-linear-gradient(-45deg,transparent 0 5px,rgba(12,16,23,.25) 5px 6px);
  }
}
/* Skeletons are pre-content: stop the shimmer on paper as well. */
@media print{.sk::after{display:none}}
