@deepfuture/dui-theme-default 0.0.2 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +9 -1
  2. package/components/accordion-item.js +11 -10
  3. package/components/alert-dialog-popup.js +9 -17
  4. package/components/avatar.js +2 -2
  5. package/components/badge.js +55 -29
  6. package/components/breadcrumb-ellipsis.js +1 -1
  7. package/components/breadcrumb-link.js +2 -2
  8. package/components/breadcrumb-page.js +1 -1
  9. package/components/breadcrumb-separator.js +1 -1
  10. package/components/breadcrumb.js +3 -2
  11. package/components/button.js +88 -51
  12. package/components/calendar.js +24 -21
  13. package/components/checkbox-group.js +1 -1
  14. package/components/checkbox.js +10 -9
  15. package/components/collapsible.js +11 -10
  16. package/components/combobox.js +65 -19
  17. package/components/command-empty.js +3 -2
  18. package/components/command-group.js +3 -2
  19. package/components/command-input.js +4 -3
  20. package/components/command-item.js +6 -5
  21. package/components/command-list.js +1 -1
  22. package/components/command-separator.js +1 -1
  23. package/components/command-shortcut.js +3 -2
  24. package/components/command.js +2 -2
  25. package/components/data-table.js +20 -19
  26. package/components/dialog-popup.js +9 -17
  27. package/components/dropzone.js +10 -9
  28. package/components/input.js +13 -12
  29. package/components/menu-item.js +11 -9
  30. package/components/menu.js +19 -1
  31. package/components/number-field.js +13 -11
  32. package/components/popover-popup.js +25 -1
  33. package/components/preview-card-popup.js +26 -1
  34. package/components/progress.js +2 -2
  35. package/components/radio.js +11 -10
  36. package/components/scroll-area.js +9 -9
  37. package/components/select.js +62 -10
  38. package/components/sidebar-group-label.js +2 -2
  39. package/components/sidebar-menu-button.js +6 -14
  40. package/components/sidebar-provider.js +6 -14
  41. package/components/sidebar.js +1 -1
  42. package/components/slider.js +8 -7
  43. package/components/switch.js +12 -11
  44. package/components/tab.js +10 -9
  45. package/components/tabs-indicator.js +3 -3
  46. package/components/tabs-panel.js +3 -2
  47. package/components/textarea.js +11 -10
  48. package/components/toggle-group.js +0 -1
  49. package/components/toggle.js +28 -11
  50. package/components/tooltip-popup.js +29 -1
  51. package/components/trunc.js +3 -3
  52. package/index.d.ts +4 -0
  53. package/index.js +6 -0
  54. package/package.json +14 -2
  55. package/prose.d.ts +2 -0
  56. package/prose.js +4 -0
  57. package/tokens-raw.js +1 -1
  58. package/tokens.css +95 -72
  59. package/tokens.js +3 -2
  60. package/types.d.ts +18 -0
  61. package/types.js +8 -0
  62. package/typography.d.ts +104 -0
  63. package/typography.js +103 -0
package/components/tab.js CHANGED
@@ -1,34 +1,35 @@
1
1
  import { css } from "lit";
2
+ import { type } from "../typography.js";
2
3
  export const tabStyles = css `
3
4
  [part="tab"] {
4
- color: var(--muted-foreground);
5
- font-size: var(--font-size-sm);
6
- line-height: var(--line-height-snug);
5
+ color: var(--text-2);
6
+ ${type("sm", { lineHeight: "var(--line-height-snug)" })}
7
7
  font-weight: var(--font-weight-medium);
8
8
  padding-inline: var(--space-2);
9
- height: 2rem;
9
+ height: var(--component-height-md);
10
+ transition-property: color, box-shadow, background, filter, transform;
10
11
  transition-duration: var(--duration-fast);
11
12
  }
12
13
 
13
14
  [part="tab"][data-active] {
14
- color: var(--foreground);
15
+ color: var(--text-1);
15
16
  }
16
17
 
17
18
  @media (hover: hover) {
18
19
  [part="tab"]:hover:not([data-disabled]) {
19
- color: var(--foreground);
20
+ color: var(--text-1);
20
21
  }
21
22
  }
22
23
 
23
24
  [part="tab"]:focus-visible {
24
25
  box-shadow:
25
- 0 0 0 var(--space-0_5) var(--background),
26
- 0 0 0 var(--space-1) var(--ring);
26
+ 0 0 0 var(--focus-ring-offset) var(--background),
27
+ 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);
27
28
  border-radius: var(--radius-sm);
28
29
  z-index: 1;
29
30
  }
30
31
 
31
32
  [part="tab"][data-disabled] {
32
- opacity: 0.5;
33
+ opacity: 0.4;
33
34
  }
34
35
  `;
@@ -1,10 +1,10 @@
1
1
  import { css } from "lit";
2
2
  export const tabsIndicatorStyles = css `
3
3
  :host {
4
- height: 1.5rem;
4
+ height: var(--space-6);
5
5
  border-radius: var(--radius-sm);
6
- background: var(--input);
7
- transition-duration: 200ms;
6
+ background: oklch(from var(--foreground) l c h / 0.08);
7
+ transition-duration: var(--duration-normal);
8
8
  transition-timing-function: var(--ease-in-out-3);
9
9
  }
10
10
  `;
@@ -1,13 +1,14 @@
1
1
  import { css } from "lit";
2
2
  export const tabsPanelStyles = css `
3
3
  [part="panel"] {
4
+ transition-property: box-shadow;
4
5
  transition-duration: var(--duration-fast);
5
6
  }
6
7
 
7
8
  [part="panel"]:focus-visible {
8
9
  box-shadow:
9
- 0 0 0 var(--space-0_5) var(--background),
10
- 0 0 0 var(--space-1) var(--ring);
10
+ 0 0 0 var(--focus-ring-offset) var(--background),
11
+ 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);
11
12
  border-radius: var(--radius-md);
12
13
  }
13
14
  `;
@@ -9,10 +9,11 @@ export const textareaStyles = css `
9
9
  font-family: var(--font-sans);
10
10
  font-size: var(--font-size);
11
11
  line-height: var(--line-height-snug);
12
- color: var(--foreground);
13
- border: var(--border-width-thin) solid var(--input);
14
- background: var(--input-bg);
12
+ color: var(--text-1);
13
+ border: var(--border-width-thin) solid var(--border);
14
+ background: var(--sunken);
15
15
  border-radius: var(--radius-md);
16
+ transition-property: border-color, box-shadow, background, filter, transform;
16
17
  transition-duration: var(--duration-fast);
17
18
  }
18
19
 
@@ -23,7 +24,7 @@ export const textareaStyles = css `
23
24
  /* Scrollbar */
24
25
  [part="textarea"] {
25
26
  scrollbar-width: thin;
26
- scrollbar-color: color-mix(in srgb, var(--muted-foreground) 50%, transparent) transparent;
27
+ scrollbar-color: color-mix(in srgb, var(--text-2) 50%, transparent) transparent;
27
28
  }
28
29
 
