/* =============================================================================
   Staple Design System — merged token set ("middle ground")
   -----------------------------------------------------------------------------
   SOURCE OF TRUTH FOR NOMENCLATURE + SHARED VALUES:
     staple-new-dashboard/src/index.css  (cloned here as ./index.css)

   This file MERGES that authoritative token set with the Clipper Kit v2.0 tokens
   (./clipper-kit-v2-tokens.css). The rules used:

     1. index.css naming + values SUPERSEDE Clipper for every shared token.
     2. Repetitive Clipper tokens are dropped and renamed to index nomenclature.
     3. Clipper-only tokens (no index equivalent) are appended, themed for
        light / dark / high-contrast.

   Use this file for NEW screens:
       <link rel="stylesheet" href="design-system.css">
       <html class="dark">                 — app-style dark (next-themes)
       <html data-theme="dark">            — prototype-style dark
       <html data-theme="high-contrast">   — prototype-style high contrast
   then reference tokens with var(--token).

   Clipper → index rename map (for porting Clipper component CSS):
       --bg              → --background
       --fg              → --foreground
       --primary-fg      → --primary-foreground
       --muted-fg        → --muted-foreground
       --accent (#f9fbfb)→ --accent (index value supersedes)
       --border-strong   → --input          (shadcn: input/control border)
       --focus           → --ring
       --font-body       → --font-sans
       --font-mono       → REMOVED             (values take --font-sans + tabular-nums)
       --on-primary      → --primary-foreground
       --on-destructive  → --destructive-foreground
       --on-success      → --success-foreground
       --on-warning      → --warning-foreground
       --radius-base(8)  → --radius-md (8px, index)   --radius (10px) = --radius-lg
       --shadow-sm/md/lg/xl → index's (flat by design; see elevation note below)

   Clipper-only tokens kept (index has no equivalent): --info*,
   --link, soft semantic surfaces (--*-bg / --*-border), the 24-colour badge
   palette, --accordion-*, --chart-label/-text (now
   aliased to core tokens), --cmd-highlight, --focus-ring*, --shadow-raised,
   --dfp-*, the spacing / radius-extras / z-index / transition scales.
   ============================================================================= */

/* ── Colour notation ──────────────────────────────────────────────────────────
   EVERY colour value in this file is 6-digit hex. No exceptions. No rgba(),
   no hsl(), no oklch(), no color-mix(), no 8-digit #RRGGBBAA, no 3-digit
   shorthand, and no `none` or `transparent` where a colour belongs.

   Where a value used to carry alpha it has a 6-digit counterpart:
     · soft tints          pre-composited against their surface (dark against
                           --card, the middle of its three)
     · --toolbar-dark-*    composited over --toolbar-dark, their only backdrop
     · shadows             composited over each theme's page ground. Light and
                           high-contrast error where a shadow falls elsewhere
                           is under 2.25 dE. Dark's translucent WHITE hairline
                           layer became var(--panel-border): compositing it
                           would make it darker than --card and invert the
                           effect, and high contrast already used var(--border)
     · --focus-ring        color-mix() resolved per theme. This FREEZES them —
                           they used to derive from --ring / --destructive, so
                           a change to either must now be mirrored here
     · flat shadow scale   --shadow-2xs..--shadow-2xl mirror the app's
                           deliberately flat Tailwind scale; expressed as
                           `0 0 0 0 #000000` so they carry a hex while nothing
                           is painted
     · --scrim,            a hex plus a companion --*-opacity token, since the
       --thumb-overlay     backdrop is arbitrary page content or an image.
                           --scrim-opacity is painted on a ::before for the
                           dialog, because opacity would fade the dialog inside

   Five tokens were minted so the kit needs no color-mix() at all:
   --input-border-hover, --highlight-bg, --icon-hover-bg, --tip-code-bg,
   --tip-eg-foreground. Each is pre-composited; a change to --primary, --input,
   --foreground or --background must be mirrored in them.

   scripts/audit_tokens.py enforces all of this. See rulebook.md § 1.
   ─────────────────────────────────────────────────────────────────────────── */

/* ── Webfont ─────────────────────────────────────────────────────────────────
   --font-sans asks for Noto Sans and nothing in the kit fetched it, so every
   standalone prototype silently rendered in -apple-system instead — the token
   was declared and unenforceable. Loaded here rather than per page so that
   "link design-system.css only" actually holds (INTEGRATION.md).

   The variable axis covers 100..900, so every weight the type scale uses
   (400 / 500 / 600) comes from one file. display=swap so text paints in the
   fallback immediately and reflows once Noto arrives, rather than blocking.

   The family name is "Noto Sans", which is already second in the --font-sans
   chain; "Noto Sans Variable" ahead of it is the @fontsource name and resolves
   only inside the React app, which loads the font through npm instead.

   One family: --font-sans. There is no display, serif or mono face.
*/
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap");

/* ===== LIGHT — the base set, on the root and on any subtree that asks for it =====
   .light / [data-theme="light"] re-declares the light values on an element, so a
   region that must read as light in every theme — a scanned document, a printed
   page, a preview of an email — takes the kit's own tokens instead of minting a
   parallel set. Custom properties inherit, so the whole subtree follows; the dark
   and high-contrast blocks below match the root and so never reach inside it. */
