/**
 * rn-motion-ui design tokens — canonical @theme block.
 *
 * Import this in your app's global CSS:
 *   @import "rn-motion-ui/tokens.css";
 *
 * Override any token in your own @theme block after the import:
 *   @theme { --color-primary: oklch(52% 0.22 250); }
 *
 * ## Surface system
 *
 * Backgrounds are organised as an elevation ladder (surface-1 … surface-3):
 *
 *  - `surface-1` is the page. `surface-3` is the resting fill for contained
 *    content AND the fill modals float on — the two share one tint; only the
 *    shadow differentiates them.
 *  - Light mode keeps the ladder neutral (2+ are pure white) — elevation is
 *    carried by the `shadow-surface-N` recipes alone.
 *  - Dark mode steps lightness up per level and adds a subtle neutral tint
 *    (hue 270, chroma 0.004) so the whole stack tracks one brand direction.
 *    Retune the tint by overriding the tinted values below.
 *  - `surface-hover` / `surface-selected` are translucent state overlays:
 *    they raise whatever surface they composite onto by a fixed perceptual
 *    delta, so one utility works at every level.
 *  - Every `shadow-surface-N` pairs with `bg-surface-N` — the shadow carries a
 *    crisp 1px ring plus progressively softer drop layers.
 *
 * Surfaces address the ladder directly — `surface-1` is the page, `surface-3`
 * the resting level for contained content (cards, inputs) and the float level
 * for modals and elevated menus. Values are spelled out literally (rather than
 * via var() chains) so uniwind can resolve every token on native exactly as
 * written.
 *
 * ## Status colors
 *
 * `danger` / `success` / `warning` / `info` are vivid filled colors (action
 * indicators, modals, toasts); pair them with `*-foreground` (white) for
 * legible text/icons on that fill.
 *
 * ## Absolute colors
 *
 * `white` and `black` are the two theme-independent tokens — the same value in
 * light and dark, so `bg-white` / `text-black` (and `useThemeColor('white')`)
 * never flip. They cover the cases where a fixed color is the design intent —
 * a glyph on a vivid status fill, a gloss highlight, a scrim — instead of a
 * hardcoded `#fff` / `#000`. Anything that should follow the theme wants
 * `foreground` / `surface-N` / `*-foreground` instead.
 *
 * ## Interactive surface family
 *
 * `--spacing-interactive-*` is the shared height for every interactive component —
 * Button, ElevatedButton, GlossyButton, ActionSwap, Input, OtpInput and Tabs all
 * read the same height per size, so a row of mixed controls lines up.
 * `--spacing-interactive-pad-*` is the shared horizontal padding for the same
 * family. `--spacing-interactive-pad-*-tight` is the reduced inset for rounded
 * or compact surfaces whose corners eat less horizontal space than a pill.
 * Override a token to retune the whole family at once.
 *
 * ## Corner radius
 *
 * Four tokens partition corner curves by surface category, so each family can be
 * retuned independently without affecting the others:
 *
 * - `--radius-interactive` (8 px) — buttons, inputs, tabs, button groups.
 * - `--radius-card` (24 px) — card containers.
 * - `--radius-card-compact` (16 px) — tight card variant (RadioCard, CheckboxCard,
 *   SwipeableList rows) that renders below the full card radius.
 * - `--radius-menu` (16 px) — HoverMenu, Dropdown, HoldMenu overlays.
 * - `--radius-modal` (32 px) — Modals, Popovers, MorphingModal, BottomSheet.
 *
 * Unlike the colors, geometry tokens carry no dark-mode counterpart — geometry
 * doesn't flip with the theme. Values are px (not rem): the effect layers that
 * trace a button's curve — the glossy dome, the elevated rim SVG, the shadow
 * rings — need the same number in JS, and px is the one unit that survives
 * that round trip unrounded (see lib/radius.ts).
 *
 * ## How the two themes are expressed
 *
 * Every token that flips is declared three times: once in `@theme` and once in
 * each of the `@variant light` / `@variant dark` blocks at the bottom of this
 * file.
 *
 *  - `@theme` holds the light values. It is what registers each token with
 *    Tailwind (so `bg-surface-1` and `shadow-surface-3` exist at all) and what
 *    lands on `:root` for the web base.
 *  - `@variant light` / `@variant dark` hold the per-theme values. `@variant`
 *    expands to `:where(.light, .light *)` / `:where(.dark, .dark *)`, which is
 *    the selector shape both the web class-switching decorator and uniwind's
 *    native theme extraction look for. Native only ever reads these two blocks:
 *    uniwind derives `vars.light` / `vars.dark` from a shared global base that
 *    diverges solely via the `@variant`-scoped declarations, so a value that
 *    lives only in `@theme` is theme-independent by construction.
 *
 * Both `@variant` blocks must declare the identical token set — uniwind logs a
 * parity error per missing token otherwise. `scripts/check-token-parity.mjs`
 * enforces that, plus `@theme` ⇄ `@variant light` agreement and both blocks
 * against the native OKLCH tables.
 *
 * Native note: the sRGB equivalents used by useThemeColor() are derived from
 * these same oklch numbers via lib/color.ts — keep the TOKEN_OKLCH table in
 * theme/use-theme-color.ts in sync when editing values here.
 */

