/* goose days v2 · design tokens
 *
 * "A field notebook with the detector's debug view taped in." See DESIGN.md for every rule these tokens serve.
 * Colours are OKLCH and every token is inside sRGB, so the hex in each comment is the exact rendering. The WCAG 2.x
 * contrast of each pair in DESIGN.md section 3.4 was computed from those hexes (0 failures).
 *
 * Theme: light-dark() follows the used color-scheme. <html data-theme="light|dark"> forces one theme. Without it,
 * the theme follows the OS. light-dark() needs Safari 17.5+ or Chrome 123+, which "current Safari and Chrome" covers.
 *
 * Fixed in both themes: --tray, --tag, the lens ramp and Patch. Patch is always a light "sticker".
 */

:root {
  color-scheme: light dark;
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }

:root {
  /* ---------- paper and ink ---------- */
  --paper:      light-dark(oklch(0.993 0.004 95),  oklch(0.180 0.007 20));   /* #fdfdfa / #151010  page */
  --paper-2:    light-dark(oklch(0.962 0.007 95),  oklch(0.235 0.008 20));   /* #f4f2ed / #221d1c  panels, unsorted tray */
  --ink:        light-dark(oklch(0.205 0.007 20),  oklch(0.960 0.005 95));   /* #1a1616 / #f3f2ee  text, drawings, keylines */
  --ink-2:      light-dark(oklch(0.460 0.012 30),  oklch(0.790 0.012 60));   /* #5f5654 / #c1b9b3  captions */
  --wire:       light-dark(oklch(0.480 0.115 18),  oklch(0.690 0.140 22));   /* #933e44 / #e57573  schematic wires, focus, Patch */
  --wire-faint: light-dark(oklch(0.830 0.045 18),  oklch(0.380 0.060 20));   /* #e3bcbc / #5e3535  dimmed wires (decor only) */
  --mist:       light-dark(oklch(0.500 0.020 260), oklch(0.740 0.020 260));  /* #5d646f / #a4abb8  "unconfirmed" text */
  --mist-line:  light-dark(oklch(0.600 0.020 260), oklch(0.560 0.020 260));  /* #79818d / #6e7581  dashed unconfirmed box */

  /* ---------- fixed in both themes ---------- */
  --tray:     oklch(0.600 0 0);              /* #808080  specimen tray = the cut-outs' baked background */
  --tray-ink: oklch(0.205 0.007 20);         /* #1a1616  the only text colour allowed on the tray (4.54:1) */
  --tag:      oklch(0.915 0.165 110);        /* #eaec5a  measurements only: "most at once" counts */
  --on-tag:   oklch(0.205 0.007 20);         /* #1a1616  text on tag (14.22:1); dark paper also passes (14.95:1) */
  --on-wire:  var(--paper);                  /* paper text on a wire chip: 6.84 / 6.40 */

  /* ---------- track colours: known geese only, by slot (geese[].slot) ----------
   * Every slot follows the classic pages' hue family (site.py --k0..7: pond blue, maple orange, teal green, plum,
   * autumn gold, violet, grass, bark), so a goose keeps its colour family on classic.html:
   * 0 cyan, 1 ember, 2 lime, 3 plum, 4 amber, 5 violet, 6 grass, 7 bark.
   * Slots 0-2 stay the colour-blind-safest trio (DESIGN 3.2); amber is darker than the --tag count yellow.
   * Slot >= 8 is neutral ink: never a wrapped or reused hue. */
  --k0: light-dark(oklch(0.780 0.125 213), oklch(0.800 0.125 213));   /* cyan    #36cce7 / #40d2ed */
  --k1: light-dark(oklch(0.700 0.160 50),  oklch(0.740 0.150 50));    /* ember   #eb7c33 / #f58b4b */
  --k2: oklch(0.880 0.215 136);                                       /* lime    #91f657 both */
  --k3: light-dark(oklch(0.540 0.150 340), oklch(0.740 0.130 340));   /* plum    #a5458a / #e189c5 */
  --k4: light-dark(oklch(0.640 0.130 75),  oklch(0.800 0.140 80));    /* amber   #ba7f14 / #edb345 */
  --k5: light-dark(oklch(0.450 0.150 290), oklch(0.710 0.120 290));   /* violet  #5740a1 / #a194e7 */
  --k6: light-dark(oklch(0.520 0.120 130), oklch(0.720 0.150 140));   /* grass   #517621 / #6ebb5d */
  --k7: light-dark(oklch(0.500 0.065 58),  oklch(0.760 0.065 65));    /* bark    #7f5a3d / #cea986 */
  --k-none: var(--ink);                                               /* slot >= 8 */

  /* text on a filled track chip (WCAG 2.x, recomputed 2026-11-04): ink on light fills, paper on dark fills in the light
   * theme; dark paper on all in the dark theme. Lines on paper: 3-7 are >= 3.37 alone; 0-2 need the ink keyline. */
  --on-k0: light-dark(oklch(0.205 0.007 20), oklch(0.180 0.007 20));  /* 9.33 / 10.48 */
  --on-k1: light-dark(oklch(0.205 0.007 20), oklch(0.180 0.007 20));  /* 6.37 / 7.79 */
  --on-k2: light-dark(oklch(0.205 0.007 20), oklch(0.180 0.007 20));  /* 13.26 / 13.92 */
  --on-k3: light-dark(oklch(0.993 0.004 95), oklch(0.180 0.007 20));  /* 5.39 / 7.69 */
  --on-k4: light-dark(oklch(0.205 0.007 20), oklch(0.180 0.007 20));  /* 5.22 / 9.94 */
  --on-k5: light-dark(oklch(0.993 0.004 95), oklch(0.180 0.007 20));  /* 7.76 / 7.08 */
  --on-k6: light-dark(oklch(0.993 0.004 95), oklch(0.180 0.007 20));  /* 5.19 / 8.00 */
  --on-k7: light-dark(oklch(0.993 0.004 95), oklch(0.180 0.007 20));  /* 5.99 / 8.67 */
  --on-k-none: var(--paper);

  /* the current goose: set per element through [data-slot] (see the plumbing below) */
  --k: var(--k-none);
  --on-k: var(--on-k-none);

  /* ---------- detector lens ramp (decorative, never encodes data) ----------
   * purple -> blue -> cyan -> lime -> tag. OKLCH L is monotonic 0.40 -> 0.915, so it reads in greyscale. Fixed in both themes. */
  --lens-0: oklch(0.400 0.140 305);   /* #5a2d83 */
  --lens-1: oklch(0.540 0.175 262);   /* #3168d2 */
  --lens-2: oklch(0.780 0.125 213);   /* #36cce7 */
  --lens-3: oklch(0.880 0.215 136);   /* #91f657 */
  --lens-4: oklch(0.915 0.165 110);   /* #eaec5a */
  --lens-ramp: linear-gradient(90deg, var(--lens-0), var(--lens-1), var(--lens-2), var(--lens-3), var(--lens-4));

  /* ---------- Patch (patch.svg reads these through var() fallbacks) ---------- */
  --patch-ink:        oklch(0.205 0.007 20);                                   /* #1a1616 */
  --patch-paper:      light-dark(oklch(0.993 0.004 95), oklch(0.960 0.005 95)); /* sticker: #fdfdfa / #f3f2ee */
  --patch-box:        oklch(0.480 0.115 18);                                   /* #933e44: light wire on the sticker */
  --patch-tray:       var(--tray);
  --patch-tag:        var(--tag);
  --patch-unsure:     oklch(0.600 0.020 260);                                  /* #79818d: confused pose, dashed box */
  --patch-unsure-text: oklch(0.500 0.020 260);                                 /* #5d646f */
  --patch-ghost:      var(--ink-2);                                            /* silhouette lines */
  --patch-ghost-fill: var(--paper-2);
  --patch-rim:        oklch(0.520 0.010 25);                                   /* eye rim, a hair lighter than ink */

  /* ---------- keylines and strokes ---------- */
  --key: light-dark(oklch(0.205 0.007 20), transparent);   /* 1 px outer keyline round every box (light theme needs it) */
  --mat: var(--paper);                                     /* the paper gap between box stroke and photo */
  --line-hair: 1px;
  --line-box: 3px;                                         /* detection box stroke */
  --line-dash: 2px;                                        /* dashed unconfirmed box */
  --line-wire: 3px;                                        /* schematic wire (the reference: about 0.4% of width) */
  --mat-w: 3px;
  --dash: 6 4;                                             /* SVG stroke-dasharray for unconfirmed boxes */
  --bracket: 14px;                                         /* lock-on corner bracket arm */
  --bracket-w: 2px;
  --focus: var(--wire);
  --focus-w: 3px;
  --focus-gap: 2px;

  /* ---------- type ----------
   * One family: Recursive (Google Fonts, OFL). Axes: wght 300-1000, CASL 0-1, MONO 0-1. Load:
   * https://fonts.googleapis.com/css2?family=Recursive:wght,CASL,MONO@300..1000,0..1,0..1&display=swap
   * (latin woff2: 142 KB; adding slnt doubles it, so italics are synthesised or avoided). */
  --font-sans: "Recursive", ui-rounded, "SF Pro Rounded", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "Recursive", ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --fv-mono: 0;      /* 0 sans, 1 mono */
  --fv-casl: 0;      /* 0 linear, 1 casual */

  --fs--2: 0.6875rem;                                   /* 11px: duplicated or decorative captions only */
  --fs--1: 0.75rem;                                     /* 12px: chips and mono captions (minimum for meaning) */
  --fs-0: 1rem;                                         /* 16px: body */
  --fs-1: 1.1875rem;                                    /* 19px: h3, card titles */
  --fs-2: clamp(1.375rem, 1.18rem + 0.9vw, 1.75rem);    /* 22-28px: h2 */
  --fs-3: clamp(1.875rem, 1.4rem + 2.3vw, 2.75rem);     /* 30-44px: h1 */
  --fs-4: clamp(2.5rem, 1.6rem + 4.2vw, 4.25rem);       /* 40-68px: big numerals (tally, totals) */
  --lh-tight: 1.08;
  --lh-snug: 1.25;
  --lh-body: 1.5;
  --wt-body: 400;
  --wt-chip: 500;
  --wt-strong: 650;
  --wt-head: 800;
  --tracking-mono: 0;
  --measure: 66ch;

  /* ---------- space (4 px base) ---------- */
  --s-1: 0.25rem;   /*  4 */
  --s-2: 0.5rem;    /*  8 */
  --s-3: 0.75rem;   /* 12 */
  --s-4: 1rem;      /* 16 */
  --s-5: 1.5rem;    /* 24 */
  --s-6: 2rem;      /* 32 */
  --s-7: 3rem;      /* 48 */
  --s-8: 4rem;      /* 64 */
  --s-9: 6rem;      /* 96 */
  --gutter: clamp(16px, 4vw, 48px);
  --page-max: 75rem;           /* 1200 */
  --topbar-h: 3.5rem;          /* also scroll-padding-top, so focus is never hidden under the bar */
  --target: 24px;              /* WCAG 2.5.8 minimum */
  --target-comfy: 44px;
  --tile: 2.375rem;            /* season-grid day tile (38px) */
  --chip-h: 1.375rem;          /* 22px non-interactive chip; interactive chips use --target or more */

  /* ---------- radii (nested: inner = outer - stroke - mat) ---------- */
  --r-box: 10px;
  --r-photo: calc(var(--r-box) - var(--line-box) - var(--mat-w));   /* 4px */
  --r-chip: 999px;
  --r-card: 16px;
  --r-tile: 8px;
  --r-tray: 20px;
  --r-patch: 11%;              /* Patch box: 22 of 200 */

  /* ---------- paper, paste and grain ---------- */
  --paste: 0 1px 0 color-mix(in oklch, var(--ink) 10%, transparent),
           0 10px 18px -12px color-mix(in oklch, var(--ink) 45%, transparent);
  --paste-lift: 0 1px 0 color-mix(in oklch, var(--ink) 12%, transparent),
                0 16px 26px -14px color-mix(in oklch, var(--ink) 50%, transparent);
  --tilt-max: 1.5deg;          /* collage tilt, deterministic per picture name; set --tilt per element */
  --tilt: 0deg;
  --grain-opacity: 0.035;
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .6 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");

  /* ---------- layers ---------- */
  --z-wires: 0;
  --z-photo: 1;
  --z-chip: 2;
  --z-sticky: 10;

  /* ---------- motion ----------
   * Motion confirms and gives feedback; it is never ambient noise. Under reduced motion or .calm, every movement
   * goes to 0 and only opacity fades of at most 120 ms remain (DESIGN.md 3.10). */
  --t-tap: 100ms;          /* press feedback */
  --t-fade: 120ms;         /* opacity only; survives reduced motion */
  --t-quick: 160ms;        /* hovers, chip slides, root crossfade */
  --t-lock: 220ms;         /* lock-on brackets, tilt straighten */
  --t-panel: 260ms;        /* tray open, dialog, view-transition morph */
  --t-draw: 600ms;         /* wire draw-on */
  --t-scan: 700ms;         /* lens scan line */
  --t-blink: 120ms;
  --t-honk: 900ms;
  --t-stagger: 40ms;       /* tally boxes, list entrances */
  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
  --ease-in: cubic-bezier(0.5, 0, 0.75, 0);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);   /* fallback; replaced by linear() below where supported */
  --motion: 1;                                     /* 0 under reduced motion / calm: multiply distances with it */
}

