Design tokens
Every colour, size, weight, radius, shadow, and duration that ties the system together. Tokens are CSS variables — override any of them in @theme and every component picks up the change.
Naming convention
Every token is prefixed with its category —
--color-*, --font-*, --radius-*, --shadow-*, --duration-*. Semantic tokens (background, foreground, muted) reference the primitives below.Brand palette
Aidash blue. The 500 step is the default; 600 for hover, 400 for dark mode.
| Token | Value | Usage |
|---|---|---|
| --color-brand-50 | oklch(0.97 0.01 250) | Backdrop tint |
| --color-brand-100 | oklch(0.93 0.04 250) | Ghost button hover |
| --color-brand-200 | oklch(0.87 0.08 250) | — |
| --color-brand-300 | oklch(0.78 0.13 250) | Disabled primary |
| --color-brand-400 | oklch(0.68 0.17 252) | Dark-mode primary |
| --color-brand-500 | oklch(0.62 0.20 255) | Default primary |
| --color-brand-600 | oklch(0.54 0.20 255) | Primary hover |
| --color-brand-700 | oklch(0.46 0.18 255) | Primary active |
| --color-brand-800 | oklch(0.38 0.15 255) | — |
| --color-brand-900 | oklch(0.30 0.12 255) | Deep backgrounds |
Semantic colours
Names components reference at runtime. Each has a light-mode and a dark-mode value.
| Token | Value | Usage |
|---|---|---|
| --background | light: oklch(1 0 0) · dark: oklch(0.145 0 0) | Page background |
| --foreground | light: oklch(0.145 0 0) · dark: oklch(0.985 0 0) | Primary text |
| --card | light: oklch(1 0 0) · dark: oklch(0.18 0 0) | Card surface |
| --card-foreground | light: oklch(0.145 0 0) · dark: oklch(0.985 0 0) | Text on cards |
| --muted | light: oklch(0.97 0 0) · dark: oklch(0.22 0 0) | Subtle surfaces / hover |
| --muted-foreground | light: oklch(0.556 0 0) · dark: oklch(0.68 0 0) | Secondary text |
| --border | light: oklch(0.92 0 0) · dark: oklch(0.26 0 0) | Hairline borders |
| --input | light: oklch(0.925 0 0) · dark: oklch(0.28 0 0) | Form input borders |
| --ring | var(--color-brand-500) | Focus ring |
| --primary | var(--color-brand-500) | Primary CTA background |
| --primary-foreground | oklch(0.985 0 0) | Text on primary |
| --destructive | var(--color-danger-500) | Destructive actions |
Typography
Font families.
| Token | Value | Usage |
|---|---|---|
| --font-body | Inter, ui-sans-serif, system-ui | Default UI font |
| --font-display | Inter, ui-sans-serif, system-ui | Headings |
| --font-mono | JetBrains Mono, ui-monospace | Code, kbd, terminals |
Radius
Corner rounding steps. Fully round shapes like chips and avatars use rounded-full and ignore these tokens.
| Token | Value | Usage |
|---|---|---|
| --radius-sm | 4px | Unused by components — free for your own UI |
| --radius-md | 6px | Kbd, menu items, table cells, small controls |
| --radius-lg | 8px | Buttons, inputs, tooltips, alerts — the default step |
| --radius-xl | 12px | Cards, modals, popovers, panels |
Shadows
Elevation levels.
| Token | Value | Usage |
|---|---|---|
| --shadow-card | 0 1px 2px rgba(0,0,0,0.04) | Card resting |
| --shadow-card-hover | 0 2px 6px rgba(0,0,0,0.06) | Card hover |
| --shadow-glow | 0 0 12px oklch(0.62 0.14 255 / 0.12) | Brand halo |
Motion
Easing and duration tokens.
| Token | Value | Usage |
|---|---|---|
| --ease-standard | cubic-bezier(0.2, 0, 0, 1) | Standard transitions |
| --ease-spring | cubic-bezier(0.25, 1.2, 0.4, 1) | Spring/bounce effects |
| --duration-fast | 120ms | Micro-interactions |
| --duration-base | 180ms | Default transitions |
| --duration-slow | 280ms | Complex transitions |
Complete source
The full token block. Drop it into app/globals.css and you're done.
app/globals.css
css
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--color-brand-50: oklch(0.97 0.01 250);
--color-brand-100: oklch(0.93 0.04 250);
--color-brand-200: oklch(0.87 0.08 250);
--color-brand-300: oklch(0.78 0.13 250);
--color-brand-400: oklch(0.68 0.17 252);
--color-brand-500: oklch(0.62 0.20 255);
--color-brand-600: oklch(0.54 0.20 255);
--color-brand-700: oklch(0.46 0.18 255);
--color-brand-800: oklch(0.38 0.15 255);
--color-brand-900: oklch(0.30 0.12 255);
--color-success: oklch(0.70 0.17 150);
--color-warn: oklch(0.78 0.16 80);
--color-danger: oklch(0.65 0.22 25);
--font-body: "Inter", ui-sans-serif, system-ui, sans-serif;
--font-display: "Inter", ui-sans-serif, system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
--shadow-card: 0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-card-hover: 0 2px 6px rgba(0, 0, 0, 0.06);
--shadow-glow: 0 0 12px oklch(0.62 0.14 255 / 0.12);
--ease-standard: cubic-bezier(0.2, 0, 0, 1);
--ease-spring: cubic-bezier(0.25, 1.2, 0.4, 1);
--duration-fast: 120ms;
--duration-base: 180ms;
--duration-slow: 280ms;
}
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--border: oklch(0.92 0 0);
--input: oklch(0.925 0 0);
--primary: var(--color-brand-500);
--primary-foreground: oklch(0.985 0 0);
--destructive: var(--color-danger);
--ring: var(--color-brand-500);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.18 0 0);
--card-foreground: oklch(0.985 0 0);
--muted: oklch(0.22 0 0);
--muted-foreground: oklch(0.68 0 0);
--border: oklch(0.26 0 0);
--input: oklch(0.28 0 0);
--primary: var(--color-brand-400);
--primary-foreground: oklch(0.145 0 0);
--destructive: var(--color-danger);
--ring: var(--color-brand-400);
}Also see
Deeper dives into individual token families.