:root,
.light,
[data-theme="light"] {
  /* A DISABLED GLYPH. It used to borrow --input, the field-stroke colour, which
     left it at 3.17:1 — near enough to the live icon that a disabled control
     did not read as disabled. WCAG exempts inactive components from both
     1.4.3 and 1.4.11, so the constraint here is perceptibility rather than
     compliance. 1.71:1 against white, and 2.99:1 against the live icon beside
     it — the separation that actually says "off" is from the ENABLED glyph, not
     from the ground. */
  --icon-color-disabled: #bfc8c8;
  /* THE CONTAINER INSET — the space between a container's edge and what it
     holds, on ALL FOUR SIDES. A panel, a dialog body, a drawer body, a card,
     an accordion drawer and a settings card are the same kind of thing, and
     each one had picked its own number: 8, 18/20, 0/12/12, 12/16/16, 20. The
     ladder below is the one .ck-card already used, so this names a standard
     that existed rather than inventing one. A container that must run its
     content full-bleed takes .is-flush, which is a decision, not a default. */
  --container-inset: var(--space-base);
  --container-inset-sm: var(--space-md);
  --container-inset-lg: var(--space-xl);
  /* The rest of the ladder. -xs is a ROW inside a list or a tight frame: a
     folder navigator row, a menu's frame around its items. -bar is a
     one-line BAR whose height is its own (toast, alert, notification head,
     accordion trigger): 12 block, 16 inline, with sm and lg steps. A
     container picks a tier from the ladder; it never invents a number.
     The per-component table is in references/rulebook.md § Container inset. */
  /* PROGRESS RING — the circular .ck-progress. Four sizes on the icon and
     control scale; the stroke thickens with the ring the way the linear bar's
     track thickens with its size. Colour is NOT here: the ring reads --track
     for the unfilled arc and the same fill tokens as the bar. */
  --progress-ring-size-sm: 16px;  --progress-ring-stroke-sm: 2px;
  --progress-ring-size: 24px;     --progress-ring-stroke: 3px;
  --progress-ring-size-lg: 40px;  --progress-ring-stroke-lg: 4px;
  --progress-ring-size-xl: 64px;  --progress-ring-stroke-xl: 6px;
  /* THE BADGE CAP — a badge, pill or chip hugs its text up to 200px, then its
     label truncates head…tail ("abc…apso"). No fixed width anywhere: not in
     a table cell, not on the duo badge. (It was a fixed 150px.) */
  --badge-max-width: 200px;
  /* THE BUTTON STROKE — 1px wide. It was set to 0.5px, but Chromium rounds any
     border under 1px up to 1px, so the thinner look comes from the COLOUR
     instead: --btn-border, a lighter stroke on outline buttons (below). */
  --btn-border-width: 1px;
  --grid-gutter: var(--canvas-gap);
  --grid-baseline-step: var(--space-sm);
  --container-inset-xs: var(--space-xs);
  --container-inset-bar: var(--space-md) var(--space-base);
  --container-inset-bar-sm: var(--space-sm) var(--space-md);
  --container-inset-bar-lg: var(--space-base) var(--space-lg);
  /* THE DRAWER'S SPACING — three numbers, and every drawer reads them.
     Head, tools, body and foot all sit on one inset, so the title, the
     search, the first card and the footer buttons share one left and one
     right edge. The body stacks its blocks on one gap; a list inside it
     (rule cards, column cards, activity items) packs tighter on its own; the
     footer's buttons sit on the action gap every button row in the kit uses. */
  --drawer-inset: var(--container-inset);
  --drawer-gap: var(--space-md);
  --drawer-list-gap: var(--space-sm);
  --drawer-action-gap: var(--space-sm);
  /* The drawer an accordion opens. It is NOT --accordion-bg: that paints the
     header row, and one token on both made the open panel indistinguishable
     from the thing that opened it. The drawer lifts toward the card, 73% of
     the way from the header, so an open section reads as content while the
     header stays chrome. */
  --accordion-panel-bg: #fcfcfc;
  /* A solid --info surface carrying text had no declared partner: the family
     shipped --info, -bg, -border and -soft-foreground and no foreground. */
  --info-foreground: #ffffff;
  /* The column-resize grip and its guide line. A proper three-theme token
     that had only ever been declared inside a prototype page. */
  --resize-accent: #1ab5f3;
  /* Neutral is a tone like any other, built from ONE colour at three
     strengths: 100% for the label and glyph, 20% for the stroke, 8% for the
     fill. It used to borrow --muted and --border instead, and in this theme
     those are the same hex (#f5f5f5), so a neutral badge was drawing its
     stroke in its own fill colour and shipped with no border at all. */
  --neutral-bg: #ebeeee;     --neutral-border: #cdd4d5;
  --neutral-soft-foreground: #05262e;
  /* ===== CORE — staple-new-dashboard/src/index.css (oklch, authoritative) ===== */
  --radius: 0.625rem;
  --background: #ffffff;
  --foreground: #05262e;
  /* Loading-shimmer sweep (minted; § 10). The skeleton swept through --input,
     a mid grey at 3.17:1 against the page — correct for a control BORDER,
     far too loud for a placeholder, which should read as absent content
     rather than as a filled bar. One step off --muted instead. */
  --skeleton-sheen: #e8eaeb;
  /* Soft primary surface (minted; § 3, § 10). The reference toast tinted its
     in-progress variant with rgba(0,59,74,.06); rgba is forbidden here, so the
     value is pre-composited against each theme's page ground. Named for the
     ROLE — the primary family's soft surface, completing the --X / --X-bg
     pattern the semantic families already have — not for the toast. */
  --primary-bg: #f0f3f4;
  /* ── Canvas — the app ground (minted; § 4, § 10) ──
     The page the app sits ON, as distinct from the default surface things sit
     IN. shadcn conflates the two because both are #ffffff by default, and this
     kit inherited that: --background was #ffffff and so was --card, so panels
     had no separation and the level was carried entirely by --panel-border.

     The flows never agreed. reconciliation-flow.html sets body to #f4f6f8 by
     hand and the kit never defined it, so the app ground was a per-page
     literal. The token started as that measured value and was then tuned one
     step darker to #eef1f3, which lifts --card's separation from the ground
     from 1.08 to 1.13:1 in light.

     --background CANNOT simply become grey: the kit uses it as the default
     CONTROL fill in 22 places — .ck-input, .ck-select, .ck-textarea,
     .ck-dd-trigger, .ck-multi-trigger, .ck-btn's base, the .ck-switch thumb,
     .ck-check and .ck-radio boxes, .ck-empty. Repointing it would turn every
     field grey. Hence a fourth level rather than a changed value.

     Light is the only theme where canvas and background diverge; dark and high
     contrast already separate the ground from --card, so canvas equals
     --background there and the four levels still read correctly. */
  --canvas: #eef1f3;
  --canvas-foreground: #05262e;
  --card: #ffffff;
  --card-foreground: #05262e;
  /* THE SECONDARY CARD — a tinted card surface, the alternative to --card
     wherever a card should read as a quieter, grouped block: a section of a
     form, a summary tile, a rule you are editing. shadcn naming: the
     component, then the role, then -foreground. Its stroke is one step up
     from the fill. Light #eaf4f6. --filter-card reads it. */
  --card-secondary: #eaf4f6;
  --card-secondary-foreground: #05262e;
  --card-secondary-border: #d8ebef;
  /* A RUNNING progress fill — work under way, lighter than --primary so it
     reads as "not done yet" beside a finished or failed one. Still a
     non-text affordance at 3:1 or better against the card (light 3.10:1,
     dark 5.81:1, high contrast 8.95:1). Bar and ring: .is-running. */
  --progress-running: #229fbf;
  /* THE GRID — columns every layout sits on, and the guide lines that show
     them. 4 / 6 / 8 / 10 / 12 columns; the gutter is the canvas gap, so a grid
     and the panels around it keep one rhythm. --grid-guide tints a column in
     the line overlay, --grid-baseline draws the 8px horizontal lines. The
     overlay is a check, never a finished look. */
  --grid-guide: #cde9f0;
  --grid-baseline: #e3eaec;
  /* The outline button's stroke — lighter than --primary so the edge reads as
     a hairline in every browser, while clearing 3:1 for a control's boundary
     (light 3.17:1 on white, dark 3.05:1 on the card). Hover steps to
     --primary. High contrast keeps the strong edge. */
  --btn-border: #6f97a1;
  --popover: #ffffff;
  --popover-foreground: #05262e;
  /* A menu's identity block — the signed-in user at the top of the account
     menu. The lightest step of the primary family, not --muted: the menu
     opens over the header bar, which sits on the grey canvas, and a grey
     block there merged with the ground it came from. Not --accent either:
     that is the "you are here" surface, and the header is not selected.
     Light: 1.12:1 from the popover, name 14.15:1, meta 4.55:1, the avatar's
     stroke 3.04:1. */
  --menu-header: #dff6fc;
  --menu-header-foreground: #05262e;
  --primary: #013c4b;
  --primary-foreground: #ffffff;
  --secondary: #f5f5f5;
  --secondary-foreground: #292f32;
  --muted: #f5f5f5;
  /* Darkened to #5a7278 on 2026-09-15 to meet WCAG 2.2 SC 1.4.3 AA. It now
     measures 5.11:1 on --background, 4.68:1 on --muted, 4.50:1 on --canvas and
     4.71:1 on --accent, so the whole muted TEXT layer clears the 4.5:1 floor —
     roughly 74 sites: hints, placeholders, timestamps, meta, breadcrumbs,
     disabled labels. Non-text uses already cleared 3:1 and only improved.
     History: #5e767d -> #738f96 (09-10, a design call) -> #5a7278. Note that
     #5e767d did NOT pass either — 4.41 on --muted, 4.24 on --canvas — so this
     layer had never met AA on three of its four surfaces; reverting was never
     the fix. --canvas is the tight one at 4.50:1 with NO headroom, so measure
     against it, not --background, before lightening either token again.
     Change --icon-color with it. § 11 records the figures. Contrast is not the
     only reason to reach for --foreground: anything a user must act on belongs
     there for hierarchy, not here. */
  --muted-foreground: #5a7278;
  /* --group is a second tinted surface, a light TEAL, for bundling a set of
     related controls into one block — a filter rule's field/operator/value
     row, and anything else built the same way. Named for the role, not the
     hue: --accent is the blue tint and stays where it is.
     Light is 1.18:1 on --card and 1.04 on --canvas, so the block reads as a
     group on either; 32 points off --accent, so it is visibly teal rather
     than a second blue. Body text on it is 13.50:1. */
  --group: #cce3df; --group-border: #64948e;
  --group-foreground: #05262e;
  --accent: #e7f9fe;
  --accent-foreground: #05262e;
  --accent-hover: #cfeff9;     /* one step deeper than --accent, for an accent surface that is also clickable (grouped-table heading rows) */
  --destructive: #e50600;
  --destructive-foreground: #ffffff;
  --success: #2e9e52;
  --success-foreground: #ffffff;
  --warning: #f2a618;
  --warning-foreground: #362207;
  --border: #f5f5f5;
  --input: #8b9292;
  /* THE FIELD STROKE — the resting edge of every field control: input,
     select, textarea, dropdown trigger, combobox, search, editor, stepper,
     OTP, phone and the action-bar field. Its own token, not --input: --input
     is also the kit's disabled text and disabled stroke in ~40 places, and a
     field edge is a quieter job. A subtle #d0d3d3 at rest (1.51:1 on white —
     below the 1.4.11 3:1 line by the design owner's decision; the label names
     the field and hover steps to --input-border-hover). Dark and high contrast
     keep the --input value. */
  --field-border: #d0d3d3;
  --input-hover: #696f6f;  /* was #cad3d4 — under WCAG 1.4.11 3:1 vs the page ground */
  --ring: #1c5260;
  --chart-1: #05b6f6;
  --chart-2: #249757;
  --chart-3: #e15e16;
  --chart-4: #db2475;
  --chart-5: #bb5bed;
  --sidebar: #fcfcfc;
  --sidebar-foreground: #292f32;
  --sidebar-primary: #013c4b;
  --sidebar-primary-foreground: #ffffff;
  --sidebar-accent: #e7f9fe;
  --sidebar-accent-foreground: #05262e;
  --sidebar-border: #e8e8e8;
  --sidebar-ring: #013c4b;

  /* Fonts (index nomenclature; fallbacks added for standalone prototypes) */
  /* Noto Sans, then the generic category, and nothing else named. -apple-system
     and BlinkMacSystemFont used to sit in the middle of this chain: they are
     San Francisco and Roboto, two more typefaces the product never chose, and
     on the machines where they resolve they are what the reader actually sees
     whenever the webfont is slow. A generic `sans-serif` is the honest
     fallback — it names no face, so nothing can quietly substitute for Noto. */
  --font-sans: "Noto Sans Variable", "Noto Sans", sans-serif;
  /* --font-mono is gone. Menlo was carrying values and IDs, and a second
     typeface for digits is a typeface the product does not need: what mono was
     actually buying there was column alignment, and font-variant-numeric:
     tabular-nums gives that in Noto Sans without a second face to load, size
     and pair. One family, everywhere. Anything still asking for --font-mono
     resolves to nothing — replace it with --font-sans. */

  /* Shadows — index ships these flat (zero-opacity) by design.
     For Clipper-style elevation see the opt-in block near the bottom. */
  /* Flat elevation scale, mirroring the app's Tailwind scale which ships
     deliberately flat. Expressed as zero geometry with a hex rather than
     `none`, so every token carries a colour while nothing is painted — the
     colour is never drawn at 0 offset / 0 blur / 0 spread, which is why it is
     #000000 in every theme rather than a per-theme value. Giving these real
     shadows would change 24 page usages, i.e. a design change smuggled into a
     notation change. */
  --shadow-2xs: 0 0 0 0 #000000;
  --shadow-xs: 0 0 0 0 #000000;
  --shadow-sm: 0 0 0 0 #000000;
  --shadow: 0 0 0 0 #000000;
  /* Note: --shadow-md carries a real value further down, with the Clipper set. */
  --shadow-lg: 0 0 0 0 #000000;
  --shadow-xl: 0 0 0 0 #000000;
  --shadow-2xl: 0 0 0 0 #000000;

  /* ── Type scale (shadcn nomenclature, Clipper Kit values) ──
     § 6 said "there is no type-scale token family yet" and § 14.5 tracked it as
     an open defect. This closes it. Names follow shadcn / Tailwind v4 exactly
     (--text-*, --font-weight-*), so `text-sm` and `font-semibold` resolve
     against them in a Tailwind build; the VALUES are the kit's own, which is
     the same composition rule the colour tokens follow — shadcn names, Clipper
     values.

     Theme-independent, so :root only, like --radius and --space-*.

     The kit had 13 distinct sizes where § 6 documented 7. Ten of them are
     tokenised below. Left alone deliberately: 8px on .icon-btn's notification
     badge, and the 9 / 10 / 11px pill-counter sizes, which are already
     component-scoped variables (--ck-pill-fs, --ck-count-fs), now fed from
     the scale rather than
     literals. Consolidating any of those changes appearance and is a design
     call, not a mechanical one. */
  /* Whole pixels only. No half-steps: a 0.5px difference is not a decision a
     reader can perceive, and it made two adjacent slots indistinguishable. */
  --text-3xs: 8px;          /* Notification badge digits — the smallest mark */
  --text-2xs: 9px;          /* Counter digits at .size-sm */
  --text-xs: 10px;          /* Uppercase group labels */
  --text-sm: 11px;          /* Table column headers (medium), small counters */
  --text-md: 12px;          /* Table cell data, hints, helper text, badge text */
  --text-base: 13px;        /* Body: labels, timestamps, input, dropdown,
                               search, list rows, options, buttons */
  --text-lg: 14px;          /* Card titles (semibold) */
  --text-xl: 16px;          /* Panel / dialog / drawer titles; inactive crumb */
  --text-2xl: 18px;         /* Header bar title and the active crumb */
  --text-3xl: 20px;         /* Auth / onboarding title */
  --text-4xl: 22px;         /* Reserved — a page hero */
  --text-5xl: 24px;         /* Reserved */
  --text-6xl: 28px;         /* Reserved */
  --text-7xl: 32px;         /* Reserved */

  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  /* 700 was already being drawn — the kit page's own weight specimen wrote
     `font:700 …` as a literal and flows reached for it the same way, because
     there was no token to reach for instead. The variable axis is loaded at
     100..900, so it costs no extra fetch. */
  --font-weight-bold: 700;

  /* Radius scale — index defines --radius + sm/md/lg/xl (calc); Clipper extras appended */
  --radius-sm: calc(var(--radius) - 4px); /* 6px  */
  --radius-md: calc(var(--radius) - 2px); /* 8px  */
  --radius-lg: var(--radius);             /* 10px */
  --radius-xl: calc(var(--radius) + 4px); /* 14px */
  --radius-xs: 4px;       /* Clipper-only. Was 2px; the checkbox box reads as a
                             rendering artefact at 2px, and the React kit already
                             shipped rounded-[4px], so the HTML kit was the outlier.
                             Moves the whole § 7b mark tier: checkbox, search
                             highlight, inline code. */
  --radius-2xl: 16px;     /* Clipper-only */
  --radius-3xl: 24px;     /* Clipper-only */
  --radius-full: 999px;   /* Clipper-only */

  /* ===== EXTENSIONS — Clipper Kit v2.0 (no index.css equivalent) ===== */

  /* Display font — index has no display slot */
  /* --font-display is gone. Fraunces was marketing-only and deliberately never
     fetched, so a product screen asking for it rendered in Times New Roman —
     a third typeface arriving by fallback rather than by choice. One family:
     anything that wanted display weight takes --font-sans at a heavier weight
     and a larger step. --font-serif (Georgia) went with it; it had no uses at
     all. */

  /* Info (semantic) + link — not present in index.css */
  --info: #387ff9; --info-bg: #eef3fb; --info-border: #d5e1f5;
  --link: #2562ee;

  /* Soft semantic surfaces — index only ships solid colour + foreground */
  --destructive-bg: #fcebeb; --destructive-border: #f7cdcc;
  /* A soft tone's -border is its -soft-foreground, in every theme. It used to
     be a pale tint of the fill — #bce5cd for success — which measured 1.38:1
     against the page and only 1.25:1 against its own --success-bg, so the
     stroke did nothing at all: a success pill was read entirely by its fill.
     High contrast already did it this way; light and dark were the outliers.
     Same change across all six semantic tones, because a strong green edge
     beside a faded amber one reads as a bug rather than a hierarchy. */
  --success-bg: #edf5f0;     --success-border: #d3e5d9;
  --warning-bg: #f7f3eb;     --warning-border: #eae0ce;

  /* Badge palette — 24 colours (foreground / soft bg / border) */
  --teal: #0f766e;     --teal-bg: #ccfbf1;     --teal-border: #99f6e4;
  --cyan: #0e7490;     --cyan-bg: #ecf4f6;     --cyan-border: #cfe3e9;
  --indigo: #4338ca;   --indigo-bg: #e0e7ff;   --indigo-border: #c7d2fe;
  --pink: #be185d;     --pink-bg: #fce7f3;     --pink-border: #fbcfe8;
  --rose: #be123c;     --rose-bg: #ffe4e6;     --rose-border: #fecdd3;
  --amber: #b45309;    --amber-bg: #fef3c7;    --amber-border: #fde68a;
  --lime: #4d7c0f;     --lime-bg: #ecfccb;     --lime-border: #d9f99d;
  --emerald: #047857;  --emerald-bg: #d1fae5;  --emerald-border: #a7f3d0;
  --violet: #6d28d9;   --violet-bg: #f3eefc;   --violet-border: #e2d4f7;
  --fuchsia: #a21caf;  --fuchsia-bg: #fae8ff;  --fuchsia-border: #f5d0fe;
  --sky: #0369a1;      --sky-bg: #e0f2fe;      --sky-border: #bae6fd;
  --slate: #475569;    --slate-bg: #f1f5f9;    --slate-border: #e2e8f0;
  --gold: #a16207;     --gold-bg: #fef9c3;     --gold-border: #fef08a;
  --crimson: #b91c1c;  --crimson-bg: #fee2e2;  --crimson-border: #fecaca;
  --sage: #3d6b50;     --sage-bg: #e8f5e9;     --sage-border: #c8e6c9;
  --purple: #6c45c1;   --purple-bg: #ede9fc;   --purple-border: #ded5f5;
  --orange: #c25e1f;   --orange-bg: #fef0e1;   --orange-border: #fbd7ae;
  --blue: #2562ee;     --blue-bg: #e3f0fe;     --blue-border: #b7d6fd;
  /* Interaction + panel surfaces. Hover and secondary states across the
     product use the nav active tint; panels take a visible stroke, since
     --border is near-invisible against the page by design. */

  /* ── Dark floating action bar (document preview toolbar, page badges) ──
     Restored: these were dropped by 83923ed, which left var(--toolbar-dark)
     unresolved and the preview bar rendering on the page ground. */
  --toolbar-dark: #08272e;              /* dark floating action-bar / page-badge surface */
  --toolbar-dark-foreground: #ffffff;   /* icons/text on the dark bar */
  --toolbar-dark-muted: #a1adb0;  /* secondary icons/labels */
  --toolbar-dark-hover: #2b454b;  /* hover fill on the dark bar */
  --toolbar-dark-active: #395258; /* active page pill on the dark bar */
  --toolbar-dark-sep: #304a4f;    /* separators on the dark bar */
  --preview-surface: #e9ebef;           /* light cool-gray preview frame the document sits on */
  --thumb-overlay: #08272e;
  --thumb-overlay-opacity: .32;  /* hover dim over a page thumbnail */
  --nav-item-bg-active: #e5f8fe;
  --hover-bg: var(--nav-item-bg-active);
  --selected-bg: var(--nav-item-bg-active);
  --selected-fg: var(--primary);
  --panel-border: #ebeff0;   /* panel / widget stroke, product-wide */

  /* --track is the UNFILLED REMAINDER of any track: the progress bar's
     background and the slider's rail. Named for the role, not for the first
     component that needed it — it serves two, and a --progress token would be
     the component-named redundancy that retired --switcher-on.

     It joins --border, --input and --ring as a bare non-text token: a track
     carries no text, so it has no -foreground partner, and the filled portion
     stays on the semantic tones (--primary / --success / --warning /
     --destructive).

     It exists because --muted measured 1.04:1 against --canvas and 1.00:1
     against a --muted panel — a bar or rail laid on either was invisible.
     --track is 1.21 vs canvas, 1.37 vs card, 1.26 vs a muted panel, and the
     --primary fill still dominates it at 8.75:1. */
  --track: #d7dddf;

  /* A toggle's OFF track. Its own value, not an alias — this is the v2.0
     kit's --switcher-off, kept because it is the switch the product's users
     already recognise. It is lighter than --input (#8b9292), so a white knob
     on it reads 2.09:1 rather than 3.17:1; that is a deliberate design
     choice, recorded here rather than discovered later.
     --track is NOT reusable for this: at #d7dddf a switch would be paler
     still, and --track has a different job (a rail behind a fill). */
  --toggle-track: #a9b6b7;
  --toggle-track-hover: #95a0a1;

  /* The recessed trough a segmented control sits in, and the label of an
     UNSELECTED segment on it. Its own pair because no existing surface fits:
     --muted is 1.04:1 against the page so the trough vanished, and --canvas is
     the app ground, which § 4 forbids putting a control group on. The label
     clears 7.14:1 on it. */
  --segment: #eef1f3;
  --segment-foreground: #3f5359;

  /* The edge of a working panel sitting on --canvas. Its own value because
     --panel-border cannot do this job: at #ebeff0 it measures 1.02:1 against
     the canvas, so a panel laid on the ground had no visible edge at all and
     was read only by its white fill (1.13:1). This is 1.63:1 against the panel
     and 1.44:1 against the canvas — evident, without becoming a hard rule
     around every region of the screen. */
  --panel-stroke: #c3ccd0;

  /* The line drawn between two related nodes on a relation canvas. Its own
     value because nothing existing does this job honestly: --panel-border and
     --panel-stroke are edges of a region, --input is a control's stroke, and
     --info is a status. A connector is structure — it says two things are
     joined — so it is read, not decorated, and carries 3:1 against the ground
     it is drawn on (WCAG 1.4.11). 3.81:1 on --canvas.
     pairing-exempt: a stroke, it carries no text. */
  --connector: #3a78d8;

  /* A relation node is drawn as a folder, so it needs a body and the lighter
     tab above it. Role, not palette: --relation-node is any node, and
     --relation-node-source is the one the tree is drawn FROM — the folder you
     arrived from, which is why it is the odd one out in the picture.
     TONED DOWN (2026-10-05): the light and dark folders keep their lightness
     but carry ~28% less saturation — teal 68→49%, orange 85→61% in light —
     because at full strength they were the loudest thing on the canvas. High
     contrast keeps its strong fills on purpose. The tab is interior to the
     folder, so its neighbour is the body rather than the ground; it only has
     to read as the same object seen from above.
     pairing-exempt: illustration fills, they carry no text. */
  --relation-node: #3ca4af;
  --relation-node-tab: #74c1c8;
  --relation-node-source: #ce8d31;
  --relation-node-source-tab: #d9ae6d;

  /* Folder panel counters — secondary blue. Change here and every panel
     that links this file follows. */
  --counter-fg: var(--blue);
  --counter-bg: var(--blue-bg);
  --counter-border: var(--blue-border);

  /* Component tokens (--switcher-* retired: on/thumb were pure aliases of
     --primary/--background; off superseded by the corrected --input) */
  --accordion-stroke: #e4e8e9; --accordion-bg: #f4f6f7;
  /* A filter rule card: a block you are EDITING inside a panel, which is
     neither a surface you are on (--accent) nor one you are reading
     (--card). Its own ground, so those two keep their meanings.
     The stroke is a step up from the fill, not a different colour — it is
     there to close the card, not to outline it. */
  /* Two shades lighter than it was (#dcecf0 / #cae3e9), lightness +4 on the
     same hue and saturation. A stack of rule cards is most of the drawer, and at
     the old weight the stack read as one heavy block. */
  --filter-card: var(--card-secondary); --filter-card-foreground: var(--card-secondary-foreground);
  --filter-card-border: var(--card-secondary-border);
  /* The operator control on a rule card: a fill a step down from the card,
     and a stroke at 3.21:1 against it (WCAG 1.4.11). Label 11.85:1. */
  --filter-op: #cfe2e7; --filter-op-foreground: #05262e;
  --filter-op-border: #7a8a8e;
  --chart-label: #08272e; --chart-text: #637477;
  --cmd-highlight: #f0f7ff;
  /* Breadcrumb header metrics. Theme-independent (spacing and type size, not
     colour), so they sit in :root only. */
  --breadcrumb-gap: 4px;
  --breadcrumb-size: 16px;
  /* Gap between the header's leading controls — panel toggle, crumb trail, info
     icon. Distinct from the right-hand action group, which sets its own. */
  --header-control-gap: 8px;
  /* Table header — grey surface is --muted; this fixes the row height so every
     data table in the product lands on the same header. */
  --table-header-height: 36px;
  /* THE CANVAS GAP — 12px. Between panels on the canvas, below the last row,
     and at both sides; the header bar pads its sides by the same number so
     its first control lines up with the panels' edge. One number, so the
     rhythm of a screen is one number. (Was 16px.) */
  --canvas-gap: var(--space-md);
  /* Gutter between the icon rail and the content column. Also the gap between
     the folder panel and the main card, so the card lands on the same gap
     whether the panel is open or collapsed. It is the canvas gap. */
  --panel-gutter: var(--canvas-gap);
  /* Focus rings (index relies on Tailwind ring utilities; kept for prototypes).
     Derived from --ring / --destructive via color-mix so they follow the theme. */
  --focus-ring: 0 0 0 3px #c6d4d7;
  --focus-ring-error: 0 0 0 3px #f9c8c7;
  --focus-ring-ai: 0 0 0 3px #ddd2f5;
  --focus-ring-success: 0 0 0 3px #d3e5d9;
  --focus-ring-offset: 2px;
  /* A small lift off the surface — x 0, y 1, blur 3. Named for the role, not
     for the switch thumb that needed it first: it also carries the slider
     thumb, a hovered page thumbnail and the floating action bar. */
  /* The system's ONE drop shadow: x 0, y 1, blur 3. Overlays cast it;
     panels resting on the canvas cast nothing; tooltips never cast it. */
  --shadow-md: 0 1px 3px #cccccc;
  --shadow-raised: var(--shadow-md);

  /* DFP status-dot colours */
  /* ROLE TOKENS promoted from the DES-667 review audit. Each names an intent
     a screen was expressing with a borrowed hue or a component-scoped token:
       --confidence-*  the extraction confidence scale — any table cell or
                       field, not only the Document Fields Panel (--dfp-* reads it)
       --match-*       the line in focus across every document being compared
       --ai-*          the AI-extracted mark: .is-ai fields, the OCR box
       --series-1..8   categorical row identity, like shadcn --chart-1..5
     Declared in every theme block, so a light-scoped region keeps them. */
  --confidence-ok: #99b7bf; --confidence-confirmed: #3d707c; --confidence-warn: #f19546;
  --dfp-ok: var(--confidence-ok); --dfp-confirmed: var(--confidence-confirmed); --dfp-matched: #5ea3fc; --dfp-warn: var(--confidence-warn);
  --match: var(--amber-bg); --match-foreground: var(--amber-soft-foreground); --match-border: var(--warning);
  --ai: var(--purple-bg); --ai-foreground: var(--purple-soft-foreground); --ai-border: var(--purple-soft-foreground);
  --series-1: var(--emerald); --series-2: var(--blue); --series-3: var(--rose); --series-4: var(--violet);
  --series-5: var(--crimson); --series-6: var(--sage); --series-7: var(--amber); --series-8: var(--cyan);

  /* Spacing scale (4px base) */
  /* Alpha, split into a companion token the way § 1 permits. It is for
     controls that are PURE GEOMETRY — a switch track and its knob, which
     carry no text and no glyph. Never put it on anything with a label: that
     is the case the no-opacity rule exists for. */
  --disabled-opacity: 0.4;

  --space-2xs: 2px; --space-xs: 4px; --space-sm: 8px; --space-md: 12px;
  --space-base: 16px; --space-lg: 20px; --space-xl: 24px; --space-2xl: 32px;
  /* The master pane of a master-detail split — a role list beside a role.
     A measure, not a colour, so it lives here once and not per theme. */
  --pane-width: 284px;
  --space-3xl: 40px; --space-4xl: 48px; --space-5xl: 64px; --space-6xl: 80px;
  --space-7xl: 96px; --space-8xl: 128px;

  /* Z-index scale */
  --z-base: 1; --z-sticky: 10; --z-dropdown: 20; --z-overlay: 30;
  --z-modal: 40; --z-topbar: 50; --z-toast: 60; --z-tooltip: 70;
  /* The gutter every floating panel keeps between itself and the window edge,
     and the gap it keeps from the control that opened it. Rulebook 12a. */
  --overlay-margin: 8px; --overlay-gap: 6px;

  /* Transition tokens */
  --duration-fast: .1s; --duration-base: .15s; --duration-moderate: .2s; --duration-slow: .3s;
  /* Every chevron in the product turns at this one speed. Named separately
     from --duration-moderate so a change to general motion cannot desync the
     chevrons from each other. Rulebook 14.9, check 8a. */
  --duration-chevron: .2s;
  --ease-default: ease; --ease-out: ease-out; --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  /* ── Interaction-state fills (minted for Button; Rulebook §8) ──
     Filled variants shift their surface on hover instead of using opacity,
     which would dim the label with it. Each keeps its family's -foreground.
     Derivation: a fill moves AWAY from its own lightness extreme (light
     surface darkens, dark surface lightens) so there is always room to move;
     the result must still clear 4.5:1 against the family foreground, else it
     shifts the other way. All 18 values verified — lowest 4.51:1. */
  --primary-hover: #26515f;
  --destructive-hover: #c10400;
  --primary-active: #3e6370;
  --destructive-active: #a40300;

  /* ── Elevation for floating surfaces (minted; Rulebook §10) ──
     The core --shadow-* scale ships flat (zero opacity) to match the app, so
     panels and overlays had been hand-rolling their own shadow values. Those were a
     near-black tint that measured ΔE 0.17 against the dark page ground —
     invisible. Per-theme values instead. */
  --shadow-panel: var(--shadow-md);
  --shadow-overlay: var(--shadow-md);

  /* Modal scrim (minted; replaced an undefined --cmd-backdrop whose literal
     fallback was carrying it) */
  --scrim: #08272e;
  --scrim-opacity: .45;

  /* Animated alpha ramps (§ 2a). A ring whose alpha varies over time cannot be
     pre-composited: the colour stays a 6-digit hex token and the alpha rides a
     companion --*-opacity token on a ::after ring. Named for the role, never the
     strength. High contrast raises every peak; the trough is always 0. */
  --pulse-attention-opacity: .42;
  --pulse-activity-opacity: .55;
  --pulse-input-opacity: .18;
  --pulse-guide-opacity: .55;

  /* Foreground for a soft-semantic surface (minted; Rulebook §3, §9).
     The solid token as text on its own -bg tint measures 1.83-4.41:1 at the
     status pill's 11px — under 4.5:1 in five of six tones. These clear it. */
  --success-soft-foreground: #227c3f;
  --warning-soft-foreground: #96650a;
  --destructive-soft-foreground: #d90500;
  --info-soft-foreground: #2c67cc;

  /* Derived surfaces, minted so the kit needs no color-mix(). Each is a
     pre-composited 6-digit hex; a change to --primary, --input,
     --foreground or --background must be mirrored here. */
  --input-border-hover: #4d6b72;
  --highlight-bg: #d1dcdf;
  --icon-hover-bg: #e8ebec;
  --tip-code-bg: #2d494f;
  --tip-eg-foreground: #b9c2c4;

  /* Text colour for a soft-semantic surface, every palette family.
     The solid token as text on its own -bg tint fails 4.5:1 in 12 of 66
     family/theme pairs at the pill's 11px. These clear it. */
  --amber-soft-foreground: #b45309;
  --blue-soft-foreground: #245fe8;
  --crimson-soft-foreground: #b91c1c;
  --cyan-soft-foreground: #0e7490;
  --emerald-soft-foreground: #047857;
  --fuchsia-soft-foreground: #a21caf;
  --gold-soft-foreground: #a16207;
  --indigo-soft-foreground: #4338ca;
  --lime-soft-foreground: #4d7c0f;
  --orange-soft-foreground: #ad531b;
  --pink-soft-foreground: #be185d;
  --purple-soft-foreground: #6c45c1;
  --rose-soft-foreground: #be123c;
  --sage-soft-foreground: #3d6b50;
  --sky-soft-foreground: #0369a1;
  --slate-soft-foreground: #475569;
  --teal-soft-foreground: #0f766e;
  --violet-soft-foreground: #6d28d9;

  /* ── Icons (Rulebook §7c) ──
     One stroke width, one size, one box, two colours. Every icon in the
     product is Lucide: 24x24 viewBox, currentColor, round caps and joins.
     --icon-stroke is unitless so it can go straight into stroke-width. */
  --icon-stroke: 2;
  --icon-size: 16px;
  --icon-box: 24px;
  /* The one sanctioned second icon size: the app's left rail. 20px glyph in a
     40px frame — see .ck-ico.size-nav and rulebook 7c. */
  --icon-size-nav: 20px;
  --icon-size-sm: 12px;
  --icon-box-sm: 18px;
  --icon-box-nav: 40px;
  /* Tracks --muted-foreground exactly, in every theme, and always has. It
     stays its OWN value rather than an alias so an icon tone can diverge from
     muted text deliberately one day — but while they are meant to read as one
     tone, they must be changed together. .ck-ico, .ck-alert-icon and
     .ck-file-icon read this; .ck-toast-icon, every chevron and the search
     magnifier read --muted-foreground. Let the two drift and icons stop
     matching each other, never mind the labels beside them. */
  --icon-color: #5a7278;
  --icon-color-destructive: #d90500;


  /* ── EMAIL BODY SWATCHES — content colours, not chrome ──────────────────
     The palette a user can apply to text inside an email they are composing.
     These are AUTHORED CONTENT: the chosen value is written into the email's
     HTML and sent, so it must be the same in every theme — an email must not
     change colour because the author had dark mode on. They are declared in
     all three themes with identical values so that is a stated rule rather
     than an omission, and so a screen never needs a literal to offer them. */
  --email-swatch-1: #003b4a;
  --email-swatch-2: #33616c;
  --email-swatch-3: #22c4ff;
  --email-swatch-4: #0a8754;
  --email-swatch-5: #c0392b;
  --email-swatch-6: #9a6b00;
  --email-swatch-7: #292e30;
  --email-swatch-8: #5d6769;
  --email-swatch-9: #8e44ad;
  --email-swatch-10: #000000;

}