@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --spring: linear(0, 0.62 18%, 1.12 38%, 0.98 58%, 1.01 78%, 1);
  }
}

/* small screens: thinner strokes (the reference's wire is ~0.4% of the page width) */
@media (max-width: 480px) {
  :root {
    --line-box: 2px;
    --line-wire: 2px;
    --bracket: 10px;
    --tile: 2.75rem;     /* the season grid turns to week rows on phones, so tiles grow */
  }
}

/* more contrast: heavier strokes, keylines in both themes, no faint wires */
@media (prefers-contrast: more) {
  :root {
    --line-box: 4px;
    --line-wire: 4px;
    --line-dash: 3px;
    --key: var(--ink);
    --wire-faint: var(--wire);
    --ink-2: var(--ink);
    --grain-opacity: 0;
  }
}

/* reduced motion, and the in-app "calm" toggle (html.calm), which does the same on demand (WCAG 2.2.2) */
@media (prefers-reduced-motion: reduce) {
  :root {
    --t-tap: 0ms; --t-quick: 0ms; --t-lock: 0ms; --t-panel: 0ms; --t-draw: 0ms; --t-scan: 0ms; --t-stagger: 0ms;
    --t-honk: 600ms;   /* the honk pose still shows, as a state swap, then returns */
    --spring: linear;
    --motion: 0;
  }
}
:root.calm {
  --t-tap: 0ms; --t-quick: 0ms; --t-lock: 0ms; --t-panel: 0ms; --t-draw: 0ms; --t-scan: 0ms; --t-stagger: 0ms;
  --t-honk: 600ms;
  --spring: linear;
  --motion: 0;
}