/* ── Token registration + light values + web :root base ────────────────── */

@theme {
  /* Surface ladder — page is surface-1; the resting fill for contained content
     and the top float both resolve to surface-3. Light mode: neutral,
     clean-canvas; shadows alone carry elevation. */
  --color-surface-1: oklch(97% 0 0);
  --color-surface-2: oklch(98.5% 0 0);
  --color-surface-3: oklch(100% 0 0);

  /* State overlays — translucent, composite on any surface level. */
  --color-surface-hover: oklch(0% 0 0 / 0.04);
  --color-surface-selected: oklch(0% 0 0 / 0.08);

  /* Foreground stack — near-extremes carry a whisper of the hue-270 tint.
     `muted` doubles as the raised neutral fill used by tabs, skeletons,
     segmented controls and the like; `muted-foreground` is its ink.

     `muted` is deliberately offset from BOTH neighbours it composites against:
     it sits 5% below `background` (95%) and 7% below `surface-1` in light, and
     7.5% above `surface-1` in dark. It used to match `background` outright in
     light mode, which made every muted track invisible on a page. Keep a
     ≥4% lightness gap from `background` on either side when retuning. */
  --color-foreground: oklch(18% 0.004 270);
  --color-muted: oklch(90% 0 0);
  --color-muted-foreground: oklch(50% 0.004 270);
  --color-border: oklch(0% 0 0 / 0.1);

  /* Flat neutral fills. `input` is the page-white field fill; `Input` itself now
     reads the surface ladder (`elevation` + `floating`) like every other
     surface, so this is left for app code that wants the old flat field colour. */
  --color-input: oklch(100% 0 0);

  /* Brand — monochrome primary (near-black on light, near-white on dark). */
  --color-primary: oklch(22% 0 0);
  --color-primary-foreground: oklch(98% 0.002 270);
  --color-secondary: oklch(92% 0 0);
  --color-secondary-foreground: oklch(32% 0.004 270);
  --color-accent: oklch(91% 0 0);
  --color-accent-foreground: oklch(22% 0.004 270);

  /* Status pairs — vivid filled background / white foreground. All
     foregrounds are white for consistent legibility on the saturated fill.
     `warning` and `info` hold the same value in both schemes: they sit at mid
     lightness already, so there is nothing a dark-mode lift fixes. */
  --color-success: oklch(70% 0.18 155);
  --color-success-foreground: oklch(100% 0 0);
  --color-warning: oklch(58% 0.18 40);
  --color-warning-foreground: oklch(100% 0 0);
  --color-info: oklch(58% 0.18 255);
  --color-info-foreground: oklch(100% 0 0);
  --color-danger: oklch(62% 0.22 25);
  --color-danger-foreground: oklch(100% 0 0);

  /* Absolute colors — the two values that do NOT flip with the theme. They are
     re-declared verbatim in both dark blocks so every platform resolves them
     the same way (and so the parity check has all three declarations to
     compare). Reach for these where a fixed color is the design intent — a
     glyph on a vivid status fill, a gloss highlight, a scrim — rather than
     hardcoding `#fff` / `#000`. For anything that should track the theme, use
     `foreground` / `surface-N` instead. */
  --color-white: oklch(100% 0 0);
  --color-black: oklch(0% 0 0);

  /* Theme-flipping background — near-white with a whisper of the hue-270 tint
     in light mode, black in dark mode. Unlike `white` / `black` (which are
     absolute and never flip), this token tracks the active scheme so a
     page-level background automatically inverts. */
  --color-background: oklch(95% 0.004 270);

  /* Frosted-glass fill — the translucent tint the frosted Surface composites
     over its backdrop blur. Flips with the scheme (near-white glass in light,
     dark glass in dark) so the pane always reads against whatever it frosts. */
  --color-glass: oklch(99% 0 0 / 0.6);

  /* Surface elevation shadows — a crisp 1px ring at full strength plus drop
     layers whose opacity decays as blur grows (natural light fall-off).
     Pair shadow-surface-N with bg-surface-N. The top rung (3) carries the full
     six-layer stack so modals keep their presence on a three-rung ladder. */
  --shadow-surface-1: 0 0 0 1px oklch(0% 0 0 / 0.06);
  --shadow-surface-2: 0 0 0 1px oklch(0% 0 0 / 0.06), 0 1px 1px -0.5px oklch(0% 0 0 / 0.06);
  --shadow-surface-3:
    0 0 0 1px oklch(0% 0 0 / 0.06), 0 1px 1px -0.5px oklch(0% 0 0 / 0.06), 0 3px 3px -1.5px oklch(0% 0 0 / 0.05),
    0 6px 6px -3px oklch(0% 0 0 / 0.05), 0 12px 12px -6px oklch(0% 0 0 / 0.04), 0 24px 24px -12px oklch(0% 0 0 / 0.04);

  /* Detached controls need only a short contact shadow and a soft lift. Keep
     both layers quiet so the surface edge and content retain the hierarchy. */
  --shadow-floating: 0 1px 2px -1px oklch(0% 0 0 / 0.08), 0 4px 12px -4px oklch(0% 0 0 / 0.1);

  /* Elevated shadow ingredients — the inset rim recipe (highlight + ring) that
     composites in front of the drop layers. Declared here in @theme so Tailwind
     registers them (no `unset` in the theme layer for tokens referenced via
     var() below), with their light-mode no-op values. Both @variant blocks below
     restate the full set — dark fills them with the real recipe, light mirrors
     these no-ops — so uniwind can extract per-theme maps. */
  --surface-hi-base: transparent;
  --surface-hi-high: transparent;
  --surface-ring-base: transparent;
  --surface-ring-high: transparent;
  --surface-rim-1: 0 0 transparent;
  --surface-rim-2: 0 0 transparent;
  --surface-rim-3: 0 0 transparent;

  /* Elevated shadow recipe — the shadow applied by the `elevated()` util and
     the `elevation` prop. Each level composites the surface *rim* (inset
     highlight + ring, declared above) in front of the `shadow-surface-N` drop
     layers, in a SINGLE box-shadow. React Native has no `::after` to paint the
     pseudo-element rim, so the two layers are combined into one shadow instead.
     One definition covers both schemes, and it belongs in @theme rather than in
     the variants: `--surface-rim-N` is a transparent no-op in light and the
     inset recipe in dark, and `--shadow-surface-N` also flips, so this token
     tracks the active theme through its dependencies — via the CSS cascade on
     web, and via uniwind's per-theme scoped vars on native. */
  --shadow-elevated-1: var(--surface-rim-1), var(--shadow-surface-1);
  --shadow-elevated-2: var(--surface-rim-2), var(--shadow-surface-2);
  --shadow-elevated-3: var(--surface-rim-3), var(--shadow-surface-3);

  /* Interactive surface family — height, horizontal padding and corner radius
     are the same box for every interactive component (buttons, inputs, tabs,
     button groups) at a given size, so a row of mixed controls lines up.
     Cards have their own `--radius-card`.

     Four heights — `xs` 24, `sm` 32, `md` 44, `lg` 56. `icon` reuses the `md`
     numbers as a square. A `pill` button ignores the corner radius and takes
     half its height instead. See lib/radius.ts for the pixel constants used by
     the effect layers. One scheme only: geometry doesn't flip with the theme,
     so there are no dark-mode counterparts below. */
  --spacing-interactive-xs: 24px;
  --spacing-interactive-sm: 32px;
  --spacing-interactive-md: 44px;
  --spacing-interactive-lg: 56px;
  --spacing-interactive-pad-xs: 8px;
  --spacing-interactive-pad-sm: 14px;
  --spacing-interactive-pad-md: 20px;
  --spacing-interactive-pad-lg: 24px;
  /* Tight horizontal padding — the reduced inset for rounded/compact surfaces
     whose corners eat less horizontal space than a pill (e.g. AnimatedBadge's
     `rounded` shape). Mirrors the pad ramp at roughly half the inset. */
  --spacing-interactive-pad-tight-xs: 4px;
  --spacing-interactive-pad-tight-sm: 6px;
  --spacing-interactive-pad-tight-md: 8px;
  --spacing-interactive-pad-tight-lg: 10px;

  --menu-vertical-padding: 4px;

  --radius-menu: 16px;
  --radius-interactive: 8px;
  --radius-card: 24px;
  --radius-card-compact: 16px;
  --radius-modal: 32px;

  /* Typography — per-weight font family tokens. One token per weight so that
     uniwind resolves the correct .ttf file on native (where fontWeight alone
     cannot select a different font file). On web the browser matches these
     family names against @font-face declarations.

     Defaults use system font stacks where all weights share the same value —
     the OS handles weight selection for built-in fonts. Override in your own
     @theme block to swap in a custom typeface with weight-specific names
     (e.g. 'Geist-Regular', 'Geist-Medium', 'Geist-SemiBold', 'Geist-Bold').

     Geometry doesn't flip with the theme, so these live only in @theme. */
  --font-sans-normal: ui-sans-serif, system-ui, sans-serif;
  --font-sans-medium: ui-sans-serif, system-ui, sans-serif;
  --font-sans-semibold: ui-sans-serif, system-ui, sans-serif;
  --font-sans-bold: ui-sans-serif, system-ui, sans-serif;
  --font-serif-normal: ui-serif, Georgia, serif;
  --font-serif-medium: ui-serif, Georgia, serif;
  --font-serif-semibold: ui-serif, Georgia, serif;
  --font-serif-bold: ui-serif, Georgia, serif;
  --font-mono-normal: ui-monospace, monospace;
  --font-mono-medium: ui-monospace, monospace;
  --font-mono-semibold: ui-monospace, monospace;
  --font-mono-bold: ui-monospace, monospace;
}