/* ===== DARK — index.css `.dark` core + Clipper dark extensions ===== */
.dark,
[data-theme="dark"] {
  /* Same relationship over the dark ground: 2.45:1. */
  --icon-color-disabled: #505f61;
  /* Same 73% lift, over the dark ground. */
  --accordion-panel-bg: #203539;
  --info-foreground: #142226;
  --resize-accent: #5ec6f6;
  /* Same construction over the dark ground. */
  --neutral-bg: #273437;     --neutral-border: #434e51;
  --neutral-soft-foreground: #ffffff;
  /* CORE (index .dark, oklch) */
  --background: #142226;
  --foreground: #ffffff;
  --skeleton-sheen: #26383d;
  --primary-bg: #1f2e32;
  /* Canvas — equals --background here; the dark ground already separates from
     --card, so a fourth value would be a distinction without a difference. */
  --canvas: #142226;
  --canvas-foreground: #ffffff;
  --card: #233a3e;
  --card-foreground: #ffffff;
  --card-secondary: #2b4348;
  --card-secondary-foreground: #ffffff;
  --card-secondary-border: #31494f;
  --progress-running: #56c2dc;
  --grid-guide: #35565c;
  --grid-baseline: #2a3e42;
  --btn-border: #5d8790;
  --popover: #2f5155;
  --popover-foreground: #ffffff;
  --menu-header: #16414f;
  --menu-header-foreground: #ffffff;
  --primary: #e7f9fe;
  --primary-foreground: #05262e;
  --secondary: #1b292d;
  --secondary-foreground: #ffffff;
  --muted: #1b292d;
  --muted-foreground: #bcd7dd;
  --group: #31544f; --group-border: #688f8a;
  --group-foreground: #ffffff;
  --accent: #233a3e;
  --accent-foreground: #ffffff;
  --accent-hover: #2f4b50;
  --destructive: #fe9b98;
  --destructive-foreground: #05262e;  /* was #ffffff — 2.03:1 on the light-red dark-theme --destructive; now 7.83:1 */
  --success: #42c070;
  --success-foreground: #142226;
  --warning: #f7b83d;
  --warning-foreground: #142226;
  --border: #233a3e;
  --input: #5f7073;
  --field-border: #5f7073;
  --input-hover: #7a888b;  /* was #233a3e — under WCAG 1.4.11 3:1 vs the page ground */
  --ring: #e7f9fe;
  --chart-1: #49ceff;
  --chart-2: #39d199;
  --chart-3: #efad32;
  --chart-4: #249757;
  --chart-5: #db2475;
  --sidebar: #142226;
  --sidebar-foreground: #ffffff;
  --sidebar-primary: #e7f9fe;
  --sidebar-primary-foreground: #05262e;
  --sidebar-accent: #233a3e;
  --sidebar-accent-foreground: #ffffff;
  --sidebar-border: #1c5260;
  --sidebar-ring: #e7f9fe;

  /* EXTENSIONS (Clipper dark) */
  --info: #92c4fe; --info-bg: #304b55; --info-border: #92c4fe;
  --link: #92c4fe;
  --destructive-bg: #3d3e41; --destructive-border: #fe9b98;
  --success-bg: #304f4c; --success-border: #6dcc8a;
  --warning-bg: #3c4945; --warning-border: #f7b83d;

  --teal: #5eead4;    --teal-bg: #2a4f50;   --teal-border: #326663;
  --cyan: #67e8f9;    --cyan-bg: #2b4f54;  --cyan-border: #34666d;
  --indigo: #a5b4fc;  --indigo-bg: #334955; --indigo-border: #44586e;
  --pink: #f472b6;    --pink-bg: #3c414c;  --pink-border: #57485c;
  --rose: #fb7185;    --rose-bg: #3d4147;  --rose-border: #594850;
  --amber: #fbbf24;   --amber-bg: #3d4a3b;  --amber-border: #595b38;
  --lime: #a3e635;    --lime-bg: #324f3d;   --lime-border: #43653c;
  --emerald: #6ee7b7; --emerald-bg: #2c4f4d; --emerald-border: #36655c;
  --violet: #a78bfa;  --violet-bg: #334455; --violet-border: #b6a1fc;
  --fuchsia: #e879f9; --fuchsia-bg: #3b4254; --fuchsia-border: #544a6d;
  --sky: #7dd3fc;     --sky-bg: #2e4c55;   --sky-border: #3a606e;
  --slate: #94a3b8;   --slate-bg: #31474d; --slate-border: #3f545c;
  --gold: #facc15;    --gold-bg: #3d4c39;   --gold-border: #595e34;
  --crimson: #fca5a5; --crimson-bg: #3d474a; --crimson-border: #595558;
  --sage: #81c784;    --sage-bg: #2e4b46;  --sage-border: #3b5d50;
  --purple: #c4b0f0;  --purple-bg: #364853; --purple-border: #d3c6f2;
  --orange: #f6bb7b;  --orange-bg: #3c4945; --orange-border: #585a4d;
  --blue: #92c4fe;    --blue-bg: #304b55;  --blue-border: #3f5c6e;
  /* Interaction + panel surfaces. Hover and secondary states across the
     product use the nav active tint; panels take a visible stroke, since
     --border is near-invisible against the page by design. */
  --nav-item-bg-active: #335258;
  --hover-bg: var(--nav-item-bg-active);
  --selected-bg: var(--nav-item-bg-active);
  --selected-fg: var(--primary);
  --panel-border: #43575a;   /* panel / widget stroke, product-wide */
  --track: #2b4045;       /* 1.49 vs page, 1.10 vs --card. #26383d would
                                collide with --card at 1.02 and vanish there */
  --toggle-track: #4a5c5f; --toggle-track-hover: #637375;   /* 2.32 vs page */
  --segment: #1b292d; --segment-foreground: #bcd7dd;        /* label 9.92 on trough */
  --panel-stroke: #4f666a;   /* 1.97 vs --card, 2.67 vs --canvas */
  --connector: #7aa9f0;              /* 6.81 vs --canvas */
  --relation-node: #6fbcc3;
  --relation-node-tab: #9ecdd1;
  --relation-node-source: #d9ab63;
  --relation-node-source-tab: #e7c592;
  /* The preview frame a document sits on. Was :root-only, so a dark theme
     rendered the light grey #e9ebef behind the page. Matches --background in
     both dark themes, which is what every consuming flow was overriding it to. */
  --preview-surface: #142226;
  --accordion-stroke: #2c5156; --accordion-bg: #19292d;
  --filter-card: var(--card-secondary); --filter-card-foreground: var(--card-secondary-foreground);
  --filter-card-border: var(--card-secondary-border);
  --filter-op: #152125; --filter-op-foreground: #ffffff;
  --filter-op-border: #7f9397;
  --chart-label: #fcfdfd; --chart-text: #aabcbe;
  --cmd-highlight: #31494d;
  --shadow-md: 0 1px 3px #0d1619;
  --shadow-raised: var(--shadow-md);
  --confidence-ok: #99b7bf; --confidence-confirmed: #66a3b0; --confidence-warn: #f5a95e;
  --dfp-ok: var(--confidence-ok); --dfp-confirmed: var(--confidence-confirmed); --dfp-matched: #7ab8ff; --dfp-warn: var(--confidence-warn);
  --match: var(--amber-bg); --match-foreground: var(--amber-soft-foreground); --match-border: var(--warning);
  --ai: var(--purple-bg); --ai-foreground: var(--purple-soft-foreground); --ai-border: var(--purple-soft-foreground);
  --series-1: var(--emerald); --series-2: var(--blue); --series-3: var(--rose); --series-4: var(--violet);
  --series-5: var(--crimson); --series-6: var(--sage); --series-7: var(--amber); --series-8: var(--cyan);
  /* Interaction-state fills — dark. Primary is light here, so hover moves
     toward its own foreground rather than toward black. */
  --primary-hover: #c3d2d6;
  --destructive-hover: #d6827f;
  --primary-active: #a6b3b6;
  --destructive-active: #ffb2ae;

  /* Elevation — dark. A tint cannot darken a dark ground, so the shadow goes
     to true black and a hairline carries the edge; the lighter --popover /
     --card surface does most of the lifting. */
  --shadow-panel: 0 0 0 1px var(--panel-border), var(--shadow-md);
  --shadow-overlay: 0 0 0 1px var(--panel-border), var(--shadow-md);

  /* Modal scrim (minted; replaced an undefined --cmd-backdrop whose literal
     fallback was carrying it) */
  --scrim: #000000;
  --scrim-opacity: .62;

  /* Animated alpha ramps (§ 2a). A ring whose alpha varies over time cannot be
     pre-composited: the colour stays a 6-digit hex token and the alpha rides a
     companion --*-opacity token on a ::after ring. Named for the role, never the
     strength. High contrast raises every peak; the trough is always 0. */
  --pulse-attention-opacity: .50;
  --pulse-activity-opacity: .62;
  --pulse-input-opacity: .24;
  --pulse-guide-opacity: .62;

  /* Foreground for a soft-semantic surface (minted; Rulebook §3, §9).
     The solid token as text on its own -bg tint measures 1.83-4.41:1 at the
     status pill's 11px — under 4.5:1 in five of six tones. These clear it. */
  --success-soft-foreground: #6dcc8a;
  --warning-soft-foreground: #f7b83d;
  --destructive-soft-foreground: #ffaca8;
  --info-soft-foreground: #92c4fe;

  /* Focus rings, per theme. These used to be one color-mix() in :root that
     derived from --ring, so they followed the theme for free. Hardcoding
     them to 6-digit hex means each theme needs its own, and a change to
     --ring or --destructive must be mirrored here. */
  --focus-ring: 0 0 0 3px #49585c;
  --focus-ring-error: 0 0 0 3px #473d3f;
  --focus-ring-ai: 0 0 0 3px #3d3a4a;
  --focus-ring-success: 0 0 0 3px #304f4c;

  /* Derived surfaces, minted so the kit needs no color-mix(). Each is a
     pre-composited 6-digit hex; a change to --primary, --input,
     --foreground or --background must be mirrored here. */
  --input-border-hover: #9caeb2;
  --highlight-bg: #3a494d;
  --icon-hover-bg: #29363a;
  --tip-code-bg: #d9dcdc;
  --tip-eg-foreground: #566063;

  /* Text colour for a soft-semantic surface, every palette family.
     The solid token as text on its own -bg tint fails 4.5:1 in 12 of 66
     family/theme pairs at the pill's 11px. These clear it. */
  --amber-soft-foreground: #fbbf24;
  --blue-soft-foreground: #92c4fe;
  --crimson-soft-foreground: #fca5a5;
  --cyan-soft-foreground: #67e8f9;
  --emerald-soft-foreground: #6ee7b7;
  --fuchsia-soft-foreground: #eb88fa;
  --gold-soft-foreground: #facc15;
  --indigo-soft-foreground: #a5b4fc;
  --lime-soft-foreground: #a3e635;
  --orange-soft-foreground: #f6bb7b;
  --pink-soft-foreground: #f88ac1;
  --purple-soft-foreground: #c4b0f0;
  --rose-soft-foreground: #ff8a98;
  --sage-soft-foreground: #81c784;
  --sky-soft-foreground: #7dd3fc;
  --slate-soft-foreground: #a4b1c3;
  --teal-soft-foreground: #5eead4;
  --violet-soft-foreground: #b6a1fc;

  /* ── Icons (Rulebook §7c) ──
     One stroke width, one size, one box, two colours. Every icon in the
     product is Lucide: 24x24 viewBox, currentColor, round caps and joins.
     --icon-stroke is unitless so it can go straight into stroke-width. */
  --icon-stroke: 2;
  --icon-size: 16px;
  --icon-box: 24px;
  /* The one sanctioned second icon size: the app's left rail. 20px glyph in a
     40px frame — see .ck-ico.size-nav and rulebook 7c. */
  --icon-size-nav: 20px;
  --icon-size-sm: 12px;
  --icon-box-sm: 18px;
  --icon-box-nav: 40px;
  --icon-color: #bcd7dd;
  --icon-color-destructive: #fe9b98;


  /* Email body swatches — identical in every theme on purpose; see :root. */
  --email-swatch-1: #003b4a;
  --email-swatch-2: #33616c;
  --email-swatch-3: #22c4ff;
  --email-swatch-4: #0a8754;
  --email-swatch-5: #c0392b;
  --email-swatch-6: #9a6b00;
  --email-swatch-7: #292e30;
  --email-swatch-8: #5d6769;
  --email-swatch-9: #8e44ad;
  --email-swatch-10: #000000;

}