/* forced colours (Windows High Contrast and the like): system colours, lens off (DESIGN.md C9) */
@media (forced-colors: active) {
  :root {
    --paper: Canvas; --paper-2: Canvas; --ink: CanvasText; --ink-2: CanvasText;
    --wire: CanvasText; --wire-faint: GrayText; --mist: GrayText; --mist-line: GrayText;
    --tag: Highlight; --on-tag: HighlightText; --key: CanvasText; --focus: Highlight;
    --k0: CanvasText; --k1: CanvasText; --k2: CanvasText; --k3: CanvasText;
    --k4: CanvasText; --k5: CanvasText; --k6: CanvasText; --k7: CanvasText; --k-none: CanvasText;
    --on-k0: Canvas; --on-k1: Canvas; --on-k2: Canvas; --on-k3: Canvas;
    --on-k4: Canvas; --on-k5: Canvas; --on-k6: Canvas; --on-k7: Canvas; --on-k-none: Canvas;
    --paste: none; --paste-lift: none; --grain-opacity: 0;
  }
}

/* ======================================================================
 * token plumbing: the few rules that make the tokens work everywhere
 * ====================================================================== */

/* the goose colour for any element that carries a known goose's slot (JS sets data-slot="0".."7", else "none") */
[data-slot="0"] { --k: var(--k0); --on-k: var(--on-k0); }
[data-slot="1"] { --k: var(--k1); --on-k: var(--on-k1); }
[data-slot="2"] { --k: var(--k2); --on-k: var(--on-k2); }
[data-slot="3"] { --k: var(--k3); --on-k: var(--on-k3); }
[data-slot="4"] { --k: var(--k4); --on-k: var(--on-k4); }
[data-slot="5"] { --k: var(--k5); --on-k: var(--on-k5); }
[data-slot="6"] { --k: var(--k6); --on-k: var(--on-k6); }
[data-slot="7"] { --k: var(--k7); --on-k: var(--on-k7); }
[data-slot="none"] { --k: var(--k-none); --on-k: var(--on-k-none); }

/* Recursive's MONO and CASL axes. font-variation-settings is inherited as one resolved value, so it is declared on
 * every element and driven by the inherited --fv-* properties: set --fv-mono: 1 on any subtree to make it mono. */
*, *::before, *::after {
  font-variation-settings: "MONO" var(--fv-mono), "CASL" var(--fv-casl);
}
.mono, code, kbd, samp, pre {
  font-family: var(--font-mono);
  --fv-mono: 1;
  font-variant-numeric: tabular-nums slashed-zero;
  letter-spacing: var(--tracking-mono);
}

html {
  scroll-padding-top: calc(var(--topbar-h) + var(--s-4));
}