/* ── Hairline border ──────────────────────────────────────────────────────
 *
 * The default border weight in the library. Outline buttons use the lighter
 * 1px `border` utility; other borders use 2px for stronger separation. The latter
 * is spelled `hairline` (all four sides) or `hairline-t` / `hairline-r` /
 * `hairline-b` / `hairline-l` (one side) instead of an arbitrary
 * `border-[2px]`. The style is `var(--tw-border-style)`, the same variable
 * Tailwind's built-in `border-*` width utilities set, so `hairline border-dashed`
 * still renders dashed. Geometry doesn't flip with the theme, so these live
 * outside `@theme` as plain custom utilities.
 */
@utility hairline {
  border-style: var(--tw-border-style);
  border-width: 2px;
}
@utility hairline-t {
  border-top-style: var(--tw-border-style);
  border-top-width: 2px;
}
@utility hairline-r {
  border-right-style: var(--tw-border-style);
  border-right-width: 2px;
}
@utility hairline-b {
  border-bottom-style: var(--tw-border-style);
  border-bottom-width: 2px;
}
@utility hairline-l {
  border-left-style: var(--tw-border-style);
  border-left-width: 2px;
}

/* ── Input vertical centring ──────────────────────────────────────────────
 *
 * A single-line `TextInput` sits inside a flex `items-center` row, so its box is
 * centred while the text inside is not. On iOS a non-zero `line-height` (set by
 * the `text-sm` / `text-base` size utilities) bottom-aligns the glyphs against
 * the field height; zeroing it there re-centres them. Android needs the same
 * result via `textAlignVertical`, which has no CSS equivalent — so it is spelled
 * as the raw `text-align-vertical` property, which uniwind passes through to the
 * native style. Apply to single-line inputs only: a multiline field must keep
 * its line-height or its lines collapse.
 */