/* ===== HIGH CONTRAST — Clipper-only mode (index has none; core values derived) ===== */
[data-theme="high-contrast"] {
  /* High contrast stays strong at 4.96:1. Dimming it to the other themes’
     ratio would defeat the one thing the theme exists for. */
  --icon-color-disabled: #7b7b7b;
  /* High contrast lifts AWAY from the page instead: its card is #000000, so
     "toward the card" would erase the drawer. */
  --accordion-panel-bg: #262626;
  --info-foreground: #000000;
  --resize-accent: #66d9ef;
  /* High contrast keeps its own stronger separation — the whole point of the
     theme is that a stroke is unmistakable, and a 20% one is not. */
  --neutral-bg: #1a1a1a;     --neutral-border: #666666;
  --neutral-soft-foreground: #ffffff;
  /* CORE (derived from Clipper high-contrast palette) */
  --background: #000000;
  --foreground: #ffffff;
  --skeleton-sheen: #2b2b2b;
  --primary-bg: #081113;
  /* Canvas — equals --background here for the same reason as dark, and because
     high contrast must not introduce a near-black that competes with #000000. */
  --canvas: #000000;
  --canvas-foreground: #ffffff;
  --card: #000000;
  --card-foreground: #ffffff;
  --card-secondary: #122a30;
  --card-secondary-foreground: #ffffff;
  --card-secondary-border: #2d4951;
  --progress-running: #2fb8d6;
  --grid-guide: #1f4a55;
  --grid-baseline: #262626;
  --btn-border: var(--primary);
  --popover: #000000;
  --popover-foreground: #ffffff;
  --menu-header: #002b36;
  --menu-header-foreground: #ffffff;
  --primary: #66d9ef;
  --primary-foreground: #000000;
  --secondary: #1a1a1a;
  --secondary-foreground: #ffffff;
  --muted: #1a1a1a;
  --muted-foreground: #e0e0e0;
  --group: #1a2f30; --group-border: #c3cfd2;
  --group-foreground: #ffffff;
  --accent: #111111;
  --accent-foreground: #ffffff;
  --accent-hover: #262626;
  --destructive: #ff4444;
  --destructive-foreground: #000000;
  --success: #44ff88;
  --success-foreground: #000000;
  --warning: #ffbb33;
  --warning-foreground: #000000;
  --border: #666666;
  --input: #999999;
  --field-border: #999999;
  --input-hover: #747474;  /* was #999999 — under WCAG 1.4.11 3:1 vs the page ground */
  --ring: #66d9ef;
  --chart-1: #66d9ef; --chart-2: #44ff88; --chart-3: #ffbb33; --chart-4: #ff79c6; --chart-5: #a78bfa;
  --sidebar: #000000;
  --sidebar-foreground: #ffffff;
  --sidebar-primary: #66d9ef;
  --sidebar-primary-foreground: #000000;
  --sidebar-accent: #1a1a1a;
  --sidebar-accent-foreground: #ffffff;
  --sidebar-border: #666666;
  --sidebar-ring: #66d9ef;

  /* EXTENSIONS (Clipper high-contrast) */
  --info: #44aaff; --info-bg: #002244; --info-border: #44aaff;
  --link: #88ccff;
  --destructive-bg: #330000; --destructive-border: #ff4444;
  --success-bg: #003300; --success-border: #44ff88;
  --warning-bg: #332200; --warning-border: #ffbb33;

  --teal: #5eead4;    --teal-bg: #0a2e2a;    --teal-border: #5eead4;
  --cyan: #67e8f9;    --cyan-bg: #0a2a30;    --cyan-border: #67e8f9;
  --indigo: #a5b4fc;  --indigo-bg: #1a1a3a;  --indigo-border: #a5b4fc;
  --pink: #f472b6;    --pink-bg: #2a0a1a;    --pink-border: #f472b6;
  --rose: #fb7185;    --rose-bg: #2a0a0f;    --rose-border: #fb7185;
  --amber: #fbbf24;   --amber-bg: #2a2000;   --amber-border: #fbbf24;
  --lime: #a3e635;    --lime-bg: #1a2a00;    --lime-border: #a3e635;
  --emerald: #6ee7b7; --emerald-bg: #002a1a; --emerald-border: #6ee7b7;
  --violet: #a78bfa;  --violet-bg: #1a0a2a;  --violet-border: #a78bfa;
  --fuchsia: #e879f9; --fuchsia-bg: #2a0a2a; --fuchsia-border: #e879f9;
  --sky: #7dd3fc;     --sky-bg: #002030;     --sky-border: #7dd3fc;
  --slate: #cbd5e1;   --slate-bg: #111111;      --slate-border: #cbd5e1;
  --gold: #facc15;    --gold-bg: #2a2000;    --gold-border: #facc15;
  --crimson: #fca5a5; --crimson-bg: #2a0a0a; --crimson-border: #fca5a5;
  --sage: #81c784;    --sage-bg: #0a2a0a;    --sage-border: #81c784;
  --purple: #c4b0f0;  --purple-bg: #1a0a2a;  --purple-border: #c4b0f0;
  --orange: #f6bb7b;  --orange-bg: #2a1a00;  --orange-border: #f6bb7b;
  --blue: #92c4fe;    --blue-bg: #001a30;    --blue-border: #92c4fe;
  /* Interaction + panel surfaces. Hover and secondary states across the
     product use the nav active tint; panels take a visible stroke, since
     --border is near-invisible against the page by design. */
  --nav-item-bg-active: #00303a;
  --hover-bg: var(--nav-item-bg-active);
  --selected-bg: var(--nav-item-bg-active);
  --selected-fg: var(--primary);
  --panel-border: #99a7ab;   /* panel / widget stroke, product-wide */
  --track: #2b2b2b;       /* 1.48 vs page */
  --toggle-track: #666666; --toggle-track-hover: #7b7b7b;   /* 3.66 vs page */
  --segment: #1a1a1a; --segment-foreground: #e0e0e0;        /* label 13.18 on trough */
  /* 8.47:1. Strong on purpose: here --card and --canvas are both #000000, so
     the stroke is the ONLY thing that draws the panel. */
  --panel-stroke: #99a7ab;
  --connector: #92c4fe;              /* 11.55 vs --canvas */
  --relation-node: #5eead4;          /* 14.20 */
  --relation-node-tab: #99f6e4;      /* 16.66 */
  --relation-node-source: #fbbf24;   /* 12.58 */
  --relation-node-source-tab: #fde68a; /* 16.86 */
  --preview-surface: #000000;
  --accordion-stroke: #666666; --accordion-bg: #1a1a1a;
  --filter-card: var(--card-secondary); --filter-card-foreground: var(--card-secondary-foreground);
  --filter-card-border: var(--card-secondary-border);
  --filter-op: #000000; --filter-op-foreground: #ffffff;
  --filter-op-border: #999999;
  --chart-label: #ffffff; --chart-text: #cccccc;
  --cmd-highlight: #0f2124;
  --shadow-md: 0 1px 3px #333333;
  --shadow-raised: var(--shadow-md);
  --confidence-ok: #5eead4; --confidence-confirmed: #66d9ef; --confidence-warn: #fbbf24;
  --dfp-ok: var(--confidence-ok); --dfp-confirmed: var(--confidence-confirmed); --dfp-matched: #7dd3fc; --dfp-warn: var(--confidence-warn);
  --match: var(--amber-bg); --match-foreground: var(--amber-soft-foreground); --match-border: var(--warning);
  --ai: var(--purple-bg); --ai-foreground: var(--purple-soft-foreground); --ai-border: var(--purple-soft-foreground);
  --series-1: var(--emerald); --series-2: var(--blue); --series-3: var(--rose); --series-4: var(--violet);
  --series-5: var(--crimson); --series-6: var(--sage); --series-7: var(--amber); --series-8: var(--cyan);
  /* Interaction-state fills — high contrast. */
  --primary-hover: #55b7ca;
  --destructive-hover: #d73838;
  --primary-active: #479bab;
  --destructive-active: #ff776f;

  /* Elevation — high contrast. Shadows are unreliable here, so a hard 1px
     ring in --border carries the boundary and the shadow only adds depth. */
  --shadow-panel: 0 0 0 1px var(--border), var(--shadow-md);
  --shadow-overlay: 0 0 0 1px var(--border), var(--shadow-md);

  /* Modal scrim (minted; replaced an undefined --cmd-backdrop whose literal
     fallback was carrying it) */
  --scrim: #000000;
  --scrim-opacity: .80;

  /* Animated alpha ramps (§ 2a). A ring whose alpha varies over time cannot be
     pre-composited: the colour stays a 6-digit hex token and the alpha rides a
     companion --*-opacity token on a ::after ring. Named for the role, never the
     strength. High contrast raises every peak; the trough is always 0. */
  --pulse-attention-opacity: .70;
  --pulse-activity-opacity: .80;
  --pulse-input-opacity: .40;
  --pulse-guide-opacity: .80;

  /* Foreground for a soft-semantic surface (minted; Rulebook §3, §9).
     The solid token as text on its own -bg tint measures 1.83-4.41:1 at the
     status pill's 11px — under 4.5:1 in five of six tones. These clear it. */
  --success-soft-foreground: #44ff88;
  --warning-soft-foreground: #ffbb33;
  --destructive-soft-foreground: #ff4444;
  --info-soft-foreground: #44aaff;

  /* Focus rings, per theme. These used to be one color-mix() in :root that
     derived from --ring, so they followed the theme for free. Hardcoding
     them to 6-digit hex means each theme needs its own, and a change to
     --ring or --destructive must be mirrored here. */
  --focus-ring: 0 0 0 3px #1a363c;
  --focus-ring-error: 0 0 0 3px #380f0f;
  --focus-ring-ai: 0 0 0 3px #2a0f38;
  --focus-ring-success: 0 0 0 3px #003300;

  /* Derived surfaces, minted so the kit needs no color-mix(). Each is a
     pre-composited 6-digit hex; a change to --primary, --input,
     --foreground or --background must be mirrored here. */
  --input-border-hover: #82b6c0;
  --highlight-bg: #12272b;
  --icon-hover-bg: #171717;
  --tip-code-bg: #d6d6d6;
  --tip-eg-foreground: #474747;

  /* Text colour for a soft-semantic surface, every palette family.
     The solid token as text on its own -bg tint fails 4.5:1 in 12 of 66
     family/theme pairs at the pill's 11px. These clear it. */
  --amber-soft-foreground: #fbbf24;
  --blue-soft-foreground: #92c4fe;
  --crimson-soft-foreground: #fca5a5;
  --cyan-soft-foreground: #67e8f9;
  --emerald-soft-foreground: #6ee7b7;
  --fuchsia-soft-foreground: #e879f9;
  --gold-soft-foreground: #facc15;
  --indigo-soft-foreground: #a5b4fc;
  --lime-soft-foreground: #a3e635;
  --orange-soft-foreground: #f6bb7b;
  --pink-soft-foreground: #f472b6;
  --purple-soft-foreground: #c4b0f0;
  --rose-soft-foreground: #fb7185;
  --sage-soft-foreground: #81c784;
  --sky-soft-foreground: #7dd3fc;
  --slate-soft-foreground: #cbd5e1;
  --teal-soft-foreground: #5eead4;
  --violet-soft-foreground: #a78bfa;

  /* ── Icons (Rulebook §7c) ──
     One stroke width, one size, one box, two colours. Every icon in the
     product is Lucide: 24x24 viewBox, currentColor, round caps and joins.
     --icon-stroke is unitless so it can go straight into stroke-width. */
  --icon-stroke: 2;
  --icon-size: 16px;
  --icon-box: 24px;
  /* The one sanctioned second icon size: the app's left rail. 20px glyph in a
     40px frame — see .ck-ico.size-nav and rulebook 7c. */
  --icon-size-nav: 20px;
  --icon-size-sm: 12px;
  --icon-box-sm: 18px;
  --icon-box-nav: 40px;
  --icon-color: #e0e0e0;
  --icon-color-destructive: #ff4444;


  /* Email body swatches — identical in every theme on purpose; see :root. */
  --email-swatch-1: #003b4a;
  --email-swatch-2: #33616c;
  --email-swatch-3: #22c4ff;
  --email-swatch-4: #0a8754;
  --email-swatch-5: #c0392b;
  --email-swatch-6: #9a6b00;
  --email-swatch-7: #292e30;
  --email-swatch-8: #5d6769;
  --email-swatch-9: #8e44ad;
  --email-swatch-10: #000000;

}

