/* Tangle design tokens — the single palette every Tangle surface renders from.
 *
 * The surface ladder is NEUTRAL GREY and the indigo is trim — accent, never
 * field. It steps in even lightness increments so a card, a nested panel and an
 * overlay each read as a distinct plane by their own fill, and carries a crisp
 * hairline (1.6:1 against the card in dark) because shadow does no work on a dark
 * canvas. Light mirrors it: white paper on a grey canvas, never white-on-white.
 *
 * Apps consume this spine as-is. If a product needs its own accent identity,
 * add a named theme in named-themes.css (`data-theme="<name>"`) — do NOT re-declare
 * these tokens in the app, or its surfaces silently stop tracking the brand. */

/* MD3 surface hierarchy */
/* Dark is the default theme (`:root`/`[data-sandbox-ui]`). It also responds to
 * the standard `[data-theme="dark"]` / `.dark` switch so any consumer can pin or
 * toggle a theme without inventing an ad-hoc `data-sandbox-theme` name. */
/*
 * Surfaces are NEUTRAL GREY and the indigo is trim.
 *
 * Colour in the surface competes with colour in the accent: on an indigo-cast
 * ladder the indigo nav pill, link and focus ring are one more indigo thing on
 * an indigo page, and the eye stops finding them. Neutral planes give the brand
 * a field to sit on, so a single accent does all the signalling.
 *
 * The canvas sits OFF pure black (#151523). A near-black page under near-white
 * ink is the glare end of the range, and it is the reading surface for long
 * sessions.
 *
 * Elevation is carried by surface lightness plus a hairline that can actually be
 * seen — a black shadow on a dark canvas renders as nothing, so shadow does no
 * work here. The hairline is 1.6:1 against the resting card — quiet by design,
 * enough to state an edge without drawing a box around every panel.
 */