@utility input-vcenter {
  text-align-vertical: center;

  @variant ios {
    line-height: 0;
  }
}

/* ── Neutral tint ─────────────────────────────────────────────────────────
 *
 * `--neutral-hue` / `--neutral-chroma` document the tint baked into the
 * surface/foreground ladder (hue 270, chroma 0.004); the surface ladder values
 * in the theme blocks spell that tint out literally so uniwind resolves them on
 * native. They live in @layer base (plain custom properties, not @theme
 * utilities) so they are always emitted verbatim and stay overridable. Nothing
 * resolves them at runtime — a
 * var() inside oklch() never folds on native — so they are documentation, and
 * the input `npx rn-motion-ui-tokens` reads to retune the ramp.
 */
@layer base {
  :root {
    --neutral-hue: 270;
    --neutral-chroma: 0.004;

    /* Light-mode no-ops for the tokens that feed --shadow-elevated-N via var().
       They are re-declared in the @variant blocks below so that uniwind can
       extract per-theme maps, but those blocks live outside any @layer — which
       means Tailwind v4 fills the @theme layer with `unset` for anything it
       can't find a declaration for. These :root entries prevent that, keeping
       a reliable fallback for web regardless of which variant (if any) matches
       at a given moment. */
    --surface-hi-base: transparent;
    --surface-hi-high: transparent;
    --surface-ring-base: transparent;
    --surface-ring-high: transparent;
    --surface-rim-1: 0 0 transparent;
    --surface-rim-2: 0 0 transparent;
    --surface-rim-3: 0 0 transparent;
  }
}

