/* ===========================================================================
   Remdingo design tokens
   ---------------------------------------------------------------------------
   Two layers, one rule: no colour literal appears outside a theme block, and no
   ramp token knows what it is for.

     Layer 1  --rd-<family>-<rung>   raw ramps, generated from a handful of seeds
     Layer 2  --rd-<role>            what the app actually paints with

   Components only ever touch layer 2. Themes only ever set seeds (and, for the
   two original themes, pins - see below). That is what lets one stylesheet serve
   a dark theme, a light theme and anything a user invents.

   THE PIN ESCAPE HATCH
   Every generated rung reads through `var(--rd-x-pin, <generated>)`. The two
   themes that shipped before this system - Midnight and Daylight - fill every
   pin with the exact colour the app used to hardcode, so switching to tokens
   changed no pixels. When someone edits a seed in the Appearance page, the
   editor writes `--rd-neutral-400-pin: initial` for the whole ramp at once;
   `initial` makes a custom property guaranteed-invalid, so every var() falls
   through to the generated value and the ramp regenerates live, with no colour
   maths in JavaScript. Themes added since simply never set a pin.

   Layer 2 is defined once, here, wired for a dark theme. Light themes re-wire
   the ~40 roles that genuinely invert (a "raised" surface moves toward white,
   not toward ink) in themes.css. Everything else is shared.

   See also: themes.css (the themes), theme.js (applying and persisting one).
   =========================================================================== */

