@opencosmos/ui 1.3.1

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 (260) hide show
  1. package/.claude/CLAUDE.md +239 -0
  2. package/README.md +161 -0
  3. package/dist/cli.mjs +151 -0
  4. package/dist/dates.d.mts +20 -0
  5. package/dist/dates.d.ts +20 -0
  6. package/dist/dates.js +240 -0
  7. package/dist/dates.js.map +1 -0
  8. package/dist/dates.mjs +203 -0
  9. package/dist/dates.mjs.map +1 -0
  10. package/dist/dnd.d.mts +126 -0
  11. package/dist/dnd.d.ts +126 -0
  12. package/dist/dnd.js +274 -0
  13. package/dist/dnd.js.map +1 -0
  14. package/dist/dnd.mjs +250 -0
  15. package/dist/dnd.mjs.map +1 -0
  16. package/dist/fontThemes-Dh8mtXES.d.mts +868 -0
  17. package/dist/fontThemes-Dh8mtXES.d.ts +868 -0
  18. package/dist/forms.d.mts +38 -0
  19. package/dist/forms.d.ts +38 -0
  20. package/dist/forms.js +198 -0
  21. package/dist/forms.js.map +1 -0
  22. package/dist/forms.mjs +159 -0
  23. package/dist/forms.mjs.map +1 -0
  24. package/dist/hooks-1b8WaQf1.d.mts +225 -0
  25. package/dist/hooks-CKW8vE9H.d.ts +225 -0
  26. package/dist/hooks.d.mts +3 -0
  27. package/dist/hooks.d.ts +3 -0
  28. package/dist/hooks.js +971 -0
  29. package/dist/hooks.js.map +1 -0
  30. package/dist/hooks.mjs +943 -0
  31. package/dist/hooks.mjs.map +1 -0
  32. package/dist/index-DscTIrZ2.d.mts +29 -0
  33. package/dist/index-DscTIrZ2.d.ts +29 -0
  34. package/dist/index.d.mts +3382 -0
  35. package/dist/index.d.ts +3382 -0
  36. package/dist/index.js +15146 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/index.mjs +14802 -0
  39. package/dist/index.mjs.map +1 -0
  40. package/dist/providers-CXPDMsl7.d.mts +30 -0
  41. package/dist/providers-Dn_Msjvz.d.ts +30 -0
  42. package/dist/providers.d.mts +3 -0
  43. package/dist/providers.d.ts +3 -0
  44. package/dist/providers.js +1885 -0
  45. package/dist/providers.js.map +1 -0
  46. package/dist/providers.mjs +1859 -0
  47. package/dist/providers.mjs.map +1 -0
  48. package/dist/tables.d.mts +10 -0
  49. package/dist/tables.d.ts +10 -0
  50. package/dist/tables.js +248 -0
  51. package/dist/tables.js.map +1 -0
  52. package/dist/tables.mjs +218 -0
  53. package/dist/tables.mjs.map +1 -0
  54. package/dist/tokens.d.mts +1065 -0
  55. package/dist/tokens.d.ts +1065 -0
  56. package/dist/tokens.js +2637 -0
  57. package/dist/tokens.js.map +1 -0
  58. package/dist/tokens.mjs +2555 -0
  59. package/dist/tokens.mjs.map +1 -0
  60. package/dist/utils-CIIM7dAC.d.ts +986 -0
  61. package/dist/utils-Cs04sxth.d.mts +986 -0
  62. package/dist/utils.d.mts +4 -0
  63. package/dist/utils.d.ts +4 -0
  64. package/dist/utils.js +874 -0
  65. package/dist/utils.js.map +1 -0
  66. package/dist/utils.mjs +806 -0
  67. package/dist/utils.mjs.map +1 -0
  68. package/dist/validation-Bj1ye-v_.d.mts +114 -0
  69. package/dist/validation-Bj1ye-v_.d.ts +114 -0
  70. package/dist/webgl.d.mts +104 -0
  71. package/dist/webgl.d.ts +104 -0
  72. package/dist/webgl.js +226 -0
  73. package/dist/webgl.js.map +1 -0
  74. package/dist/webgl.mjs +195 -0
  75. package/dist/webgl.mjs.map +1 -0
  76. package/package.json +267 -0
  77. package/src/cli.ts +206 -0
  78. package/src/component-registry.ts +183 -0
  79. package/src/components/actions/Button.test.tsx +61 -0
  80. package/src/components/actions/Button.tsx +70 -0
  81. package/src/components/actions/Link.tsx +78 -0
  82. package/src/components/actions/Magnetic.tsx +68 -0
  83. package/src/components/actions/Toggle.test.tsx +40 -0
  84. package/src/components/actions/Toggle.tsx +47 -0
  85. package/src/components/actions/ToggleGroup.tsx +70 -0
  86. package/src/components/actions/index.ts +5 -0
  87. package/src/components/backgrounds/FaultyTerminal.tsx +426 -0
  88. package/src/components/backgrounds/OrbBackground.tsx +424 -0
  89. package/src/components/backgrounds/WarpBackground.tsx +358 -0
  90. package/src/components/backgrounds/index.ts +3 -0
  91. package/src/components/blocks/Hero.tsx +142 -0
  92. package/src/components/blocks/social/OpenGraphCard.tsx +243 -0
  93. package/src/components/cursor/SplashCursor.tsx +1315 -0
  94. package/src/components/cursor/TargetCursor.tsx +187 -0
  95. package/src/components/cursor/index.ts +2 -0
  96. package/src/components/data-display/AspectImage.tsx +73 -0
  97. package/src/components/data-display/Avatar.test.tsx +35 -0
  98. package/src/components/data-display/Avatar.tsx +55 -0
  99. package/src/components/data-display/Badge.test.tsx +43 -0
  100. package/src/components/data-display/Badge.tsx +84 -0
  101. package/src/components/data-display/Brand.tsx +123 -0
  102. package/src/components/data-display/Calendar.tsx +70 -0
  103. package/src/components/data-display/Card.test.tsx +92 -0
  104. package/src/components/data-display/Card.tsx +115 -0
  105. package/src/components/data-display/Code.tsx +210 -0
  106. package/src/components/data-display/CollapsibleCodeBlock.tsx +238 -0
  107. package/src/components/data-display/DataTable.tsx +119 -0
  108. package/src/components/data-display/DescriptionList.tsx +41 -0
  109. package/src/components/data-display/GitHubIcon.tsx +44 -0
  110. package/src/components/data-display/Heading.test.tsx +36 -0
  111. package/src/components/data-display/Heading.tsx +83 -0
  112. package/src/components/data-display/StatCard.tsx +195 -0
  113. package/src/components/data-display/Table.tsx +133 -0
  114. package/src/components/data-display/Text.test.tsx +48 -0
  115. package/src/components/data-display/Text.tsx +144 -0
  116. package/src/components/data-display/Timeline.tsx +194 -0
  117. package/src/components/data-display/TreeView.tsx +226 -0
  118. package/src/components/data-display/Typewriter.tsx +119 -0
  119. package/src/components/data-display/VariableWeightText.tsx +130 -0
  120. package/src/components/data-display/index.ts +19 -0
  121. package/src/components/feedback/Alert.test.tsx +44 -0
  122. package/src/components/feedback/Alert.tsx +65 -0
  123. package/src/components/feedback/EmptyState.tsx +113 -0
  124. package/src/components/feedback/Progress.test.tsx +60 -0
  125. package/src/components/feedback/Progress.tsx +30 -0
  126. package/src/components/feedback/ProgressBar.tsx +158 -0
  127. package/src/components/feedback/Skeleton.test.tsx +39 -0
  128. package/src/components/feedback/Skeleton.tsx +45 -0
  129. package/src/components/feedback/Sonner.tsx +28 -0
  130. package/src/components/feedback/Spinner.test.tsx +33 -0
  131. package/src/components/feedback/Spinner.tsx +99 -0
  132. package/src/components/feedback/Stepper.tsx +307 -0
  133. package/src/components/feedback/Toast/Toast.tsx +243 -0
  134. package/src/components/feedback/Toast/index.ts +2 -0
  135. package/src/components/feedback/index.ts +9 -0
  136. package/src/components/forms/Checkbox.test.tsx +40 -0
  137. package/src/components/forms/Checkbox.tsx +31 -0
  138. package/src/components/forms/ColorPicker.tsx +118 -0
  139. package/src/components/forms/Combobox.tsx +96 -0
  140. package/src/components/forms/DragDrop.tsx +440 -0
  141. package/src/components/forms/FileUpload.tsx +252 -0
  142. package/src/components/forms/FilterButton.tsx +65 -0
  143. package/src/components/forms/Form.tsx +197 -0
  144. package/src/components/forms/Input.test.tsx +46 -0
  145. package/src/components/forms/Input.tsx +43 -0
  146. package/src/components/forms/InputOTP.tsx +81 -0
  147. package/src/components/forms/Label.test.tsx +20 -0
  148. package/src/components/forms/Label.tsx +25 -0
  149. package/src/components/forms/RadioGroup.tsx +51 -0
  150. package/src/components/forms/SearchBar.tsx +215 -0
  151. package/src/components/forms/Select.test.tsx +118 -0
  152. package/src/components/forms/Select.tsx +274 -0
  153. package/src/components/forms/Slider.tsx +29 -0
  154. package/src/components/forms/Switch.test.tsx +76 -0
  155. package/src/components/forms/Switch.tsx +30 -0
  156. package/src/components/forms/TextField.tsx +152 -0
  157. package/src/components/forms/Textarea.test.tsx +41 -0
  158. package/src/components/forms/Textarea.tsx +29 -0
  159. package/src/components/forms/ThemeSwitcher.tsx +290 -0
  160. package/src/components/forms/ThemeToggle.tsx +151 -0
  161. package/src/components/forms/index.ts +19 -0
  162. package/src/components/layout/Accordion.test.tsx +66 -0
  163. package/src/components/layout/Accordion.tsx +64 -0
  164. package/src/components/layout/AspectRatio.tsx +7 -0
  165. package/src/components/layout/Carousel.tsx +277 -0
  166. package/src/components/layout/Collapsible.test.tsx +40 -0
  167. package/src/components/layout/Collapsible.tsx +31 -0
  168. package/src/components/layout/Container.test.tsx +45 -0
  169. package/src/components/layout/Container.tsx +99 -0
  170. package/src/components/layout/CustomizerPanel.tsx +400 -0
  171. package/src/components/layout/DatePicker.tsx +57 -0
  172. package/src/components/layout/Footer/Footer.tsx +175 -0
  173. package/src/components/layout/Footer/index.ts +2 -0
  174. package/src/components/layout/GlassSurface.tsx +82 -0
  175. package/src/components/layout/Grid.test.tsx +31 -0
  176. package/src/components/layout/Grid.tsx +130 -0
  177. package/src/components/layout/Header/Header.tsx +450 -0
  178. package/src/components/layout/Header/index.ts +2 -0
  179. package/src/components/layout/PageLayout.tsx +180 -0
  180. package/src/components/layout/PageTemplate.tsx +158 -0
  181. package/src/components/layout/Resizable.tsx +48 -0
  182. package/src/components/layout/ScrollArea.tsx +53 -0
  183. package/src/components/layout/Separator.test.tsx +28 -0
  184. package/src/components/layout/Separator.tsx +29 -0
  185. package/src/components/layout/Sidebar.tsx +171 -0
  186. package/src/components/layout/Stack.test.tsx +41 -0
  187. package/src/components/layout/Stack.tsx +89 -0
  188. package/src/components/layout/glass-surface.css +60 -0
  189. package/src/components/layout/index.ts +18 -0
  190. package/src/components/motion/AnimatedBeam.tsx +159 -0
  191. package/src/components/navigation/Breadcrumb.test.tsx +57 -0
  192. package/src/components/navigation/Breadcrumb.tsx +119 -0
  193. package/src/components/navigation/Breadcrumbs.tsx +221 -0
  194. package/src/components/navigation/Command.tsx +159 -0
  195. package/src/components/navigation/Menubar.tsx +115 -0
  196. package/src/components/navigation/NavLink.tsx +55 -0
  197. package/src/components/navigation/NavigationMenu.tsx +125 -0
  198. package/src/components/navigation/Pagination.tsx +121 -0
  199. package/src/components/navigation/SecondaryNav.tsx +100 -0
  200. package/src/components/navigation/Tabs.test.tsx +47 -0
  201. package/src/components/navigation/Tabs.tsx +60 -0
  202. package/src/components/navigation/TertiaryNav.tsx +90 -0
  203. package/src/components/navigation/index.ts +10 -0
  204. package/src/components/overlays/AlertDialog.test.tsx +69 -0
  205. package/src/components/overlays/AlertDialog.tsx +166 -0
  206. package/src/components/overlays/ContextMenu.tsx +243 -0
  207. package/src/components/overlays/Dialog.test.tsx +79 -0
  208. package/src/components/overlays/Dialog.tsx +158 -0
  209. package/src/components/overlays/Drawer.tsx +128 -0
  210. package/src/components/overlays/Dropdown.tsx +253 -0
  211. package/src/components/overlays/DropdownMenu.tsx +242 -0
  212. package/src/components/overlays/HoverCard.tsx +32 -0
  213. package/src/components/overlays/Modal.tsx +250 -0
  214. package/src/components/overlays/NotificationCenter.tsx +364 -0
  215. package/src/components/overlays/Popover.test.tsx +40 -0
  216. package/src/components/overlays/Popover.tsx +46 -0
  217. package/src/components/overlays/Sheet.tsx +163 -0
  218. package/src/components/overlays/Tooltip.test.tsx +33 -0
  219. package/src/components/overlays/Tooltip.tsx +32 -0
  220. package/src/components/overlays/index.ts +12 -0
  221. package/src/dates.ts +2 -0
  222. package/src/dnd.ts +1 -0
  223. package/src/forms.ts +1 -0
  224. package/src/globals.css +187 -0
  225. package/src/hooks/index.ts +6 -0
  226. package/src/hooks/useForm.ts +247 -0
  227. package/src/hooks/useMotionPreference.test.ts +102 -0
  228. package/src/hooks/useMotionPreference.ts +78 -0
  229. package/src/hooks/useTheme.ts +58 -0
  230. package/src/hooks.ts +9 -0
  231. package/src/index.ts +168 -0
  232. package/src/lib/animations.ts +356 -0
  233. package/src/lib/breadcrumbs.ts +94 -0
  234. package/src/lib/colors.ts +493 -0
  235. package/src/lib/store/customizer.ts +482 -0
  236. package/src/lib/store/index.ts +3 -0
  237. package/src/lib/store/theme.ts +55 -0
  238. package/src/lib/syntax-parser/index.ts +50 -0
  239. package/src/lib/syntax-parser/patterns.ts +64 -0
  240. package/src/lib/syntax-parser/tokenizer.ts +117 -0
  241. package/src/lib/syntax-parser/types.ts +27 -0
  242. package/src/lib/utils.ts +6 -0
  243. package/src/lib/validation.ts +204 -0
  244. package/src/lib/webgl/Color.ts +11 -0
  245. package/src/lib/webgl/Mesh.ts +41 -0
  246. package/src/lib/webgl/Program.ts +118 -0
  247. package/src/lib/webgl/Renderer.ts +51 -0
  248. package/src/lib/webgl/Triangle.ts +27 -0
  249. package/src/lib/webgl/Vec3.ts +18 -0
  250. package/src/lib/webgl/index.ts +13 -0
  251. package/src/nativewind-env.d.ts +1 -0
  252. package/src/providers/ThemeProvider.tsx +461 -0
  253. package/src/providers/index.ts +1 -0
  254. package/src/providers.ts +7 -0
  255. package/src/tables.ts +1 -0
  256. package/src/test/setup.ts +39 -0
  257. package/src/theme.css +158 -0
  258. package/src/tokens.ts +7 -0
  259. package/src/utils.ts +12 -0
  260. package/src/webgl.ts +1 -0