/* ── Per-scheme values — @variant light / @variant dark ────────────────── */
/*
 * The @theme block above registers every token as a Tailwind design token and
 * carries the light values. The two blocks below restate the tokens that FLIP
 * with the scheme, once per scheme, via `@variant`.
 *
 * ## Why @variant, and not @media + .dark
 *
 * `@variant light` / `@variant dark` expand to uniwind's `@custom-variant`
 * definitions, which cover both switch mechanisms in one declaration:
 *
 *   &:where(.dark, .dark *)                          → a manual .dark class
 *   @media (prefers-color-scheme: dark) {             → the OS preference,
 *     &:not(:where(.light, .light *, .dark, .dark *)) }  suppressed by either class
 *
 * Web keeps the behaviour the previous hand-written pair of blocks
 * (`@media (prefers-color-scheme: dark) { :root:not(.light) }` plus a separate
 * `.dark`) gave it: a `.light` class is still an ABSOLUTE override that opts out
 * of OS dark, and `.dark` still forces dark over an OS-light preference. It also
 * gains a case the old form could not express — the class matches DESCENDANTS
 * (`.dark *`), so a subtree can be themed against the document, not just the
 * document root. Both selectors are `:where()`, i.e. specificity 0, so a theme
 * value never fights an author override.
 *
 * It is also the ONLY form that works on native. Uniwind resolves a token per
 * theme from `scopedVars['__uniwind-theme-<scheme>']`, and it fills that bucket
 * only for declarations whose selector carries `:where(.light|.dark, …)` — i.e.
 * only for `@variant`. Under the old form nothing landed there, so uniwind's
 * light and dark var maps were byte-identical and every surface rendered with
 * whichever block the bundler wrote last (dark), in both schemes.
 *
 * Both blocks must declare the SAME token set: uniwind logs one error per
 * missing token when they diverge (it does not fail the build).
 * scripts/check-token-parity.mjs enforces that, and that the light values here
 * agree with the @theme block and the native OKLCH tables.
 *
 * Dark surfaces: progressive lightness per ladder level, hue-270 tint at
 * chroma 0.004 throughout. Dark shadows: the 1px ring darkens as elevation
 * grows (set inline per level) and drop layers run denser than light mode so
 * they stay visible against the dark substrate.
 */