/* -----------------------------------------------------------------------------
   OPTIONAL: Clipper elevation.
   index.css ships --shadow-sm/md/lg/xl flat (zero-opacity). Overlay components
   ported from Clipper (dialogs, dropdowns, toasts, popovers) need real shadows.
   Uncomment to restore the Clipper elevation scale across all themes.
   Values are pre-composited against each theme's page ground, so they are
   6-digit hex like everything else in this file.
   -----------------------------------------------------------------------------
   :root {
     --shadow-sm: 0 1px 2px #f0f0f0;
     --shadow-md: 0 4px 12px #ebebeb;
     --shadow-lg: 0 8px 30px #e0e0e0;
     --shadow-xl: 0 20px 60px #d9d9d9;
   }
   .dark, [data-theme="dark"] {
     --shadow-sm: 0 1px 2px #101b1e;
     --shadow-md: 0 4px 12px #0e181b;
     --shadow-lg: 0 8px 30px #0c1417;
     --shadow-xl: 0 20px 60px #0a1113;
   }
   [data-theme="high-contrast"] {
     --shadow-sm: 0 1px 2px #1a1a1a;
     --shadow-md: 0 4px 12px #141414;
     --shadow-lg: 0 8px 30px #0f0f0f;
     --shadow-xl: 0 20px 60px #0d0d0d;
   }
   ----------------------------------------------------------------------------- */