:root {
    color-scheme: dark;

    /* -----------------------------------------------------------------------
       Seeds. Nine colours; everything below is built out of them. Overridden
       per theme - the values here are Midnight's, so an unknown or missing
       data-theme still renders a complete, sane app.
       ----------------------------------------------------------------------- */
    --rd-neutral-ground: #16162a;   /* the canvas everything sits on */
    --rd-neutral-ink: #e0e0e0;      /* maximum-contrast foreground */
    --rd-neutral-recess: #12121f;   /* the sunken end of the ramp */
    --rd-accent: #7fdbda;           /* focus, selection, primary actions */
    --rd-accent-shade: var(--rd-accent);  /* what darker accent steps mix toward */
    --rd-success: #a8f0dc;
    --rd-danger: #f0a6a6;
    --rd-warning: #f0d6a0;
    --rd-violet: #f0a6ca;           /* second accent */

    /* Which way "raised" moves. The one token that encodes the dark/light
       elevation inversion: dark themes lift toward ink, light toward white. */
    --rd-neutral-elevate: var(--rd-neutral-ink);

    /* -----------------------------------------------------------------------
       Layer 1a: the neutral ramp.
       An emphasis ladder, not a lightness ladder - rung 0 is the deepest well,
       rung 400 is the surface/foreground boundary, rung 950 is maximum ink.
       Reading it that way is what lets the same semantic layer serve two themes
       that invert.
       ----------------------------------------------------------------------- */
    /* Rungs 200-300 are SURFACES: they move along --rd-neutral-elevate, which
       means "away from the canvas" - toward ink in a dark theme, toward white
       in a light one. Rungs 350-450 are BOUNDARIES: they always move toward
       ink, because a border has to be darker than the card in a light theme
       even though a card is lighter than the canvas. Getting this wrong is how
       a generated light theme ends up with invisible borders.
       The mix percentages are tokens so each theme family can retune them - a
       light theme needs a much bigger push to white, and a much smaller push to
       ink, than a dark theme does. */
    --rd-rung-200-mix: 3%;
    --rd-rung-250-mix: 5%;
    --rd-rung-300-mix: 8%;
    --rd-rung-350-mix: 12%;
    --rd-rung-400-mix: 18%;
    --rd-rung-450-mix: 26%;

    --rd-neutral-0:   var(--rd-neutral-0-pin, var(--rd-neutral-recess));
    --rd-neutral-50:  var(--rd-neutral-50-pin,  color-mix(in oklab, var(--rd-neutral-ground) 25%, var(--rd-neutral-recess)));
    --rd-neutral-100: var(--rd-neutral-100-pin, color-mix(in oklab, var(--rd-neutral-ground) 55%, var(--rd-neutral-recess)));
    --rd-neutral-150: var(--rd-neutral-150-pin, var(--rd-neutral-ground));
    --rd-neutral-200: var(--rd-neutral-200-pin, color-mix(in oklab, var(--rd-neutral-elevate) var(--rd-rung-200-mix), var(--rd-neutral-ground)));
    --rd-neutral-250: var(--rd-neutral-250-pin, color-mix(in oklab, var(--rd-neutral-elevate) var(--rd-rung-250-mix), var(--rd-neutral-ground)));
    --rd-neutral-300: var(--rd-neutral-300-pin, color-mix(in oklab, var(--rd-neutral-elevate) var(--rd-rung-300-mix), var(--rd-neutral-ground)));
    --rd-neutral-350: var(--rd-neutral-350-pin, color-mix(in oklab, var(--rd-neutral-ink) var(--rd-rung-350-mix), var(--rd-neutral-ground)));
    --rd-neutral-400: var(--rd-neutral-400-pin, color-mix(in oklab, var(--rd-neutral-ink) var(--rd-rung-400-mix), var(--rd-neutral-ground)));
    --rd-neutral-450: var(--rd-neutral-450-pin, color-mix(in oklab, var(--rd-neutral-ink) var(--rd-rung-450-mix), var(--rd-neutral-ground)));
    --rd-neutral-500: var(--rd-neutral-500-pin, color-mix(in oklab, var(--rd-neutral-ink) 42%, var(--rd-neutral-ground)));
    --rd-neutral-550: var(--rd-neutral-550-pin, color-mix(in oklab, var(--rd-neutral-ink) 50%, var(--rd-neutral-ground)));
    --rd-neutral-600: var(--rd-neutral-600-pin, color-mix(in oklab, var(--rd-neutral-ink) 57%, var(--rd-neutral-ground)));
    --rd-neutral-650: var(--rd-neutral-650-pin, color-mix(in oklab, var(--rd-neutral-ink) 64%, var(--rd-neutral-ground)));
    --rd-neutral-700: var(--rd-neutral-700-pin, color-mix(in oklab, var(--rd-neutral-ink) 76%, var(--rd-neutral-ground)));
    --rd-neutral-750: var(--rd-neutral-750-pin, color-mix(in oklab, var(--rd-neutral-ink) 80%, var(--rd-neutral-ground)));
    --rd-neutral-800: var(--rd-neutral-800-pin, color-mix(in oklab, var(--rd-neutral-ink) 84%, var(--rd-neutral-ground)));
    --rd-neutral-850: var(--rd-neutral-850-pin, color-mix(in oklab, var(--rd-neutral-ink) 88%, var(--rd-neutral-ground)));
    --rd-neutral-900: var(--rd-neutral-900-pin, color-mix(in oklab, var(--rd-neutral-ink) 94%, var(--rd-neutral-ground)));
    --rd-neutral-925: var(--rd-neutral-925-pin, color-mix(in oklab, var(--rd-neutral-ink) 97%, var(--rd-neutral-ground)));
    --rd-neutral-950: var(--rd-neutral-950-pin, var(--rd-neutral-ink));

    /* -----------------------------------------------------------------------
       Layer 1b: accent and status ramps.
       Darker steps mix toward --rd-accent-shade rather than toward black, so a
       pale accent still produces a legible "accent text on accent tint".
       ----------------------------------------------------------------------- */
    --rd-accent-400:     var(--rd-accent-400-pin, color-mix(in oklab, var(--rd-accent) 72%, var(--rd-neutral-recess)));
    --rd-accent-500:     var(--rd-accent);
    --rd-accent-ink:     var(--rd-accent-600-pin, color-mix(in oklab, var(--rd-accent) 82%, var(--rd-accent-shade)));
    --rd-accent-on-tint: var(--rd-accent-700-pin, color-mix(in oklab, var(--rd-accent) 68%, var(--rd-accent-shade)));
    --rd-accent-ink-deep:var(--rd-accent-800-pin, color-mix(in oklab, var(--rd-accent) 55%, var(--rd-accent-shade)));
    --rd-accent-data:    var(--rd-accent);   /* meter/chart fill; re-seeded in light */

    --rd-success-300: var(--rd-success-300-pin, color-mix(in oklab, var(--rd-success) 62%, var(--rd-neutral-recess)));
    --rd-success-400: var(--rd-success-400-pin, color-mix(in oklab, var(--rd-success) 78%, var(--rd-neutral-recess)));
    --rd-success-500: var(--rd-success-500-pin, color-mix(in oklab, var(--rd-success) 88%, var(--rd-neutral-recess)));
    --rd-success-600: var(--rd-success-600-pin, color-mix(in oklab, var(--rd-success) 92%, var(--rd-accent-shade)));
    --rd-success-800: var(--rd-success-800-pin, color-mix(in oklab, var(--rd-success) 62%, var(--rd-accent-shade)));
    --rd-success-850: var(--rd-success-850-pin, color-mix(in oklab, var(--rd-success) 55%, var(--rd-accent-shade)));
    --rd-danger-400:  var(--rd-danger-400-pin,  color-mix(in oklab, var(--rd-danger) 80%, var(--rd-neutral-recess)));
    --rd-warning-icon:var(--rd-warning-icon-pin,color-mix(in oklab, var(--rd-warning) 78%, var(--rd-neutral-recess)));
    --rd-violet-solid:var(--rd-violet-solid-pin,color-mix(in oklab, var(--rd-violet) 85%, var(--rd-neutral-recess)));

    /* -----------------------------------------------------------------------
       Alpha percentages. Where the two themes disagree on how strong a tint
       should be, the percentage itself is a token - a dark theme needs a
       heavier wash than a light one to read at all.
       ----------------------------------------------------------------------- */
    --rd-veil-alpha: 50%;
    --rd-veil-8-alpha: 8%;
    --rd-wash-chip-alpha: 3%;
    --rd-soft-alpha: 10%;
    --rd-medium-alpha: 15%;
    --rd-firm-alpha: 30%;
    --rd-glow-alpha: 25%;
    --rd-accent-border-alpha: 25%;
    --rd-grad-from-alpha: 20%;
    --rd-grad-to-alpha: 10%;
    --rd-grad-from-hover-alpha: 30%;
    --rd-grad-to-hover-alpha: 15%;
    --rd-lift-2-alpha: 2%;
    --rd-lift-6-alpha: 6%;
    --rd-danger-10-alpha: 10%;
    --rd-danger-15-alpha: 15%;
    --rd-danger-border-alpha: 50%;
    --rd-warning-tint-alpha: 15%;
    --rd-violet-tint-alpha: 15%;
    --rd-linear-chip-alpha: 30%;
    --rd-linear-btn-alpha: 20%;
    --rd-shadow-rest-alpha: 20%;
    --rd-shadow-raised-alpha: 30%;
    --rd-shadow-overlay-alpha: 40%;
    --rd-shadow-modal-alpha: 40%;
    --rd-scrim-alpha: 55%;
    --rd-map-fill-alpha: 15%;
    --rd-map-line-alpha: 40%;
    --rd-tag-fill-mix: 18%;
    --rd-tag-border-mix: 32%;
    --rd-tag-text-mix: 100%;
    --rd-tag-hover-mix: 30%;
    --rd-dim-opacity: 0.5;
    --rd-drag-source-opacity: 0.4;

    /* Raised when the editor detects the canvas and a card have landed within
       0.04 lightness of each other, since the shadow is then the only cue that
       a card is a card. Zero unless the editor says otherwise. */
    --rd-shadow-contrast-boost: 0%;

    /* =======================================================================
       Layer 2: roles. Named after what the app shows, wired here for dark.
       ======================================================================= */

    /* --- Surfaces --- */
    --rd-canvas: var(--rd-neutral-150);
    --rd-sidebar: var(--rd-neutral-200);
    --rd-trough: var(--rd-neutral-250);          /* the lane a kanban column sits in */
    --rd-surface: var(--rd-neutral-300);         /* cards, rows, panels */
    --rd-popover: var(--rd-neutral-250);
    --rd-modal: var(--rd-neutral-300);
    --rd-drawer: var(--rd-neutral-50);
    --rd-surface-quiet: var(--rd-neutral-300);
    --rd-list-row: var(--rd-neutral-250);
    --rd-note-row: var(--rd-neutral-100);
    --rd-field: var(--rd-neutral-250);
    --rd-field-on-card: var(--rd-neutral-300);
    --rd-field-sunken: var(--rd-neutral-0);
    --rd-field-inline: var(--rd-neutral-0);
    --rd-field-inline-focus: var(--rd-neutral-50);
    --rd-surface-veiled: color-mix(in srgb, var(--rd-neutral-300) var(--rd-veil-alpha), transparent);
    --rd-integration-card: color-mix(in srgb, var(--rd-neutral-300) 50%, transparent);
    --rd-integration-inner: color-mix(in srgb, var(--rd-neutral-300) 80%, transparent);
    --rd-integration-chip: color-mix(in srgb, var(--rd-neutral-400) 50%, transparent);
    --rd-canvas-vignette: color-mix(in srgb, var(--rd-neutral-400) 30%, transparent);

    /* --- Borders & dividers --- */
    --rd-border: var(--rd-neutral-400);
    --rd-border-strong: var(--rd-neutral-450);
    --rd-border-faint: var(--rd-neutral-350);
    --rd-border-inset: var(--rd-neutral-300);
    --rd-border-soft: color-mix(in srgb, var(--rd-neutral-400) 50%, transparent);
    --rd-border-softest: color-mix(in srgb, var(--rd-neutral-400) 30%, transparent);
    --rd-border-lift: color-mix(in srgb, var(--rd-neutral-950) var(--rd-lift-6-alpha), transparent);
    --rd-divider-toolbar: color-mix(in srgb, var(--rd-neutral-950) 10%, transparent);
    --rd-swatch-ring: color-mix(in srgb, var(--rd-neutral-950) 18%, transparent);
    --rd-row-outline: color-mix(in oklab, var(--rd-accent) 22%, var(--rd-neutral-400));
    --rd-meta-separator: var(--rd-neutral-400);

    /* --- Text & icons, most-emphatic first --- */
    --rd-text-max: var(--rd-neutral-950);
    --rd-text-strong: var(--rd-neutral-925);
    --rd-text: var(--rd-neutral-900);
    --rd-text-table: var(--rd-neutral-850);
    --rd-text-control: var(--rd-neutral-800);
    --rd-text-nav: var(--rd-neutral-750);
    --rd-text-emphasis: var(--rd-neutral-700);
    --rd-text-muted: var(--rd-neutral-650);
    --rd-text-glyph-chrome: var(--rd-neutral-650);
    --rd-text-label: var(--rd-neutral-600);
    --rd-text-glyph: var(--rd-neutral-550);
    --rd-text-faint: var(--rd-neutral-500);
    --rd-text-disabled: color-mix(in srgb, var(--rd-neutral-950) 38%, transparent);
    --rd-text-on-brand: #374151;   /* the pale brand surfaces are fixed, so their ink is too */

    /* Ink on a solid accent fill. Flips black/white from the fill's own
       lightness, so a user who picks a near-white accent still gets readable
       badge text. The literal below is the fallback where relative colour
       syntax is unsupported - see the @supports block at the end. */
    --rd-text-on-accent: oklch(from var(--rd-accent) clamp(0, calc((0.70 - l) * 1000), 1) 0 0);
    /* Same trick for status fills. A component sets --rd-status-fill locally,
       so --rd-text-on-solid is declared in the locally-derived block below. */
    --rd-status-fill: var(--rd-accent);

    /* --- Accent surfaces & pointer states --- */
    --rd-accent-fg: var(--rd-accent-500);
    --rd-hover: var(--rd-neutral-350);
    --rd-row-hover: var(--rd-neutral-350);
    --rd-inline-edit-hover: var(--rd-neutral-350);
    --rd-hover-lift: color-mix(in srgb, var(--rd-neutral-950) var(--rd-lift-2-alpha), transparent);
    --rd-hover-over-swatch: color-mix(in srgb, var(--rd-neutral-950) 12%, transparent);
    --rd-pressed: color-mix(in srgb, var(--rd-neutral-950) 16%, transparent);
    --rd-accent-wash: color-mix(in srgb, var(--rd-accent) 3%, transparent);
    --rd-accent-wash-chip: color-mix(in srgb, var(--rd-accent) var(--rd-wash-chip-alpha), transparent);
    --rd-accent-wash-drop: color-mix(in srgb, var(--rd-accent) 5%, transparent);
    --rd-accent-veil: color-mix(in srgb, var(--rd-accent) var(--rd-veil-8-alpha), transparent);
    --rd-accent-soft: color-mix(in srgb, var(--rd-accent) var(--rd-soft-alpha), transparent);
    --rd-accent-medium: color-mix(in srgb, var(--rd-accent) var(--rd-medium-alpha), transparent);
    --rd-accent-firm: color-mix(in srgb, var(--rd-accent) var(--rd-firm-alpha), transparent);
    --rd-accent-glow: color-mix(in srgb, var(--rd-accent) var(--rd-glow-alpha), transparent);
    --rd-accent-border-soft: color-mix(in srgb, var(--rd-accent) var(--rd-accent-border-alpha), transparent);
    --rd-accent-grad-from: color-mix(in srgb, var(--rd-accent) var(--rd-grad-from-alpha), transparent);
    --rd-accent-grad-to: color-mix(in srgb, var(--rd-accent) var(--rd-grad-to-alpha), transparent);
    --rd-accent-grad-from-hover: color-mix(in srgb, var(--rd-accent) var(--rd-grad-from-hover-alpha), transparent);
    --rd-accent-grad-to-hover: color-mix(in srgb, var(--rd-accent) var(--rd-grad-to-hover-alpha), transparent);
    --rd-selected-surface: var(--rd-neutral-400);
    --rd-nav-selected: color-mix(in srgb, var(--rd-accent) 12%, transparent);
    /* Keeps the selected nav pill separable from plain hover even when the
       chosen accent is close to the neutral it sits on. */
    --rd-selected-floor: color-mix(in oklab, var(--rd-nav-selected) 94%, var(--rd-accent));
    --rd-neutral-action-hover: color-mix(in oklab, var(--rd-accent) 14%, var(--rd-neutral-400));
    --rd-drop-placeholder: var(--rd-accent-wash-drop);

    /* --- Focus & selection --- */
    --rd-focus-ring: color-mix(in srgb, var(--rd-accent) 15%, transparent);
    --rd-focus-ring-soft: color-mix(in srgb, var(--rd-accent) 10%, transparent);
    /* Mixing ink into the accent guarantees the keyboard ring keeps a usable
       delta against the page whatever accent is chosen. */
    --rd-focus-outline: color-mix(in oklab, var(--rd-neutral-ink) 45%, var(--rd-accent));
    --rd-focus-outline-offset: 2px;
    --rd-selection-bg: color-mix(in srgb, var(--rd-accent) 30%, transparent);
    --rd-selection-fg: var(--rd-neutral-950);
    --rd-caret: var(--rd-accent-fg);

    /* --- Controls --- */
    --rd-control: var(--rd-neutral-400);
    --rd-control-hover: var(--rd-neutral-450);
    --rd-chip: var(--rd-neutral-400);
    --rd-chip-neutral: var(--rd-neutral-400);
    --rd-meter-track: var(--rd-neutral-300);
    --rd-toggle-track-off: var(--rd-neutral-400);
    --rd-toggle-track-on: color-mix(in srgb, var(--rd-accent) 30%, transparent);
    --rd-toggle-thumb-off: var(--rd-text-glyph-chrome);
    --rd-toggle-thumb-on: var(--rd-accent-500);
    --rd-button-solid-bg: var(--rd-accent-500);
    --rd-button-solid-fg: var(--rd-text-on-accent);
    --rd-button-solid-bg-hover: color-mix(in oklab, var(--rd-accent) 88%, var(--rd-neutral-ink));
    --rd-disabled-bg: color-mix(in srgb, var(--rd-neutral-950) 6%, transparent);
    --rd-field-autofill-bg: var(--rd-field);
    --rd-field-autofill-fg: var(--rd-text);
    --rd-scrollbar-thumb: var(--rd-neutral-400);
    --rd-scrollbar-thumb-hover: var(--rd-neutral-450);
    --rd-scrollbar-track: transparent;
    --rd-select-chevron: var(--rd-text-glyph-chrome);
    /* A board column carries its own colour; this is the fallback for one that
       has not been given one. --rd-column-accent is set per column, inline. */
    --rd-column-accent-default: var(--rd-text-muted);

    /* --- Status roles --- */
    --rd-success-fg: var(--rd-success);
    --rd-success-on-tint: var(--rd-success-800);
    --rd-success-dot: var(--rd-success-500);
    --rd-success-dot-account: var(--rd-success-400);
    --rd-success-label: var(--rd-success-850);
    --rd-success-surface: var(--rd-success-surface-pin, color-mix(in oklab, var(--rd-success) 26%, var(--rd-neutral-150)));
    --rd-success-surface-hover: var(--rd-success-surface-hover-pin, color-mix(in oklab, var(--rd-success) 38%, var(--rd-neutral-150)));
    --rd-success-tint-10: color-mix(in srgb, var(--rd-success) 10%, transparent);
    --rd-success-tint-15: color-mix(in srgb, var(--rd-success) 15%, transparent);
    --rd-success-tint-30: color-mix(in srgb, var(--rd-success) 30%, transparent);
    --rd-pill-selected: var(--rd-selected-surface);
    --rd-pill-selected-fg: var(--rd-text);
    --rd-danger-fg: var(--rd-danger);
    --rd-danger-dot: var(--rd-danger-400);
    --rd-danger-surface: var(--rd-danger-surface-pin, color-mix(in oklab, var(--rd-danger) 22%, var(--rd-neutral-150)));
    --rd-danger-tint-10: color-mix(in srgb, var(--rd-danger) var(--rd-danger-10-alpha), transparent);
    --rd-danger-tint-15: color-mix(in srgb, var(--rd-danger) var(--rd-danger-15-alpha), transparent);
    --rd-danger-border: color-mix(in srgb, var(--rd-danger) var(--rd-danger-border-alpha), transparent);
    /* The overdue-reminder red. Deliberately the same in every theme: it is the
       one colour in the app that has to mean "look at this right now". */
    --rd-alert-fg: #dc2626;
    /* Nav-entry alert marker: a section is holding something that wants you.
       Shares the overdue red on purpose - a red mark in the sidebar should mean
       the same thing wherever it appears. */
    --rd-nav-dot: var(--rd-alert-fg);
    --rd-warning-tint: color-mix(in srgb, var(--rd-warning) var(--rd-warning-tint-alpha), transparent);
    --rd-violet-tint: color-mix(in srgb, var(--rd-violet-solid) var(--rd-violet-tint-alpha), transparent);
    --rd-defer-fg: var(--rd-accent-ink-deep);
    --rd-defer-surface: var(--rd-defer-surface-pin, color-mix(in oklab, var(--rd-accent) 22%, var(--rd-neutral-150)));
    --rd-defer-surface-hover: var(--rd-defer-surface-hover-pin, color-mix(in oklab, var(--rd-accent) 34%, var(--rd-neutral-150)));
    --rd-status-todo-dot: var(--rd-text-glyph-chrome);
    --rd-status-todo-label: var(--rd-text-control);

    /* --- Elevation --- */
    --rd-shadow-base: #000000;
    --rd-shadow-rest: color-mix(in srgb, var(--rd-shadow-base) calc(var(--rd-shadow-rest-alpha) + var(--rd-shadow-contrast-boost)), transparent);
    --rd-shadow-raised: color-mix(in srgb, var(--rd-shadow-base) calc(var(--rd-shadow-raised-alpha) + var(--rd-shadow-contrast-boost)), transparent);
    --rd-shadow-overlay: color-mix(in srgb, var(--rd-shadow-base) calc(var(--rd-shadow-overlay-alpha) + var(--rd-shadow-contrast-boost)), transparent);
    --rd-shadow-modal-color: color-mix(in srgb, var(--rd-shadow-base) var(--rd-shadow-modal-alpha), transparent);
    --rd-scrim: color-mix(in srgb, var(--rd-shadow-base) var(--rd-scrim-alpha), transparent);
    --rd-shadow-card: 0 2px 8px var(--rd-shadow-rest);
    --rd-shadow-lifted: 0 4px 16px var(--rd-shadow-raised);
    --rd-shadow-popover: 0 8px 24px var(--rd-shadow-overlay);
    --rd-shadow-drawer: -8px 0 24px var(--rd-shadow-overlay);
    --rd-shadow-modal: 0 16px 48px var(--rd-shadow-modal-color);

    /* --- Tag chips ---
       A tag's colour is chosen by the user and is never themed. What IS themed
       is how much of it to show: a dark theme floats the chip on a transparent
       ground, a light theme needs a solid ground under it to stay legible. */
    --rd-tag-ground: transparent;
    --rd-tag-contrast-floor: 18%;

    /* --- Mind map: six categorical hues --- */
    --rd-map-1: #7fdbda;
    --rd-map-2: #f0a6ca;
    --rd-map-3: #a8f0dc;
    --rd-map-4: #b8a9f0;
    --rd-map-5: #f0d6a6;
    --rd-map-6: #a6c8f0;
    /* A node sets --rd-map-node to one of the six, inline. The tokens derived
       from it are NOT declared here - see the locally-derived block below. */
    --rd-map-node: var(--rd-map-1);
    --rd-section-icon-mindmap: var(--rd-map-4);

    /* --- Linear workflow states. These mirror Linear's own state colours, so
       they read the same as the tool they came from in either theme. --- */
    --rd-state-progress: #3b82f6;
    --rd-state-review: #a855f7;
    --rd-state-done: #22c55e;
    --rd-state-todo: #f59e0b;
    --rd-state-neutral: #64748b;
    --rd-state-progress-icon: var(--rd-state-progress-icon-pin, color-mix(in oklab, var(--rd-state-progress) 72%, var(--rd-neutral-recess)));
    --rd-state-review-icon:   var(--rd-state-review-icon-pin,   color-mix(in oklab, var(--rd-state-review) 72%, var(--rd-neutral-recess)));
    --rd-state-done-icon:     var(--rd-state-done-icon-pin,     color-mix(in oklab, var(--rd-state-done) 72%, var(--rd-neutral-recess)));
    --rd-state-todo-icon:     var(--rd-state-todo-icon-pin,     color-mix(in oklab, var(--rd-state-todo) 72%, var(--rd-neutral-recess)));
    --rd-state-neutral-icon:  var(--rd-state-neutral-icon-pin,  color-mix(in oklab, var(--rd-state-neutral) 65%, var(--rd-neutral-recess)));
    --rd-meta-project: #22d3ee;
    --rd-meta-parent: #c084fc;
    --rd-meta-cycle: #f472b6;
    --rd-link-issue: #818cf8;
    --rd-avatar-busy: var(--rd-success-600);
    --rd-avatar-idle: var(--rd-avatar-idle-pin, color-mix(in oklab, var(--rd-state-neutral) 80%, var(--rd-neutral-ground)));
    --rd-avatar-placeholder: var(--rd-selected-surface);
    --rd-count-zero: #f97316;
    --rd-count-busy: var(--rd-state-done);
    /* An outstanding-items count, e.g. the "(3)" beside a person. Literal like
       the two above, and for the same reason: derived from --rd-warning it comes
       out cream in the pastel themes, and a count you are meant to spot while
       scanning has to actually be orange in all of them. Short of
       --rd-alert-fg - worth noticing, not worth interrupting for. Light themes
       take it a shade deeper; see themes.css. */
    --rd-count-outstanding: #f97316;

    /* --- Brand marks. Fixed in every theme - they identify something outside
       the app, so a theme does not get to repaint them. --- */
    --rd-brand-sky: #a8d8ea;
    --rd-brand-sky-hover: var(--rd-brand-sky-hover-pin, color-mix(in oklab, var(--rd-brand-sky) 86%, var(--rd-accent-shade)));
    --rd-brand-mauve: #9b6b9e;
    --rd-brand-mauve-hover: var(--rd-brand-mauve-hover-pin, color-mix(in oklab, var(--rd-brand-mauve) 55%, var(--rd-neutral-recess)));
    --rd-brand-mauve-ring: color-mix(in srgb, var(--rd-brand-mauve-hover) 20%, transparent);
    --rd-brand-linear: #5e6ad2;
    --rd-brand-linear-fg: var(--rd-brand-linear-fg-pin, color-mix(in oklab, var(--rd-brand-linear) 62%, var(--rd-neutral-ink)));
    --rd-brand-linear-chip: color-mix(in srgb, var(--rd-brand-linear) var(--rd-linear-chip-alpha), transparent);
    --rd-brand-linear-btn: color-mix(in srgb, var(--rd-brand-linear) var(--rd-linear-btn-alpha), transparent);

    /* =======================================================================
       Density. A second attribute on the same element as the theme:
           <html data-theme="midnight" data-density="compact">
       :root carries the comfortable set - which is exactly the sizes the app
       shipped with, so the default is a no-op - and the [data-density="compact"]
       block below redefines the same names. No colour token moves.
       ======================================================================= */
    --rd-space-1: 3px;
    --rd-space-2: 4px;
    --rd-space-3: 6px;
    --rd-space-4: 8px;
    --rd-space-5: 12px;
    --rd-space-6: 16px;
    --rd-space-7: 20px;
    --rd-space-8: 24px;
    --rd-space-9: 32px;

    --rd-pad-card: 10px 12px;
    --rd-pad-panel: 12px 14px;
    --rd-pad-row: 8px 12px;
    --rd-pad-menu-item: 8px 14px;
    --rd-pad-field: 8px 12px;
    --rd-pad-field-sm: 6px 12px;
    --rd-pad-control: 8px 14px;
    --rd-pad-chip: 1px 7px;
    --rd-pad-section: 40px 20px;

    --rd-control-h-xs: 20px;
    --rd-control-h-sm: 24px;
    --rd-control-h-md: 32px;
    --rd-control-h-lg: 38px;
    --rd-icon-btn: 28px;
    --rd-icon-tile: 32px;
    --rd-swatch: 22px;
    --rd-avatar-sm: 28px;
    --rd-row-h: 34px;
    --rd-nav-item-h: 36px;
    --rd-row-min-h: 56px;
    --rd-divider-h: 28px;

    --rd-font-2xs: 10px;
    --rd-font-xs: 11px;
    --rd-font-sm: 12px;
    --rd-font-md: 13px;
    --rd-font-base: 14px;
    --rd-font-lg: 16px;
    --rd-font-xl: 20px;
    --rd-leading-tight: 1.4;
    --rd-leading-body: 1.55;

    /* Radii and strokes do not move with density: the 2px/3px/4px markers are
       structural, and shifting them changes what they mean. */
    --rd-radius-xs: 2px;
    --rd-radius-sm: 4px;
    --rd-radius-md: 6px;
    --rd-radius-lg: 8px;
    --rd-radius-xl: 12px;
    --rd-radius-pill: 999px;
    --rd-hairline: 1px;
    --rd-ring-w: 2px;
    --rd-accent-bar-w: 3px;
    --rd-marker-w: 4px;
}