:root,
[data-sandbox-ui],
[data-theme="dark"],
.dark {
  --md3-surface: #151523;                   /* L0 page canvas */
  --md3-surface-dim: #0f0f1a;               /* recessed page */
  --md3-surface-bright: #393957;
  /* Same value as --md3-surface-dim by design, not by drift: both name the floor
   * of the ladder, and dark has no plane below it to give them. They stay two
   * tokens because the roles diverge in light, where the well is paper (#ffffff)
   * and the recessed page is grey (#d9d9e6) — a consumer binding to the wrong one
   * there gets the wrong surface. */
  --md3-surface-container-lowest: #0f0f1a;  /* L-1 terminal/code well */
  --md3-surface-container-low: #222235;     /* L1 chrome, field wells */
  --md3-surface-container: #2d2e43;         /* L2 resting card */
  --md3-surface-container-high: #32324e;    /* L3 nested / hover */
  --md3-surface-container-highest: #393957; /* L4 overlay */
  --md3-surface-variant: #32324e;
  --md3-on-surface: #e3e6ed;
  --md3-on-surface-variant: #b2b4c7;

  --md3-primary: #A5B4FC;
  --md3-primary-dim: #7C6CF6;
  --md3-primary-container: #4C3FC5;
  --md3-on-primary: #ffffff;
  --md3-on-primary-container: #E0E7FF;
  --md3-primary-fixed: #A5AAFC;
  --md3-primary-fixed-dim: #818CF8;

  --md3-secondary: #C7D2FE;
  --md3-secondary-dim: #A5B4FC;
  --md3-secondary-container: #312E81;
  --md3-on-secondary: #E8E5FF;
  --md3-on-secondary-container: #E8E5FF;

  --md3-tertiary: #10B981;
  --md3-outline: #898da9;
  --md3-outline-variant: #474a6b;

  --md3-error: #ff5277;
  --md3-error-dim: #eb2855;
  --md3-error-container: #82042b;
  --md3-on-error: #ffffff;
  --md3-on-error-container: #ffbdf2;

  --md3-inverse-surface: #fdfdfd;
  --md3-inverse-primary: #4C3FC5;
  --md3-inverse-on-surface: #000000;
  --md3-surface-tint: #A5B4FC;

  /* Semantic HSL bridge — the neutral-grey surface ladder */
  --hsl-background: 240 24% 11%;     /* L0 canvas #151523 */
  /* 92% L, not pure white: near-white ink on the canvas is the glare end of the
   * range, and the tiers below it need room to separate. 91% holds 10.6:1 on the
   * card — AAA with headroom — and leaves four ink steps the eye can tell apart. */
  --hsl-foreground: 225 22% 91%;     /* #e3e6ed */
  --hsl-card: 238 20% 22%;           /* L2 card #2d2e43 */
  --hsl-card-foreground: 225 22% 91%;
  --hsl-popover: 239 22% 25%;        /* L3 #32324e — the NESTED plane despite
     the name; the overlay plane is --md3-surface-container-highest. A popover
     carries body text, and the ladder above L3 is reserved for planes that lift
     by shadow, so it sits on L3 and the ink ramp reaches it. */
  --hsl-popover-foreground: 225 22% 91%;
  /* The fill indigo, NOT the bright one: `.btn-primary` puts white on this, and
   * #6366F1 carries white at only 4.47:1. This clears the floor at 7.4:1. The
   * bright indigo stays available for accent TEXT via --accent-text. */
  --hsl-primary: 246 54% 51%;       /* #4c3fc6 */
  --hsl-primary-foreground: 0 0% 100%;
  --hsl-secondary: 239 22% 25%;      /* L3 #32324e */
  --hsl-secondary-foreground: 225 22% 91%;
  --hsl-muted: 239 22% 25%;          /* L3 hover well */
  --hsl-muted-foreground: 234 16% 74%;  /* #b2b4c7 — high enough that the
     reduced-opacity caption derivatives (/70, /60) still clear the large-text
     contrast floor against the L2 card. */
  --hsl-accent: 239 22% 25%;         /* neutral hover (indigo lives in accent-surface-strong) */
  --hsl-accent-foreground: 225 22% 91%;
  --hsl-destructive: 348 74% 48%;
  --hsl-destructive-foreground: 0 0% 100%;
  /* Quiet on purpose: 1.6:1 against the resting card. Shadow does no work on a
   * dark canvas, so the hairline is what states where a plane ends. */
  --hsl-border: 236 20% 35%;         /* #474a6b = --md3-outline-variant */
  --hsl-input: 240 24% 15%;          /* recessed field well */
  /* Brighter than --primary on purpose: the ring is NON-TEXT and has to clear
   * 3:1 against BOTH canvas and card. The fill indigo is tuned to carry white
   * text instead, so the two cannot be the same value. */
  --hsl-ring: 233 100% 87%;
  --hsl-success: 160 84% 39%;
  --hsl-warning: 40 94% 56%;
  --hsl-info: 200 88% 56%;

  /* Tailwind/shadcn aliases */
  --background: var(--hsl-background);
  --foreground: var(--hsl-foreground);
  --card: var(--hsl-card);
  --card-foreground: var(--hsl-card-foreground);
  --popover: var(--hsl-popover);
  --popover-foreground: var(--hsl-popover-foreground);
  --primary: var(--hsl-primary);
  --primary-foreground: var(--hsl-primary-foreground);
  --secondary: var(--hsl-secondary);
  --secondary-foreground: var(--hsl-secondary-foreground);
  --muted: var(--hsl-muted);
  --muted-foreground: var(--hsl-muted-foreground);
  --accent: var(--hsl-accent);
  --accent-foreground: var(--hsl-accent-foreground);
  --destructive: var(--hsl-destructive);
  --destructive-foreground: var(--hsl-destructive-foreground);
  --border: var(--hsl-border);
  /* shadcn's `--input` is the input BORDER and the Switch's off-track — a
   * mid-tone that has to stay visible AGAINST a surface. It is deliberately NOT
   * the field fill: pointing it at the recessed well would tint a border and a
   * track the same color as the plane behind them, and both would vanish. The
   * field fill is --hsl-input / --bg-input below. */
  --input: var(--hsl-muted-foreground);
  --ring: var(--hsl-ring);
  --success: var(--hsl-success);
  --warning: var(--hsl-warning);
  --error: var(--hsl-destructive);
  --info: var(--hsl-info);

  /* Sidebar tokens — L1 chrome: one step BELOW the canvas here, so the nav reads
   * as chrome the content sits in front of rather than as another card. */
  --sidebar-background: 242 26% 8%;   /* L1 chrome #0f0f1a */
  --sidebar-foreground: 225 22% 91%;
  --sidebar-primary: 246 54% 51%;
  --sidebar-primary-foreground: 0 0% 100%;
  --sidebar-accent: 239 22% 25%;      /* L3 hover well */
  --sidebar-accent-foreground: 225 22% 91%;
  --sidebar-border: 236 20% 35%;
  --sidebar-ring: 233 100% 87%;

  /* Depth scale — tracks the MD3 ladder (canvas / card / nested / overlay) */
  --depth-1: #151523;
  --depth-2: #2d2e43;
  --depth-3: #32324e;
  --depth-4: #393957;

  /* Status colors */
  --status-running: #10B981;
  --status-creating: #A5B4FC;
  --status-stopped: #FFB800;
  --status-warm: #FF8A4C;
  --status-cold: #4AABFF;
  --status-error: #FF4D6D;
  --status-deleted: #6B7094;

  /* Status surface tokens — bg / border / text for each semantic color */
  --surface-success-bg: #2f5146;
  --surface-success-border: #3c7760;
  --surface-success-text: #5ed7a4;
  --surface-warning-bg: #6a402c;
  --surface-warning-border: #916436;
  --surface-warning-text: #f4c14f;
  --surface-danger-bg: #733b36;
  --surface-danger-border: #9a5b56;
  --surface-danger-text: #ffada9;
  --surface-info-bg: #2d4e67;
  --surface-info-border: #3d7292;
  --surface-info-text: #67cdff;
  --surface-teal-bg: #042f2e;
  --surface-teal-border: #134e4a;
  --surface-teal-text: #2dd4bf;
  --surface-violet-bg: #1e1b4b;
  --surface-violet-border: #3730a3;
  --surface-violet-text: #B8B2F5;
  --surface-orange-bg: #431407;
  --surface-orange-border: #7c2d12;
  --surface-orange-text: #fb923c;

  /* Run-mix ramp — the fills of a proportional status bar.
   *
   * Separate from the `--surface-*-text` tones because a 6px bar is read
   * differently from a chip: it is told by hue alone, at a size too small to
   * carry a glyph or a label, so its slices must ALSO separate from each other
   * in greyscale. These five are spaced at least 1.18:1 apart in relative
   * luminance — 1.30 in dark, 1.20 in light, where the ramp has less room
   * before it runs into the paper — and each clears 3:1 against the track, so
   * the mix stays countable with any form of colour blindness and in a
   * monochrome screenshot. 1.18 is the floor the gate holds them to.
   *
   * Ranked by how much the reader needs to tell them apart: succeeded is
   * brightest and cancelled quietest, so the two that matter — succeeded and
   * failed — sit at opposite ends and can never be confused.
   *
   * Spacing them by OKLCH lightness does NOT work: that is perceptual, and the
   * contrast ratio is computed from relative luminance, so an even perceptual
   * ramp left every pair at 1.1:1. Solved in luminance space instead. */
  --run-mix-succeeded: #76edb9;
  --run-mix-waiting: #e9b642;
  --run-mix-failed: #e1918e;
  --run-mix-in-flight: #2d9bca;
  --run-mix-cancelled: #767d90;

  --surface-neutral-bg: var(--depth-3);
  --surface-neutral-border: var(--border-subtle);
  --surface-neutral-text: var(--text-muted);

  /* Legacy glass aliases — mapped to solid depth tokens */
  --glass-bg: var(--depth-2);
  --glass-bg-strong: var(--depth-3);
  --glass-border: var(--border-subtle);
  --glass-border-hover: var(--border-default);
  --glass-blur: 0px;

  /* Mesh glows — off; depth comes from the ladder, not from glow */
  --mesh-teal: transparent;
  --mesh-violet: transparent;
  --mesh-blue: transparent;

  /* Brand gradients — the indigo spark, kept ONLY for the logo mark + send button */
  --tangle-gradient: linear-gradient(135deg, #4C3FC5, #A5B4FC);
  --tangle-gradient-text: linear-gradient(135deg, #C7D2FE, #A5B4FC);
  --accent-gradient-strong: linear-gradient(135deg, #4C3FC5, #7C6CF6);
  /* Accent wells — soft = hover neutral, strong = active/selected row (indigo) */
  --accent-surface-soft: rgba(165, 180, 252, 0.07);
  --accent-surface-strong: rgba(76, 63, 197, 0.30);
  /* The BRIGHT indigo, and only ever as text: --primary is the fill (it carries
   * white), and at 6.7:1 on the card this is the one that stays legible as ink. */
  --accent-text: #A5B4FC;

  /* Surfaces — solid fills off the ladder (no radial mesh) */
  --bg-root: #151523;
  --bg-dark: var(--depth-1);
  --bg-card: var(--depth-2);
  --bg-elevated: var(--depth-4);
  --bg-section: var(--depth-1);
  --bg-input: hsl(var(--hsl-input));  /* the field well — same color, hex-free */
  --bg-hover: rgba(165, 180, 252, 0.07);
  --bg-selection: rgba(124, 108, 246, 0.28);

  /* Text — neutral */
  /* Four steps the eye can actually separate: 10.6 / 7.8 / 6.5 / 5.4 against the
   * L2 card. --text-dim is the faintest tier but it is still TEXT, so it clears
   * the 4.5:1 body floor rather than only the 3:1 large-text one.
   *
   * Solved against the WHOLE ladder, not against one plane. A faint tier tuned
   * on the card alone still has to clear the floor on the nested and overlay
   * planes above it, which carry the modals, the drawers and every dropdown
   * menu — so both ends meet in the middle: the faint tiers sit high enough for
   * the overlay, and the planes above the card sit low enough for them. The
   * card, the chrome and the canvas are fixed points. tokens.test.ts asserts
   * every tier on every plane, so a retune cannot open a gap on one plane while
   * looking correct on another. */
  --text-primary: #e3e6ed;
  --text-secondary: #c2c7d4;
  --text-muted: #b2b4c7;
  --text-dim: #9ea5b9;

  /* Brand accents — Tangle */
  --brand-primary: #7C6CF6;
  --brand-strong: #2E2A5E;
  --brand-strong-text: #ffffff;
  --brand-strong-text-muted: rgba(255, 255, 255, 0.7);
  --brand-strong-text-dim: rgba(255, 255, 255, 0.5);
  --brand-cool: #818CF8;
  --brand-glow: #A5AAFC;
  --brand-purple: #C7D2FE;
  --brand-vibrant: #6366F1;
  --brand-emerald: #10B981;

  /* Borders — neutral hairlines */
  --border-subtle: rgba(165, 180, 252, 0.10);
  --border-default: rgba(165, 180, 252, 0.16);
  --border-hover: rgba(165, 180, 252, 0.28);
  --border-accent: rgba(129, 140, 248, 0.35);
  --border-accent-hover: rgba(129, 140, 248, 0.50);

  /* Buttons */
  --btn-primary-bg: #4C3FC5;
  --btn-primary-hover: #5A50D6;
  --btn-primary-text: #ffffff;
  --btn-cta-bg: #4C3FC5;
  --btn-cta-text: #FFFFFF;

  /* Code / runtime syntax */
  --code-keyword: #A5AAFC;
  --code-string: #34D399;
  --code-function: #6D9FFF;
  --code-number: #FFB347;
  --code-success: #10B981;
  --code-comment: #606294;
  --code-error: #FF4D6D;

  /* Shadows — flat, no inner ring, no indigo glow */
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-dropdown: 0 8px 30px rgba(0, 0, 0, 0.45);
  --shadow-glow: none;
  --shadow-accent: 0 1px 2px rgba(0, 0, 0, 0.3);
  /* The lift above --shadow-dropdown, for a surface that covers the page
     rather than sitting beside it: a drawer, a modal, a floating dock.
     Two layers — a tight contact shadow plus a wide ambient one.
     Alone among the shadows this is derived from --hsl-foreground instead of
     a fixed rgba, so it INVERTS with the theme. That is what makes it work in
     dark: a black shadow on a dark canvas renders as nothing (see the ladder
     note at the top of this file), while the foreground is near-white there,
     so the same declaration reads as a soft halo. One definition therefore
     serves both themes and the light block does not restate it. */
  --shadow-overlay:
    0 2px 6px hsl(var(--hsl-foreground) / 0.1),
    0 16px 40px hsl(var(--hsl-foreground) / 0.16);
  --shadow-status-running: none;
  --shadow-status-creating: none;
  --shadow-status-error: none;

  /* Radii */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 12px;          /* chrome stays tight (was 16px) */
  --radius-pill: 999px;
  --radius-full: 999px;
  --radius-composer: 26px;    /* centered composer pill */
  --radius: 0.5rem;           /* 8px chrome default (was 10px) */

  /* Density */
  --control-height: 2.25rem;
  --panel-padding: 1rem;
  --content-max-width: 80rem;

  /* Typography scale — override per-app for custom type hierarchy.
     Components reference these instead of hardcoded pixel values. */
  --font-size-xs: 0.6875rem;      /* 11px — labels, timestamps */
  --font-size-sm: 0.75rem;        /* 12px — captions, meta */
  --font-size-base: 0.9375rem;    /* 15px — message body */
  --font-size-lg: 1rem;           /* 16px — emphasized text */
  --font-size-xl: 1.25rem;        /* 20px — section title (h2) */
  /* Display tier — page titles, marketing section heads, and heroes.
     Hero sizes are fluid (clamp) so they scale with the viewport without
     per-breakpoint overrides; the dense-app sizes above stay fixed. */
  --font-size-2xl: 1.5rem;        /* 24px — large section title */
  --font-size-3xl: 1.875rem;      /* 30px — page title (h1) */
  --font-size-4xl: 2.25rem;       /* 36px — compact marketing section head */
  --font-size-hero: clamp(2rem, 1.2rem + 3.2vw, 3rem);    /* 32→48px — secondary hero */
  --font-size-display: clamp(2.5rem, 1.1rem + 5vw, 4rem); /* 40→64px — primary hero */
  --line-height-tight: 1.3;
  --line-height-base: 1.6;        /* tighter body rhythm (was 1.75) */
  --line-height-relaxed: 1.75;
  --line-height-display: 1.05;    /* heroes — near-solid set */
  --line-height-heading: 1.15;    /* page/section titles */
  /* Letter-spacing — titles tighten, eyebrows/labels open up */
  --tracking-tight: -0.02em;      /* display + page titles */
  --tracking-snug: -0.01em;       /* section titles */
  --tracking-wide: 0.08em;        /* uppercase eyebrows / stat labels */

  /* Component spacing — override per-app for tighter/looser layouts */
  --avatar-size: 2rem;            /* 32px — chat avatars */
  --timeline-dot-size: 0.625rem;  /* 10px — timeline connector dots */
  --indicator-dot-size: 0.25rem;  /* 4px — thinking indicator dots */
  --code-padding-x: 0.75rem;
  --code-padding-y: 0.625rem;
  --code-font-size: 0.8125rem;
  --code-line-height: 1.5;
  --chat-message-px: 0.875rem;
  --chat-message-py: 0.5rem;
  --chat-input-py: 0.625rem;
  --card-padding: 1.25rem;
  --tool-card-px: 0.75rem;
  --tool-card-py: 0.5rem;
  --tool-icon-size: 1.75rem;

  /* Syntax highlighting — override per-theme in vault section */
  --syntax-comment: #8b8fbc;
  --syntax-keyword: #A78FFF;
  --syntax-string: #10b981;
  --syntax-function: #6D9FFF;
  --syntax-number: #FFB347;
  --syntax-meta: #8263FF;
  --syntax-error: #FF4D6D;
  --syntax-variable: #C4C0D8;
  --syntax-foreground: #E8E6F6;

  /* Transitions */
  --transition-fast: 0.1s ease;
  --transition-default: 0.16s ease;
  --transition-medium: 0.24s ease;

  /* Fonts — unified on Inter (dark + light) */
  --font-sans: "Inter", "Geist", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-display: "Inter", "Geist", sans-serif;
  --font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
}

/* Light theme — reachable via the named `vault` theme or the standard
 * `[data-theme="light"]` / `.light` switch. Both blocks are single-attribute/
 * class selectors, and this one is later in source order, so when an element
 * carries both `data-sandbox-ui` (dark) and `data-theme="light"`, light wins. */
[data-sandbox-theme="vault"],
[data-theme="light"],
.light {
  /* Light theme — clean professional, warm purple accents */

  /* MD3 surface hierarchy */
  /* The light ladder ALTERNATES; it is not monotonic, and that is deliberate.
   * On a tinted canvas, a raised plane is PAPER (white) and a recessed one is a
   * tinted WELL. So card and overlay are both white and separate from each other
   * by shadow and ring, not by fill — which is how light-mode elevation actually
   * reads. Forcing a strictly-darkening ladder here is what produced the
   * white-on-white flatness this palette replaced. Pinned in tokens.test.ts. */
  --md3-surface: #e9e9f1;                   /* L0 page canvas — neutral grey, BELOW the wells */
  --md3-surface-dim: #d9d9e6;
  --md3-surface-bright: #ffffff;
  --md3-surface-container-lowest: #ffffff;  /* insets read as paper */
  --md3-surface-container-low: #f7f7fa;     /* L1 chrome, field wells — well */
  --md3-surface-container: #ffffff;         /* L2 resting card — paper */
  --md3-surface-container-high: #f2f2f7;    /* L3 nested / hover — well */
  --md3-surface-container-highest: #ffffff; /* L4 overlay — paper + shadow */
  --md3-surface-variant: #f2f2f7;
  --md3-on-surface: #2b2c3e;
  --md3-on-surface-variant: #494b5d;

  --md3-primary: #3E349E;
  --md3-primary-dim: #352B88;
  --md3-primary-container: #352B88;
  --md3-on-primary: #ffffff;
  --md3-on-primary-container: #9B93F0;
  --md3-primary-fixed: #E8E5FF;
  --md3-primary-fixed-dim: #C5C0F0;

  --md3-secondary: #524A78;
  --md3-secondary-dim: #3E3660;
  --md3-secondary-container: #E8E5FF;
  --md3-on-secondary: #ffffff;
  --md3-on-secondary-container: #524A78;

  --md3-tertiary: #065F46;
  --md3-tertiary-container: #D1FAE5;
  --md3-outline: #737696;
  --md3-outline-variant: #cecfde;

  --md3-error: #ba1a1a;
  --md3-error-dim: #93000a;
  --md3-error-container: #ffdad6;
  --md3-on-error: #ffffff;
  --md3-on-error-container: #93000a;

  --md3-inverse-surface: #2e2e3e;
  --md3-inverse-primary: #A5AAFC;
  --md3-inverse-on-surface: #f0f1f4;
  --md3-surface-tint: #6366F1;

  /* Semantic HSL bridge — white paper on a neutral-grey canvas */
  --hsl-background: 240 24% 93%;     /* L0 canvas #e9e9f1 */
  /* Ink, not black. Pure #0d0d0d on white paper measures 19.5:1 — a hair off the
   * 21:1 ceiling — and that maximum is what reads as glare rather than as
   * legibility. 20.5% L lands 13.7:1 on the card and 11.4:1 on the canvas: AAA with
   * headroom in both places, and a step the eye reads as text instead of as a
   * hole. */
  --hsl-foreground: 235 18% 20.5%;     /* #2b2c3e */
  --hsl-card: 0 0% 100%;            /* L2 card = white paper */
  --hsl-card-foreground: 235 18% 20.5%;
  --hsl-popover: 0 0% 100%;
  --hsl-popover-foreground: 235 18% 20.5%;
  --hsl-primary: 246 54% 51%;       /* #4c3fc6 — carries white at 7.4:1 */
  --hsl-primary-foreground: 0 0% 100%;
  --hsl-secondary: 240 26% 96%;      /* L3 #f2f2f7 */
  --hsl-secondary-foreground: 235 18% 20.5%;
  --hsl-muted: 240 26% 96%;          /* L3 hover well */
  /* 34% L: the shared components fade captions with /70 and /60, and a
   * translucent foreground renders as the token COMPOSITED over the plane behind
   * it. Against white paper that compositing is brutal — a lighter value puts the
   * /60 caption under the 3:1 large-text floor. This holds 3.0:1 there and 8.6:1
   * at full strength, still a clear step below the 13.7:1 body ink. */
  --hsl-muted-foreground: 235 12% 32.5%;  /* #494b5d text-muted */
  --hsl-accent: 240 26% 96%;         /* neutral hover */
  --hsl-accent-foreground: 235 18% 20.5%;
  --hsl-destructive: 0 72% 41%;
  --hsl-destructive-foreground: 0 0% 100%;
  --hsl-border: 238 20% 84%;         /* #cecfde = --md3-outline-variant */
  --hsl-input: 240 30% 97%;          /* field well */
  --hsl-ring: 246 54% 51%;
  --hsl-success: 160 84% 30%;
  --hsl-warning: 41 96% 50%;
  --hsl-info: 212 80% 50%;

  /* depth-2 (card) and depth-4 (elevated) are BOTH paper, on purpose: in light,
   * a popover does not out-lighten a white card — it lifts by shadow. See the
   * ladder note above. */
  --depth-1: #e9e9f1;  /* canvas */
  --depth-2: #ffffff;  /* card — paper */
  --depth-3: #f2f2f7;  /* nested well */
  --depth-4: #ffffff;  /* elevated — paper, separated by shadow */

  --status-running: #059669;
  --status-creating: #3E349E;
  --status-stopped: #B45309;
  --status-warm: #C05621;
  --status-cold: #1D6FA4;
  --status-error: #ba1a1a;
  --status-deleted: #6B6B82;

  --glass-bg: var(--depth-2);
  --glass-bg-strong: var(--depth-1);
  --glass-border: var(--border-subtle);
  --glass-border-hover: var(--border-default);

  /* Status surface overrides — light values */
  --surface-success-bg: #ecfdf5;
  --surface-success-border: #a7f3d0;
  --surface-success-text: #047857;
  --surface-warning-bg: #fffbeb;
  --surface-warning-border: #fde68a;
  --surface-warning-text: #ab4f09;
  --surface-danger-bg: #fff1f2;
  --surface-danger-border: #fecdd3;
  --surface-danger-text: #b91c1c;
  --surface-info-bg: #f0f9ff;
  --surface-info-border: #bae6fd;
  --surface-info-text: #0369a1;
  --surface-teal-bg: #f0fdfa;
  --surface-teal-border: #99f6e4;
  --surface-teal-text: #0f766e;
  --surface-violet-bg: #F0EEFF;
  --surface-violet-border: #C5C0F0;
  --surface-violet-text: #3E349E;
  --surface-orange-bg: #fff7ed;
  --surface-orange-border: #fed7aa;
  --surface-orange-text: #c2410c;

  /* Run-mix ramp — the fills of a proportional status bar.
   *
   * Separate from the `--surface-*-text` tones because a 6px bar is read
   * differently from a chip: it is told by hue alone, at a size too small to
   * carry a glyph or a label, so its slices must ALSO separate from each other
   * in greyscale. These five are spaced at least 1.18:1 apart in relative
   * luminance — 1.30 in dark, 1.20 in light, where the ramp has less room
   * before it runs into the paper — and each clears 3:1 against the track, so
   * the mix stays countable with any form of colour blindness and in a
   * monochrome screenshot. 1.18 is the floor the gate holds them to.
   *
   * Ranked by how much the reader needs to tell them apart: succeeded is
   * brightest and cancelled quietest, so the two that matter — succeeded and
   * failed — sit at opposite ends and can never be confused.
   *
   * Spacing them by OKLCH lightness does NOT work: that is perceptual, and the
   * contrast ratio is computed from relative luminance, so an even perceptual
   * ramp left every pair at 1.1:1. Solved in luminance space instead. */
  --run-mix-succeeded: #3c9b78;
  --run-mix-waiting: #c16227;
  --run-mix-failed: #cd342f;
  --run-mix-in-flight: #00679e;
  --run-mix-cancelled: #515367;

  --surface-neutral-bg: var(--depth-3);
  --surface-neutral-border: var(--border-subtle);
  --surface-neutral-text: var(--text-muted);

  /* Sidebar — light, flat surface + hairline */
  --sidebar-background: 0 0% 100%;     /* white paper */
  --sidebar-foreground: 235 18% 20.5%;
  --sidebar-primary: 246 54% 51%;     /* #4c3fc6 */
  --sidebar-primary-foreground: 0 0% 100%;
  --sidebar-accent: 240 26% 96%;       /* L3 hover well */
  --sidebar-accent-foreground: 235 18% 20.5%;
  --sidebar-border: 238 20% 84%;   /* = --md3-outline-variant */
  --sidebar-ring: 246 54% 51%;

  --mesh-teal: transparent;
  --mesh-violet: transparent;
  --mesh-blue: transparent;

  /* Surfaces — flat single-neutral light */
  --bg-root: #e9e9f1;
  --bg-dark: var(--depth-1);
  --bg-card: var(--depth-2);
  /* Paper, exactly like --bg-card: in light you cannot raise a plane by making it
   * lighter than white, so an overlay lifts by SHADOW. A consumer that fills with
   * --bg-elevated and applies no shadow gets no separation from a card — that is
   * the contract, not an oversight (--hsl-popover is white for the same reason).
   * Pair it with --shadow-dropdown. */
  --bg-elevated: var(--depth-4);
  --bg-section: var(--depth-1);
  --bg-input: hsl(var(--hsl-input));  /* the field well — same color, hex-free */
  --bg-hover: rgba(76, 63, 198, 0.06);
  --bg-selection: rgba(76, 63, 198, 0.16);

  /* Mirrors the dark ramp's spacing: 13.7 / 10.5 / 8.6 / 5.6 against white paper.
   * Every step carries the 240 cast so the ink belongs to the palette.
   *
   * --text-dim is pinned from the CANVAS (#e9e9f1), not the white card: it is
   * the faintest tier, so the tinted L0 is the surface that binds it, and a
   * value chosen against paper alone sits under the 4.5:1 body floor there.
   * 4.6 on the canvas, 5.6 on the card — both floors are asserted in
   * tokens.test.ts, because a ratio quoted in a comment drifts the moment a
   * surface moves and nothing catches it. */
  --text-primary: #2b2c3e;
  --text-secondary: #3d3e52;
  --text-muted: #494b5d;
  --text-dim: #65677b;

  --brand-primary: #6366F1;
  --brand-strong: #2E2A5E;
  --brand-strong-text: #ffffff;
  --brand-strong-text-muted: rgba(255, 255, 255, 0.7);
  --brand-strong-text-dim: rgba(255, 255, 255, 0.5);
  --brand-cool: #818CF8;
  --brand-glow: #A5AAFC;
  --brand-purple: #6366F1;
  --brand-vibrant: #6366F1;
  --brand-emerald: #059669;

  --border-subtle: rgba(60, 52, 140, 0.10);
  --border-default: rgba(60, 52, 140, 0.14);
  --border-hover: rgba(60, 52, 140, 0.24);
  --border-accent: rgba(91, 78, 212, 0.18);
  --border-accent-hover: rgba(91, 78, 212, 0.35);

  --btn-primary-bg: #4C3FC5;
  --btn-primary-hover: #5A50D6;
  --btn-primary-text: #ffffff;
  --btn-cta-bg: #4C3FC5;
  --btn-cta-text: #ffffff;

  --code-keyword: #3E349E;
  --code-string: #059669;
  --code-function: #352B88;
  --code-number: #B45309;
  --code-success: #059669;
  --code-comment: #6B6E8A;
  --code-error: #ba1a1a;

  /* Shadows — flat, no inner ring, no glow */
  --shadow-card: 0 1px 2px rgba(25, 28, 36, 0.06);
  --shadow-dropdown: 0 8px 30px rgba(25, 28, 36, 0.10);
  --shadow-glow: none;
  --shadow-accent: 0 1px 2px rgba(25, 28, 36, 0.06);

  /* Indigo spark kept for logo + send; accent-fill is the active row well */
  --tangle-gradient: linear-gradient(135deg, #4F46E5, #5B4ED4);
  --tangle-gradient-text: linear-gradient(135deg, #4F46E5, #5B4ED4);
  --accent-gradient-strong: linear-gradient(135deg, #4F46E5, #5B4ED4);
  --accent-surface-soft: rgba(76, 63, 198, 0.05);
  --accent-surface-strong: rgba(76, 63, 198, 0.13);
  --accent-text: #5047eb;

  /* Typography — unified on Inter */
  --font-sans: "Inter", "Geist", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-display: "Inter", "Geist", sans-serif;
  --font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;

  /* Radius — unified chrome scale (matches dark; 8px md) */
  --radius: 0.5rem;
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 12px;
  --radius-pill: 999px;
  --radius-full: 999px;
  --radius-composer: 26px;
}