29
30
  [part="textarea"]::-webkit-scrollbar {
@@ -35,28 +36,28 @@ export const textareaStyles = css `
35
36
  }
36
37
 
37
38
  [part="textarea"]::-webkit-scrollbar-thumb {
38
- background: color-mix(in srgb, var(--muted-foreground) 50%, transparent);
39
+ background: color-mix(in srgb, var(--text-2) 50%, transparent);
39
40
  border-radius: var(--radius-sm);
40
41
  border: 0.125rem solid transparent;
41
42
  background-clip: padding-box;
42
43
  }
43
44
 
44
45
  [part="textarea"]::-webkit-scrollbar-thumb:hover {
45
- background: color-mix(in srgb, var(--muted-foreground) 70%, transparent);
46
+ background: color-mix(in srgb, var(--text-2) 70%, transparent);
46
47
  }
47
48
 
48
49
  [part="textarea"]::placeholder {
49
- color: var(--muted-foreground);
50
+ color: var(--text-3);
50
51
  }
51
52
 
52
53
  [part="textarea"]:focus-visible {
53
54
  box-shadow:
54
- 0 0 0 var(--space-0_5) var(--background),
55
- 0 0 0 var(--space-1) var(--ring);
55
+ 0 0 0 var(--focus-ring-offset) var(--background),
56
+ 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);
56
57
  }
57
58
 
58
59
  [part="textarea"]:disabled {
59
- opacity: 0.5;
60
+ opacity: 0.4;
60
61
  }
61
62
 
62
63
  [part="textarea"][data-invalid] {
@@ -3,7 +3,6 @@ export const toggleGroupStyles = css `
3
3
  [part="root"] {
4
4
  gap: var(--space-1);
5
5
  border-radius: var(--radius-md);
6
- background: var(--muted);
7
6
  padding: var(--space-0_5);
8
7
  }
9
8
  `;
@@ -1,34 +1,51 @@
1
1
  import { css } from "lit";
2
+ import { type } from "../typography.js";
2
3
  export const toggleStyles = css `
4
+ /* --_select / --_interact alpha overlay pattern */
5
+
3
6
  [part="root"] {
4
- height: var(--space-9);
7
+ --_select: 0;
8
+ --_interact: 0;
9
+ --toggle-gap: var(--space-1_5);
10
+ --icon-size: var(--space-4);
11
+ --icon-color: currentColor;
12
+ height: var(--component-height-md);
5
13
  padding: 0 var(--space-2_5);
6
14
  border-radius: var(--radius-md);
7
- font-size: var(--font-size-sm);
15
+ border: var(--border-width-thin) solid var(--border);
16
+ ${type("sm")}
8
17
  font-weight: var(--font-weight-medium);
9
- color: var(--muted-foreground);
10
- transition-property: background, color;
18
+ color: var(--text-2);
19
+ background: oklch(from var(--foreground) l c h / calc(var(--_select) + var(--_interact)));
20
+ transition-property: background, color, box-shadow;
11
21
  transition-duration: var(--duration-fast);
22
+ min-width: var(--component-height-md);
12
23
  }
13
24
 
14
25
  @media (hover: hover) {
15
26
  [part="root"]:hover:not(:disabled):not([data-pressed]) {
16
- background: var(--muted);
17
- color: var(--foreground);
27
+ --_interact: 0.05;
28
+ color: var(--text-1);
18
29
  }
19
30
  }
20
31
 
21
32
  [part="root"][data-pressed] {
22
- background: var(--secondary);
23
- color: var(--foreground);
33
+ --_select: 0.10;
34
+ color: var(--text-1);
35
+ }
36
+
37
+ [part="root"]:active:not(:disabled) {
38
+ --_interact: 0.10;
24
39
  }
25
40
 
26
41
  [part="root"]:focus-visible {
27
- outline: 2px solid var(--ring);
28
- outline-offset: 2px;
42
+ outline: none;
43
+ box-shadow:
44
+ 0 0 0 var(--focus-ring-offset) var(--background),
45
+ 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);
29
46
  }
30
47
 
31
48
  [part="root"]:disabled {
32
- opacity: 0.5;
49
+ opacity: 0.4;
33
50
  }
34
51
  `;
@@ -1,2 +1,30 @@
1
1
  import { css } from "lit";
2
- export const tooltipPopupStyles = css ``;
2
+ import { type } from "../typography.js";
3
+ export const tooltipPopupStyles = css `
4
+ .Popup {
5
+ padding: var(--space-0_5) var(--space-1_5);
6
+ border-radius: var(--radius-sm);
7
+ background: color-mix(
8
+ in oklch,
9
+ var(--foreground) 90%,
10
+ oklch(0 0 0 / 0)
11
+ );
12
+ backdrop-filter: var(--filter-blur-sm);
13
+ color: var(--background);
14
+ font-family: var(--font-sans);
15
+ ${type("xs", { lineHeight: "var(--line-height-snug)" })}
16
+ box-shadow: var(--shadow-sm);
17
+ max-width: var(--space-80);
18
+ transition-duration: var(--duration-fastest);
19
+ transition-timing-function: var(--ease-out-3);
20
+ }
21
+
22
+ .Arrow .arrow-fill {
23
+ fill: color-mix(in oklch, var(--foreground) 90%, oklch(0 0 0 / 0));
24
+ }
25
+
26
+ .Arrow .arrow-stroke {
27
+ fill: none;
28
+ stroke: none;
29
+ }
30
+ `;
@@ -1,9 +1,9 @@
1
1
  import { css } from "lit";
2
+ import { type } from "../typography.js";
2
3
  export const truncStyles = css `
3
4
  [part="root"] {
4
5
  font-family: var(--font-sans);
5
- font-size: var(--font-size-sm);
6
- line-height: var(--line-height-normal);
7
- color: var(--foreground);
6
+ ${type("sm")}
7
+ color: var(--text-1);
8
8
  }