/* ===========================================================================
   Locally-derived tokens.

   A custom property is substituted where it is DECLARED, not where it is used.
   A token like `--rd-map-node-surface: color-mix(…, var(--rd-map-node), …)`
   declared on :root therefore bakes in :root's --rd-map-node once, and every
   descendant inherits that single answer - so setting --rd-map-node per node
   would do nothing at all, and every mind-map depth would come out the same
   colour.

   Declaring them on every element instead makes each element re-derive from the
   --rd-map-node / --rd-column-accent / --rd-status-fill it has actually
   inherited, which is the entire point of setting those per node, per column
   and per badge. This is the same trick Tailwind uses for its ring and shadow
   variables, and the cost is a handful of extra computed properties per element.
   =========================================================================== */
*,
::before,
::after {
    /* Mind map: a node sets --rd-map-node inline, these follow it. */
    --rd-map-node-surface: color-mix(in srgb, var(--rd-map-node) var(--rd-map-fill-alpha), transparent);
    --rd-map-node-line: color-mix(in srgb, var(--rd-map-node) var(--rd-map-line-alpha), transparent);
    --rd-map-node-text: color-mix(in oklab, var(--rd-map-node) 70%, var(--rd-text-strong));
    --rd-map-node-glow: color-mix(in srgb, var(--rd-map-node) 19%, transparent);
    --rd-map-node-ring: color-mix(in srgb, var(--rd-map-node) 38%, transparent);
    --rd-map-node-veil: color-mix(in srgb, var(--rd-map-node) 8%, transparent);

    /* Board columns: a column sets --rd-column-accent inline. */
    --rd-column-count-bg: color-mix(in srgb, var(--rd-column-accent, var(--rd-column-accent-default)) 15%, transparent);

    /* Solid status fills: a badge sets --rd-status-fill, and the ink on it is
       computed from that fill's own lightness rather than guessed. */
    --rd-text-on-solid: oklch(from var(--rd-status-fill) clamp(0, calc((0.70 - l) * 1000), 1) 0 0);
}