@@ -0,0 +1,1859 @@
1
+ "use client";
2
+
3
+ // src/providers/ThemeProvider.tsx
4
+ import { useEffect, useState } from "react";
5
+
6
+ // src/lib/store/theme.ts
7
+ import { create } from "zustand";
8
+ import { persist } from "zustand/middleware";
9
+ var useThemeStore = create()(
10
+ persist(
11
+ (set, get) => ({
12
+ // Defaults
13
+ theme: "volt",
14
+ mode: "dark",
15
+ // Actions
16
+ setTheme: (theme) => set({ theme }),
17
+ setMode: (mode) => set({ mode }),
18
+ toggleMode: () => set((state) => ({ mode: state.mode === "light" ? "dark" : "light" })),
19
+ // Computed
20
+ get themeConfig() {
21
+ const state = get();
22
+ return { name: state.theme, mode: state.mode };
23
+ }
24
+ }),
25
+ {
26
+ name: "ecosystem-theme",
27
+ // Only persist theme and mode
28
+ partialize: (state) => ({
29
+ theme: state.theme,
30
+ mode: state.mode
31
+ })
32
+ }
33
+ )
34
+ );
35
+
36
+ // src/lib/store/customizer.ts
37
+ import { create as create2 } from "zustand";
38
+ import { persist as persist2 } from "zustand/middleware";
39
+
40
+ // ../tokens/src/studio.ts
41
+ var studioTokens = {
42
+ light: {
43
+ colors: {
44
+ // Backgrounds
45
+ background: "#ffffff",
46
+ backgroundSecondary: "#fafafa",
47
+ backgroundTertiary: "#f5f5f5",
48
+ // Foregrounds
49
+ foreground: "#0a0a0a",
50
+ foregroundSecondary: "#525252",
51
+ foregroundTertiary: "#a3a3a3",
52
+ // Brand
53
+ primary: "#0a0a0a",
54
+ primaryForeground: "#ffffff",
55
+ secondary: "#f5f5f5",
56
+ secondaryForeground: "#0a0a0a",
57
+ accent: "#0070f3",
58
+ accentForeground: "#ffffff",
59
+ // Borders
60
+ border: "#d4d4d4",
61
+ borderSubtle: "#f5f5f5",
62
+ // States
63
+ hover: "#fafafa",
64
+ active: "#f0f0f0",
65
+ // Link hover states
66
+ linkHover: "#0a0a0a",
67
+ linkHoverForeground: "#ffffff",
68
+ // Semantic
69
+ success: "#00a86b",
70
+ successForeground: "#ffffff",
71
+ warning: "#f59e0b",
72
+ warningForeground: "#ffffff",
73
+ error: "#ef4444",
74
+ errorForeground: "#ffffff",
75
+ info: "#0070f3",
76
+ infoForeground: "#ffffff",
77
+ // Component-specific colors
78
+ card: "#ffffff",
79
+ cardForeground: "#0a0a0a",
80
+ popover: "#ffffff",
81
+ popoverForeground: "#0a0a0a",
82
+ muted: "#f5f5f5",
83
+ mutedForeground: "#737373",
84
+ destructive: "#ef4444",
85
+ destructiveForeground: "#ffffff",
86
+ input: "#d4d4d4",
87
+ ring: "#0a0a0a",
88
+ // Surface is used by various components
89
+ surface: "#fafafa",
90
+ // Glass effects
91
+ glass: "rgba(255, 255, 255, 0.7)",
92
+ glassBorder: "rgba(0, 0, 0, 0.1)"
93
+ },
94
+ effects: {
95
+ blur: {
96
+ sm: "blur(4px)",
97
+ md: "blur(8px)",
98
+ lg: "blur(16px)",
99
+ xl: "blur(24px)"
100
+ },
101
+ shadow: {
102
+ sm: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
103
+ md: "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
104
+ lg: "0 10px 15px -3px rgba(0, 0, 0, 0.1)",
105
+ xl: "0 20px 25px -5px rgba(0, 0, 0, 0.1)",
106
+ "2xl": "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
107
+ }
108
+ }
109
+ },
110
+ dark: {
111
+ colors: {
112
+ // Backgrounds
113
+ background: "#000000",
114
+ backgroundSecondary: "#171717",
115
+ backgroundTertiary: "#262626",
116
+ // Foregrounds
117
+ foreground: "#fafafa",
118
+ foregroundSecondary: "#a3a3a3",
119
+ foregroundTertiary: "#858585",
120
+ // Brand
121
+ primary: "#ffffff",
122
+ primaryForeground: "#0a0a0a",
123
+ secondary: "#262626",
124
+ secondaryForeground: "#fafafa",
125
+ accent: "#0090ff",
126
+ accentForeground: "#ffffff",
127
+ // Borders
128
+ border: "#404040",
129
+ borderSubtle: "#1a1a1a",
130
+ // States
131
+ hover: "#1a1a1a",
132
+ active: "#262626",
133
+ // Link hover states
134
+ linkHover: "#ffffff",
135
+ linkHoverForeground: "#0a0a0a",
136
+ // Semantic
137
+ success: "#10b981",
138
+ successForeground: "#ffffff",
139
+ warning: "#f59e0b",
140
+ warningForeground: "#ffffff",
141
+ error: "#ef4444",
142
+ errorForeground: "#ffffff",
143
+ info: "#0090ff",
144
+ infoForeground: "#ffffff",
145
+ // Component-specific colors
146
+ card: "#0a0a0a",
147
+ cardForeground: "#fafafa",
148
+ popover: "#0a0a0a",
149
+ popoverForeground: "#fafafa",
150
+ muted: "#262626",
151
+ mutedForeground: "#a3a3a3",
152
+ destructive: "#ef4444",
153
+ destructiveForeground: "#ffffff",
154
+ input: "#404040",
155
+ ring: "#d4d4d4",
156
+ // Surface is used by various components
157
+ surface: "#171717",
158
+ // Glass effects
159
+ glass: "rgba(0, 0, 0, 0.7)",
160
+ glassBorder: "rgba(255, 255, 255, 0.1)"
161
+ },
162
+ effects: {
163
+ blur: {
164
+ sm: "blur(4px)",
165
+ md: "blur(8px)",
166
+ lg: "blur(16px)",
167
+ xl: "blur(24px)"
168
+ },
169
+ shadow: {
170
+ sm: "0 1px 2px 0 rgba(0, 0, 0, 0.3)",
171
+ md: "0 4px 6px -1px rgba(0, 0, 0, 0.5)",
172
+ lg: "0 10px 15px -3px rgba(0, 0, 0, 0.6)",
173
+ xl: "0 20px 25px -5px rgba(0, 0, 0, 0.7)",
174
+ "2xl": "0 25px 50px -12px rgba(0, 0, 0, 0.8)"
175
+ }
176
+ }
177
+ },
178
+ /**
179
+ * Motion personality for Studio theme
180
+ */
181
+ motion: {
182
+ // Duration scales based on motion slider (0-10)
183
+ getDuration: (intensity) => {
184
+ if (intensity === 0) return "0ms";
185
+ const ms = 150 + (intensity - 1) * 40;
186
+ return `${ms}ms`;
187
+ },
188
+ // Easing curves - smooth and professional
189
+ ease: {
190
+ default: "cubic-bezier(0.4, 0, 0.2, 1)",
191
+ // ease-in-out
192
+ in: "cubic-bezier(0.4, 0, 1, 1)",
193
+ out: "cubic-bezier(0, 0, 0.2, 1)",
194
+ spring: "cubic-bezier(0.16, 1, 0.3, 1)"
195
+ // Smooth spring
196
+ }
197
+ },
198
+ /**
199
+ * Interaction tokens for Studio theme
200
+ * Subtle, professional — minimal overlay, gentle scale
201
+ */
202
+ interactions: {
203
+ hover: { overlayColor: { light: "#000000", dark: "#ffffff" }, opacity: 0.06 },
204
+ active: { scale: 0.98 },
205
+ focus: { ringWidth: "2px", ringOffset: "2px" },
206
+ disabled: { opacity: 0.5 }
207
+ },
208
+ typography: {
209
+ heading: {
210
+ fontFamily: "var(--font-geist-sans)",
211
+ fontWeight: "600",
212
+ letterSpacing: "-0.02em"
213
+ },
214
+ body: {
215
+ fontFamily: "var(--font-geist-sans)",
216
+ fontWeight: "400",
217
+ letterSpacing: "0"
218
+ },
219
+ mono: {
220
+ fontFamily: "var(--font-geist-mono)",
221
+ fontWeight: "400",
222
+ letterSpacing: "0"
223
+ }
224
+ }
225
+ };
226
+
227
+ // ../tokens/src/terra.ts
228
+ var terraTokens = {
229
+ light: {
230
+ colors: {
231
+ // Warm, earthy backgrounds
232
+ background: "#faf8f5",
233
+ backgroundSecondary: "#f5f1eb",
234
+ backgroundTertiary: "#ede8e0",
235
+ // Warm neutrals for text
236
+ foreground: "#2d2823",
237
+ foregroundSecondary: "#5a524a",
238
+ foregroundTertiary: "#8a7f72",
239
+ // Muted sage green as primary
240
+ primary: "#7a9b7f",
241
+ primaryForeground: "#faf8f5",
242
+ primaryHover: "#6a8b6f",
243
+ // Secondary - warm stone
244
+ secondary: "#ede8e0",
245
+ secondaryForeground: "#2d2823",
246
+ // Warm terracotta accent
247
+ accent: "#c17a5f",
248
+ accentForeground: "#faf8f5",
249
+ accentHover: "#b16a4f",
250
+ // Semantic colors with muted, organic tones
251
+ success: "#6b8e6f",
252
+ successForeground: "#faf8f5",
253
+ warning: "#d4a574",
254
+ warningForeground: "#2d2823",
255
+ error: "#c17a5f",
256
+ errorForeground: "#faf8f5",
257
+ info: "#8b9dc3",
258
+ infoForeground: "#faf8f5",
259
+ // Borders - warm subtle
260
+ border: "#e0d8cf",
261
+ borderSubtle: "#ede8e0",
262
+ // States
263
+ hover: "#f5f1eb",
264
+ active: "#ede8e0",
265
+ // Link hover states - Muted sage green
266
+ linkHover: "#7a9b7f",
267
+ linkHoverForeground: "#faf8f5",
268
+ // Soft glass effects
269
+ glass: "rgba(250, 248, 245, 0.85)",
270
+ glassBorder: "rgba(122, 155, 127, 0.15)"
271
+ },
272
+ effects: {
273
+ blur: {
274
+ sm: "blur(6px)",
275
+ md: "blur(12px)",
276
+ lg: "blur(20px)",
277
+ xl: "blur(32px)"
278
+ },
279
+ shadow: {
280
+ sm: "0 2px 4px 0 rgba(45, 40, 35, 0.06)",
281
+ md: "0 4px 8px -2px rgba(45, 40, 35, 0.08)",
282
+ lg: "0 8px 16px -4px rgba(45, 40, 35, 0.12)",
283
+ xl: "0 16px 32px -8px rgba(45, 40, 35, 0.16)",
284
+ "2xl": "0 24px 48px -12px rgba(45, 40, 35, 0.20)"
285
+ }
286
+ }
287
+ },
288
+ dark: {
289
+ colors: {
290
+ // Deep forest backgrounds
291
+ background: "#1a1614",
292
+ backgroundSecondary: "#252220",
293
+ backgroundTertiary: "#2f2b28",
294
+ // Warm light text
295
+ foreground: "#f5f1eb",
296
+ foregroundSecondary: "#c7bfb5",
297
+ foregroundTertiary: "#8a7f72",
298
+ // Brighter sage for dark mode
299
+ primary: "#a8c5ad",
300
+ primaryForeground: "#1a1614",
301
+ primaryHover: "#b8d5bd",
302
+ // Secondary - lighter warm stone
303
+ secondary: "#2f2b28",
304
+ secondaryForeground: "#f5f1eb",
305
+ // Warm peachy accent for dark
306
+ accent: "#e5a78a",
307
+ accentForeground: "#1a1614",
308
+ accentHover: "#f5b79a",
309
+ // Semantic colors adjusted for dark
310
+ success: "#95b89a",
311
+ successForeground: "#1a1614",
312
+ warning: "#e5c59a",
313
+ warningForeground: "#1a1614",
314
+ error: "#e5a78a",
315
+ errorForeground: "#1a1614",
316
+ info: "#a8b5d5",
317
+ infoForeground: "#1a1614",
318
+ // Borders
319
+ border: "#3a3530",
320
+ borderSubtle: "#2f2b28",
321
+ // States
322
+ hover: "#252220",
323
+ active: "#2f2b28",
324
+ // Link hover states - Brighter sage for dark mode
325
+ linkHover: "#a8c5ad",
326
+ linkHoverForeground: "#1a1614",
327
+ // Dark glass effects
328
+ glass: "rgba(26, 22, 20, 0.85)",
329
+ glassBorder: "rgba(168, 197, 173, 0.2)"
330
+ },
331
+ effects: {
332
+ blur: {
333
+ sm: "blur(6px)",
334
+ md: "blur(12px)",
335
+ lg: "blur(20px)",
336
+ xl: "blur(32px)"
337
+ },
338
+ shadow: {
339
+ sm: "0 2px 4px 0 rgba(0, 0, 0, 0.3)",
340
+ md: "0 4px 8px -2px rgba(0, 0, 0, 0.4)",
341
+ lg: "0 8px 16px -4px rgba(0, 0, 0, 0.5)",
342
+ xl: "0 16px 32px -8px rgba(0, 0, 0, 0.6)",
343
+ "2xl": "0 24px 48px -12px rgba(0, 0, 0, 0.7)"
344
+ }
345
+ }
346
+ },
347
+ motion: {
348
+ getDuration: (intensity) => {
349
+ if (intensity === 0) return "0ms";
350
+ const ms = 300 + (intensity - 1) * 60;
351
+ return `${ms}ms`;
352
+ },
353
+ ease: {
354
+ default: "cubic-bezier(0.33, 1, 0.68, 1)",
355
+ // Organic, flowing
356
+ in: "cubic-bezier(0.4, 0, 1, 1)",
357
+ out: "cubic-bezier(0, 0, 0.2, 1)",
358
+ spring: "cubic-bezier(0.16, 1, 0.3, 1)"
359
+ }
360
+ },
361
+ /**
362
+ * Interaction tokens for Terra theme
363
+ * Warm, organic — earthy overlay tones, softer scale
364
+ */
365
+ interactions: {
366
+ hover: { overlayColor: { light: "#2d2823", dark: "#f5f1eb" }, opacity: 0.07 },
367
+ active: { scale: 0.97 },
368
+ focus: { ringWidth: "2px", ringOffset: "2px" },
369
+ disabled: { opacity: 0.5 }
370
+ },
371
+ typography: {
372
+ heading: {
373
+ fontFamily: "var(--font-terra-serif)",
374
+ // Lora serif
375
+ fontWeight: "600",
376
+ letterSpacing: "-0.01em"
377
+ },
378
+ body: {
379
+ fontFamily: "var(--font-terra-sans)",
380
+ // Instrument Sans
381
+ fontWeight: "400",
382
+ letterSpacing: "0"
383
+ },
384
+ mono: {
385
+ fontFamily: "var(--font-terra-mono)",
386
+ fontWeight: "400",
387
+ letterSpacing: "0"
388
+ }
389
+ }
390
+ };
391
+
392
+ // ../tokens/src/volt.ts
393
+ var voltTokens = {
394
+ light: {
395
+ colors: {
396
+ // Bright, punchy backgrounds
397
+ background: "#ffffff",
398
+ backgroundSecondary: "#f8f9fb",
399
+ backgroundTertiary: "#f0f2f5",
400
+ // Sharp contrast text
401
+ foreground: "#0a0a0a",
402
+ foregroundSecondary: "#4a4a4a",
403
+ foregroundTertiary: "#8a8a8a",
404
+ // Electric blue primary (WCAG AA compliant)
405
+ primary: "#0066ff",
406
+ primaryForeground: "#ffffff",
407
+ primaryHover: "#0052cc",
408
+ // Secondary - cool gray
409
+ secondary: "#f0f2f5",
410
+ secondaryForeground: "#0a0a0a",
411
+ // Vibrant cyan accent
412
+ accent: "#00d9ff",
413
+ accentForeground: "#0a0a0a",
414
+ accentHover: "#00c3e6",
415
+ // Bold semantic colors
416
+ success: "#00cc66",
417
+ successForeground: "#ffffff",
418
+ warning: "#ffaa00",
419
+ warningForeground: "#0a0a0a",
420
+ error: "#ff3366",
421
+ errorForeground: "#ffffff",
422
+ info: "#3399ff",
423
+ infoForeground: "#ffffff",
424
+ // Borders
425
+ border: "#e0e4ea",
426
+ borderSubtle: "#f0f2f5",
427
+ // States
428
+ hover: "#f8f9fb",
429
+ active: "#f0f2f5",
430
+ // Link hover states - Electric blue with high contrast
431
+ linkHover: "#0066ff",
432
+ linkHoverForeground: "#ffffff",
433
+ // Crisp glass effects
434
+ glass: "rgba(255, 255, 255, 0.8)",
435
+ glassBorder: "rgba(0, 102, 255, 0.2)"
436
+ },
437
+ effects: {
438
+ blur: {
439
+ sm: "blur(8px)",
440
+ md: "blur(16px)",
441
+ lg: "blur(32px)",
442
+ xl: "blur(48px)"
443
+ },
444
+ shadow: {
445
+ sm: "0 0 8px rgba(0, 102, 255, 0.15)",
446
+ md: "0 0 16px rgba(0, 102, 255, 0.2)",
447
+ lg: "0 0 24px rgba(0, 102, 255, 0.25)",
448
+ xl: "0 0 32px rgba(0, 102, 255, 0.3)",
449
+ "2xl": "0 0 48px rgba(0, 102, 255, 0.4)"
450
+ }
451
+ }
452
+ },
453
+ dark: {
454
+ colors: {
455
+ // Pure black cyberpunk background
456
+ background: "#000000",
457
+ backgroundSecondary: "#0a0a0a",
458
+ backgroundTertiary: "#141414",
459
+ // Bright white text
460
+ foreground: "#ffffff",
461
+ foregroundSecondary: "#b3b3b3",
462
+ foregroundTertiary: "#666666",
463
+ // Neon blue primary
464
+ primary: "#0099ff",
465
+ primaryForeground: "#000000",
466
+ primaryHover: "#00aaff",
467
+ // Secondary - dark gray
468
+ secondary: "#141414",
469
+ secondaryForeground: "#ffffff",
470
+ // Neon cyan accent
471
+ accent: "#00ffff",
472
+ accentForeground: "#000000",
473
+ accentHover: "#33ffff",
474
+ // Neon semantic colors
475
+ success: "#00ff99",
476
+ successForeground: "#000000",
477
+ warning: "#ffcc00",
478
+ warningForeground: "#000000",
479
+ error: "#ff0066",
480
+ errorForeground: "#ffffff",
481
+ info: "#66ccff",
482
+ infoForeground: "#000000",
483
+ // Borders
484
+ border: "#1a1a1a",
485
+ borderSubtle: "#141414",
486
+ // States
487
+ hover: "#0a0a0a",
488
+ active: "#141414",
489
+ // Link hover states - Neon cyan (high luma)
490
+ linkHover: "#00ffff",
491
+ linkHoverForeground: "#000000",
492
+ // Dark glass with glow
493
+ glass: "rgba(0, 0, 0, 0.8)",
494
+ glassBorder: "rgba(0, 153, 255, 0.3)"
495
+ },
496
+ effects: {
497
+ blur: {
498
+ sm: "blur(8px)",
499
+ md: "blur(16px)",
500
+ lg: "blur(32px)",
501
+ xl: "blur(48px)"
502
+ },
503
+ shadow: {
504
+ sm: "0 0 12px rgba(0, 153, 255, 0.4)",
505
+ md: "0 0 20px rgba(0, 153, 255, 0.5)",
506
+ lg: "0 0 32px rgba(0, 153, 255, 0.6)",
507
+ xl: "0 0 48px rgba(0, 153, 255, 0.7)",
508
+ "2xl": "0 0 64px rgba(0, 153, 255, 0.8)"
509
+ }
510
+ }
511
+ },
512
+ motion: {
513
+ getDuration: (intensity) => {
514
+ if (intensity === 0) return "0ms";
515
+ const ms = 100 + (intensity - 1) * 25;
516
+ return `${ms}ms`;
517
+ },
518
+ ease: {
519
+ default: "cubic-bezier(0.16, 1, 0.3, 1)",
520
+ // Snappy spring
521
+ in: "cubic-bezier(0.4, 0, 1, 1)",
522
+ out: "cubic-bezier(0, 0, 0.2, 1)",
523
+ spring: "cubic-bezier(0.68, -0.55, 0.27, 1.55)"
524
+ // Bouncy
525
+ }
526
+ },
527
+ /**
528
+ * Interaction tokens for Volt theme
529
+ * Electric, brand-tinted — blue overlay, punchy scale
530
+ */
531
+ interactions: {
532
+ hover: { overlayColor: { light: "#0066ff", dark: "#0099ff" }, opacity: 0.1 },
533
+ active: { scale: 0.96 },
534
+ focus: { ringWidth: "2px", ringOffset: "2px" },
535
+ disabled: { opacity: 0.5 }
536
+ },
537
+ typography: {
538
+ heading: {
539
+ fontFamily: "var(--font-volt-sans)",
540
+ // Space Grotesk
541
+ fontWeight: "700",
542
+ // Bold
543
+ letterSpacing: "-0.03em"
544
+ },
545
+ body: {
546
+ fontFamily: "var(--font-volt-sans)",
547
+ fontWeight: "400",
548
+ letterSpacing: "0"
549
+ },
550
+ mono: {
551
+ fontFamily: "var(--font-volt-mono)",
552
+ // Fira Code
553
+ fontWeight: "400",
554
+ letterSpacing: "0"
555
+ }
556
+ }
557
+ };
558
+
559
+ // ../tokens/src/speedboat.ts
560
+ var speedboatTokens = {
561
+ light: {
562
+ colors: {
563
+ // Backgrounds
564
+ background: "#FFFFFF",
565
+ backgroundSecondary: "#F8F8F8",
566
+ // grey50
567
+ backgroundTertiary: "#ECECEC",
568
+ // grey100
569
+ // Foregrounds
570
+ foreground: "#212121",
571
+ // grey900 — ContentPrimary
572
+ foregroundSecondary: "#5D5D5D",
573
+ // grey700 — ContentSecondary
574
+ foregroundTertiary: "#8891A7",
575
+ // grey500 — muted icons
576
+ // Brand
577
+ primary: "#346BEA",
578
+ // accent blue
579
+ primaryForeground: "#FFFFFF",
580
+ secondary: "#EBF0FD",
581
+ // blue100 — chip bg
582
+ secondaryForeground: "#1E49AA",
583
+ // blue600 — chip text
584
+ accent: "#346BEA",
585
+ // same as primary for Speedboat
586
+ accentForeground: "#FFFFFF",
587
+ // Borders
588
+ border: "#ECECEC",
589
+ // grey100 — BorderPrimary
590
+ borderSubtle: "#F8F8F8",
591
+ // grey50
592
+ // States
593
+ hover: "#F8F8F8",
594
+ // grey50
595
+ active: "#ECECEC",
596
+ // grey100
597
+ // Link hover states
598
+ linkHover: "#1E49AA",
599
+ // blue600
600
+ linkHoverForeground: "#FFFFFF",
601
+ // Semantic
602
+ success: "#2E7D32",
603
+ successForeground: "#FFFFFF",
604
+ warning: "#E65100",
605
+ warningForeground: "#FFFFFF",
606
+ error: "#C62828",
607
+ errorForeground: "#FFFFFF",
608
+ info: "#346BEA",
609
+ infoForeground: "#FFFFFF",
610
+ // Component-specific colors
611
+ card: "#FFFFFF",
612
+ cardForeground: "#212121",
613
+ popover: "#FFFFFF",
614
+ popoverForeground: "#212121",
615
+ muted: "#F8F8F8",
616
+ // grey50
617
+ mutedForeground: "#8891A7",
618
+ // grey500
619
+ destructive: "#C62828",
620
+ // error red
621
+ destructiveForeground: "#FFFFFF",
622
+ input: "#DFDFDF",
623
+ // grey200 — input borders
624
+ ring: "#346BEA",
625
+ // accent blue for focus rings
626
+ // Surface
627
+ surface: "#F8F8F8",
628
+ // grey50
629
+ // Glass effects
630
+ glass: "rgba(255, 255, 255, 0.85)",
631
+ glassBorder: "rgba(0, 0, 0, 0.08)"
632
+ },
633
+ effects: {
634
+ blur: {
635
+ sm: "blur(4px)",
636
+ md: "blur(8px)",
637
+ lg: "blur(16px)",
638
+ xl: "blur(24px)"
639
+ },
640
+ shadow: {
641
+ sm: "0 1px 2px rgba(0, 0, 0, 0.05)",
642
+ md: "0 2px 8px rgba(0, 0, 0, 0.08)",
643
+ lg: "0 4px 16px rgba(0, 0, 0, 0.10)",
644
+ xl: "0 8px 24px rgba(0, 0, 0, 0.12)",
645
+ "2xl": "0 16px 48px rgba(0, 0, 0, 0.16)"
646
+ }
647
+ }
648
+ },
649
+ dark: {
650
+ colors: {
651
+ // Backgrounds — derived dark palette
652
+ background: "#0F1117",
653
+ backgroundSecondary: "#1A1C25",
654
+ backgroundTertiary: "#252833",
655
+ // Foregrounds
656
+ foreground: "#F0F0F2",
657
+ foregroundSecondary: "#A0A3B1",
658
+ foregroundTertiary: "#6B6F80",
659
+ // Brand — keep the accent blue, slightly brighten for dark bg
660
+ primary: "#4A7FF7",
661
+ primaryForeground: "#FFFFFF",
662
+ secondary: "#1E2540",
663
+ secondaryForeground: "#A6C1FF",
664
+ // blue300
665
+ accent: "#4A7FF7",
666
+ accentForeground: "#FFFFFF",
667
+ // Borders
668
+ border: "#2E3140",
669
+ borderSubtle: "#1A1C25",
670
+ // States
671
+ hover: "#1A1C25",
672
+ active: "#252833",
673
+ // Link hover states
674
+ linkHover: "#A6C1FF",
675
+ // blue300 — lighter for dark mode
676
+ linkHoverForeground: "#0F1117",
677
+ // Semantic — slightly brighter versions for dark bg
678
+ success: "#4CAF50",
679
+ successForeground: "#FFFFFF",
680
+ warning: "#FF8A50",
681
+ warningForeground: "#FFFFFF",
682
+ error: "#EF5350",
683
+ errorForeground: "#FFFFFF",
684
+ info: "#4A7FF7",
685
+ infoForeground: "#FFFFFF",
686
+ // Component-specific colors
687
+ card: "#1A1C25",
688
+ cardForeground: "#F0F0F2",
689
+ popover: "#1A1C25",
690
+ popoverForeground: "#F0F0F2",
691
+ muted: "#252833",
692
+ mutedForeground: "#6B6F80",
693
+ destructive: "#EF5350",
694
+ destructiveForeground: "#FFFFFF",
695
+ input: "#2E3140",
696
+ ring: "#4A7FF7",
697
+ // Surface
698
+ surface: "#1A1C25",
699
+ // Glass effects
700
+ glass: "rgba(15, 17, 23, 0.85)",
701
+ glassBorder: "rgba(255, 255, 255, 0.08)"
702
+ },
703
+ effects: {
704
+ blur: {
705
+ sm: "blur(4px)",
706
+ md: "blur(8px)",
707
+ lg: "blur(16px)",
708
+ xl: "blur(24px)"
709
+ },
710
+ shadow: {
711
+ sm: "0 1px 2px rgba(0, 0, 0, 0.20)",
712
+ md: "0 2px 8px rgba(0, 0, 0, 0.30)",
713
+ lg: "0 4px 16px rgba(0, 0, 0, 0.35)",
714
+ xl: "0 8px 24px rgba(0, 0, 0, 0.40)",
715
+ "2xl": "0 16px 48px rgba(0, 0, 0, 0.50)"
716
+ }
717
+ }
718
+ },
719
+ /**
720
+ * Motion personality for Speedboat theme
721
+ * Professional and snappy — slightly faster than Studio
722
+ */
723
+ motion: {
724
+ getDuration: (intensity) => {
725
+ if (intensity === 0) return "0ms";
726
+ const ms = 120 + (intensity - 1) * 35;
727
+ return `${ms}ms`;
728
+ },
729
+ ease: {
730
+ default: "cubic-bezier(0.4, 0, 0.2, 1)",
731
+ in: "cubic-bezier(0.4, 0, 1, 1)",
732
+ out: "cubic-bezier(0, 0, 0.2, 1)",
733
+ spring: "cubic-bezier(0.16, 1, 0.3, 1)"
734
+ }
735
+ },
736
+ /**
737
+ * Interaction tokens for Speedboat theme
738
+ * Professional, clean — matches Studio's subtle feel
739
+ */
740
+ interactions: {
741
+ hover: { overlayColor: { light: "#000000", dark: "#ffffff" }, opacity: 0.06 },
742
+ active: { scale: 0.98 },
743
+ focus: { ringWidth: "2px", ringOffset: "2px" },
744
+ disabled: { opacity: 0.5 }
745
+ },
746
+ /**
747
+ * Typography for Speedboat theme
748
+ * Montserrat headings + Roboto body — Moloco brand fonts
749
+ */
750
+ typography: {
751
+ heading: {
752
+ fontFamily: "var(--font-montserrat)",
753
+ fontWeight: "700",
754
+ letterSpacing: "-0.01em"
755
+ },
756
+ body: {
757
+ fontFamily: "var(--font-roboto)",
758
+ fontWeight: "400",
759
+ letterSpacing: "0"
760
+ },
761
+ mono: {
762
+ fontFamily: "var(--font-geist-mono)",
763
+ fontWeight: "400",
764
+ letterSpacing: "0"
765
+ }
766
+ }
767
+ };
768
+
769
+ // ../tokens/src/syntax.ts
770
+ var syntaxColors = {
771
+ light: {
772
+ comment: "#22863a",
773
+ // Green for comments
774
+ keyword: "#8250df",
775
+ // Purple for keywords (import, export, const, etc.)
776
+ function: "#6639ba",
777
+ // Purple for function names
778
+ string: "#c1592a",
779
+ // Orange for strings
780
+ number: "#0a3069",
781
+ // Blue for numbers
782
+ boolean: "#0550ae",
783
+ // Blue for booleans
784
+ operator: "#1a1a1a",
785
+ // Almost black for operators
786
+ property: "#0550ae",
787
+ // Blue for properties
788
+ className: "#005cc5",
789
+ // Blue for class names
790
+ tag: "#005cc5",
791
+ // Blue for HTML/JSX tags
792
+ attribute: "#0550ae",
793
+ // Blue for attributes
794
+ variable: "#0550ae",
795
+ // Blue for variables
796
+ punctuation: "#57606a",
797
+ // Gray for punctuation
798
+ plain: "#1a1a1a"
799
+ // Default text color
800
+ },
801
+ dark: {
802
+ comment: "#6A9955",
803
+ // Green for comments
804
+ keyword: "#C586C0",
805
+ // Purple for keywords (import, export, const, etc.)
806
+ function: "#DCDCAA",
807
+ // Yellow for function names
808
+ string: "#CE9178",
809
+ // Orange for strings
810
+ number: "#B5CEA8",
811
+ // Light green for numbers
812
+ boolean: "#569CD6",
813
+ // Blue for booleans
814
+ operator: "#D4D4D4",
815
+ // Light gray for operators
816
+ property: "#9CDCFE",
817
+ // Light blue for properties
818
+ className: "#4EC9B0",
819
+ // Cyan for class names
820
+ tag: "#4EC9B0",
821
+ // Cyan for HTML/JSX tags
822
+ attribute: "#9CDCFE",
823
+ // Light blue for attributes
824
+ variable: "#9CDCFE",
825
+ // Light blue for variables
826
+ punctuation: "#808080",
827
+ // Gray for punctuation
828
+ plain: "#D4D4D4"
829
+ // Default text color
830
+ }
831
+ };
832
+ var codeColors = {
833
+ light: {
834
+ // Block code background - cool gray for subtle distinction
835
+ blockBackground: "#F8F9FA",
836
+ // Inline code background - pale amber for warmth and visibility
837
+ inlineBackground: "#FEF3E7",
838
+ // Border color for definition and separation
839
+ border: "#E1E4E8"
840
+ },
841
+ dark: {
842
+ // Block code background - VS Code-inspired dark background
843
+ blockBackground: "#1E1E1E",
844
+ // Inline code background - slightly lighter for contrast
845
+ inlineBackground: "#252525",
846
+ // Border color for definition
847
+ border: "#3D3D3D"
848
+ }
849
+ };
850
+
851
+ // ../tokens/src/color-utils.ts
852
+ function hexToRgb(hex) {
853
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
854
+ return result ? {
855
+ r: parseInt(result[1], 16),
856
+ g: parseInt(result[2], 16),
857
+ b: parseInt(result[3], 16)
858
+ } : null;
859
+ }
860
+ function hexToHSL(hex) {
861
+ const rgb = hexToRgb(hex);
862
+ if (!rgb) return { h: 0, s: 0, l: 0 };
863
+ const r = rgb.r / 255;
864
+ const g = rgb.g / 255;
865
+ const b = rgb.b / 255;
866
+ const max = Math.max(r, g, b);
867
+ const min = Math.min(r, g, b);
868
+ let h = 0, s = 0, l = (max + min) / 2;
869
+ if (max !== min) {
870
+ const d = max - min;
871
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
872
+ switch (max) {
873
+ case r:
874
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
875
+ break;
876
+ case g:
877
+ h = ((b - r) / d + 2) / 6;
878
+ break;
879
+ case b:
880
+ h = ((r - g) / d + 4) / 6;
881
+ break;
882
+ }
883
+ }
884
+ return {
885
+ h: Math.round(h * 360),
886
+ s: Math.round(s * 100),
887
+ l: Math.round(l * 100)
888
+ };
889
+ }
890
+ function hslToHex(h, s, l) {
891
+ h = h / 360;
892
+ s = s / 100;
893
+ l = l / 100;
894
+ let r, g, b;
895
+ if (s === 0) {
896
+ r = g = b = l;
897
+ } else {
898
+ const hue2rgb = (p2, q2, t) => {
899
+ if (t < 0) t += 1;
900
+ if (t > 1) t -= 1;
901
+ if (t < 1 / 6) return p2 + (q2 - p2) * 6 * t;
902
+ if (t < 1 / 2) return q2;
903
+ if (t < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - t) * 6;
904
+ return p2;
905
+ };
906
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
907
+ const p = 2 * l - q;
908
+ r = hue2rgb(p, q, h + 1 / 3);
909
+ g = hue2rgb(p, q, h);
910
+ b = hue2rgb(p, q, h - 1 / 3);
911
+ }
912
+ const toHex = (x) => {
913
+ const hex = Math.round(x * 255).toString(16);
914
+ return hex.length === 1 ? "0" + hex : hex;
915
+ };
916
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
917
+ }
918
+ function adjustLightness(hex, percent) {
919
+ const hsl = hexToHSL(hex);
920
+ const newL = Math.max(0, Math.min(100, hsl.l + percent));
921
+ return hslToHex(hsl.h, hsl.s, newL);
922
+ }
923
+ function adjustSaturation(hex, percent) {
924
+ const hsl = hexToHSL(hex);
925
+ const newS = Math.max(0, Math.min(100, hsl.s + percent));
926
+ return hslToHex(hsl.h, newS, hsl.l);
927
+ }
928
+ function rotateHue(hex, degrees) {
929
+ const hsl = hexToHSL(hex);
930
+ const newH = (hsl.h + degrees) % 360;
931
+ return hslToHex(newH, hsl.s, hsl.l);
932
+ }
933
+ function adjustOpacity(hex, opacity) {
934
+ const rgb = hexToRgb(hex);
935
+ if (!rgb) return hex;
936
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${opacity})`;
937
+ }
938
+ function getLuminance(r, g, b) {
939
+ const [rs, gs, bs] = [r, g, b].map((c) => {
940
+ const srgb = c / 255;
941
+ return srgb <= 0.03928 ? srgb / 12.92 : Math.pow((srgb + 0.055) / 1.055, 2.4);
942
+ });
943
+ return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
944
+ }
945
+ function getContrastRatio(hex1, hex2) {
946
+ const rgb1 = hexToRgb(hex1);
947
+ const rgb2 = hexToRgb(hex2);
948
+ if (!rgb1 || !rgb2) return 0;
949
+ const lum1 = getLuminance(rgb1.r, rgb1.g, rgb1.b);
950
+ const lum2 = getLuminance(rgb2.r, rgb2.g, rgb2.b);
951
+ const lighter = Math.max(lum1, lum2);
952
+ const darker = Math.min(lum1, lum2);
953
+ return (lighter + 0.05) / (darker + 0.05);
954
+ }
955
+ function getOptimalForeground(bgHex, whiteHex = "#ffffff", blackHex = "#000000") {
956
+ const whiteRatio = getContrastRatio(bgHex, whiteHex);
957
+ const blackRatio = getContrastRatio(bgHex, blackHex);
958
+ return whiteRatio > blackRatio ? whiteHex : blackHex;
959
+ }
960
+
961
+ // ../tokens/src/token-graph.ts
962
+ var primaryColorDerivations = {
963
+ // Links use primary color
964
+ "--color-link": {
965
+ source: "--color-primary",
966
+ transform: (primary) => primary,
967
+ description: "Links inherit primary brand color"
968
+ },
969
+ // Focus ring uses primary color
970
+ "--color-ring": {
971
+ source: "--color-primary",
972
+ transform: (primary) => primary,
973
+ description: "Focus rings use primary for brand consistency"
974
+ },
975
+ // Link hover is slightly darker primary
976
+ "--color-link-hover": {
977
+ source: "--color-primary",
978
+ transform: (primary) => adjustLightness(primary, -10),
979
+ description: "Link hover is 10% darker for visual feedback"
980
+ },
981
+ // Chart primary series
982
+ "--chart-1": {
983
+ source: "--color-primary",
984
+ transform: (primary) => primary,
985
+ description: "First chart series uses primary"
986
+ },
987
+ // Chart secondary series (lighter tint)
988
+ "--chart-2": {
989
+ source: "--color-primary",
990
+ transform: (primary) => adjustLightness(primary, 20),
991
+ description: "Second chart series is lighter tint of primary"
992
+ },
993
+ // Chart tertiary series (darker shade)
994
+ "--chart-3": {
995
+ source: "--color-primary",
996
+ transform: (primary) => adjustLightness(primary, -15),
997
+ description: "Third chart series is darker shade of primary"
998
+ },
999
+ // Chart quaternary (desaturated primary)
1000
+ "--chart-4": {
1001
+ source: "--color-primary",
1002
+ transform: (primary) => adjustSaturation(primary, -30),
1003
+ description: "Fourth chart series is muted primary"
1004
+ },
1005
+ // Chart quinary (complementary color)
1006
+ "--chart-5": {
1007
+ source: "--color-primary",
1008
+ transform: (primary) => rotateHue(primary, 180),
1009
+ description: "Fifth chart series is complementary to primary"
1010
+ }
1011
+ };
1012
+ var secondaryColorDerivations = {
1013
+ // Hover states
1014
+ "--color-hover": {
1015
+ source: "--color-secondary",
1016
+ transform: (secondary) => secondary,
1017
+ description: "Hover backgrounds use secondary"
1018
+ },
1019
+ // Active states
1020
+ "--color-active": {
1021
+ source: "--color-secondary",
1022
+ transform: (secondary) => adjustLightness(secondary, -5),
1023
+ description: "Active state is slightly darker secondary"
1024
+ },
1025
+ // Muted backgrounds
1026
+ "--color-muted": {
1027
+ source: "--color-secondary",
1028
+ transform: (secondary) => secondary,
1029
+ description: "Muted sections use secondary color"
1030
+ }
1031
+ };
1032
+ var accentColorDerivations = {
1033
+ // Info semantic color uses accent
1034
+ "--color-info": {
1035
+ source: "--color-accent",
1036
+ transform: (accent) => accent,
1037
+ description: "Info semantic color uses accent"
1038
+ },
1039
+ // Info foreground calculated for contrast
1040
+ "--color-info-foreground": {
1041
+ source: "--color-accent",
1042
+ transform: (accent) => getOptimalForeground(accent),
1043
+ description: "Info foreground calculated for contrast"
1044
+ }
1045
+ };
1046
+ var modeSpecificDerivations = {
1047
+ "--color-primary-muted": {
1048
+ light: {
1049
+ source: "--color-primary",
1050
+ transform: (primary) => adjustLightness(primary, 40),
1051
+ description: "Muted primary for light backgrounds"
1052
+ },
1053
+ dark: {
1054
+ source: "--color-primary",
1055
+ transform: (primary) => adjustLightness(primary, -20),
1056
+ description: "Muted primary for dark backgrounds"
1057
+ }
1058
+ },
1059
+ "--color-primary-subtle": {
1060
+ light: {
1061
+ source: "--color-primary",
1062
+ transform: (primary) => adjustOpacity(primary, 0.1),
1063
+ description: "Subtle primary background for light mode"
1064
+ },
1065
+ dark: {
1066
+ source: "--color-primary",
1067
+ transform: (primary) => adjustOpacity(primary, 0.2),
1068
+ description: "Subtle primary background for dark mode"
1069
+ }
1070
+ }
1071
+ };
1072
+ function computeDerivedTokens(sourceToken, sourceValue, mode) {
1073
+ const derived = {};
1074
+ Object.entries(primaryColorDerivations).forEach(([token, config]) => {
1075
+ if (config.source === sourceToken) {
1076
+ derived[token] = config.transform(sourceValue);
1077
+ }
1078
+ });
1079
+ Object.entries(secondaryColorDerivations).forEach(([token, config]) => {
1080
+ if (config.source === sourceToken) {
1081
+ derived[token] = config.transform(sourceValue);
1082
+ }
1083
+ });
1084
+ Object.entries(accentColorDerivations).forEach(([token, config]) => {
1085
+ if (config.source === sourceToken) {
1086
+ derived[token] = config.transform(sourceValue);
1087
+ }
1088
+ });
1089
+ Object.entries(modeSpecificDerivations).forEach(([token, configs]) => {
1090
+ const config = configs[mode];
1091
+ if (config.source === sourceToken) {
1092
+ derived[token] = config.transform(sourceValue);
1093
+ }
1094
+ });
1095
+ return derived;
1096
+ }
1097
+
1098
+ // src/lib/colors.ts
1099
+ var colorTokens = {
1100
+ // Background colors
1101
+ background: "var(--color-background)",
1102
+ backgroundSecondary: "var(--color-background-secondary)",
1103
+ backgroundTertiary: "var(--color-background-tertiary)",
1104
+ surface: "var(--color-surface)",
1105
+ // Foreground/Text colors
1106
+ foreground: "var(--color-foreground)",
1107
+ foregroundSecondary: "var(--color-foreground-secondary)",
1108
+ foregroundTertiary: "var(--color-foreground-tertiary)",
1109
+ textPrimary: "var(--color-text-primary)",
1110
+ textSecondary: "var(--color-text-secondary)",
1111
+ textMuted: "var(--color-text-muted)",
1112
+ // Brand colors
1113
+ primary: "var(--color-primary)",
1114
+ primaryForeground: "var(--color-primary-foreground)",
1115
+ secondary: "var(--color-secondary)",
1116
+ secondaryForeground: "var(--color-secondary-foreground)",
1117
+ accent: "var(--color-accent)",
1118
+ accentForeground: "var(--color-accent-foreground)",
1119
+ // Semantic colors
1120
+ success: "var(--color-success)",
1121
+ successForeground: "var(--color-success-foreground)",
1122
+ warning: "var(--color-warning)",
1123
+ warningForeground: "var(--color-warning-foreground)",
1124
+ error: "var(--color-error)",
1125
+ errorForeground: "var(--color-error-foreground)",
1126
+ info: "var(--color-info)",
1127
+ infoForeground: "var(--color-info-foreground)",
1128
+ // Borders
1129
+ border: "var(--color-border)",
1130
+ borderSubtle: "var(--color-border-subtle)",
1131
+ // Interactive states
1132
+ hover: "var(--color-hover)",
1133
+ active: "var(--color-active)",
1134
+ focus: "var(--color-focus)",
1135
+ // Links
1136
+ link: "var(--color-link)",
1137
+ linkHover: "var(--color-link-hover)",
1138
+ linkHoverForeground: "var(--color-link-hover-foreground)"
1139
+ };
1140
+ var semanticColors = {
1141
+ /**
1142
+ * Status colors for indicating states
1143
+ */
1144
+ status: {
1145
+ success: {
1146
+ bg: colorTokens.success,
1147
+ fg: colorTokens.successForeground
1148
+ },
1149
+ warning: {
1150
+ bg: colorTokens.warning,
1151
+ fg: colorTokens.warningForeground
1152
+ },
1153
+ error: {
1154
+ bg: colorTokens.error,
1155
+ fg: colorTokens.errorForeground
1156
+ },
1157
+ info: {
1158
+ bg: colorTokens.info,
1159
+ fg: colorTokens.infoForeground
1160
+ }
1161
+ },
1162
+ /**
1163
+ * Brand colors for primary UI elements
1164
+ */
1165
+ brand: {
1166
+ primary: {
1167
+ bg: colorTokens.primary,
1168
+ fg: colorTokens.primaryForeground
1169
+ },
1170
+ secondary: {
1171
+ bg: colorTokens.secondary,
1172
+ fg: colorTokens.secondaryForeground
1173
+ },
1174
+ accent: {
1175
+ bg: colorTokens.accent,
1176
+ fg: colorTokens.accentForeground
1177
+ }
1178
+ },
1179
+ /**
1180
+ * Interactive state colors
1181
+ */
1182
+ interactive: {
1183
+ default: {
1184
+ bg: colorTokens.background,
1185
+ fg: colorTokens.foreground
1186
+ },
1187
+ hover: {
1188
+ bg: colorTokens.hover,
1189
+ fg: colorTokens.foreground
1190
+ },
1191
+ active: {
1192
+ bg: colorTokens.active,
1193
+ fg: colorTokens.foreground
1194
+ },
1195
+ focus: {
1196
+ border: colorTokens.focus
1197
+ }
1198
+ }
1199
+ };
1200
+ function hexToRgb2(hex) {
1201
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1202
+ return result ? {
1203
+ r: parseInt(result[1], 16),
1204
+ g: parseInt(result[2], 16),
1205
+ b: parseInt(result[3], 16)
1206
+ } : null;
1207
+ }
1208
+ function getLuminance2(r, g, b) {
1209
+ const [rs, gs, bs] = [r, g, b].map((c) => {
1210
+ const srgb = c / 255;
1211
+ return srgb <= 0.03928 ? srgb / 12.92 : Math.pow((srgb + 0.055) / 1.055, 2.4);
1212
+ });
1213
+ return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
1214
+ }
1215
+ function getContrastRatio2(hex1, hex2) {
1216
+ const rgb1 = hexToRgb2(hex1);
1217
+ const rgb2 = hexToRgb2(hex2);
1218
+ if (!rgb1 || !rgb2) return 0;
1219
+ const lum1 = getLuminance2(rgb1.r, rgb1.g, rgb1.b);
1220
+ const lum2 = getLuminance2(rgb2.r, rgb2.g, rgb2.b);
1221
+ const lighter = Math.max(lum1, lum2);
1222
+ const darker = Math.min(lum1, lum2);
1223
+ return (lighter + 0.05) / (darker + 0.05);
1224
+ }
1225
+ function hexToHSL2(hex) {
1226
+ const rgb = hexToRgb2(hex);
1227
+ if (!rgb) return { h: 0, s: 0, l: 0 };
1228
+ const r = rgb.r / 255;
1229
+ const g = rgb.g / 255;
1230
+ const b = rgb.b / 255;
1231
+ const max = Math.max(r, g, b);
1232
+ const min = Math.min(r, g, b);
1233
+ let h = 0, s = 0;
1234
+ const l = (max + min) / 2;
1235
+ if (max !== min) {
1236
+ const d = max - min;
1237
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1238
+ switch (max) {
1239
+ case r:
1240
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
1241
+ break;
1242
+ case g:
1243
+ h = ((b - r) / d + 2) / 6;
1244
+ break;
1245
+ case b:
1246
+ h = ((r - g) / d + 4) / 6;
1247
+ break;
1248
+ }
1249
+ }
1250
+ return {
1251
+ h: Math.round(h * 360),
1252
+ s: Math.round(s * 100),
1253
+ l: Math.round(l * 100)
1254
+ };
1255
+ }
1256
+ function hslToHex2(h, s, l) {
1257
+ h = h / 360;
1258
+ s = s / 100;
1259
+ l = l / 100;
1260
+ let r, g, b;
1261
+ if (s === 0) {
1262
+ r = g = b = l;
1263
+ } else {
1264
+ const hue2rgb = (p2, q2, t) => {
1265
+ if (t < 0) t += 1;
1266
+ if (t > 1) t -= 1;
1267
+ if (t < 1 / 6) return p2 + (q2 - p2) * 6 * t;
1268
+ if (t < 1 / 2) return q2;
1269
+ if (t < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - t) * 6;
1270
+ return p2;
1271
+ };
1272
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1273
+ const p = 2 * l - q;
1274
+ r = hue2rgb(p, q, h + 1 / 3);
1275
+ g = hue2rgb(p, q, h);
1276
+ b = hue2rgb(p, q, h - 1 / 3);
1277
+ }
1278
+ const toHex = (x) => {
1279
+ const hex = Math.round(x * 255).toString(16);
1280
+ return hex.length === 1 ? "0" + hex : hex;
1281
+ };
1282
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
1283
+ }
1284
+ function getOptimalForeground2(bgHex, whiteHex = "#ffffff", blackHex = "#000000") {
1285
+ const whiteRatio = getContrastRatio2(bgHex, whiteHex);
1286
+ const blackRatio = getContrastRatio2(bgHex, blackHex);
1287
+ return whiteRatio > blackRatio ? whiteHex : blackHex;
1288
+ }
1289
+ function generateColorScale(baseHex) {
1290
+ const hsl = hexToHSL2(baseHex);
1291
+ return {
1292
+ 50: hslToHex2(hsl.h, Math.max(hsl.s - 10, 20), 95),
1293
+ 100: hslToHex2(hsl.h, Math.max(hsl.s - 5, 30), 90),
1294
+ 200: hslToHex2(hsl.h, hsl.s, 80),
1295
+ 300: hslToHex2(hsl.h, hsl.s, 70),
1296
+ 400: hslToHex2(hsl.h, hsl.s, 60),
1297
+ 500: baseHex,
1298
+ // Base color
1299
+ 600: hslToHex2(hsl.h, Math.min(hsl.s + 5, 100), 45),
1300
+ 700: hslToHex2(hsl.h, Math.min(hsl.s + 10, 100), 35),
1301
+ 800: hslToHex2(hsl.h, Math.min(hsl.s + 15, 100), 25),
1302
+ 900: hslToHex2(hsl.h, Math.min(hsl.s + 20, 100), 15)
1303
+ };
1304
+ }
1305
+
1306
+ // src/lib/store/customizer.ts
1307
+ var useCustomizer = create2()(
1308
+ persist2(
1309
+ (set, get) => ({
1310
+ motion: 5,
1311
+ prefersReducedMotion: false,
1312
+ customizationMode: "simple",
1313
+ customColors: {},
1314
+ savedPalettes: [],
1315
+ customFontThemes: {},
1316
+ savedFontThemes: [],
1317
+ setMotion: (level) => set({ motion: level }),
1318
+ setPrefersReducedMotion: (value) => set({ prefersReducedMotion: value }),
1319
+ setCustomizationMode: (mode) => set({ customizationMode: mode }),
1320
+ setCustomPrimaryColor: (theme, mode, hexColor) => {
1321
+ const state = get();
1322
+ const currentPalette = state.customColors[theme]?.[mode];
1323
+ const scale = generateColorScale(hexColor);
1324
+ const primaryForeground = getOptimalForeground2(hexColor);
1325
+ const derivedTokens = computeDerivedTokens("--color-primary", hexColor, mode);
1326
+ const isSimple = state.customizationMode === "simple";
1327
+ const palette = {
1328
+ primary: hexColor,
1329
+ primaryForeground,
1330
+ secondary: isSimple ? void 0 : currentPalette?.secondary,
1331
+ secondaryForeground: isSimple ? void 0 : currentPalette?.secondaryForeground,
1332
+ accent: isSimple ? void 0 : currentPalette?.accent,
1333
+ accentForeground: isSimple ? void 0 : currentPalette?.accentForeground,
1334
+ scale,
1335
+ derivedTokens
1336
+ };
1337
+ set((state2) => ({
1338
+ customColors: {
1339
+ ...state2.customColors,
1340
+ [theme]: {
1341
+ ...state2.customColors[theme],
1342
+ [mode]: palette
1343
+ }
1344
+ }
1345
+ }));
1346
+ },
1347
+ setCustomSecondaryColor: (theme, mode, hexColor) => {
1348
+ const state = get();
1349
+ const currentPalette = state.customColors[theme]?.[mode];
1350
+ if (!currentPalette) return;
1351
+ const secondaryForeground = getOptimalForeground2(hexColor);
1352
+ const derivedTokens = computeDerivedTokens("--color-secondary", hexColor, mode);
1353
+ set((state2) => ({
1354
+ customColors: {
1355
+ ...state2.customColors,
1356
+ [theme]: {
1357
+ ...state2.customColors[theme],
1358
+ [mode]: {
1359
+ ...currentPalette,
1360
+ secondary: hexColor,
1361
+ secondaryForeground,
1362
+ derivedTokens: {
1363
+ ...currentPalette.derivedTokens,
1364
+ ...derivedTokens
1365
+ }
1366
+ }
1367
+ }
1368
+ }
1369
+ }));
1370
+ },
1371
+ setCustomAccentColor: (theme, mode, hexColor) => {
1372
+ const state = get();
1373
+ const currentPalette = state.customColors[theme]?.[mode];
1374
+ if (!currentPalette) return;
1375
+ const accentForeground = getOptimalForeground2(hexColor);
1376
+ const derivedTokens = computeDerivedTokens("--color-accent", hexColor, mode);
1377
+ set((state2) => ({
1378
+ customColors: {
1379
+ ...state2.customColors,
1380
+ [theme]: {
1381
+ ...state2.customColors[theme],
1382
+ [mode]: {
1383
+ ...currentPalette,
1384
+ accent: hexColor,
1385
+ accentForeground,
1386
+ derivedTokens: {
1387
+ ...currentPalette.derivedTokens,
1388
+ ...derivedTokens
1389
+ }
1390
+ }
1391
+ }
1392
+ }
1393
+ }));
1394
+ },
1395
+ applyColorPalette: (theme, mode, colors) => {
1396
+ const scale = generateColorScale(colors.primary);
1397
+ const primaryForeground = getOptimalForeground2(colors.primary);
1398
+ let derivedTokens = computeDerivedTokens("--color-primary", colors.primary, mode);
1399
+ const secondary = colors.secondary;
1400
+ const secondaryForeground = secondary ? getOptimalForeground2(secondary) : void 0;
1401
+ if (secondary) {
1402
+ const secondaryDerived = computeDerivedTokens("--color-secondary", secondary, mode);
1403
+ derivedTokens = { ...derivedTokens, ...secondaryDerived };
1404
+ }
1405
+ const accent = colors.accent;
1406
+ const accentForeground = accent ? getOptimalForeground2(accent) : void 0;
1407
+ if (accent) {
1408
+ const accentDerived = computeDerivedTokens("--color-accent", accent, mode);
1409
+ derivedTokens = { ...derivedTokens, ...accentDerived };
1410
+ }
1411
+ const palette = {
1412
+ name: colors.name,
1413
+ description: colors.description,
1414
+ primary: colors.primary,
1415
+ primaryForeground,
1416
+ secondary,
1417
+ secondaryForeground,
1418
+ accent,
1419
+ accentForeground,
1420
+ scale,
1421
+ derivedTokens
1422
+ };
1423
+ set((state) => ({
1424
+ customColors: {
1425
+ ...state.customColors,
1426
+ [theme]: {
1427
+ ...state.customColors[theme],
1428
+ [mode]: palette
1429
+ }
1430
+ }
1431
+ }));
1432
+ },
1433
+ resetCustomColors: (theme, mode) => {
1434
+ if (mode) {
1435
+ set((state) => ({
1436
+ customColors: {
1437
+ ...state.customColors,
1438
+ [theme]: {
1439
+ ...state.customColors[theme],
1440
+ [mode]: void 0
1441
+ }
1442
+ }
1443
+ }));
1444
+ } else {
1445
+ set((state) => {
1446
+ const { [theme]: _, ...rest } = state.customColors;
1447
+ return { customColors: rest };
1448
+ });
1449
+ }
1450
+ },
1451
+ getActiveColorPalette: (theme, mode) => {
1452
+ return get().customColors[theme]?.[mode] || null;
1453
+ },
1454
+ // Saved palette management
1455
+ savePalette: (paletteData) => {
1456
+ const id = `custom-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1457
+ const newPalette = {
1458
+ ...paletteData,
1459
+ id,
1460
+ category: "custom",
1461
+ createdAt: Date.now()
1462
+ };
1463
+ set((state) => ({
1464
+ savedPalettes: [...state.savedPalettes, newPalette]
1465
+ }));
1466
+ },
1467
+ updatePalette: (id, updates) => {
1468
+ set((state) => ({
1469
+ savedPalettes: state.savedPalettes.map(
1470
+ (p) => p.id === id ? { ...p, ...updates } : p
1471
+ )
1472
+ }));
1473
+ },
1474
+ renamePalette: (id, newName) => {
1475
+ set((state) => ({
1476
+ savedPalettes: state.savedPalettes.map(
1477
+ (p) => p.id === id ? { ...p, name: newName } : p
1478
+ )
1479
+ }));
1480
+ },
1481
+ deletePalette: (id) => {
1482
+ set((state) => ({
1483
+ savedPalettes: state.savedPalettes.filter((p) => p.id !== id)
1484
+ }));
1485
+ },
1486
+ reorderPalettes: (palettes) => {
1487
+ set({ savedPalettes: palettes });
1488
+ },
1489
+ getSavedPalettes: () => {
1490
+ return get().savedPalettes;
1491
+ },
1492
+ // Font theme management
1493
+ applyFontTheme: (theme, mode, fontTheme) => {
1494
+ set((state) => ({
1495
+ customFontThemes: {
1496
+ ...state.customFontThemes,
1497
+ [theme]: {
1498
+ ...state.customFontThemes[theme],
1499
+ [mode]: fontTheme
1500
+ }
1501
+ }
1502
+ }));
1503
+ },
1504
+ resetCustomFonts: (theme, mode) => {
1505
+ if (mode) {
1506
+ set((state) => ({
1507
+ customFontThemes: {
1508
+ ...state.customFontThemes,
1509
+ [theme]: {
1510
+ ...state.customFontThemes[theme],
1511
+ [mode]: void 0
1512
+ }
1513
+ }
1514
+ }));
1515
+ } else {
1516
+ set((state) => {
1517
+ const { [theme]: _, ...rest } = state.customFontThemes;
1518
+ return { customFontThemes: rest };
1519
+ });
1520
+ }
1521
+ },
1522
+ getActiveFontTheme: (theme, mode) => {
1523
+ return get().customFontThemes[theme]?.[mode] || null;
1524
+ },
1525
+ // Saved font theme management
1526
+ saveFontTheme: (fontThemeData) => {
1527
+ const id = `font-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1528
+ const newFontTheme = {
1529
+ ...fontThemeData,
1530
+ id,
1531
+ category: "custom",
1532
+ createdAt: Date.now(),
1533
+ isCustom: true
1534
+ };
1535
+ set((state) => ({
1536
+ savedFontThemes: [...state.savedFontThemes, newFontTheme]
1537
+ }));
1538
+ },
1539
+ updateFontTheme: (id, updates) => {
1540
+ set((state) => ({
1541
+ savedFontThemes: state.savedFontThemes.map(
1542
+ (ft) => ft.id === id ? { ...ft, ...updates } : ft
1543
+ )
1544
+ }));
1545
+ },
1546
+ renameFontTheme: (id, newName) => {
1547
+ set((state) => ({
1548
+ savedFontThemes: state.savedFontThemes.map(
1549
+ (ft) => ft.id === id ? { ...ft, name: newName } : ft
1550
+ )
1551
+ }));
1552
+ },
1553
+ deleteFontTheme: (id) => {
1554
+ set((state) => ({
1555
+ savedFontThemes: state.savedFontThemes.filter((ft) => ft.id !== id)
1556
+ }));
1557
+ },
1558
+ reorderFontThemes: (fontThemes) => {
1559
+ set({ savedFontThemes: fontThemes });
1560
+ },
1561
+ getSavedFontThemes: () => {
1562
+ return get().savedFontThemes;
1563
+ }
1564
+ }),
1565
+ {
1566
+ name: "ecosystem-customizer",
1567
+ version: 4,
1568
+ partialize: (state) => ({
1569
+ motion: state.motion,
1570
+ prefersReducedMotion: state.prefersReducedMotion,
1571
+ customizationMode: state.customizationMode,
1572
+ customColors: state.customColors,
1573
+ savedPalettes: state.savedPalettes,
1574
+ customFontThemes: state.customFontThemes,
1575
+ savedFontThemes: state.savedFontThemes
1576
+ })
1577
+ }
1578
+ )
1579
+ );
1580
+
1581
+ // src/providers/ThemeProvider.tsx
1582
+ import { Fragment, jsx } from "react/jsx-runtime";
1583
+ var themeTokens = {
1584
+ studio: studioTokens,
1585
+ terra: terraTokens,
1586
+ volt: voltTokens,
1587
+ speedboat: speedboatTokens
1588
+ };
1589
+ var fontFamilies = {
1590
+ studio: {
1591
+ heading: "var(--font-studio-heading)",
1592
+ body: "var(--font-studio-body)",
1593
+ mono: "var(--font-mono)"
1594
+ },
1595
+ terra: {
1596
+ sans: "var(--font-terra-body)",
1597
+ serif: "var(--font-terra-heading)",
1598
+ mono: "var(--font-mono)"
1599
+ },
1600
+ volt: {
1601
+ sans: "var(--font-volt-heading)",
1602
+ mono: "var(--font-mono)"
1603
+ },
1604
+ speedboat: {
1605
+ heading: "var(--font-montserrat)",
1606
+ body: "var(--font-roboto)",
1607
+ mono: "var(--font-mono)"
1608
+ }
1609
+ };
1610
+ function extractBlurValue(blurFunction) {
1611
+ const match = blurFunction.match(/blur\(([^)]+)\)/);
1612
+ return match ? match[1] : "8px";
1613
+ }
1614
+ function getThemeVars(theme, mode, motionIntensity) {
1615
+ const tokens = themeTokens[theme];
1616
+ const modeTokens = tokens[mode];
1617
+ const colors = modeTokens?.colors;
1618
+ const effects = modeTokens?.effects;
1619
+ const fonts = fontFamilies[theme];
1620
+ const motion = tokens.motion;
1621
+ const interactions = tokens.interactions;
1622
+ const duration = motion?.getDuration?.(motionIntensity) || "300ms";
1623
+ const durationMs = parseInt(duration) || 300;
1624
+ return {
1625
+ // Colors - Base
1626
+ "--color-background": colors?.background || "#ffffff",
1627
+ "--color-background-secondary": colors?.backgroundSecondary || colors?.background || "#fafafa",
1628
+ "--color-background-tertiary": colors?.backgroundTertiary || colors?.backgroundSecondary || colors?.background || "#f5f5f5",
1629
+ "--color-foreground": colors?.foreground || "#0a0a0a",
1630
+ "--color-primary": colors?.primary || "#0a0a0a",
1631
+ "--color-primary-foreground": colors?.primaryForeground || "#ffffff",
1632
+ "--color-secondary": colors?.secondary || "#f5f5f5",
1633
+ "--color-secondary-foreground": colors?.secondaryForeground || "#0a0a0a",
1634
+ "--color-accent": colors?.accent || colors?.primary || "#0070f3",
1635
+ "--color-accent-foreground": colors?.accentForeground || "#ffffff",
1636
+ "--color-success": colors?.success || "#00a86b",
1637
+ "--color-success-foreground": colors?.successForeground || "#ffffff",
1638
+ "--color-warning": colors?.warning || "#f59e0b",
1639
+ "--color-warning-foreground": colors?.warningForeground || "#ffffff",
1640
+ "--color-error": colors?.error || "#ef4444",
1641
+ "--color-error-foreground": colors?.errorForeground || "#ffffff",
1642
+ "--color-info": colors?.info || colors?.accent || "#0070f3",
1643
+ "--color-info-foreground": colors?.infoForeground || "#ffffff",
1644
+ "--color-glass": colors?.glass || "rgba(255, 255, 255, 0.7)",
1645
+ "--color-glass-border": colors?.glassBorder || "rgba(0, 0, 0, 0.1)",
1646
+ // Semantic color aliases (matching README examples)
1647
+ "--color-text-primary": colors?.foreground || "#0a0a0a",
1648
+ "--color-text-secondary": colors?.foregroundSecondary || "#525252",
1649
+ "--color-text-muted": colors?.foregroundTertiary || "#a3a3a3",
1650
+ "--color-surface": colors?.backgroundSecondary || colors?.background || "#fafafa",
1651
+ "--color-border": colors?.border || colors?.glassBorder || "rgba(0, 0, 0, 0.1)",
1652
+ "--color-focus": colors?.accent || colors?.primary || "#0070f3",
1653
+ // Links and focus rings (can be overridden by derived tokens)
1654
+ "--color-link": colors?.link || colors?.primary || "#0a0a0a",
1655
+ "--color-ring": colors?.ring || colors?.primary || "#0a0a0a",
1656
+ // Interactive states
1657
+ "--color-hover": colors?.hover || colors?.backgroundSecondary || "#fafafa",
1658
+ "--color-active": colors?.active || colors?.backgroundTertiary || "#f0f0f0",
1659
+ "--color-link-hover": colors?.linkHover || colors?.primary || "#0a0a0a",
1660
+ "--color-link-hover-foreground": colors?.linkHoverForeground || colors?.background || "#ffffff",
1661
+ // Component-specific (previously only set in globals.css defaults)
1662
+ "--color-card": colors?.card || colors?.background || "#ffffff",
1663
+ "--color-card-foreground": colors?.cardForeground || colors?.foreground || "#0a0a0a",
1664
+ "--color-popover": colors?.popover || colors?.background || "#ffffff",
1665
+ "--color-popover-foreground": colors?.popoverForeground || colors?.foreground || "#0a0a0a",
1666
+ "--color-muted": colors?.muted || colors?.backgroundSecondary || "#f5f5f5",
1667
+ "--color-muted-foreground": colors?.mutedForeground || colors?.foregroundTertiary || "#737373",
1668
+ "--color-destructive": colors?.destructive || colors?.error || "#ef4444",
1669
+ "--color-destructive-foreground": colors?.destructiveForeground || "#ffffff",
1670
+ "--color-input": colors?.input || colors?.border || "#d4d4d4",
1671
+ // Effects - Blur (full function for style attributes)
1672
+ "--effect-blur-sm": effects?.blur?.sm || "blur(4px)",
1673
+ "--effect-blur-md": effects?.blur?.md || "blur(8px)",
1674
+ "--effect-blur-lg": effects?.blur?.lg || "blur(16px)",
1675
+ "--effect-blur-xl": effects?.blur?.xl || effects?.blur?.lg || "blur(24px)",
1676
+ // Effects - Blur (raw values for Tailwind blur-*/backdrop-blur-* utilities)
1677
+ "--blur-sm": extractBlurValue(effects?.blur?.sm || "blur(4px)"),
1678
+ "--blur-md": extractBlurValue(effects?.blur?.md || "blur(8px)"),
1679
+ "--blur-lg": extractBlurValue(effects?.blur?.lg || "blur(16px)"),
1680
+ "--blur-xl": extractBlurValue(effects?.blur?.xl || "blur(24px)"),
1681
+ // Effects - Shadow (complete set)
1682
+ "--effect-shadow-sm": effects?.shadow?.sm || "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
1683
+ "--effect-shadow-md": effects?.shadow?.md || "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
1684
+ "--effect-shadow-lg": effects?.shadow?.lg || "0 10px 15px -3px rgba(0, 0, 0, 0.1)",
1685
+ "--effect-shadow-xl": effects?.shadow?.xl || "0 20px 25px -5px rgba(0, 0, 0, 0.1)",
1686
+ "--effect-shadow-2xl": effects?.shadow?.["2xl"] || "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
1687
+ // Interaction tokens (theme-aware)
1688
+ "--color-interaction-overlay": interactions?.hover?.overlayColor?.[mode] || (mode === "dark" ? "#ffffff" : "#000000"),
1689
+ "--opacity-interaction-hover": String(interactions?.hover?.opacity ?? 0.08),
1690
+ "--scale-interaction-active": String(interactions?.active?.scale ?? 0.98),
1691
+ "--color-interaction-focus-ring": colors?.ring || colors?.primary || "#0a0a0a",
1692
+ "--width-interaction-focus-ring": interactions?.focus?.ringWidth || "2px",
1693
+ "--width-interaction-focus-offset": interactions?.focus?.ringOffset || "2px",
1694
+ "--opacity-interaction-disabled": String(interactions?.disabled?.opacity ?? 0.5),
1695
+ // Typography - Font Families
1696
+ "--font-heading": fonts?.heading || (theme === "terra" && fonts?.serif ? fonts.serif : fonts?.sans) || "var(--font-studio-heading)",
1697
+ "--font-body": fonts?.body || fonts?.sans || "var(--font-studio-body)",
1698
+ "--font-mono": fonts?.mono || "var(--font-studio-mono)",
1699
+ // Motion - Easing (complete set)
1700
+ "--ease-default": motion?.ease?.default || "cubic-bezier(0.4, 0, 0.2, 1)",
1701
+ "--ease-in": motion?.ease?.in || "cubic-bezier(0.4, 0, 1, 1)",
1702
+ "--ease-out": motion?.ease?.out || "cubic-bezier(0, 0, 0.2, 1)",
1703
+ "--ease-spring": motion?.ease?.spring || "cubic-bezier(0.16, 1, 0.3, 1)",
1704
+ // Motion - Duration (computed from theme + user motion preference)
1705
+ "--duration-default": duration,
1706
+ "--duration-fast": `${Math.max(0, Math.round(durationMs * 0.5))}ms`,
1707
+ "--duration-slow": `${Math.min(1e3, Math.round(durationMs * 1.5))}ms`,
1708
+ // Syntax Highlighting - Based on VS Code Dark+ theme
1709
+ "--syntax-comment": mode === "light" ? syntaxColors.light.comment : syntaxColors.dark.comment,
1710
+ "--syntax-keyword": mode === "light" ? syntaxColors.light.keyword : syntaxColors.dark.keyword,
1711
+ "--syntax-function": mode === "light" ? syntaxColors.light.function : syntaxColors.dark.function,
1712
+ "--syntax-string": mode === "light" ? syntaxColors.light.string : syntaxColors.dark.string,
1713
+ "--syntax-number": mode === "light" ? syntaxColors.light.number : syntaxColors.dark.number,
1714
+ "--syntax-boolean": mode === "light" ? syntaxColors.light.boolean : syntaxColors.dark.boolean,
1715
+ "--syntax-operator": mode === "light" ? syntaxColors.light.operator : syntaxColors.dark.operator,
1716
+ "--syntax-property": mode === "light" ? syntaxColors.light.property : syntaxColors.dark.property,
1717
+ "--syntax-className": mode === "light" ? syntaxColors.light.className : syntaxColors.dark.className,
1718
+ "--syntax-tag": mode === "light" ? syntaxColors.light.tag : syntaxColors.dark.tag,
1719
+ "--syntax-attribute": mode === "light" ? syntaxColors.light.attribute : syntaxColors.dark.attribute,
1720
+ "--syntax-variable": mode === "light" ? syntaxColors.light.variable : syntaxColors.dark.variable,
1721
+ "--syntax-punctuation": mode === "light" ? syntaxColors.light.punctuation : syntaxColors.dark.punctuation,
1722
+ "--syntax-plain": mode === "light" ? syntaxColors.light.plain : syntaxColors.dark.plain,
1723
+ // Code Block Backgrounds and Borders - Accessible contrast (WCAG AA 4.5:1)
1724
+ "--code-block-bg": mode === "light" ? codeColors.light.blockBackground : codeColors.dark.blockBackground,
1725
+ "--code-inline-bg": mode === "light" ? codeColors.light.inlineBackground : codeColors.dark.inlineBackground,
1726
+ "--code-border": mode === "light" ? codeColors.light.border : codeColors.dark.border
1727
+ };
1728
+ }
1729
+ function mergeCustomColorTokens(baseTokens, customPalette) {
1730
+ return {
1731
+ ...baseTokens,
1732
+ // Override primary color
1733
+ "--color-primary": customPalette.primary,
1734
+ "--color-primary-foreground": customPalette.primaryForeground,
1735
+ // Apply color scale (for utilities like bg-primary-200)
1736
+ "--color-primary-50": customPalette.scale[50],
1737
+ "--color-primary-100": customPalette.scale[100],
1738
+ "--color-primary-200": customPalette.scale[200],
1739
+ "--color-primary-300": customPalette.scale[300],
1740
+ "--color-primary-400": customPalette.scale[400],
1741
+ "--color-primary-500": customPalette.scale[500],
1742
+ "--color-primary-600": customPalette.scale[600],
1743
+ "--color-primary-700": customPalette.scale[700],
1744
+ "--color-primary-800": customPalette.scale[800],
1745
+ "--color-primary-900": customPalette.scale[900],
1746
+ // Override secondary color if provided (advanced mode)
1747
+ ...customPalette.secondary && {
1748
+ "--color-secondary": customPalette.secondary,
1749
+ "--color-secondary-foreground": customPalette.secondaryForeground || baseTokens["--color-secondary-foreground"]
1750
+ },
1751
+ // Override accent color if provided (advanced mode)
1752
+ ...customPalette.accent && {
1753
+ "--color-accent": customPalette.accent,
1754
+ "--color-accent-foreground": customPalette.accentForeground || baseTokens["--color-accent-foreground"]
1755
+ },
1756
+ // Apply ALL derived tokens from dependency graph
1757
+ ...customPalette.derivedTokens
1758
+ };
1759
+ }
1760
+ function validateThemeTokens(theme, mode) {
1761
+ if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") return;
1762
+ const root = document.documentElement;
1763
+ const style = getComputedStyle(root);
1764
+ const requiredTokens = [
1765
+ "--color-background",
1766
+ "--color-foreground",
1767
+ "--color-primary",
1768
+ "--color-primary-foreground",
1769
+ "--color-border",
1770
+ "--color-ring",
1771
+ "--font-heading",
1772
+ "--font-body",
1773
+ "--font-mono"
1774
+ ];
1775
+ const missingTokens = [];
1776
+ const invalidTokens = [];
1777
+ requiredTokens.forEach((token) => {
1778
+ const value = style.getPropertyValue(token).trim();
1779
+ if (!value) {
1780
+ missingTokens.push(token);
1781
+ } else if (token.startsWith("--color-") && !value.match(/^(#|rgb|hsl|var\()/)) {
1782
+ invalidTokens.push(`${token} = "${value}"`);
1783
+ } else if (token.startsWith("--font-") && value === "") {
1784
+ invalidTokens.push(`${token} = empty`);
1785
+ }
1786
+ });
1787
+ if (missingTokens.length > 0) {
1788
+ console.warn(
1789
+ `[ThemeProvider] Missing CSS variables for theme "${theme}" (${mode} mode):`,
1790
+ missingTokens
1791
+ );
1792
+ }
1793
+ if (invalidTokens.length > 0) {
1794
+ console.warn(
1795
+ `[ThemeProvider] Invalid CSS variable values for theme "${theme}" (${mode} mode):`,
1796
+ invalidTokens
1797
+ );
1798
+ }
1799
+ if (missingTokens.length === 0 && invalidTokens.length === 0) {
1800
+ console.log(`[ThemeProvider] \u2713 Theme validation passed for "${theme}" (${mode} mode)`);
1801
+ }
1802
+ }
1803
+ function ThemeProvider({ children, defaultTheme, defaultMode }) {
1804
+ const { theme, mode, setTheme, setMode } = useThemeStore();
1805
+ const customPalette = useCustomizer((state) => state.customColors?.[theme]?.[mode]);
1806
+ const motionIntensity = useCustomizer((state) => state.motion);
1807
+ const [isTransitioning, setIsTransitioning] = useState(false);
1808
+ const [mounted, setMounted] = useState(false);
1809
+ useEffect(() => {
1810
+ if (!defaultTheme && !defaultMode) return;
1811
+ const persisted = typeof window !== "undefined" && localStorage.getItem("ecosystem-theme");
1812
+ if (persisted) return;
1813
+ if (defaultTheme) setTheme(defaultTheme);
1814
+ if (defaultMode) setMode(defaultMode);
1815
+ }, []);
1816
+ useEffect(() => {
1817
+ setMounted(true);
1818
+ }, []);
1819
+ useEffect(() => {
1820
+ if (!mounted) return;
1821
+ setIsTransitioning(true);
1822
+ const root = document.documentElement;
1823
+ const baseTokens = getThemeVars(theme, mode, motionIntensity);
1824
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
1825
+ console.log("[ThemeProvider] Update:", {
1826
+ theme,
1827
+ mode,
1828
+ motionIntensity,
1829
+ hasCustomPalette: !!customPalette,
1830
+ customPrimary: customPalette?.primary,
1831
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1832
+ });
1833
+ }
1834
+ const finalTokens = customPalette ? mergeCustomColorTokens(baseTokens, customPalette) : baseTokens;
1835
+ root.classList.add("theme-transitioning");
1836
+ Object.entries(finalTokens).forEach(([key, value]) => {
1837
+ root.style.setProperty(key, value);
1838
+ });
1839
+ root.setAttribute("data-theme", theme);
1840
+ root.setAttribute("data-mode", mode);
1841
+ root.setAttribute("data-custom-colors", customPalette ? "active" : "default");
1842
+ if (mode === "dark") {
1843
+ root.classList.add("dark");
1844
+ } else {
1845
+ root.classList.remove("dark");
1846
+ }
1847
+ validateThemeTokens(theme, mode);
1848
+ const timeout = setTimeout(() => {
1849
+ root.classList.remove("theme-transitioning");
1850
+ setIsTransitioning(false);
1851
+ }, 400);
1852
+ return () => clearTimeout(timeout);
1853
+ }, [theme, mode, mounted, customPalette, motionIntensity]);
1854
+ return /* @__PURE__ */ jsx(Fragment, { children });
1855
+ }
1856
+ export {
1857
+ ThemeProvider
1858
+ };
1859
+ //# sourceMappingURL=providers.mjs.map