@variant dark {
  --color-surface-1: oklch(20.5% 0.004 270);
  --color-surface-2: oklch(23.5% 0.004 270);
  --color-surface-3: oklch(26.4% 0.004 270);
  --color-surface-hover: oklch(100% 0 0 / 0.04);
  --color-surface-selected: oklch(100% 0 0 / 0.08);
  --color-foreground: oklch(94% 0.004 270);
  --color-muted: oklch(28% 0.004 270);
  --color-muted-foreground: oklch(73% 0.004 270);
  --color-border: oklch(100% 0 0 / 0.1);
  --color-input: oklch(22% 0 0);
  --color-primary: oklch(95% 0.004 270);
  --color-primary-foreground: oklch(13% 0.004 270);
  --color-secondary: oklch(35% 0.004 270);
  --color-secondary-foreground: oklch(94% 0.004 270);
  --color-accent: oklch(31% 0.004 270);
  --color-accent-foreground: oklch(95% 0.004 270);
  --color-success: oklch(72% 0.18 155);
  --color-success-foreground: oklch(100% 0 0);
  --color-warning: oklch(58% 0.18 40);
  --color-warning-foreground: oklch(100% 0 0);
  --color-info: oklch(58% 0.18 255);
  --color-info-foreground: oklch(100% 0 0);
  --color-danger: oklch(66% 0.22 25);
  --color-danger-foreground: oklch(100% 0 0);

  /* Absolute colors — same value in both schemes, restated so both variant
     blocks stay a complete mirror of each other. */
  --color-white: oklch(100% 0 0);
  --color-black: oklch(0% 0 0);

  --color-background: oklch(0% 0 0);
  --color-glass: oklch(20% 0.004 270 / 0.5);

  --shadow-surface-1: 0 0 0 0 oklch(0% 0 0 / 0);
  --shadow-surface-2: 0 1px 1px -0.5px oklch(0% 0 0 / 0.18);
  --shadow-surface-3:
    0 0 0 1px oklch(0% 0 0 / 0.18), 0 1px 1px -0.5px oklch(0% 0 0 / 0.18), 0 3px 3px -1.5px oklch(0% 0 0 / 0.16),
    0 6px 6px -3px oklch(0% 0 0 / 0.16), 0 12px 12px -6px oklch(0% 0 0 / 0.14), 0 24px 24px -12px oklch(0% 0 0 / 0.14);

  /* Rim highlight (top edge) and ring (full perimeter). Both step up with
     elevation and feed the inset --surface-rim-N recipe below. */
  --surface-hi-base: oklch(1 0 0 / 0.01);
  --surface-hi-high: oklch(1 0 0 / 0.04);
  --surface-ring-base: oklch(1 0 0 / 0.02);
  --surface-ring-high: oklch(1 0 0 / 0.06);

  /* Inset portion of the dark elevation recipe — the rim highlight + ring that
     would otherwise sit above opaque children via an ::after pseudo-element. RN
     has no pseudo-elements, so --shadow-elevated-N composites this rim in front
     of the drop layers within one box-shadow instead. */
  --surface-rim-1: inset 0 0 0 1px var(--surface-ring-base);
  --surface-rim-2: inset 0 1px 0 0 var(--surface-hi-base), inset 0 0 0 1px var(--surface-ring-base);
  --surface-rim-3: inset 0 1px 0 0 var(--surface-hi-high), inset 0 0 0 1px var(--surface-ring-high);
}