@supports not (color: oklch(from #000 l c h)) {
    *,
    ::before,
    ::after {
        --rd-text-on-solid: #ffffff;
    }
}

:root[data-density="compact"] {
    --rd-space-1: 2px;
    --rd-space-2: 3px;
    --rd-space-3: 4px;
    --rd-space-4: 6px;
    --rd-space-5: 8px;
    --rd-space-6: 12px;
    --rd-space-7: 16px;
    --rd-space-8: 20px;
    --rd-space-9: 28px;

    --rd-pad-card: 6px 9px;
    --rd-pad-panel: 8px 10px;
    --rd-pad-row: 5px 8px;
    --rd-pad-menu-item: 5px 10px;
    --rd-pad-field: 6px 10px;
    --rd-pad-field-sm: 4px 10px;
    --rd-pad-control: 4px 10px;
    --rd-pad-chip: 0 6px;
    --rd-pad-section: 24px 14px;

    --rd-control-h-xs: 16px;
    --rd-control-h-sm: 20px;
    --rd-control-h-md: 26px;
    --rd-control-h-lg: 32px;
    --rd-icon-btn: 24px;
    --rd-icon-tile: 26px;
    --rd-swatch: 18px;
    --rd-avatar-sm: 22px;
    --rd-row-h: 28px;
    --rd-nav-item-h: 30px;
    --rd-row-min-h: 44px;
    --rd-divider-h: 22px;

    --rd-font-2xs: 9px;
    --rd-font-xs: 10px;
    --rd-font-sm: 11px;
    --rd-font-md: 12px;
    --rd-font-base: 13px;
    --rd-font-lg: 15px;
    --rd-font-xl: 18px;
    --rd-leading-tight: 1.25;
    --rd-leading-body: 1.4;

    --rd-radius-sm: 3px;
    --rd-radius-md: 5px;
    --rd-radius-lg: 6px;
    --rd-radius-xl: 8px;
}

/* ===========================================================================
   App-wide rules the token system now makes possible. None of these existed
   before - the app had no focus ring, no selection colour, and left native
   controls and autofilled inputs rendering in the OS's own palette.
   =========================================================================== */

::selection {
    background-color: var(--rd-selection-bg);
    color: var(--rd-selection-fg);
}

:focus-visible {
    outline: var(--rd-ring-w) solid var(--rd-focus-outline);
    outline-offset: var(--rd-focus-outline-offset);
}

input, textarea, select {
    caret-color: var(--rd-caret);
}

/* Chrome paints autofilled inputs its own yellow and ignores background-color.
   An inset shadow the height of the field is the only way to override it. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
    -webkit-box-shadow: 0 0 0 1000px var(--rd-field-autofill-bg) inset;
    -webkit-text-fill-color: var(--rd-field-autofill-fg);
    caret-color: var(--rd-caret);
}

/* Windows high-contrast mode replaces the palette wholesale. Hand it the system
   colours rather than fighting it, but keep tag chips and cards painting their
   own colour - they carry meaning the system palette would flatten. */
@media (forced-colors: active) {
    :root {
        --rd-border: CanvasText;
        --rd-text: CanvasText;
        --rd-canvas: Canvas;
        --rd-surface: Canvas;
        --rd-accent-fg: LinkText;
    }
    .tag-chip,
    .kanban-card {
        forced-color-adjust: none;
    }
}

/* Relative colour syntax computes the ink for a solid accent fill from that
   fill's own lightness. Where it is unsupported, fall back to the literals the
   app used before tokens - correct for both built-in themes, and no worse than
   what shipped for any other. */
@supports not (color: oklch(from #000 l c h)) {
    :root {
        --rd-text-on-accent: #12122a;
        --rd-text-on-solid: #ffffff;
    }
}