9
9
  `;
package/index.d.ts CHANGED
@@ -80,3 +80,7 @@ export { toggleGroupStyles } from "./components/toggle-group.js";
80
80
  export { numberFieldStyles } from "./components/number-field.js";
81
81
  export { menubarStyles } from "./components/menubar.js";
82
82
  export { calendarStyles } from "./components/calendar.js";
83
+ export { proseSheet } from "./prose.js";
84
+ export { type, typeScale } from "./typography.js";
85
+ export type { TypeSize } from "./typography.js";
86
+ export type { ButtonVariant, ButtonAppearance, ButtonSize, BadgeVariant, BadgeAppearance, SpinnerVariant, SpinnerSize, TextareaVariant, SidebarVariant, SidebarMenuButtonSize, ToolbarSize, } from "./types.js";
package/index.js CHANGED
@@ -78,10 +78,12 @@ import { toggleGroupStyles } from "./components/toggle-group.js";
78
78
  import { numberFieldStyles } from "./components/number-field.js";
79
79
  import { menubarStyles } from "./components/menubar.js";
80
80
  import { calendarStyles } from "./components/calendar.js";
81
+ import { proseSheet } from "./prose.js";
81
82
  import { tokenSheet } from "./tokens.js";
82
83
  export const defaultTheme = {
83
84
  tokens: tokenSheet,
84
85
  base: themedBase,
86
+ prose: proseSheet,
85
87
  styles: new Map([
86
88
  ["dui-accordion", accordionStyles],
87
89
  ["dui-accordion-item", accordionItemStyles],
@@ -244,3 +246,7 @@ export { toggleGroupStyles } from "./components/toggle-group.js";
244
246
  export { numberFieldStyles } from "./components/number-field.js";
245
247
  export { menubarStyles } from "./components/menubar.js";
246
248
  export { calendarStyles } from "./components/calendar.js";
249
+ // --- Prose ---
250
+ export { proseSheet } from "./prose.js";
251
+ // --- Typography helpers ---
252
+ export { type, typeScale } from "./typography.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepfuture/dui-theme-default",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "description": "DUI default theme — design tokens and aesthetic component styles",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -66,14 +66,26 @@
66
66
  "import": "./components/tooltip-popup.js",
67
67
  "types": "./components/tooltip-popup.d.ts"
68
68
  },
69
+ "./types": {
70
+ "import": "./types.js",
71
+ "types": "./types.d.ts"
72
+ },
69
73
  "./tokens": {
70
74
  "import": "./tokens.js",
71
75
  "types": "./tokens.d.ts"
72
76
  },
77
+ "./prose": {
78
+ "import": "./prose.js",
79
+ "types": "./prose.d.ts"
80
+ },
73
81
  "./tokens-raw": {
74
82
  "import": "./tokens-raw.js",
75
83
  "types": "./tokens-raw.d.ts"
76
84
  },
85
+ "./typography": {
86
+ "import": "./typography.js",
87
+ "types": "./typography.d.ts"
88
+ },
77
89
  "./components/dialog": {
78
90
  "import": "./components/dialog.js",
79
91
  "types": "./components/dialog.d.ts"
@@ -346,7 +358,7 @@
346
358
  "README.md"
347
359
  ],
348
360
  "dependencies": {
349
- "@deepfuture/dui-core": "0.0.2",
361
+ "@deepfuture/dui-core": "0.0.5",
350
362
  "lit": "^3.3.2"
351
363
  },
352
364
  "sideEffects": false,
package/prose.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ declare const proseSheet: CSSStyleSheet;
2
+ export { proseSheet };
package/prose.js ADDED
@@ -0,0 +1,4 @@
1
+ import proseCSS from "./prose.css" with { type: "text" };
2
+ const proseSheet = new CSSStyleSheet();
3
+ proseSheet.replaceSync(proseCSS);
4
+ export { proseSheet };
package/tokens-raw.js CHANGED
@@ -1,2 +1,2 @@
1
- const tokensCSS = "/* =================================================================\n * DUI Design Tokens\n * =================================================================\n * Combined token system: spacing, typography, borders, elevation,\n * motion, colors, sizing, and focus.\n *\n * Tokens are declared on :root so they cascade through the entire\n * document, including into shadow DOM via CSS custom property\n * inheritance.\n *\n * Dark mode: apply data-theme=\"dark\" on <html> to switch palettes.\n * ================================================================= */\n\n:root {\n /* -----------------------------------------------------------\n * Spacing (Tailwind base-4 system)\n * ----------------------------------------------------------- */\n --space-0: 0;\n --space-px: 1px;\n --space-0_5: 0.125rem; /* 2px */\n --space-1: 0.25rem; /* 4px */\n --space-1_5: 0.375rem; /* 6px */\n --space-2: 0.5rem; /* 8px */\n --space-2_5: 0.625rem; /* 10px */\n --space-3: 0.75rem; /* 12px */\n --space-3_5: 0.875rem; /* 14px */\n --space-4: 1rem; /* 16px */\n --space-4_5: 1.125rem; /* 18px */\n --space-5: 1.25rem; /* 20px */\n --space-6: 1.5rem; /* 24px */\n --space-7: 1.75rem; /* 28px */\n --space-8: 2rem; /* 32px */\n --space-9: 2.25rem; /* 36px */\n --space-10: 2.5rem; /* 40px */\n --space-11: 2.75rem; /* 44px */\n --space-12: 3rem; /* 48px */\n --space-14: 3.5rem; /* 56px */\n --space-16: 4rem; /* 64px */\n --space-20: 5rem; /* 80px */\n --space-24: 6rem; /* 96px */\n --space-28: 7rem; /* 112px */\n --space-32: 8rem; /* 128px */\n --space-36: 9rem; /* 144px */\n --space-40: 10rem; /* 160px */\n --space-44: 11rem; /* 176px */\n --space-48: 12rem; /* 192px */\n --space-52: 13rem; /* 208px */\n --space-56: 14rem; /* 224px */\n --space-60: 15rem; /* 240px */\n --space-64: 16rem; /* 256px */\n --space-72: 18rem; /* 288px */\n --space-80: 20rem; /* 320px */\n --space-96: 24rem; /* 384px */\n\n /* -----------------------------------------------------------\n * Typography\n * ----------------------------------------------------------- */\n --font-sans:\n 'Inter', system-ui, -apple-system, sans-serif,\n \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-serif: ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif;\n --font-mono:\n 'JetBrains Mono', ui-monospace, SFMono-Regular, \"SF Mono\", Menlo,\n Consolas, \"Liberation Mono\", monospace;\n\n --font-size-2xs: 0.65rem;\n --font-size-xs: 0.75rem;\n --font-size-sm: 0.875rem;\n --font-size-base: 0.9375rem;\n --font-size-md: 1rem;\n --font-size-lg: 1.125rem;\n --font-size-xl: 1.25rem;\n --font-size-2xl: 1.5rem;\n --font-size-3xl: 1.875rem;\n --font-size-4xl: 2.25rem;\n --font-size-5xl: 3rem;\n --font-size-6xl: 3.75rem;\n --font-size-7xl: 4.5rem;\n\n --letter-spacing-tightest: -0.02em;\n --letter-spacing-tighter: -0.015em;\n --letter-spacing-tight: -0.01em;\n --letter-spacing-normal: 0em;\n --letter-spacing-wide: 0.006em;\n --letter-spacing-wider: 0.012em;\n\n --font-size-fluid-sm: clamp(0.813rem, 0.75rem + 0.315vw, 0.875rem);\n --font-size-fluid-md: clamp(0.875rem, 0.813rem + 0.315vw, 1rem);\n --font-size-fluid-lg: clamp(1rem, 0.938rem + 0.315vw, 1.125rem);\n --font-size-fluid-xl: clamp(1.125rem, 1rem + 0.625vw, 1.25rem);\n --font-size-fluid-2xl: clamp(1.25rem, 1.125rem + 0.625vw, 1.5rem);\n --font-size-fluid-3xl: clamp(1.5rem, 1.313rem + 0.938vw, 1.875rem);\n --font-size-fluid-4xl: clamp(1.875rem, 1.625rem + 1.25vw, 2.25rem);\n --font-size-fluid-5xl: clamp(2.25rem, 1.875rem + 1.875vw, 3rem);\n\n --font-weight-regular: 400;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n\n --line-height-none: 1;\n --line-height-tight: 1.25;\n --line-height-snug: 1.375;\n --line-height-normal: 1.5;\n --line-height-relaxed: 1.625;\n\n /* -----------------------------------------------------------\n * Borders\n * ----------------------------------------------------------- */\n --radius-none: 0;\n --radius-xs: 0.125rem;\n --radius-sm: 0.25rem;\n --radius-md: 0.5rem;\n --radius-lg: 1rem;\n --radius-xl: 1.5rem;\n --radius-2xl: 2rem;\n --radius-full: 9999px;\n\n --border-width-hairline: 0.5px;\n --border-width-thin: 1px;\n --border-width-medium: 2px;\n --border-width-thick: 4px;\n\n /* -----------------------------------------------------------\n * Elevation\n * ----------------------------------------------------------- */\n --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --shadow-none: 0 0 0 0 transparent;\n\n --z-base: 0;\n --z-dropdown: 700;\n --z-sticky: 800;\n --z-overlay: 900;\n --z-modal: 1000;\n --z-popover: 1100;\n --z-toast: 1200;\n --z-tooltip: 1300;\n\n /* -----------------------------------------------------------\n * Motion\n * ----------------------------------------------------------- */\n --duration-instant: 50ms;\n --duration-faster: 100ms;\n --duration-fast: 150ms;\n --duration-normal: 250ms;\n --duration-slow: 400ms;\n --duration-slower: 700ms;\n\n --ease-1: cubic-bezier(0.25, 0, 0.5, 1);\n --ease-2: cubic-bezier(0.25, 0, 0.4, 1);\n --ease-3: cubic-bezier(0.25, 0, 0.3, 1);\n --ease-4: cubic-bezier(0.25, 0, 0.2, 1);\n --ease-5: cubic-bezier(0.25, 0, 0.1, 1);\n --ease-in-1: cubic-bezier(0.25, 0, 1, 1);\n --ease-in-2: cubic-bezier(0.5, 0, 1, 1);\n --ease-in-3: cubic-bezier(0.7, 0, 1, 1);\n --ease-in-4: cubic-bezier(0.9, 0, 1, 1);\n --ease-in-5: cubic-bezier(1, 0, 1, 1);\n --ease-out-1: cubic-bezier(0, 0, 0.75, 1);\n --ease-out-2: cubic-bezier(0, 0, 0.5, 1);\n --ease-out-3: cubic-bezier(0, 0, 0.3, 1);\n --ease-out-4: cubic-bezier(0, 0, 0.1, 1);\n --ease-out-5: cubic-bezier(0, 0, 0, 1);\n --ease-in-out-1: cubic-bezier(0.1, 0, 0.9, 1);\n --ease-in-out-2: cubic-bezier(0.3, 0, 0.7, 1);\n --ease-in-out-3: cubic-bezier(0.5, 0, 0.5, 1);\n --ease-in-out-4: cubic-bezier(0.7, 0, 0.3, 1);\n --ease-in-out-5: cubic-bezier(0.9, 0, 0.1, 1);\n\n --ease-sine-in: cubic-bezier(0.47, 0, 0.745, 0.715);\n --ease-sine-out: cubic-bezier(0.39, 0.575, 0.565, 1);\n --ease-sine-in-out: cubic-bezier(0.445, 0.05, 0.55, 0.95);\n --ease-quad-in: cubic-bezier(0.55, 0.085, 0.68, 0.53);\n --ease-quad-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);\n --ease-quad-in-out: cubic-bezier(0.455, 0.03, 0.515, 0.955);\n --ease-cubic-in: cubic-bezier(0.55, 0.055, 0.675, 0.19);\n --ease-cubic-out: cubic-bezier(0.215, 0.61, 0.355, 1);\n --ease-cubic-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);\n --ease-quart-in: cubic-bezier(0.895, 0.03, 0.685, 0.22);\n --ease-quart-out: cubic-bezier(0.165, 0.84, 0.44, 1);\n --ease-quart-in-out: cubic-bezier(0.77, 0, 0.175, 1);\n --ease-quint-in: cubic-bezier(0.755, 0.05, 0.855, 0.06);\n --ease-quint-out: cubic-bezier(0.23, 1, 0.32, 1);\n --ease-quint-in-out: cubic-bezier(0.86, 0, 0.07, 1);\n --ease-expo-in: cubic-bezier(0.95, 0.05, 0.795, 0.035);\n --ease-expo-out: cubic-bezier(0.19, 1, 0.22, 1);\n --ease-expo-in-out: cubic-bezier(1, 0, 0, 1);\n --ease-circ-in: cubic-bezier(0.6, 0.04, 0.98, 0.335);\n --ease-circ-out: cubic-bezier(0.075, 0.82, 0.165, 1);\n --ease-circ-in-out: cubic-bezier(0.785, 0.135, 0.15, 0.86);\n\n /* -----------------------------------------------------------\n * Filters (presets for filter / backdrop-filter tokens)\n * ----------------------------------------------------------- */\n --filter-none: none;\n --filter-blur-sm: blur(4px);\n --filter-blur-md: blur(8px);\n --filter-blur-lg: blur(16px);\n --filter-blur-xl: blur(24px);\n --filter-brightness-dim: brightness(0.8);\n --filter-brightness-bright: brightness(1.15);\n --filter-saturate-muted: saturate(0.5);\n --filter-saturate-vivid: saturate(1.5);\n --filter-grayscale: grayscale(1);\n\n /* -----------------------------------------------------------\n * Clip Paths (shape presets)\n * ----------------------------------------------------------- */\n --clip-none: none;\n --clip-circle: circle(50%);\n --clip-squircle: inset(0 round 30%);\n --clip-hexagon: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);\n --clip-octagon: polygon(29.3% 0%, 70.7% 0%, 100% 29.3%, 100% 70.7%, 70.7% 100%, 29.3% 100%, 0% 70.7%, 0% 29.3%);\n --clip-chevron-right: polygon(0% 0%, 75% 0%, 100% 50%, 75% 100%, 0% 100%, 25% 50%);\n --clip-bevel: polygon(8% 0%, 92% 0%, 100% 8%, 100% 92%, 92% 100%, 8% 100%, 0% 92%, 0% 8%);\n\n /* -----------------------------------------------------------\n * Component Sizing\n * ----------------------------------------------------------- */\n --component-height-xxs: 1.25rem;\n --component-height-xs: 1.5rem;\n --component-height-sm: 1.75rem;\n --component-height-md: 2rem;\n --component-height-lg: 2.25rem;\n --component-height-xl: 2.5rem;\n\n /* -----------------------------------------------------------\n * Focus Ring\n * ----------------------------------------------------------- */\n --focus-ring-color: var(--ring);\n --focus-ring-width: 2px;\n --focus-ring-style: solid;\n --focus-ring-offset: 2px;\n --focus-ring-duration: var(--duration-fast);\n --focus-ring-easing: var(--ease-out-3);\n\n /* -----------------------------------------------------------\n * Colors: Brand (theme-independent)\n * ----------------------------------------------------------- */\n --brand: oklch(0.728 0.1304 73.28);\n --brand-foreground: oklch(1 0.02 73.28);\n}\n\n/* =================================================================\n * LIGHT THEME (default)\n * ================================================================= */\n:root:not([data-theme=\"dark\"]) {\n --background: oklch(0.97 0 0);\n --foreground: oklch(0.145 0.005 286);\n --muted: oklch(0.965 0.002 286);\n --muted-foreground: oklch(0.556 0.016 286);\n --card: oklch(0.99 0 0);\n --card-foreground: oklch(0.145 0.005 286);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.145 0.005 286);\n --primary: oklch(0.205 0.042 265);\n --primary-foreground: oklch(0.985 0.002 248);\n --secondary: oklch(0.93 0.002 286);\n --secondary-foreground: oklch(0.3 0.042 265);\n --accent: oklch(0.93 0.04 62);\n --accent-foreground: oklch(0.32 0.06 55);\n --destructive: oklch(0.6 0.19 25);\n --destructive-foreground: oklch(0.995 0.06 25);\n --success: oklch(0.5 0.15 150);\n --success-foreground: oklch(0.985 0 0);\n --warning: oklch(0.72 0.15 75);\n --warning-foreground: oklch(0.28 0.06 55);\n --info: oklch(0.53 0.16 245);\n --info-foreground: oklch(0.985 0 0);\n --input: oklch(0.922 0.004 286);\n --input-bg: oklch(0.97 0.002 286);\n --border: oklch(0.922 0.004 286);\n --ring: oklch(0.551 0.2 245);\n --meter-track: oklch(0.965 0.002 286);\n --meter-fill: oklch(0.205 0.042 265);\n --scrim: oklch(0 0 0 / 0.5);\n --chart-1: oklch(0.58 0.17 35);\n --chart-2: oklch(0.55 0.13 185);\n --chart-3: oklch(0.52 0.14 265);\n --chart-4: oklch(0.62 0.15 85);\n --chart-5: oklch(0.55 0.16 310);\n}\n\n/* =================================================================\n * DARK THEME\n * ================================================================= */\n:root[data-theme=\"dark\"] {\n --background: oklch(0.26 0.019 243);\n --foreground: oklch(0.9353 0.0173 243);\n --muted: oklch(0.27 0.03 243);\n --muted-foreground: oklch(0.9353 0.0173 243 / 0.4);\n --card: oklch(0.29 0.028 243);\n --card-foreground: oklch(0.985 0.002 243);\n --popover: oklch(0.309 0.032 243);\n --popover-foreground: oklch(0.985 0.002 243);\n --primary: oklch(0.985 0.002 243);\n --primary-foreground: oklch(0.205 0.042 243);\n --secondary: oklch(0.826 0.041 243 / 0.2);\n --secondary-foreground: oklch(0.9353 0.0173 243 / 1);\n --accent: oklch(0.7001 0.1329 62.25);\n --accent-foreground: oklch(1 0.1 62.25);\n --destructive: oklch(0.63 0.2 25);\n --destructive-foreground: oklch(0.99 0.1 25);\n --success: oklch(0.65 0.17 145);\n --success-foreground: oklch(1 0.1 145);\n --warning: oklch(0.78 0.15 80);\n --warning-foreground: oklch(1 0.05 80);\n --info: oklch(0.64 0.16 245);\n --info-foreground: oklch(1 0.1 245);\n --input: oklch(0.826 0.041 202 / 0.2);\n --input-bg: oklch(0.826 0.041 202 / 0.08);\n --border: oklch(0.826 0.041 202 / 0.14);\n --ring: oklch(0.55 0.16 245);\n --meter-track: oklch(0.269 0.007 286);\n --meter-fill: oklch(0.985 0.002 248);\n --scrim: oklch(0.18 0.017 244 / 0.6);\n --chart-1: oklch(0.58 0.17 264);\n --chart-2: oklch(0.62 0.15 162);\n --chart-3: oklch(0.7 0.16 80);\n --chart-4: oklch(0.6 0.19 303);\n --chart-5: oklch(0.62 0.18 16);\n}\n\n/* =================================================================\n * Base document styles\n * ================================================================= */\n:root {\n color: var(--foreground);\n font-family: var(--font-sans);\n line-height: var(--line-height-normal);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n";
1
+ const tokensCSS = "/* =================================================================\n * DUI Design Tokens\n * =================================================================\n * Combined token system: spacing, typography, borders, elevation,\n * motion, colors, sizing, and focus.\n *\n * Tokens are declared on :root so they cascade through the entire\n * document, including into shadow DOM via CSS custom property\n * inheritance.\n *\n * Dark mode: apply data-theme=\"dark\" on <html> to switch palettes.\n * ================================================================= */\n\n:root {\n /* -----------------------------------------------------------\n * Spacing (Tailwind base-4 system)\n * ----------------------------------------------------------- */\n --space-0: 0;\n --space-px: 1px;\n --space-0_5: 0.125rem; /* 2px */\n --space-1: 0.25rem; /* 4px */\n --space-1_5: 0.375rem; /* 6px */\n --space-2: 0.5rem; /* 8px */\n --space-2_5: 0.625rem; /* 10px */\n --space-3: 0.75rem; /* 12px */\n --space-3_5: 0.875rem; /* 14px */\n --space-4: 1rem; /* 16px */\n --space-4_5: 1.125rem; /* 18px */\n --space-5: 1.25rem; /* 20px */\n --space-6: 1.5rem; /* 24px */\n --space-7: 1.75rem; /* 28px */\n --space-8: 2rem; /* 32px */\n --space-9: 2.25rem; /* 36px */\n --space-10: 2.5rem; /* 40px */\n --space-11: 2.75rem; /* 44px */\n --space-12: 3rem; /* 48px */\n --space-14: 3.5rem; /* 56px */\n --space-16: 4rem; /* 64px */\n --space-20: 5rem; /* 80px */\n --space-24: 6rem; /* 96px */\n --space-28: 7rem; /* 112px */\n --space-32: 8rem; /* 128px */\n --space-36: 9rem; /* 144px */\n --space-40: 10rem; /* 160px */\n --space-44: 11rem; /* 176px */\n --space-48: 12rem; /* 192px */\n --space-52: 13rem; /* 208px */\n --space-56: 14rem; /* 224px */\n --space-60: 15rem; /* 240px */\n --space-64: 16rem; /* 256px */\n --space-72: 18rem; /* 288px */\n --space-80: 20rem; /* 320px */\n --space-96: 24rem; /* 384px */\n\n /* -----------------------------------------------------------\n * Typography\n * ----------------------------------------------------------- */\n --font-sans:\n 'Inter', system-ui, -apple-system, sans-serif,\n \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-serif: ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif;\n --font-mono:\n 'JetBrains Mono', ui-monospace, SFMono-Regular, \"SF Mono\", Menlo,\n Consolas, \"Liberation Mono\", monospace;\n\n --font-size-2xs: 0.65rem;\n --font-size-xs: 0.75rem;\n --font-size-sm: 0.875rem;\n --font-size-base: 0.9375rem;\n --font-size-md: 1rem;\n --font-size-lg: 1.125rem;\n --font-size-xl: 1.25rem;\n --font-size-2xl: 1.5rem;\n --font-size-3xl: 1.875rem;\n --font-size-4xl: 2.25rem;\n --font-size-5xl: 3rem;\n --font-size-6xl: 3.75rem;\n --font-size-7xl: 4.5rem;\n\n --letter-spacing-tightest: -0.02em;\n --letter-spacing-tighter: -0.015em;\n --letter-spacing-tight: -0.01em;\n --letter-spacing-normal: 0em;\n --letter-spacing-wide: 0.006em;\n --letter-spacing-wider: 0.012em;\n\n --font-size-fluid-sm: clamp(0.813rem, 0.75rem + 0.315vw, 0.875rem);\n --font-size-fluid-md: clamp(0.875rem, 0.813rem + 0.315vw, 1rem);\n --font-size-fluid-lg: clamp(1rem, 0.938rem + 0.315vw, 1.125rem);\n --font-size-fluid-xl: clamp(1.125rem, 1rem + 0.625vw, 1.25rem);\n --font-size-fluid-2xl: clamp(1.25rem, 1.125rem + 0.625vw, 1.5rem);\n --font-size-fluid-3xl: clamp(1.5rem, 1.313rem + 0.938vw, 1.875rem);\n --font-size-fluid-4xl: clamp(1.875rem, 1.625rem + 1.25vw, 2.25rem);\n --font-size-fluid-5xl: clamp(2.25rem, 1.875rem + 1.875vw, 3rem);\n\n --font-weight-regular: 400;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n\n --line-height-none: 1;\n --line-height-tight: 1.25;\n --line-height-snug: 1.375;\n --line-height-normal: 1.5;\n --line-height-relaxed: 1.625;\n\n /* -----------------------------------------------------------\n * Borders\n * ----------------------------------------------------------- */\n --radius-none: 0;\n --radius-xs: 0.125rem;\n --radius-sm: 0.25rem;\n --radius-md: 0.5rem;\n --radius-lg: 1rem;\n --radius-xl: 1.5rem;\n --radius-2xl: 2rem;\n --radius-full: 9999px;\n\n --border-width-hairline: 0.5px;\n --border-width-thin: 1px;\n --border-width-medium: 2px;\n --border-width-thick: 4px;\n\n /* -----------------------------------------------------------\n * Elevation\n * ----------------------------------------------------------- */\n --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --shadow-none: 0 0 0 0 transparent;\n\n --z-base: 0;\n --z-dropdown: 700;\n --z-sticky: 800;\n --z-overlay: 900;\n --z-modal: 1000;\n --z-popover: 1100;\n --z-toast: 1200;\n --z-tooltip: 1300;\n\n /* -----------------------------------------------------------\n * Motion\n * ----------------------------------------------------------- */\n --duration-instant: 50ms;\n --duration-fastest: 75ms;\n --duration-faster: 100ms;\n --duration-fast: 150ms;\n --duration-normal: 250ms;\n --duration-slow: 400ms;\n --duration-slower: 700ms;\n\n --ease-1: cubic-bezier(0.25, 0, 0.5, 1);\n --ease-2: cubic-bezier(0.25, 0, 0.4, 1);\n --ease-3: cubic-bezier(0.25, 0, 0.3, 1);\n --ease-4: cubic-bezier(0.25, 0, 0.2, 1);\n --ease-5: cubic-bezier(0.25, 0, 0.1, 1);\n --ease-in-1: cubic-bezier(0.25, 0, 1, 1);\n --ease-in-2: cubic-bezier(0.5, 0, 1, 1);\n --ease-in-3: cubic-bezier(0.7, 0, 1, 1);\n --ease-in-4: cubic-bezier(0.9, 0, 1, 1);\n --ease-in-5: cubic-bezier(1, 0, 1, 1);\n --ease-out-1: cubic-bezier(0, 0, 0.75, 1);\n --ease-out-2: cubic-bezier(0, 0, 0.5, 1);\n --ease-out-3: cubic-bezier(0, 0, 0.3, 1);\n --ease-out-4: cubic-bezier(0, 0, 0.1, 1);\n --ease-out-5: cubic-bezier(0, 0, 0, 1);\n --ease-in-out-1: cubic-bezier(0.1, 0, 0.9, 1);\n --ease-in-out-2: cubic-bezier(0.3, 0, 0.7, 1);\n --ease-in-out-3: cubic-bezier(0.5, 0, 0.5, 1);\n --ease-in-out-4: cubic-bezier(0.7, 0, 0.3, 1);\n --ease-in-out-5: cubic-bezier(0.9, 0, 0.1, 1);\n\n --ease-sine-in: cubic-bezier(0.47, 0, 0.745, 0.715);\n --ease-sine-out: cubic-bezier(0.39, 0.575, 0.565, 1);\n --ease-sine-in-out: cubic-bezier(0.445, 0.05, 0.55, 0.95);\n --ease-quad-in: cubic-bezier(0.55, 0.085, 0.68, 0.53);\n --ease-quad-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);\n --ease-quad-in-out: cubic-bezier(0.455, 0.03, 0.515, 0.955);\n --ease-cubic-in: cubic-bezier(0.55, 0.055, 0.675, 0.19);\n --ease-cubic-out: cubic-bezier(0.215, 0.61, 0.355, 1);\n --ease-cubic-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);\n --ease-quart-in: cubic-bezier(0.895, 0.03, 0.685, 0.22);\n --ease-quart-out: cubic-bezier(0.165, 0.84, 0.44, 1);\n --ease-quart-in-out: cubic-bezier(0.77, 0, 0.175, 1);\n --ease-quint-in: cubic-bezier(0.755, 0.05, 0.855, 0.06);\n --ease-quint-out: cubic-bezier(0.23, 1, 0.32, 1);\n --ease-quint-in-out: cubic-bezier(0.86, 0, 0.07, 1);\n --ease-expo-in: cubic-bezier(0.95, 0.05, 0.795, 0.035);\n --ease-expo-out: cubic-bezier(0.19, 1, 0.22, 1);\n --ease-expo-in-out: cubic-bezier(1, 0, 0, 1);\n --ease-circ-in: cubic-bezier(0.6, 0.04, 0.98, 0.335);\n --ease-circ-out: cubic-bezier(0.075, 0.82, 0.165, 1);\n --ease-circ-in-out: cubic-bezier(0.785, 0.135, 0.15, 0.86);\n\n /* -----------------------------------------------------------\n * Filters (presets for filter / backdrop-filter tokens)\n * ----------------------------------------------------------- */\n --filter-none: none;\n --filter-blur-sm: blur(4px);\n --filter-blur-md: blur(8px);\n --filter-blur-lg: blur(16px);\n --filter-blur-xl: blur(24px);\n --filter-brightness-dim: brightness(0.8);\n --filter-brightness-bright: brightness(1.15);\n --filter-saturate-muted: saturate(0.5);\n --filter-saturate-vivid: saturate(1.5);\n --filter-grayscale: grayscale(1);\n\n /* -----------------------------------------------------------\n * Clip Paths (shape presets)\n * ----------------------------------------------------------- */\n --clip-none: none;\n --clip-circle: circle(50%);\n --clip-squircle: inset(0 round 30%);\n --clip-hexagon: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);\n --clip-octagon: polygon(29.3% 0%, 70.7% 0%, 100% 29.3%, 100% 70.7%, 70.7% 100%, 29.3% 100%, 0% 70.7%, 0% 29.3%);\n --clip-chevron-right: polygon(0% 0%, 75% 0%, 100% 50%, 75% 100%, 0% 100%, 25% 50%);\n --clip-bevel: polygon(8% 0%, 92% 0%, 100% 8%, 100% 92%, 92% 100%, 8% 100%, 0% 92%, 0% 8%);\n\n /* -----------------------------------------------------------\n * Component Sizing\n * ----------------------------------------------------------- */\n --component-height-xxs: 1.25rem;\n --component-height-xs: 1.5rem;\n --component-height-sm: 1.75rem;\n --component-height-md: 2rem;\n --component-height-lg: 2.25rem;\n --component-height-xl: 2.5rem;\n\n /* -----------------------------------------------------------\n * Focus Ring\n * ----------------------------------------------------------- */\n --focus-ring-color: var(--accent);\n --focus-ring-width: 2px;\n --focus-ring-offset: 2px;\n --focus-ring-duration: var(--duration-fast);\n --focus-ring-easing: var(--ease-out-3);\n\n /* -----------------------------------------------------------\n * Colors: Brand (theme-independent)\n * ----------------------------------------------------------- */\n --brand: oklch(0.728 0.1304 73.28);\n --brand-foreground: oklch(1 0.02 73.28);\n}\n\n/* =================================================================\n * COLOR SYSTEM\n * =================================================================\n * Built on two principles:\n * 1. Operations on a base — colors are relationships, not fixed values.\n * 2. Fewer primitives, more derivation — 4 primitives, everything\n * else computed via oklch(from ...) and color-mix().\n *\n * Layer 1: Primitives (only values a theme author picks)\n * Layer 2: Derived tokens (computed from primitives, never per-theme)\n * Layer 3: Interaction states (component-level, not tokens)\n * ================================================================= */\n\n/* -----------------------------------------------------------------\n * LIGHT THEME (default)\n * ----------------------------------------------------------------- */\n:root:not([data-theme=\"dark\"]) {\n /* --- Layer 1: Primitives --- */\n --background: oklch(0.97 0 0);\n --foreground: oklch(0.15 0 0);\n --accent: oklch(0.55 0.25 260);\n --destructive: oklch(0.55 0.22 25);\n}\n\n/* -----------------------------------------------------------------\n * DARK THEME\n * ----------------------------------------------------------------- */\n:root[data-theme=\"dark\"] {\n /* --- Layer 1: Primitives --- */\n --background: oklch(0.15 0.015 260);\n --foreground: oklch(0.93 0 0);\n --accent: oklch(0.75 0.18 260);\n --destructive: oklch(0.70 0.18 25);\n}\n\n/* -----------------------------------------------------------------\n * Layer 2: Derived tokens (computed from primitives)\n * Defined once — same rules for light and dark.\n * ----------------------------------------------------------------- */\n:root {\n /* Surfaces — lightness offsets from background.\n Positive = elevated (brighter). Negative = sunken (darker). */\n --sunken: oklch(from var(--background) calc(l - 0.03) c h);\n --surface-1: oklch(from var(--background) calc(l + 0.02) c h);\n --surface-2: oklch(from var(--background) calc(l + 0.05) c h);\n --surface-3: oklch(from var(--background) calc(l + 0.09) c h);\n\n /* Borders — foreground at reduced alpha.\n Semi-transparent so they adapt to any surface. */\n --border: oklch(from var(--foreground) l c h / 0.15);\n --border-strong: oklch(from var(--foreground) l c h / 0.25);\n\n /* Text tiers — foreground at reduced alpha.\n Semi-transparent so they adapt to any surface. */\n --text-1: oklch(from var(--foreground) l c h / 0.90);\n --text-2: oklch(from var(--foreground) l c h / 0.63);\n --text-3: oklch(from var(--foreground) l c h / 0.45);\n\n /* Accent surfaces — for badges, pills, tinted cards */\n --accent-subtle: oklch(from var(--accent) l c h / 0.10);\n --accent-text: color-mix(in oklch, var(--accent) 80%, var(--foreground));\n\n /* Destructive surfaces */\n --destructive-subtle: oklch(from var(--destructive) l c h / 0.10);\n --destructive-text: color-mix(in oklch, var(--destructive) 80%, var(--foreground));\n\n /* Utility — scrim overlay for modals/dialogs */\n --scrim: oklch(from var(--foreground) l c h / 0.35);\n\n /* Meter / progress bar defaults */\n --meter-track: var(--surface-1);\n --meter-fill: var(--accent);\n\n /* Chart palette (theme-independent) */\n --chart-1: oklch(0.58 0.17 35);\n --chart-2: oklch(0.55 0.13 185);\n --chart-3: oklch(0.52 0.14 265);\n --chart-4: oklch(0.62 0.15 85);\n --chart-5: oklch(0.55 0.16 310);\n\n /* -----------------------------------------------------------\n * Prose (rich-text / markdown content)\n * ----------------------------------------------------------- */\n --prose-body: var(--text-1);\n --prose-headings: var(--foreground);\n --prose-lead: var(--text-2);\n --prose-links: var(--accent);\n --prose-links-hover: var(--accent-text);\n --prose-bold: var(--foreground);\n --prose-code: var(--foreground);\n --prose-code-bg: var(--surface-1);\n --prose-pre-bg: var(--surface-1);\n --prose-pre-border: var(--border);\n --prose-blockquote-border: var(--accent);\n --prose-blockquote-text: var(--text-2);\n --prose-hr: var(--border);\n --prose-th-border: var(--border-strong);\n --prose-td-border: var(--border);\n --prose-caption: var(--text-3);\n --prose-kbd-bg: var(--surface-2);\n --prose-kbd-border: var(--border-strong);\n}\n\n/* =================================================================\n * Base document styles\n * ================================================================= */\n:root {\n color: var(--text-1);\n font-family: var(--font-sans);\n line-height: var(--line-height-normal);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n";
2
2
  export { tokensCSS };
package/tokens.css CHANGED
@@ -145,6 +145,7 @@
145
145
  * Motion
146
146
  * ----------------------------------------------------------- */
147
147
  --duration-instant: 50ms;
148
+ --duration-fastest: 75ms;
148
149
  --duration-faster: 100ms;
149
150
  --duration-fast: 150ms;
150
151
  --duration-normal: 250ms;
@@ -232,9 +233,8 @@
232
233
  /* -----------------------------------------------------------
233
234
  * Focus Ring
234
235
  * ----------------------------------------------------------- */
235
- --focus-ring-color: var(--ring);
236
+ --focus-ring-color: var(--accent);
236
237
  --focus-ring-width: 2px;
237
- --focus-ring-style: solid;
238
238
  --focus-ring-offset: 2px;
239
239
  --focus-ring-duration: var(--duration-fast);
240
240
  --focus-ring-easing: var(--ease-out-3);
@@ -247,90 +247,113 @@
247
247
  }
248
248
 
249
249
  /* =================================================================
250
- * LIGHT THEME (default)
250
+ * COLOR SYSTEM
251
+ * =================================================================
252
+ * Built on two principles:
253
+ * 1. Operations on a base — colors are relationships, not fixed values.
254
+ * 2. Fewer primitives, more derivation — 4 primitives, everything
255
+ * else computed via oklch(from ...) and color-mix().
256
+ *
257
+ * Layer 1: Primitives (only values a theme author picks)
258
+ * Layer 2: Derived tokens (computed from primitives, never per-theme)
259
+ * Layer 3: Interaction states (component-level, not tokens)
251
260
  * ================================================================= */
261
+
262
+ /* -----------------------------------------------------------------
263
+ * LIGHT THEME (default)
264
+ * ----------------------------------------------------------------- */
252
265
  :root:not([data-theme="dark"]) {
253
- --background: oklch(0.97 0 0);
254
- --foreground: oklch(0.145 0.005 286);
255
- --muted: oklch(0.965 0.002 286);
256
- --muted-foreground: oklch(0.556 0.016 286);
257
- --card: oklch(0.99 0 0);
258
- --card-foreground: oklch(0.145 0.005 286);
259
- --popover: oklch(1 0 0);
260
- --popover-foreground: oklch(0.145 0.005 286);
261
- --primary: oklch(0.205 0.042 265);
262
- --primary-foreground: oklch(0.985 0.002 248);
263
- --secondary: oklch(0.93 0.002 286);
264
- --secondary-foreground: oklch(0.3 0.042 265);
265
- --accent: oklch(0.93 0.04 62);
266
- --accent-foreground: oklch(0.32 0.06 55);
267
- --destructive: oklch(0.6 0.19 25);
268
- --destructive-foreground: oklch(0.995 0.06 25);
269
- --success: oklch(0.5 0.15 150);
270
- --success-foreground: oklch(0.985 0 0);
271
- --warning: oklch(0.72 0.15 75);
272
- --warning-foreground: oklch(0.28 0.06 55);
273
- --info: oklch(0.53 0.16 245);
274
- --info-foreground: oklch(0.985 0 0);
275
- --input: oklch(0.922 0.004 286);
276
- --input-bg: oklch(0.97 0.002 286);
277
- --border: oklch(0.922 0.004 286);
278
- --ring: oklch(0.551 0.2 245);
279
- --meter-track: oklch(0.965 0.002 286);
280
- --meter-fill: oklch(0.205 0.042 265);
281
- --scrim: oklch(0 0 0 / 0.5);
266
+ /* --- Layer 1: Primitives --- */
267
+ --background: oklch(0.97 0 0);
268
+ --foreground: oklch(0.15 0 0);
269
+ --accent: oklch(0.55 0.25 260);
270
+ --destructive: oklch(0.55 0.22 25);
271
+ }
272
+
273
+ /* -----------------------------------------------------------------
274
+ * DARK THEME
275
+ * ----------------------------------------------------------------- */
276
+ :root[data-theme="dark"] {
277
+ /* --- Layer 1: Primitives --- */
278
+ --background: oklch(0.15 0.015 260);
279
+ --foreground: oklch(0.93 0 0);
280
+ --accent: oklch(0.75 0.18 260);
281
+ --destructive: oklch(0.70 0.18 25);
282
+ }
283
+
284
+ /* -----------------------------------------------------------------
285
+ * Layer 2: Derived tokens (computed from primitives)
286
+ * Defined once — same rules for light and dark.
287
+ * ----------------------------------------------------------------- */
288
+ :root {
289
+ /* Surfaces — lightness offsets from background.
290
+ Positive = elevated (brighter). Negative = sunken (darker). */
291
+ --sunken: oklch(from var(--background) calc(l - 0.03) c h);
292
+ --surface-1: oklch(from var(--background) calc(l + 0.02) c h);
293
+ --surface-2: oklch(from var(--background) calc(l + 0.05) c h);
294
+ --surface-3: oklch(from var(--background) calc(l + 0.09) c h);
295
+
296
+ /* Borders — foreground at reduced alpha.
297
+ Semi-transparent so they adapt to any surface. */
298
+ --border: oklch(from var(--foreground) l c h / 0.15);
299
+ --border-strong: oklch(from var(--foreground) l c h / 0.25);
300
+
301
+ /* Text tiers — foreground at reduced alpha.
302
+ Semi-transparent so they adapt to any surface. */
303
+ --text-1: oklch(from var(--foreground) l c h / 0.90);
304
+ --text-2: oklch(from var(--foreground) l c h / 0.63);
305
+ --text-3: oklch(from var(--foreground) l c h / 0.45);
306
+
307
+ /* Accent surfaces — for badges, pills, tinted cards */
308
+ --accent-subtle: oklch(from var(--accent) l c h / 0.10);
309
+ --accent-text: color-mix(in oklch, var(--accent) 80%, var(--foreground));
310
+
311
+ /* Destructive surfaces */
312
+ --destructive-subtle: oklch(from var(--destructive) l c h / 0.10);
313
+ --destructive-text: color-mix(in oklch, var(--destructive) 80%, var(--foreground));
314
+
315
+ /* Utility — scrim overlay for modals/dialogs */
316
+ --scrim: oklch(from var(--foreground) l c h / 0.35);
317
+
318
+ /* Meter / progress bar defaults */
319
+ --meter-track: var(--surface-1);
320
+ --meter-fill: var(--accent);
321
+
322
+ /* Chart palette (theme-independent) */
282
323
  --chart-1: oklch(0.58 0.17 35);
283
324
  --chart-2: oklch(0.55 0.13 185);
284
325
  --chart-3: oklch(0.52 0.14 265);
285
326
  --chart-4: oklch(0.62 0.15 85);
286
327
  --chart-5: oklch(0.55 0.16 310);
287
- }
288
328
 
289
- /* =================================================================
290
- * DARK THEME
291
- * ================================================================= */
292
- :root[data-theme="dark"] {
293
- --background: oklch(0.26 0.019 243);
294
- --foreground: oklch(0.9353 0.0173 243);
295
- --muted: oklch(0.27 0.03 243);
296
- --muted-foreground: oklch(0.9353 0.0173 243 / 0.4);
297
- --card: oklch(0.29 0.028 243);
298
- --card-foreground: oklch(0.985 0.002 243);
299
- --popover: oklch(0.309 0.032 243);
300
- --popover-foreground: oklch(0.985 0.002 243);
301
- --primary: oklch(0.985 0.002 243);
302
- --primary-foreground: oklch(0.205 0.042 243);
303
- --secondary: oklch(0.826 0.041 243 / 0.2);
304
- --secondary-foreground: oklch(0.9353 0.0173 243 / 1);
305
- --accent: oklch(0.7001 0.1329 62.25);
306
- --accent-foreground: oklch(1 0.1 62.25);
307
- --destructive: oklch(0.63 0.2 25);
308
- --destructive-foreground: oklch(0.99 0.1 25);
309
- --success: oklch(0.65 0.17 145);
310
- --success-foreground: oklch(1 0.1 145);
311
- --warning: oklch(0.78 0.15 80);
312
- --warning-foreground: oklch(1 0.05 80);
313
- --info: oklch(0.64 0.16 245);
314
- --info-foreground: oklch(1 0.1 245);
315
- --input: oklch(0.826 0.041 202 / 0.2);
316
- --input-bg: oklch(0.826 0.041 202 / 0.08);
317
- --border: oklch(0.826 0.041 202 / 0.14);
318
- --ring: oklch(0.55 0.16 245);
319
- --meter-track: oklch(0.269 0.007 286);
320
- --meter-fill: oklch(0.985 0.002 248);
321
- --scrim: oklch(0.18 0.017 244 / 0.6);
322
- --chart-1: oklch(0.58 0.17 264);
323
- --chart-2: oklch(0.62 0.15 162);
324
- --chart-3: oklch(0.7 0.16 80);
325
- --chart-4: oklch(0.6 0.19 303);
326
- --chart-5: oklch(0.62 0.18 16);
329
+ /* -----------------------------------------------------------
330
+ * Prose (rich-text / markdown content)
331
+ * ----------------------------------------------------------- */
332
+ --prose-body: var(--text-1);
333
+ --prose-headings: var(--foreground);
334
+ --prose-lead: var(--text-2);
335
+ --prose-links: var(--accent);
336
+ --prose-links-hover: var(--accent-text);
337
+ --prose-bold: var(--foreground);
338
+ --prose-code: var(--foreground);
339
+ --prose-code-bg: var(--surface-1);
340
+ --prose-pre-bg: var(--surface-1);
341
+ --prose-pre-border: var(--border);
342
+ --prose-blockquote-border: var(--accent);
343
+ --prose-blockquote-text: var(--text-2);
344
+ --prose-hr: var(--border);
345
+ --prose-th-border: var(--border-strong);
346
+ --prose-td-border: var(--border);
347
+ --prose-caption: var(--text-3);
348
+ --prose-kbd-bg: var(--surface-2);
349
+ --prose-kbd-border: var(--border-strong);
327
350
  }
328
351
 
329
352
  /* =================================================================
330
353
  * Base document styles
331
354
  * ================================================================= */
332
355
  :root {
333
- color: var(--foreground);
356
+ color: var(--text-1);
334
357
  font-family: var(--font-sans);
335
358
  line-height: var(--line-height-normal);
336
359
  -webkit-font-smoothing: antialiased;