/* ── Light mode — the scoped mirror of the @theme defaults ────────────────
 *
 * The same values as the @theme block above, restated as a theme variant.
 * @theme registers the tokens (so `bg-surface-3` exists) and supplies the
 * unscoped fallback; this block is what makes light an ADDRESSABLE theme
 * rather than just the absence of dark.
 *
 * It is not redundant: uniwind derives its per-theme variable maps solely from
 * `@variant` blocks, and expects every theme to declare the same variable set. A
 * token present in `dark` but not `light` does not fail the build — it logs one
 * error per missing token and then resolves to the unscoped `@theme` value in
 * the theme that lacks it, which reads as "this token ignores the toggle". Keep
 * the three blocks (@theme, @variant light, @variant dark) in agreement;
 * scripts/check-token-parity.mjs enforces it.
 */

@variant light {
  --color-surface-1: oklch(97% 0 0);
  --color-surface-2: oklch(98.5% 0 0);
  --color-surface-3: oklch(100% 0 0);
  --color-surface-hover: oklch(0% 0 0 / 0.04);
  --color-surface-selected: oklch(0% 0 0 / 0.08);
  --color-foreground: oklch(18% 0.004 270);
  --color-muted: oklch(90% 0 0);
  --color-muted-foreground: oklch(50% 0.004 270);
  --color-border: oklch(0% 0 0 / 0.1);
  --color-input: oklch(100% 0 0);
  --color-primary: oklch(22% 0 0);
  --color-primary-foreground: oklch(98% 0.002 270);
  --color-secondary: oklch(92% 0 0);
  --color-secondary-foreground: oklch(32% 0.004 270);
  --color-accent: oklch(91% 0 0);
  --color-accent-foreground: oklch(22% 0.004 270);
  --color-success: oklch(70% 0.18 155);
  --color-success-foreground: oklch(100% 0 0);
  --color-warning: oklch(58% 0.18 40);
  --color-warning-foreground: oklch(100% 0 0);
  --color-info: oklch(58% 0.18 255);
  --color-info-foreground: oklch(100% 0 0);
  --color-danger: oklch(62% 0.22 25);
  --color-danger-foreground: oklch(100% 0 0);

  /* Absolute colors — same value in both schemes, restated so all three
     declarations stay a complete mirror of one another. */
  --color-white: oklch(100% 0 0);
  --color-black: oklch(0% 0 0);

  --color-background: oklch(95% 0.004 270);
  --color-glass: oklch(99% 0 0 / 0.6);

  --shadow-surface-1: 0 0 0 1px oklch(0% 0 0 / 0.06);
  --shadow-surface-2: 0 0 0 1px oklch(0% 0 0 / 0.06), 0 1px 1px -0.5px oklch(0% 0 0 / 0.06);
  --shadow-surface-3:
    0 0 0 1px oklch(0% 0 0 / 0.06), 0 1px 1px -0.5px oklch(0% 0 0 / 0.06), 0 3px 3px -1.5px oklch(0% 0 0 / 0.05),
    0 6px 6px -3px oklch(0% 0 0 / 0.05), 0 12px 12px -6px oklch(0% 0 0 / 0.04), 0 24px 24px -12px oklch(0% 0 0 / 0.04);

  /* Light mode has no rim — the outer rings alone carry elevation. Declared as
     fully transparent (rather than omitted) because every theme must define the
     same variable set, and because --shadow-elevated-N composites them
     unconditionally. */
  --surface-hi-base: transparent;
  --surface-hi-high: transparent;
  --surface-ring-base: transparent;
  --surface-ring-high: transparent;

  --surface-rim-1: 0 0 transparent;
  --surface-rim-2: 0 0 transparent;
  --surface-rim-3: 0 0 transparent;
}