/* -----------------------------------------------------------------------------
   Tailwind v4 mapping (mirrors index.css @theme inline, plus --color-info /
   --color-link). Ignored by browsers when this file is used as plain CSS, so it
   is harmless in standalone prototypes and active in a Tailwind v4 build.
   Badge-palette colours are available directly via var(--teal) … var(--blue).
   ----------------------------------------------------------------------------- */
@theme inline {
  --color-filter-card: var(--filter-card);
  --color-filter-card-border: var(--filter-card-border);
  --color-filter-card-foreground: var(--filter-card-foreground);
  --color-filter-op: var(--filter-op);
  --color-filter-op-border: var(--filter-op-border);
  --color-filter-op-foreground: var(--filter-op-foreground);
  --color-background: var(--background);
  --color-canvas: var(--canvas);
  --color-canvas-foreground: var(--canvas-foreground);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-bg: var(--primary-bg);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-success: var(--success);
  --color-success-foreground: var(--success-foreground);
  --color-warning: var(--warning);
  --color-warning-foreground: var(--warning-foreground);
  --color-info: var(--info);
  --color-link: var(--link);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-skeleton-sheen: var(--skeleton-sheen);
  --color-track: var(--track);
  --color-toggle-track: var(--toggle-track);
  --color-toggle-track-hover: var(--toggle-track-hover);
  --color-segment: var(--segment);
  --color-segment-foreground: var(--segment-foreground);
  --color-panel-stroke: var(--panel-stroke);
  --color-connector: var(--connector);
  --color-relation-node: var(--relation-node);
  --color-relation-node-tab: var(--relation-node-tab);
  --color-relation-node-source: var(--relation-node-source);
  --color-relation-node-source-tab: var(--relation-node-source-tab);
  --color-focus-ring-ai: var(--focus-ring-ai);
  --color-group: var(--group);
  --color-group-foreground: var(--group-foreground);
  --color-ring: var(--ring);
  --color-chart-1: var(--chart-1);
  --color-chart-2: var(--chart-2);
  --color-chart-3: var(--chart-3);
  --color-chart-4: var(--chart-4);
  --color-chart-5: var(--chart-5);
  --color-sidebar: var(--sidebar);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-ring: var(--sidebar-ring);
  --font-sans: var(--font-sans);
  --text-3xs: var(--text-3xs);
  --text-2xs: var(--text-2xs);
  --text-xs: var(--text-xs);
  --text-sm: var(--text-sm);
  --text-md: var(--text-md);
  --text-base: var(--text-base);
  --text-lg: var(--text-lg);
  --text-xl: var(--text-xl);
  --text-2xl: var(--text-2xl);
  --text-3xl: var(--text-3xl);
  --text-4xl: var(--text-4xl);
  --text-5xl: var(--text-5xl);
  --text-6xl: var(--text-6xl);
  --text-7xl: var(--text-7xl);
  --font-weight-normal: var(--font-weight-normal);
  --font-weight-medium: var(--font-weight-medium);
  --font-weight-semibold: var(--font-weight-semibold);
  --font-weight-bold: var(--font-weight-bold);
  --radius-sm: var(--radius-sm);
  --radius-md: var(--radius-md);
  --radius-lg: var(--radius-lg);
  --radius-xl: var(--radius-xl);
  --shadow-2xs: var(--shadow-2xs);
  --shadow-xs: var(--shadow-xs);
  --shadow-sm: var(--shadow-sm);
  --shadow: var(--shadow);
  --shadow-md: var(--shadow-md);
  --shadow-lg: var(--shadow-lg);
  --shadow-xl: var(--shadow-xl);
  --shadow-2xl: var(--shadow-2xl);
}
