:root { /* Color primitives */ --color-neutral-0: oklch(100% 0 0); --color-neutral-50: oklch(98.4% 0 0); --color-neutral-100: oklch(96.8% 0 0); --color-neutral-150: oklch(93% 0.004 257); --color-neutral-200: oklch(92.9% 0 0); --color-neutral-300: oklch(86.9% 0 0); --color-neutral-400: oklch(70.4% 0 0); --color-neutral-500: oklch(55.4% 0 0); --color-neutral-600: oklch(44.6% 0 0); --color-neutral-700: oklch(34% 0.014 257); --color-neutral-800: oklch(26% 0.012 257); --color-neutral-900: oklch(20% 0.01 257); --color-neutral-950: oklch(14% 0.008 257); --color-neutral-1000: oklch(0% 0 0); /* Dark surface primitives: purpose-built for dark theme surface hierarchy. Consumers remap these to control dark theme surfaces independently of the light-mode neutral scale. */ --color-neutral-dark-base: oklch(30% 0.012 257); --color-neutral-dark-subtle: oklch(36% 0.014 257); --color-neutral-dark-muted: oklch(38% 0.016 257); --color-neutral-dark-border: oklch(46% 0.016 257); --color-neutral-dark-input: oklch(26% 0.012 257); --color-neutral-dark-input-readonly: oklch(27% 0.012 257); /* Slate accent: hue 257, low chroma */ --color-accent-100: oklch(96.8% 0.007 257); --color-accent-200: oklch(92.9% 0.013 257); --color-accent-300: oklch(86.9% 0.022 257); --color-accent-400: oklch(70.4% 0.04 257); --color-accent-460: oklch(60% 0.055 257); --color-accent-480: oklch(52% 0.05 257); --color-accent-500: oklch(44% 0.043 257); --color-accent-600: oklch(37.2% 0.044 257); --color-accent-700: oklch(27.9% 0.041 257); --color-accent-800: oklch(20.8% 0.042 257); /* Feedback color primitives: numeric scale per category. Steps 100-600: lightest to darkest, matching accent scale pattern. Light semantic tokens reference 100 (bg), 300 (base/border), 500 (text). Dark semantic tokens reference 200 (text), 300 (base), 400 (border), 600 (bg). */ --color-success-100: oklch(94% 0.08 145); --color-success-200: oklch(75% 0.16 145); --color-success-250: oklch(58% 0.16 145); /* Dark-mode filled surface. n950-on: 5.04:1, passes AA. */ --color-success-300: oklch(52% 0.18 145); --color-success-400: oklch(40% 0.14 145); --color-success-500: oklch(38% 0.16 145); --color-success-600: oklch(20% 0.06 145); --color-warning-100: oklch(95% 0.1 85); --color-warning-200: oklch(82% 0.18 85); --color-warning-300: oklch(72% 0.22 85); --color-warning-400: oklch(55% 0.18 85); --color-warning-500: oklch(48% 0.18 85); --color-warning-600: oklch(20% 0.06 85); --color-danger-100: oklch(95% 0.06 15); --color-danger-200: oklch(75% 0.18 15); --color-danger-250: oklch(60% 0.2 15); /* Dark-mode filled surface. n950-on: 4.59:1, passes AA. */ --color-danger-300: oklch(56% 0.22 15); --color-danger-400: oklch(50% 0.18 15); --color-danger-500: oklch(42% 0.2 15); --color-danger-600: oklch(20% 0.05 15); --color-info-100: oklch(94% 0.06 230); --color-info-200: oklch(75% 0.16 230); --color-info-300: oklch(53% 0.18 230); /* Darkened from 55% for white-on contrast: 4.69:1, passes AA. */ --color-info-400: oklch(48% 0.14 230); --color-info-500: oklch(40% 0.16 230); --color-info-600: oklch(18% 0.05 230); /* Space primitives */ --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem; --space-5: 1.25rem; --space-6: 1.5rem; --space-8: 2rem; --space-10: 2.5rem; --space-12: 3rem; --space-16: 4rem; --space-24: 6rem; --space-32: 8rem; /* Shadow primitives */ --shadow-sm: 0 1px 3px oklch(0% 0 0 / 0.1), 0 1px 2px oklch(0% 0 0 / 0.06); --shadow-md: 0 4px 6px oklch(0% 0 0 / 0.1), 0 2px 4px oklch(0% 0 0 / 0.06); --shadow-lg: 0 10px 15px oklch(0% 0 0 / 0.1), 0 4px 6px oklch(0% 0 0 / 0.05); --shadow-sm-dark: 0 1px 3px oklch(0% 0 0 / 0.4), 0 1px 2px oklch(0% 0 0 / 0.24); --shadow-md-dark: 0 4px 6px oklch(0% 0 0 / 0.4), 0 2px 4px oklch(0% 0 0 / 0.24); --shadow-lg-dark: 0 10px 15px oklch(0% 0 0 / 0.5), 0 4px 6px oklch(0% 0 0 / 0.3); /* Z-index primitives */ --z-header: 10; --z-dropdown: 50; --z-modal: 100; --z-toast: 150; /* Radius primitives */ --radius-none: 0; --radius-sm: 0.25rem; --radius-md: 0.375rem; --radius-lg: 0.5rem; --radius-xl: 0.75rem; --radius-2xl: 1rem; --radius-full: 9999px; /* Duration primitives */ --duration-fast: 100ms; --duration-base: 200ms; --duration-slow: 300ms; --duration-deliberate: 500ms; /* Typography primitives */ --font-size-xs: 0.75rem; --font-size-sm: 0.875rem; --font-size-md: 1rem; --font-size-lg: 1.125rem; --font-size-xl: 1.25rem; --font-size-2xl: 1.5rem; --font-size-3xl: 1.875rem; --font-size-4xl: 2.25rem; --line-height-tight: 1.25; --line-height-snug: 1.375; --line-height-normal: 1.5; --line-height-relaxed: 1.625; --font-weight-thin: 100; --font-weight-extralight: 200; --font-weight-light: 300; --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; --font-weight-extrabold: 800; --font-weight-black: 900; --font-family-sans: ui-sans-serif, system-ui, -apple-system, sans-serif; --font-family-serif: ui-serif, Georgia, Cambria, serif; --font-family-mono: ui-monospace, "SFMono-Regular", Menlo, monospace; } /* Semantic tokens: light theme */ :root, [data-theme="light"] { /* Surfaces */ --nuka-bg-base: var(--color-neutral-0); --nuka-bg-subtle: var(--color-neutral-50); --nuka-bg-muted: var(--color-neutral-100); --nuka-bg-emphasis: var(--color-neutral-900); /* Borders */ --nuka-border-base: var(--color-neutral-200); --nuka-border-strong: var(--color-neutral-400); --nuka-border-focus: var(--color-accent-500); /* Text */ --nuka-text-base: var(--color-neutral-900); --nuka-text-muted: var(--color-neutral-600); --nuka-text-subtle: var(--color-neutral-400); --nuka-text-inverse: var(--color-neutral-0); --nuka-text-disabled: var(--color-neutral-300); /* Accent */ --nuka-accent-bg: var(--color-accent-500); --nuka-accent-bg-hover: var(--color-accent-600); --nuka-accent-bg-active: var(--color-accent-700); --nuka-accent-bg-subtle: var(--color-accent-100); --nuka-accent-border: var(--color-accent-400); --nuka-accent-text: var(--color-accent-500); /* * NOTE: --nuka-accent-text uses accent-500 (#43546a) on neutral-0 (white). * Contrast: 7.74:1, passes AAA. Safe to use for any text size. */ --nuka-accent-fg: var(--color-neutral-0); /* Foreground for content on --nuka-accent-bg. Override independently of --nuka-text-inverse when the accent color is customized. 7.74:1 on accent-500. */ --nuka-accent-bg-disabled: var(--color-neutral-200); /* Borders */ --nuka-border-disabled: var(--color-neutral-200); /* Shadows */ --nuka-shadow-card: var(--shadow-sm); --nuka-shadow-overlay: var(--shadow-md); --nuka-shadow-modal: var(--shadow-lg); /* Z-index */ --nuka-z-header: var(--z-header); --nuka-z-dropdown: var(--z-dropdown); --nuka-z-modal: var(--z-modal); --nuka-z-toast: var(--z-toast); /* Font family */ --nuka-font-heading: var(--font-family-serif); --nuka-font-body: var(--font-family-sans); --nuka-font-ui: var(--font-family-sans); --nuka-font-code: var(--font-family-mono); /* Overlay */ /* No matching primitive: alpha-composite value, not a scale step. 0.5 opacity is intentional for both themes. Consumer-overridable if dark mode needs higher opacity for visual weight. */ --nuka-bg-overlay: oklch(0% 0 0 / 0.5); /* Duration */ --nuka-duration-fast: var(--duration-fast); --nuka-duration-base: var(--duration-base); --nuka-duration-slow: var(--duration-slow); --nuka-duration-deliberate: var(--duration-deliberate); /* Input surfaces */ --nuka-input-bg: var(--color-neutral-0); --nuka-input-bg-disabled: var(--color-neutral-100); --nuka-input-bg-readonly: var(--color-neutral-50); /* Input borders */ --nuka-input-border: var(--color-neutral-300); --nuka-input-border-hover: var(--color-neutral-400); /* Scrollbar */ --nuka-scroll-thumb: var(--color-neutral-400); --nuka-scroll-track: var(--color-neutral-100); /* Feedback */ --nuka-success-base: var(--color-success-300); --nuka-success-bg: var(--color-success-100); --nuka-success-text: var(--color-success-500); --nuka-success-border: var(--color-success-300); --nuka-success-fg: var(--color-neutral-0); /* 5.51:1 on success-base (success-300). White on filled success surfaces. */ --nuka-warning-base: var(--color-warning-300); --nuka-warning-fg: var(--color-neutral-900); /* Warning hue cannot pass 4.5:1 with white text at amber lightness. Dark foreground on warning surfaces. 7.11:1 on warning-300. */ --nuka-warning-bg: var(--color-warning-100); --nuka-warning-text: var(--color-warning-500); --nuka-warning-border: var(--color-warning-400); --nuka-danger-base: var(--color-danger-300); --nuka-danger-bg: var(--color-danger-100); --nuka-danger-text: var(--color-danger-500); --nuka-danger-border: var(--color-danger-300); --nuka-danger-fg: var(--color-neutral-0); /* 4.65:1 on danger-base (danger-300). White on filled danger surfaces. */ --nuka-info-base: var(--color-info-300); --nuka-info-bg: var(--color-info-100); --nuka-info-text: var(--color-info-500); --nuka-info-border: var(--color-info-300); --nuka-info-fg: var(--color-neutral-0); /* 4.69:1 on info-base (info-300). White on filled info surface. */ } /* Semantic tokens: dark theme */ [data-theme="dark"] { /* Surfaces */ --nuka-bg-base: var(--color-neutral-dark-base); --nuka-bg-subtle: var(--color-neutral-dark-subtle); --nuka-bg-muted: var(--color-neutral-dark-muted); --nuka-bg-emphasis: var(--color-neutral-0); /* Borders */ --nuka-border-base: var(--color-neutral-dark-border); --nuka-border-strong: var(--color-neutral-500); --nuka-border-focus: var(--color-accent-400); /* Text */ --nuka-text-base: var(--color-neutral-150); --nuka-text-muted: oklch( 68% 0.01 257 ); /* dark-only: trace tint for color temperature consistency */ --nuka-text-subtle: oklch( 46% 0.01 257 ); /* dark-only: trace tint for color temperature consistency */ --nuka-text-inverse: var(--color-neutral-950); --nuka-text-disabled: oklch( 50% 0.01 257 ); /* dark-only: visible but subdued */ /* Accent */ --nuka-accent-bg: var(--color-accent-500); --nuka-accent-bg-hover: var(--color-accent-480); --nuka-accent-bg-active: var(--color-accent-460); --nuka-accent-bg-subtle: oklch( 35% 0.02 257 ); /* dark-only: sits above bg-base */ --nuka-accent-border: var(--color-accent-400); --nuka-accent-text: var(--color-accent-300); /* * NOTE: --nuka-accent-text uses accent-300 in dark mode. * Verified: 6.74:1 minimum (on bg-muted at 38% L). Passes AA. */ --nuka-accent-fg: var(--color-neutral-0); --nuka-accent-bg-disabled: var(--color-neutral-700); /* Borders */ --nuka-border-disabled: var(--color-neutral-700); /* Shadows */ --nuka-shadow-card: var(--shadow-sm-dark); --nuka-shadow-overlay: var(--shadow-md-dark); --nuka-shadow-modal: var(--shadow-lg-dark); /* Overlay */ --nuka-bg-overlay: oklch(0% 0 0 / 0.72); /* Input surfaces */ --nuka-input-bg: var(--color-neutral-dark-input); --nuka-input-bg-disabled: var(--color-neutral-800); --nuka-input-bg-readonly: var(--color-neutral-dark-input-readonly); /* Input borders */ --nuka-input-border: var(--color-neutral-700); --nuka-input-border-hover: var(--color-neutral-500); /* Scrollbar */ --nuka-scroll-thumb: var(--color-neutral-dark-border); --nuka-scroll-track: var(--color-neutral-dark-subtle); /* Feedback */ --nuka-success-base: var(--color-success-250); --nuka-success-bg: var(--color-success-600); --nuka-success-text: var(--color-success-200); --nuka-success-border: var(--color-success-300); --nuka-success-fg: var(--color-neutral-950); /* 4.65:1 on success-base (success-250). Dark fg on lighter dark-mode surface. */ --nuka-warning-base: var(--color-warning-300); --nuka-warning-fg: var(--color-neutral-900); /* 7.30:1 on warning-base (warning-300). Only valid on warning-base, not warning-bg. See variants.ts for actual pairings. */ --nuka-warning-bg: var(--color-warning-600); --nuka-warning-text: var(--color-warning-200); --nuka-warning-border: var(--color-warning-400); --nuka-danger-base: var(--color-danger-250); --nuka-danger-bg: var(--color-danger-600); --nuka-danger-text: var(--color-danger-200); --nuka-danger-border: var(--color-danger-400); --nuka-danger-fg: var(--color-neutral-950); /* 5.04:1 on danger-base (danger-250). Dark fg on lighter dark-mode surface. */ --nuka-info-base: var(--color-info-300); --nuka-info-bg: var(--color-info-600); --nuka-info-text: var(--color-info-200); --nuka-info-border: var(--color-info-400); --nuka-info-fg: var(--color-neutral-950); /* Dark fg on lighter dark-mode info surface. Symmetric with danger/success/warning. */ } /* Surface-level overrides: redefine focus ring for inverse surfaces inside each theme scope. The descendant selector (0,2,0) wins over the theme rule (0,1,0) when a [data-surface="inverse"] descendant is inside a themed subtree. See ADR-050 for the reasoning and the contrast ratios below. */ [data-theme="light"] [data-surface="inverse"], :root [data-surface="inverse"] { /* accent-400 on neutral-900: ~6.9:1, passes WCAG 2.2 AA 3:1 for UI components */ --nuka-border-focus: var(--color-accent-400); } [data-theme="dark"] [data-surface="inverse"] { /* accent-500 on neutral-0: ~7.8:1, passes WCAG 2.2 AA 3:1 for UI components */ --nuka-border-focus: var(--color-accent-500); }