/**
 * Design tokens — the single source for every colour, font, and spacing step in
 * the builder chrome. The reasoning behind each group, and the rules that keep
 * this list from growing back into scattered literals, live in docs/design.md.
 *
 * Deliberately NOT covered: the canvas iframe. It renders the user's own
 * document and inherits nothing from here — that isolation is spec §5.2, and
 * breaking it would let builder chrome bleed into exported HTML.
 */

/* Inter Variable v4.1 (rsms/inter, OFL-1.1 — licence beside the font), subset to the
   Latin range so a UI typeface costs a fraction of the ~350 kB full multi-script file.
   The `unicode-range` matches that subset: a character outside it (Cyrillic, Vietnamese
   diacritics beyond Latin-1, CJK) falls through per-glyph to the system stack below
   rather than this face failing to load or blocking render — `font-display: swap` is the
   other half of that same degrade-gracefully contract. */
@font-face {
  font-family: 'Inter Variable';
  src: url('./fonts/InterVariable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074,
    U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* The chrome is committed to dark (docs/design.md). Declaring it lets the
     browser render scrollbars and form controls to match instead of painting
     light widgets onto dark panels. */
  color-scheme: dark;

  /* Surfaces — one neutral ramp, from the recessed field a user types into up
     to the raised control they click. */
  --bg-app: oklch(18% 0 0);
  --bg-panel: oklch(22% 0 0);
  --bg-field: oklch(14% 0 0);
  --bg-raised: oklch(28% 0 0);
  --bg-hover: oklch(32% 0 0);
  --bg-active: oklch(38% 0 0);

  /* The ground the canvas iframe sits on. Deliberately light: the user's
     document is light, and a dark chrome around a light page is what separates
     "the thing you are editing" from "the tool you are editing it with". */
  --canvas-ground: oklch(94% 0 0);

  --border: oklch(32% 0 0);
  --border-strong: oklch(38% 0 0);

  --text: oklch(92% 0 0);
  --text-dim: oklch(68% 0 0);
  --text-inverse: oklch(20% 0 0);

  /* Accent — one hue (250), two weights. `fill` is a background on the dark
     chrome (a selected Structure row, a pressed tab); `line` is a 1–2px mark
     that has to survive on any substrate, including the user's own light canvas
     (the canvas selection outline, the Structure drop indicator). One value
     cannot do both legibly, so the shared identity is the hue, not the
     lightness. Selection is what this accent is FOR — nothing decorative may
     borrow it. */
  --accent-fill: oklch(45% 0.15 250);
  --accent-line: oklch(60% 0.2 250);

  /* Focus. Reserved: never reuse this for hover, selection, or decoration.
     Its exclusivity is the whole reason a focus ring reads at a glance. */
  --focus: oklch(70% 0.2 250);
  --focus-width: 2px;
  --focus-offset: 2px;

  /* Status */
  --good: oklch(75% 0.16 145);
  --danger: oklch(75% 0.18 25);
  --danger-bg: oklch(40% 0.18 25);
  --warn: oklch(75% 0.18 60);
  --warn-bg: oklch(35% 0.1 90);
  --info: oklch(78% 0.14 220);
  --refused: oklch(64% 0.19 45);

  /* Roles — what KIND of node a Layers row, a canvas label or a breadcrumb names.
     One lightness (76%) for every chromatic hue so no role shouts over another; the
     achromatic roles differ (body 85%, text and comment 68%). `--role-ink` is the
     text colour on any role fill. Role colour names kind, never state: selection
     keeps the accent, focus keeps `--focus` (docs/design.md rule 6). Contrast is
     checked by src/styles/tokens.test.ts. */
  --role-body: oklch(85% 0 0);
  --role-landmark: oklch(76% 0.11 175);
  --role-container: oklch(76% 0.05 260);
  --role-heading: oklch(76% 0.12 300);
  --role-text: oklch(68% 0 0);
  --role-link: oklch(76% 0.12 215);
  --role-list: oklch(76% 0.12 85);
  --role-media: oklch(76% 0.12 350);
  --role-interactive: oklch(76% 0.12 130);
  --role-table: oklch(76% 0.11 45);
  --role-comment: oklch(68% 0 0);
  --role-ink: oklch(18% 0 0);

  /* Code — the six token families the HTML, CSS and JavaScript panes distinguish.
     One lightness band (72–78%) so no family shouts over the others on the field
     background; the gutter is dimmer than body text because line numbers are
     reference, not content. `src/styles/tokens.test.ts` checks each against
     `--bg-field`. */
  --code-tag: oklch(76% 0.12 20);
  --code-attribute: oklch(78% 0.11 85);
  --code-string: oklch(76% 0.11 145);
  --code-comment: oklch(62% 0.02 250);
  --code-keyword: oklch(74% 0.13 300);
  --code-value: oklch(78% 0.1 230);
  --code-gutter: oklch(52% 0 0);
  --code-gutter-active: oklch(72% 0 0);
  --code-active-line: oklch(18% 0 0);

  /* Type. `--font-ui` is the default for chrome; `--font-code` is a role,
     applied only where the content itself is markup, CSS, or a tag name. */
  --font-ui: 'Inter Variable', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-code: ui-monospace, SFMono-Regular, Menlo, monospace;
  --text-xs: 11px;
  --text-sm: 12px;
  --text-base: 13px;
  --leading: 1.5;

  /* Spacing — steps, so density can have rhythm instead of one pad everywhere. */
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 12px;
  --space-6: 16px;

  --control-h: 26px;
  --radius: 3px;

  /* A second, softer scale for the admin's rounded surfaces (cards, the
     floating nav pill). `--radius` above is the builder's and does not move. */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 20px;
  /* The dashboard shell. Larger than --radius-lg because it wraps the whole
     sheet rather than a control. */
  --radius-xl: 30px;
  --radius-card: 24px;
  --radius-pill: 999px;

  /* One soft, layered elevation for the admin's floating surfaces (the pill
     nav, panels lifted off the gradient ground). Shared because a shadow's
     colour is black regardless of theme — only the surface it sits on
     changes. */
  --shadow-sheet: 0 1px 2px oklch(0% 0 0 / 8%), 0 12px 32px oklch(0% 0 0 / 12%);
  /* Cards on the admin ground: a long, soft, hue-250 tinted shadow — elevation, not a
     border. The sheet keeps --shadow-sheet. */
  --shadow-card: 0 18px 40px -28px oklch(30% 0.06 250 / 35%);
  /* The card's elevation as a single drop-shadow: a `clip-path` clips `box-shadow` away, so a
     card cut to a shape paints its lift with `filter` instead. `drop-shadow()` takes no spread
     radius, hence the shorter blur and lighter alpha rather than a reuse of --shadow-card. */
  --shadow-card-drop: 0 18px 24px oklch(30% 0.06 250 / 18%);
  /* The same tint pulled in tight, for something small that pops above the thing it
     describes — a chart tooltip — rather than resting on the ground like a card. */
  --shadow-pop: 0 6px 14px -6px oklch(30% 0.06 250 / 40%);
}

/* The admin workspace: a light scope on top of the same token names, so every
   `.admin` component keeps reading `--bg-panel`, `--text`, `--border`, and so
   on unchanged. The builder's own `:root` values above stay dark and
   untouched — see docs/design.md and CLAUDE.md's locked stack decisions. */
.admin {
  color-scheme: light;
  --radius: 8px;
  --radius-2: var(--radius-md);
  --space-7: 24px;
  --space-8: 32px;
  --text-lg: 16px;
  --text-muted: var(--text-dim);
  --surface: var(--bg-panel);
  --surface-2: var(--bg-field);
  --success: var(--good);
  --ease-ui: cubic-bezier(0.23, 1, 0.32, 1);
  --shadow-control: 0 1px 2px oklch(20% 0 0 / 6%);

  /* A cool ground, so cards and their tinted shadows have something to sit on. */
  --bg-app: oklch(95.5% 0.012 250);
  /* The Overview's shell: a step lighter than the ground, so cards (99%) lift off it and the
     socket's notch reads as a cut rather than white on white. */
  --bg-sheet: oklch(97.5% 0.008 250);
  --bg-panel: oklch(99% 0 0);
  /* A light-theme surface ramp reads the other way round from the dark one above: the
     sheet is whitest, and each step past it (a callout box, a hover, an active/selected
     row) goes a little greyer rather than a little brighter. */
  --bg-field: oklch(94% 0 0);
  --bg-raised: oklch(92% 0 0);
  --bg-hover: oklch(90% 0 0);
  --bg-active: oklch(88% 0 0);

  --border: oklch(90% 0 0);
  /* Raised from oklch(80% 0 0): that value read at 1.82:1 against the sheet, short of the
     3:1 WCAG 2.2 SC 1.4.11 floor for a user-interface component's boundary. 64% clears it
     (3.27:1) while staying a neutral grey, not a second accent. */
  --border-strong: oklch(64% 0 0);

  --text: oklch(20% 0 0);
  --text-dim: oklch(46% 0 0);

  /* The dark theme's accent, status and role fills are tuned to sit on a dark ground and
     carry light text; none of that reads on white. Same hues, re-tuned as light tints
     (accent) or as text-safe deep tones (status) so the same names stay legible here. */
  --accent-fill: oklch(78% 0.15 250);
  --accent-line: oklch(50% 0.16 250);
  --good: oklch(40% 0.14 145);
  --danger: oklch(46% 0.18 25);
  --warn: oklch(42% 0.18 60);

  /* The one hue a data series is drawn in — Analytics.tsx's visitors trend line and the
     breakdown bars, and the Overview grid's Audience bar chart. Never the accent above,
     which docs/design.md reserves for selection alone. Two weights, the same idiom as
     the accent's own fill/line split: `-strong` marks the standout value (a chart's
     busiest bucket), not a second colour. */
  --chart-series: oklch(50% 0.16 230);
  --chart-series-strong: oklch(40% 0.18 230);
  /* Overview's geographic figure: a faint cool halo under the WebGL sphere and a
     translucent label surface. Kept here because component styles own no colours. */
  --globe-glow: color-mix(in oklch, var(--accent-fill) 12%, var(--bg-panel));
  --globe-label-bg: color-mix(in oklch, var(--bg-panel) 82%, transparent);
  /* Status tints under a status label (Sources badges, the step rail, held notes), light
     enough that the text colour on top stays readable. Kept here for the same reason. */
  --good-tint: color-mix(in oklch, var(--good) 16%, transparent);
  --warn-tint: color-mix(in oklch, var(--warn) 18%, transparent);
  --danger-tint: color-mix(in oklch, var(--danger) 16%, transparent);
  --accent-tint: color-mix(in oklch, var(--accent-line) 12%, transparent);

  /* The dark chrome's --focus (70% 0.2 250) falls through unread here in every stylesheet
     that renders inside .admin — controls.css's `:focus-visible` is global, not scoped —
     and reads below the 3:1 non-text floor on every admin surface. Darkened so the ring
     stays the same hue and clears 3:1 against the sheet, the ground, every raised surface
     and the accent-fill pill (tokens.admin.test.ts's non-text contrast gate). */
  --focus: oklch(48% 0.19 255);
}
