gridsmith-ui 0.1.0

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.
package/dist/roots.css ADDED
@@ -0,0 +1,599 @@
1
+ /* ==========================================================================
2
+ Root Control Engine
3
+ Derives all design tokens from user-configurable root values.
4
+ L1 roots are set by ThemeContext (inline styles on :root).
5
+ L2 derived scales use CSS calc/oklch for reactive updates.
6
+ L3 semantic tokens map scale steps to component-facing names.
7
+ ========================================================================== */
8
+
9
+ :root {
10
+ /* ── L1: Root Controls (defaults — overridden by ThemeContext) ───── */
11
+
12
+ --ds-hue-primary: 264;
13
+ --ds-hue-neutral: 260;
14
+ --ds-hue-destructive: 27;
15
+ --ds-hue-success: 153;
16
+ --ds-hue-warning: 75;
17
+ --ds-sat-primary: 1;
18
+ --ds-sat-neutral: 1;
19
+
20
+ --ds-radius-base: 8px;
21
+ --ds-border-base: 1px;
22
+ --ds-space-unit: 4px;
23
+
24
+ --ds-font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
25
+ --ds-font-mono: "JetBrains Mono", ui-monospace, monospace;
26
+ --ds-font-display: "Inter", sans-serif;
27
+ --ds-text-base: 14px;
28
+ --ds-weight-base: 500;
29
+ --ds-weight-heading: 700;
30
+ --ds-weight-emphasis: 600;
31
+ --ds-weight-strong: 700;
32
+ --ds-weight-heavy: 800;
33
+
34
+ --ds-shadow-offset: 0px;
35
+ --ds-shadow-offset-x: 0px;
36
+ --ds-shadow-offset-y: 0px;
37
+ --ds-shadow-blur: 8px;
38
+ --ds-shadow-alpha: 0.1;
39
+
40
+ --ds-transition-speed: 200ms;
41
+ --ds-transition-ease: ease-in-out;
42
+
43
+ --ds-sidebar-width: 224px;
44
+ --ds-sidebar-compact-width: 72px;
45
+ --ds-sidebar-collapsed-width: 56px;
46
+ --ds-sidebar-item-height: 36px;
47
+ --ds-sidebar-item-radius: var(--ds-radius-md);
48
+ --ds-sidebar-item-padding-x: var(--ds-space-3);
49
+ --ds-sidebar-nav-padding: var(--ds-space-3) var(--ds-space-2);
50
+ --ds-navbar-height: 48px;
51
+ --ds-navbar-height-compact: 40px;
52
+ --ds-drawer-width: 280px;
53
+
54
+ --ds-chart-height-sm: 12rem;
55
+ --ds-chart-height-md: 16rem;
56
+ --ds-chart-height-lg: 20rem;
57
+
58
+ --ds-control-height-sm: 32px;
59
+ --ds-control-height-md: 40px;
60
+ --ds-control-height-lg: 48px;
61
+ --ds-dropdown-max-height: 256px;
62
+ --ds-tab-rail-width: 180px;
63
+ --ds-icon-size-sm: 14px;
64
+ --ds-icon-size-md: 16px;
65
+ --ds-gradient: none;
66
+
67
+ /* ── L1: Glass Roots (defaults = off for non-glass presets) ──── */
68
+
69
+ --ds-glass-blur: 0px;
70
+ --ds-glass-tint: 1;
71
+ --ds-glass-saturate: 100%;
72
+ --ds-glass-border-alpha: 0;
73
+
74
+ /* ── L2: Derived Colour Scales ──────────────────────────────────── */
75
+
76
+ /* Primary (chroma scaled by --ds-sat-primary) */
77
+ --ds-primary-50: oklch(0.97 calc(0.025 * var(--ds-sat-primary)) var(--ds-hue-primary));
78
+ --ds-primary-100: oklch(0.93 calc(0.050 * var(--ds-sat-primary)) var(--ds-hue-primary));
79
+ --ds-primary-200: oklch(0.87 calc(0.100 * var(--ds-sat-primary)) var(--ds-hue-primary));
80
+ --ds-primary-300: oklch(0.77 calc(0.150 * var(--ds-sat-primary)) var(--ds-hue-primary));
81
+ --ds-primary-400: oklch(0.66 calc(0.180 * var(--ds-sat-primary)) var(--ds-hue-primary));
82
+ --ds-primary-500: oklch(0.55 calc(0.200 * var(--ds-sat-primary)) var(--ds-hue-primary));
83
+ --ds-primary-600: oklch(0.47 calc(0.185 * var(--ds-sat-primary)) var(--ds-hue-primary));
84
+ --ds-primary-700: oklch(0.40 calc(0.165 * var(--ds-sat-primary)) var(--ds-hue-primary));
85
+ --ds-primary-800: oklch(0.33 calc(0.135 * var(--ds-sat-primary)) var(--ds-hue-primary));
86
+ --ds-primary-900: oklch(0.25 calc(0.100 * var(--ds-sat-primary)) var(--ds-hue-primary));
87
+ --ds-primary-950: oklch(0.17 calc(0.060 * var(--ds-sat-primary)) var(--ds-hue-primary));
88
+
89
+ /* Neutral (low chroma, tinted by hue, scaled by --ds-sat-neutral) */
90
+ --ds-neutral-50: oklch(0.97 calc(0.007 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
91
+ --ds-neutral-100: oklch(0.94 calc(0.009 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
92
+ --ds-neutral-200: oklch(0.90 calc(0.010 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
93
+ --ds-neutral-300: oklch(0.84 calc(0.010 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
94
+ --ds-neutral-400: oklch(0.71 calc(0.009 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
95
+ --ds-neutral-500: oklch(0.55 calc(0.007 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
96
+ --ds-neutral-600: oklch(0.45 calc(0.006 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
97
+ --ds-neutral-700: oklch(0.37 calc(0.005 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
98
+ --ds-neutral-800: oklch(0.27 calc(0.004 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
99
+ --ds-neutral-900: oklch(0.20 calc(0.003 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
100
+ --ds-neutral-950: oklch(0.13 calc(0.002 * var(--ds-sat-neutral)) var(--ds-hue-neutral));
101
+
102
+ /* Destructive */
103
+ --ds-destructive-50: oklch(0.97 0.015 var(--ds-hue-destructive));
104
+ --ds-destructive-100: oklch(0.93 0.040 var(--ds-hue-destructive));
105
+ --ds-destructive-400: oklch(0.66 0.200 var(--ds-hue-destructive));
106
+ --ds-destructive-500: oklch(0.55 0.220 var(--ds-hue-destructive));
107
+ --ds-destructive-600: oklch(0.47 0.200 var(--ds-hue-destructive));
108
+ --ds-destructive-950: oklch(0.15 0.050 var(--ds-hue-destructive));
109
+
110
+ /* Success */
111
+ --ds-success-50: oklch(0.97 0.020 var(--ds-hue-success));
112
+ --ds-success-100: oklch(0.93 0.045 var(--ds-hue-success));
113
+ --ds-success-400: oklch(0.66 0.170 var(--ds-hue-success));
114
+ --ds-success-500: oklch(0.52 0.160 var(--ds-hue-success));
115
+ --ds-success-600: oklch(0.45 0.145 var(--ds-hue-success));
116
+ --ds-success-950: oklch(0.15 0.040 var(--ds-hue-success));
117
+
118
+ /* Warning (higher lightness — amber/yellow needs it for perception) */
119
+ --ds-warning-50: oklch(0.97 0.020 var(--ds-hue-warning));
120
+ --ds-warning-100: oklch(0.93 0.060 var(--ds-hue-warning));
121
+ --ds-warning-400: oklch(0.78 0.155 var(--ds-hue-warning));
122
+ --ds-warning-500: oklch(0.75 0.160 var(--ds-hue-warning));
123
+ --ds-warning-600: oklch(0.65 0.145 var(--ds-hue-warning));
124
+ --ds-warning-950: oklch(0.20 0.040 var(--ds-hue-warning));
125
+
126
+ /* Info (fixed blue hue 230 — universally recognised as informational) */
127
+ --ds-info-50: oklch(0.97 0.020 230);
128
+ --ds-info-400: oklch(0.66 0.170 230);
129
+ --ds-info-500: oklch(0.52 0.160 230);
130
+ --ds-info-950: oklch(0.15 0.040 230);
131
+
132
+ /* ── L2: Derived Shape Scales ───────────────────────────────────── */
133
+
134
+ --ds-radius-none: 0px;
135
+ --ds-radius-sm: calc(var(--ds-radius-base) * 0.5);
136
+ --ds-radius-md: var(--ds-radius-base);
137
+ --ds-radius-lg: calc(var(--ds-radius-base) * 1.5);
138
+ --ds-radius-xl: calc(var(--ds-radius-base) * 2);
139
+ --ds-radius-full: 9999px;
140
+
141
+ --ds-border-width: var(--ds-border-base);
142
+ --ds-border-width-thick: calc(var(--ds-border-base) * 2);
143
+ --ds-border-width-thicker: calc(var(--ds-border-base) * 2.5);
144
+ --ds-divider-width: var(--ds-border-width);
145
+
146
+ /* ── L2: Derived Type Scale ─────────────────────────────────────── */
147
+
148
+ --ds-font-size-2xs: calc(var(--ds-text-base) * 0.714);
149
+ --ds-font-size-xs: calc(var(--ds-text-base) * 0.786);
150
+ --ds-font-size-sm: calc(var(--ds-text-base) * 0.929);
151
+ --ds-font-size-body: var(--ds-text-base);
152
+ --ds-font-size-lg: calc(var(--ds-text-base) * 1.286);
153
+ --ds-font-size-xl: calc(var(--ds-text-base) * 1.571);
154
+ --ds-font-size-2xl: calc(var(--ds-text-base) * 2);
155
+ --ds-font-size-3xl: calc(var(--ds-text-base) * 2.571);
156
+ --ds-line-height-body: 1.5;
157
+ --ds-line-height-tight: 1.25;
158
+
159
+ /* ── L2: Derived Opacity Scale ───────────────────────────────────── */
160
+
161
+ --ds-opacity-disabled: 0.5;
162
+
163
+ /* ── L2: Derived Spacing Scale ──────────────────────────────────── */
164
+
165
+ --ds-space-effective: calc(var(--ds-space-unit) * var(--ds-density));
166
+ --ds-space-0\.5: calc(var(--ds-space-effective) * 0.5);
167
+ --ds-space-1: var(--ds-space-effective);
168
+ --ds-space-1\.5: calc(var(--ds-space-effective) * 1.5);
169
+ --ds-space-2: calc(var(--ds-space-effective) * 2);
170
+ --ds-space-2\.5: calc(var(--ds-space-effective) * 2.5);
171
+ --ds-space-3: calc(var(--ds-space-effective) * 3);
172
+ --ds-space-4: calc(var(--ds-space-effective) * 4);
173
+ --ds-space-5: calc(var(--ds-space-effective) * 5);
174
+ --ds-space-6: calc(var(--ds-space-effective) * 6);
175
+ --ds-space-8: calc(var(--ds-space-effective) * 8);
176
+ --ds-space-10: calc(var(--ds-space-effective) * 10);
177
+ --ds-space-12: calc(var(--ds-space-effective) * 12);
178
+
179
+ /* ── L1: Density & Breakpoints ─────────────────────────────────── */
180
+
181
+ --ds-density: 1;
182
+
183
+ --ds-bp-sm: 640px;
184
+ --ds-bp-md: 768px;
185
+ --ds-bp-lg: 1024px;
186
+ --ds-bp-xl: 1280px;
187
+ --ds-touch-target-min: 44px;
188
+
189
+ /* ── L1: Z-Index Scale ─────────────────────────────────────────── */
190
+
191
+ --ds-z-dropdown: 100;
192
+ --ds-z-sticky: 200;
193
+ --ds-z-overlay: 300;
194
+ --ds-z-modal: 400;
195
+ --ds-z-tooltip: 500;
196
+ --ds-z-toast: 600;
197
+
198
+ /* ── L2: Derived Shadow Scale ───────────────────────────────────── */
199
+
200
+ --ds-shadow-sm:
201
+ calc(var(--ds-shadow-offset-x) * 0.5) calc(var(--ds-shadow-offset-y) * 0.5) var(--ds-shadow-blur) 0 oklch(0% 0 0 / var(--ds-shadow-alpha));
202
+
203
+ --ds-shadow-md:
204
+ var(--ds-shadow-offset-x) var(--ds-shadow-offset-y) calc(var(--ds-shadow-blur) * 1.5) 0 oklch(0% 0 0 / var(--ds-shadow-alpha));
205
+
206
+ --ds-shadow-lg:
207
+ calc(var(--ds-shadow-offset-x) * 2) calc(var(--ds-shadow-offset-y) * 2) calc(var(--ds-shadow-blur) * 2.5) 0 oklch(0% 0 0 / var(--ds-shadow-alpha));
208
+
209
+ --ds-shadow-xl:
210
+ calc(var(--ds-shadow-offset-x) * 3) calc(var(--ds-shadow-offset-y) * 3) calc(var(--ds-shadow-blur) * 3.5) 0 oklch(0% 0 0 / var(--ds-shadow-alpha));
211
+
212
+ --ds-shadow-card:
213
+ calc(var(--ds-shadow-offset-x) * 1.5) calc(var(--ds-shadow-offset-y) * 1.5) calc(var(--ds-shadow-blur) * 2) 0 oklch(0% 0 0 / var(--ds-shadow-alpha));
214
+
215
+ --ds-shadow-button:
216
+ calc(var(--ds-shadow-offset-x) * 0.5) calc(var(--ds-shadow-offset-y) * 0.5) var(--ds-shadow-blur) 0 oklch(0% 0 0 / var(--ds-shadow-alpha));
217
+
218
+ --ds-shadow-button-pressed: var(--ds-shadow-button);
219
+
220
+ --ds-shadow-dropdown:
221
+ var(--ds-shadow-offset-x) var(--ds-shadow-offset-y) calc(var(--ds-shadow-blur) * 2) 0 oklch(0% 0 0 / var(--ds-shadow-alpha));
222
+
223
+ --ds-shadow-modal:
224
+ calc(var(--ds-shadow-offset-x) * 2) calc(var(--ds-shadow-offset-y) * 2) calc(var(--ds-shadow-blur) * 3.5) 0 oklch(0% 0 0 / var(--ds-shadow-alpha));
225
+
226
+ --ds-shadow-focus: 0 0 0 2px var(--ds-primary-500);
227
+
228
+ /* ── L2: Derived Glass Tokens ────────────────────────────────────
229
+ When glass roots are at defaults (blur:0, tint:1, saturate:100%),
230
+ these resolve to solid white / no-op filter / transparent border.
231
+ Glass presets override the L1 roots to activate the effect. ─── */
232
+
233
+ --ds-glass-bg: oklch(1 0 0 / var(--ds-glass-tint));
234
+ --ds-glass-filter: blur(var(--ds-glass-blur)) saturate(var(--ds-glass-saturate));
235
+ --ds-glass-border: oklch(1 0 0 / var(--ds-glass-border-alpha));
236
+ --ds-glass-inset: inset 0 1px 0 0 oklch(1 0 0 / calc(var(--ds-glass-border-alpha) * 1.6));
237
+
238
+ /* ── L3: Semantic Tokens (Light Mode) ───────────────────────────── */
239
+
240
+ --ds-bg-canvas: var(--ds-neutral-50);
241
+ --ds-bg-surface: oklch(1 0 0);
242
+ --ds-bg-surface-elevated: oklch(1 0 0);
243
+ --ds-bg-muted: var(--ds-neutral-100);
244
+ --ds-bg-emphasis: var(--ds-neutral-200);
245
+
246
+ --ds-text-primary: var(--ds-neutral-950);
247
+ --ds-text-secondary: var(--ds-neutral-600);
248
+ --ds-text-muted: var(--ds-neutral-400);
249
+ --ds-text-on-primary: oklch(1 0 0);
250
+
251
+ --ds-border-default: var(--ds-neutral-300);
252
+ --ds-border-subtle: var(--ds-neutral-200);
253
+ --ds-border-strong: var(--ds-neutral-500);
254
+ --ds-border-focus: var(--ds-primary-500);
255
+
256
+ --ds-accent-primary: var(--ds-primary-500);
257
+ --ds-accent-primary-hover: var(--ds-primary-600);
258
+ --ds-accent-primary-active: var(--ds-primary-700);
259
+ --ds-accent-subtle: color-mix(in oklch, var(--ds-accent-primary) 10%, transparent);
260
+
261
+ --ds-status-success: var(--ds-success-500);
262
+ --ds-status-success-bg: var(--ds-success-50);
263
+ --ds-status-warning: var(--ds-warning-500);
264
+ --ds-status-warning-bg: var(--ds-warning-50);
265
+ --ds-status-error: var(--ds-destructive-500);
266
+ --ds-status-error-bg: var(--ds-destructive-50);
267
+ --ds-status-info: var(--ds-info-500);
268
+ --ds-status-info-bg: var(--ds-info-50);
269
+
270
+ --ds-sidebar-bg: var(--ds-neutral-100);
271
+ --ds-sidebar-border: var(--ds-neutral-200);
272
+ --ds-sidebar-item-hover: var(--ds-neutral-200);
273
+ --ds-sidebar-item-active: var(--ds-bg-surface);
274
+ --ds-sidebar-text: var(--ds-text-primary);
275
+ --ds-sidebar-text-secondary: var(--ds-text-secondary);
276
+ --ds-sidebar-text-muted: var(--ds-text-muted);
277
+ --ds-sidebar-accent: var(--ds-accent-primary);
278
+ --ds-sidebar-accent-subtle: color-mix(in oklch, var(--ds-sidebar-accent) 10%, transparent);
279
+
280
+ /* Tab strip — presets can override for stronger contrast (e.g. Modern Dark) */
281
+ --ds-tab-hover-bg: var(--ds-bg-muted);
282
+ --ds-tab-active-bg: var(--ds-bg-surface);
283
+
284
+ --ds-input-bg: oklch(1 0 0);
285
+ --ds-input-border: var(--ds-neutral-300);
286
+ --ds-input-focus-ring: var(--ds-primary-500);
287
+ --ds-input-shadow: none;
288
+
289
+ --ds-check-bg: var(--ds-accent-primary);
290
+ --ds-check-fg: var(--ds-text-on-primary);
291
+ --ds-check-border: var(--ds-accent-primary);
292
+ }
293
+
294
+ /* ── Dark Mode Semantic Overrides ─────────────────────────────────── */
295
+ /* Layered surface hierarchy: sidebar(darkest) < canvas < surface < elevated.
296
+ This gives cards/panels visible lift and keeps the sidebar anchored. */
297
+
298
+ [data-mode="dark"] {
299
+ --ds-glass-inset: inset 0 1px 0 0 oklch(1 0 0 / calc(var(--ds-glass-border-alpha) * 0.5));
300
+
301
+ /* Surfaces — canvas is NOT the darkest; sidebar sinks below it */
302
+ --ds-bg-canvas: var(--ds-neutral-900);
303
+ --ds-bg-surface: var(--ds-neutral-800);
304
+ --ds-bg-surface-elevated: var(--ds-neutral-700);
305
+ --ds-bg-muted: var(--ds-neutral-700);
306
+ --ds-bg-emphasis: var(--ds-neutral-600);
307
+
308
+ /* Text — muted at 400 instead of 500 for legibility on dark backgrounds */
309
+ --ds-text-primary: var(--ds-neutral-50);
310
+ --ds-text-secondary: var(--ds-neutral-300);
311
+ --ds-text-muted: var(--ds-neutral-400);
312
+ --ds-text-on-primary: oklch(1 0 0);
313
+
314
+ /* Borders — bumped one step lighter for visibility against 800/900 surfaces */
315
+ --ds-border-default: var(--ds-neutral-600);
316
+ --ds-border-subtle: var(--ds-neutral-700);
317
+ --ds-border-strong: var(--ds-neutral-400);
318
+ --ds-border-focus: var(--ds-primary-400);
319
+
320
+ /* Status — lighter foreground tones, deeper backgrounds */
321
+ --ds-status-success: var(--ds-success-400);
322
+ --ds-status-success-bg: var(--ds-success-950);
323
+ --ds-status-warning: var(--ds-warning-400);
324
+ --ds-status-warning-bg: var(--ds-warning-950);
325
+ --ds-status-error: var(--ds-destructive-400);
326
+ --ds-status-error-bg: var(--ds-destructive-950);
327
+ --ds-status-info: var(--ds-info-400);
328
+ --ds-status-info-bg: var(--ds-info-950);
329
+
330
+ /* Sidebar — sits at canvas level, border provides separation */
331
+ --ds-sidebar-bg: var(--ds-neutral-800);
332
+ --ds-sidebar-border: var(--ds-neutral-700);
333
+ --ds-sidebar-item-hover: var(--ds-neutral-900);
334
+ --ds-sidebar-item-active: var(--ds-neutral-700);
335
+ --ds-sidebar-text: var(--ds-text-primary);
336
+ --ds-sidebar-text-secondary: var(--ds-text-secondary);
337
+ --ds-sidebar-text-muted: var(--ds-text-muted);
338
+ --ds-sidebar-accent: var(--ds-accent-primary);
339
+
340
+ --ds-tab-hover-bg: var(--ds-bg-muted);
341
+ --ds-tab-active-bg: var(--ds-bg-surface);
342
+
343
+ /* Inputs */
344
+ --ds-input-bg: var(--ds-neutral-800);
345
+ --ds-input-border: var(--ds-neutral-600);
346
+ --ds-input-focus-ring: var(--ds-primary-400);
347
+
348
+ /* Shadows — amplified alpha so they're visible on dark surfaces */
349
+ --ds-shadow-sm:
350
+ calc(var(--ds-shadow-offset-x) * 0.5) calc(var(--ds-shadow-offset-y) * 0.5) var(--ds-shadow-blur) 0 oklch(0% 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * 3), 1));
351
+
352
+ --ds-shadow-md:
353
+ var(--ds-shadow-offset-x) var(--ds-shadow-offset-y) calc(var(--ds-shadow-blur) * 1.5) 0 oklch(0% 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * 3), 1));
354
+
355
+ --ds-shadow-lg:
356
+ calc(var(--ds-shadow-offset-x) * 2) calc(var(--ds-shadow-offset-y) * 2) calc(var(--ds-shadow-blur) * 2.5) 0 oklch(0% 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * 3), 1));
357
+
358
+ --ds-shadow-xl:
359
+ calc(var(--ds-shadow-offset-x) * 3) calc(var(--ds-shadow-offset-y) * 3) calc(var(--ds-shadow-blur) * 3.5) 0 oklch(0% 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * 3), 1));
360
+
361
+ --ds-shadow-card:
362
+ calc(var(--ds-shadow-offset-x) * 1.5) calc(var(--ds-shadow-offset-y) * 1.5) calc(var(--ds-shadow-blur) * 2) 0 oklch(0% 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * 3), 1));
363
+
364
+ --ds-shadow-button:
365
+ calc(var(--ds-shadow-offset-x) * 0.5) calc(var(--ds-shadow-offset-y) * 0.5) var(--ds-shadow-blur) 0 oklch(0% 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * 3), 1));
366
+
367
+ --ds-shadow-dropdown:
368
+ var(--ds-shadow-offset-x) var(--ds-shadow-offset-y) calc(var(--ds-shadow-blur) * 2) 0 oklch(0% 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * 3), 1));
369
+
370
+ --ds-shadow-modal:
371
+ calc(var(--ds-shadow-offset-x) * 2) calc(var(--ds-shadow-offset-y) * 2) calc(var(--ds-shadow-blur) * 3.5) 0 oklch(0% 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * 3), 1));
372
+
373
+ --ds-shadow-focus: 0 0 0 2px var(--ds-primary-400);
374
+ }
375
+
376
+ /* ── Glass Fallback ──────────────────────────────────────────────── */
377
+
378
+ @supports not (backdrop-filter: blur(1px)) {
379
+ :root {
380
+ --ds-glass-tint: 0.85;
381
+ --ds-glass-blur: 0px;
382
+ }
383
+ }
384
+
385
+ @media (prefers-reduced-transparency: reduce) {
386
+ :root {
387
+ --ds-glass-tint: 0.90;
388
+ --ds-glass-blur: 2px;
389
+ --ds-glass-border-alpha: 0.3;
390
+ }
391
+ }
392
+
393
+ /* ── Reduced Motion ─────────────────────────────────────────────── */
394
+
395
+ @media (prefers-reduced-motion: reduce) {
396
+ :root {
397
+ --ds-transition-speed: 0ms;
398
+ }
399
+ }
400
+
401
+ /* ── Shadow Mode: Neumorphic ────────────────────────────────────
402
+ Dual opposing shadows: dark bottom-right + bright top-left.
403
+ Responsive to offset/blur/alpha sliders via root variables.
404
+ Shadow colour is configurable via --ds-nm-dark-* properties,
405
+ allowing themes to use tinted greys (neumorphism), coloured
406
+ shadows (claymorphism), or chassis greys (industrial).
407
+ Presets override these via lightOverrides (inline styles). ── */
408
+
409
+ [data-shadow="neumorphic"] {
410
+ /* Configurable shadow colour — defaults to pure black / pure white.
411
+ Presets override for tinted material-matching shadows. */
412
+ --ds-nm-dark-l: 0;
413
+ --ds-nm-dark-c: 0;
414
+ --ds-nm-dark-h: 0;
415
+ --ds-nm-light-mult: 0.7;
416
+
417
+ --ds-input-shadow:
418
+ inset calc(var(--ds-shadow-offset-x) * 0.5) calc(var(--ds-shadow-offset-y) * 0.5) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha)),
419
+ inset calc(var(--ds-shadow-offset-x) * -0.5) calc(var(--ds-shadow-offset-y) * -0.5) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(1 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * var(--ds-nm-light-mult)), 1));
420
+
421
+ --ds-shadow-sm:
422
+ calc(var(--ds-shadow-offset-x) * 0.33) calc(var(--ds-shadow-offset-y) * 0.33) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha)),
423
+ calc(var(--ds-shadow-offset-x) * -0.33) calc(var(--ds-shadow-offset-y) * -0.33) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(1 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * var(--ds-nm-light-mult)), 1));
424
+
425
+ --ds-shadow-md:
426
+ var(--ds-shadow-offset-x) var(--ds-shadow-offset-y) var(--ds-shadow-blur) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha)),
427
+ calc(var(--ds-shadow-offset-x) * -1) calc(var(--ds-shadow-offset-y) * -1) var(--ds-shadow-blur) 0 oklch(1 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * var(--ds-nm-light-mult)), 1));
428
+
429
+ --ds-shadow-lg:
430
+ calc(var(--ds-shadow-offset-x) * 1.5) calc(var(--ds-shadow-offset-y) * 1.5) calc(var(--ds-shadow-blur) * 1.5) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha)),
431
+ calc(var(--ds-shadow-offset-x) * -1.5) calc(var(--ds-shadow-offset-y) * -1.5) calc(var(--ds-shadow-blur) * 1.5) 0 oklch(1 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * var(--ds-nm-light-mult)), 1));
432
+
433
+ --ds-shadow-xl:
434
+ calc(var(--ds-shadow-offset-x) * 2) calc(var(--ds-shadow-offset-y) * 2) calc(var(--ds-shadow-blur) * 2) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha)),
435
+ calc(var(--ds-shadow-offset-x) * -2) calc(var(--ds-shadow-offset-y) * -2) calc(var(--ds-shadow-blur) * 2) 0 oklch(1 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * var(--ds-nm-light-mult)), 1));
436
+
437
+ --ds-shadow-card:
438
+ calc(var(--ds-shadow-offset-x) * 1.2) calc(var(--ds-shadow-offset-y) * 1.2) calc(var(--ds-shadow-blur) * 1.2) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha)),
439
+ calc(var(--ds-shadow-offset-x) * -1.2) calc(var(--ds-shadow-offset-y) * -1.2) calc(var(--ds-shadow-blur) * 1.2) 0 oklch(1 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * var(--ds-nm-light-mult)), 1));
440
+
441
+ --ds-shadow-button:
442
+ calc(var(--ds-shadow-offset-x) * 0.33) calc(var(--ds-shadow-offset-y) * 0.33) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha)),
443
+ calc(var(--ds-shadow-offset-x) * -0.33) calc(var(--ds-shadow-offset-y) * -0.33) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(1 0 0 / clamp(0, calc(var(--ds-shadow-alpha) * var(--ds-nm-light-mult)), 1));
444
+
445
+ --ds-shadow-dropdown:
446
+ var(--ds-shadow-offset-x) var(--ds-shadow-offset-y) calc(var(--ds-shadow-blur) * 1.5) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha));
447
+
448
+ --ds-shadow-modal:
449
+ calc(var(--ds-shadow-offset-x) * 2) calc(var(--ds-shadow-offset-y) * 2) calc(var(--ds-shadow-blur) * 2.5) 0 oklch(var(--ds-nm-dark-l) var(--ds-nm-dark-c) var(--ds-nm-dark-h) / var(--ds-shadow-alpha));
450
+ }
451
+
452
+ [data-shadow="neumorphic"][data-mode="dark"] {
453
+ --ds-input-shadow:
454
+ inset calc(var(--ds-shadow-offset-x) * 0.5) calc(var(--ds-shadow-offset-y) * 0.5) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2)),
455
+ inset calc(var(--ds-shadow-offset-x) * -0.5) calc(var(--ds-shadow-offset-y) * -0.5) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(1 0 0 / calc(var(--ds-shadow-alpha) * 0.12));
456
+
457
+ --ds-shadow-sm:
458
+ calc(var(--ds-shadow-offset-x) * 0.33) calc(var(--ds-shadow-offset-y) * 0.33) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2)),
459
+ calc(var(--ds-shadow-offset-x) * -0.33) calc(var(--ds-shadow-offset-y) * -0.33) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(1 0 0 / calc(var(--ds-shadow-alpha) * 0.12));
460
+
461
+ --ds-shadow-md:
462
+ var(--ds-shadow-offset-x) var(--ds-shadow-offset-y) var(--ds-shadow-blur) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2)),
463
+ calc(var(--ds-shadow-offset-x) * -1) calc(var(--ds-shadow-offset-y) * -1) var(--ds-shadow-blur) 0 oklch(1 0 0 / calc(var(--ds-shadow-alpha) * 0.12));
464
+
465
+ --ds-shadow-lg:
466
+ calc(var(--ds-shadow-offset-x) * 1.5) calc(var(--ds-shadow-offset-y) * 1.5) calc(var(--ds-shadow-blur) * 1.5) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2)),
467
+ calc(var(--ds-shadow-offset-x) * -1.5) calc(var(--ds-shadow-offset-y) * -1.5) calc(var(--ds-shadow-blur) * 1.5) 0 oklch(1 0 0 / calc(var(--ds-shadow-alpha) * 0.12));
468
+
469
+ --ds-shadow-xl:
470
+ calc(var(--ds-shadow-offset-x) * 2) calc(var(--ds-shadow-offset-y) * 2) calc(var(--ds-shadow-blur) * 2) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2)),
471
+ calc(var(--ds-shadow-offset-x) * -2) calc(var(--ds-shadow-offset-y) * -2) calc(var(--ds-shadow-blur) * 2) 0 oklch(1 0 0 / calc(var(--ds-shadow-alpha) * 0.12));
472
+
473
+ --ds-shadow-card:
474
+ calc(var(--ds-shadow-offset-x) * 1.2) calc(var(--ds-shadow-offset-y) * 1.2) calc(var(--ds-shadow-blur) * 1.2) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2)),
475
+ calc(var(--ds-shadow-offset-x) * -1.2) calc(var(--ds-shadow-offset-y) * -1.2) calc(var(--ds-shadow-blur) * 1.2) 0 oklch(1 0 0 / calc(var(--ds-shadow-alpha) * 0.12));
476
+
477
+ --ds-shadow-button:
478
+ calc(var(--ds-shadow-offset-x) * 0.33) calc(var(--ds-shadow-offset-y) * 0.33) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2)),
479
+ calc(var(--ds-shadow-offset-x) * -0.33) calc(var(--ds-shadow-offset-y) * -0.33) calc(var(--ds-shadow-blur) * 0.5) 0 oklch(1 0 0 / calc(var(--ds-shadow-alpha) * 0.12));
480
+
481
+ --ds-shadow-dropdown:
482
+ var(--ds-shadow-offset-x) var(--ds-shadow-offset-y) calc(var(--ds-shadow-blur) * 1.5) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2));
483
+
484
+ --ds-shadow-modal:
485
+ calc(var(--ds-shadow-offset-x) * 2) calc(var(--ds-shadow-offset-y) * 2) calc(var(--ds-shadow-blur) * 2.5) 0 oklch(0 0 0 / calc(var(--ds-shadow-alpha) * 2));
486
+ }
487
+
488
+ /* ── Shadow Mode: Glow ──────────────────────────────────────────
489
+ Emissive bloom using the primary hue. No directional offset.
490
+ Uses --ds-hue-primary to construct glow colour so it stays
491
+ reactive to hue slider changes. ──────────────────────────────── */
492
+
493
+ [data-shadow="glow"] {
494
+ --ds-shadow-sm:
495
+ 0 0 calc(var(--ds-shadow-blur) * 0.5) 0 oklch(0.6 0.15 var(--ds-hue-primary) / var(--ds-shadow-alpha));
496
+
497
+ --ds-shadow-md:
498
+ 0 0 var(--ds-shadow-blur) 0 oklch(0.6 0.15 var(--ds-hue-primary) / var(--ds-shadow-alpha)),
499
+ 0 0 calc(var(--ds-shadow-blur) * 2) 0 oklch(0.6 0.15 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.4));
500
+
501
+ --ds-shadow-lg:
502
+ 0 0 calc(var(--ds-shadow-blur) * 1.5) 0 oklch(0.6 0.15 var(--ds-hue-primary) / var(--ds-shadow-alpha)),
503
+ 0 0 calc(var(--ds-shadow-blur) * 3) 0 oklch(0.6 0.15 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.3));
504
+
505
+ --ds-shadow-xl:
506
+ 0 0 calc(var(--ds-shadow-blur) * 2) 0 oklch(0.6 0.15 var(--ds-hue-primary) / var(--ds-shadow-alpha)),
507
+ 0 0 calc(var(--ds-shadow-blur) * 4) 0 oklch(0.6 0.15 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.25));
508
+
509
+ --ds-shadow-card:
510
+ 0 0 calc(var(--ds-shadow-blur) * 1.2) 0 oklch(0.6 0.15 var(--ds-hue-primary) / var(--ds-shadow-alpha)),
511
+ 0 0 calc(var(--ds-shadow-blur) * 2.5) 0 oklch(0.6 0.15 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.35));
512
+
513
+ --ds-shadow-button:
514
+ 0 0 calc(var(--ds-shadow-blur) * 0.5) 0 oklch(0.6 0.15 var(--ds-hue-primary) / var(--ds-shadow-alpha));
515
+
516
+ --ds-shadow-dropdown:
517
+ 0 0 var(--ds-shadow-blur) 0 oklch(0.6 0.15 var(--ds-hue-primary) / var(--ds-shadow-alpha)),
518
+ 0 0 calc(var(--ds-shadow-blur) * 2.5) 0 oklch(0.6 0.15 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.3));
519
+
520
+ --ds-shadow-modal:
521
+ 0 0 calc(var(--ds-shadow-blur) * 2) 0 oklch(0.6 0.15 var(--ds-hue-primary) / var(--ds-shadow-alpha)),
522
+ 0 0 calc(var(--ds-shadow-blur) * 4) 0 oklch(0.6 0.15 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.25));
523
+ }
524
+
525
+ [data-shadow="glow"][data-mode="dark"] {
526
+ --ds-shadow-sm:
527
+ 0 0 calc(var(--ds-shadow-blur) * 0.75) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 1.5));
528
+
529
+ --ds-shadow-md:
530
+ 0 0 calc(var(--ds-shadow-blur) * 1.2) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 1.5)),
531
+ 0 0 calc(var(--ds-shadow-blur) * 2.5) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.6));
532
+
533
+ --ds-shadow-lg:
534
+ 0 0 calc(var(--ds-shadow-blur) * 2) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 1.5)),
535
+ 0 0 calc(var(--ds-shadow-blur) * 4) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.5));
536
+
537
+ --ds-shadow-xl:
538
+ 0 0 calc(var(--ds-shadow-blur) * 2.5) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 1.5)),
539
+ 0 0 calc(var(--ds-shadow-blur) * 5) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.4));
540
+
541
+ --ds-shadow-card:
542
+ 0 0 calc(var(--ds-shadow-blur) * 1.5) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 1.5)),
543
+ 0 0 calc(var(--ds-shadow-blur) * 3) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.5));
544
+
545
+ --ds-shadow-button:
546
+ 0 0 calc(var(--ds-shadow-blur) * 0.75) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 1.5));
547
+
548
+ --ds-shadow-dropdown:
549
+ 0 0 calc(var(--ds-shadow-blur) * 1.5) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 1.5)),
550
+ 0 0 calc(var(--ds-shadow-blur) * 3) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.5));
551
+
552
+ --ds-shadow-modal:
553
+ 0 0 calc(var(--ds-shadow-blur) * 2.5) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 1.5)),
554
+ 0 0 calc(var(--ds-shadow-blur) * 5) 0 oklch(0.65 0.18 var(--ds-hue-primary) / calc(var(--ds-shadow-alpha) * 0.4));
555
+ }
556
+
557
+ /* ── Responsive Density Overrides ──────────────────────────────
558
+ Compact on small viewports, spacious on large.
559
+ Custom --ds-density from ThemeContext/CustomPanel overrides these. ── */
560
+
561
+ @media (max-width: 640px) {
562
+ :root:not([style*="--ds-density"]) {
563
+ --ds-density: 0.875;
564
+ }
565
+ }
566
+
567
+ @media (min-width: 1280px) {
568
+ :root:not([style*="--ds-density"]) {
569
+ --ds-density: 1;
570
+ }
571
+ }
572
+
573
+ /* ── Sketch / Hand-Drawn Mode ───────────────────────────────────
574
+ Activated via data-sketch attribute on <html>.
575
+ Applies wobbly border-radius to surfaces. ─────────────────── */
576
+
577
+ [data-sketch] {
578
+ --ds-sketch-wobble-lg: 255px 15px 225px 15px / 15px 225px 15px 255px;
579
+ --ds-sketch-wobble-md: 185px 12px 165px 12px / 12px 165px 12px 185px;
580
+ --ds-sketch-wobble-sm: 95px 8px 85px 8px / 8px 85px 8px 95px;
581
+ }
582
+
583
+ /* Cards, dialogs, alerts, dropdowns — large surfaces */
584
+ [data-sketch] [class*="rounded-[var(--ds-radius-md)"] {
585
+ border-radius: var(--ds-sketch-wobble-lg);
586
+ }
587
+
588
+ [data-sketch] [class*="rounded-[var(--ds-radius-xl)"] {
589
+ border-radius: var(--ds-sketch-wobble-lg);
590
+ }
591
+
592
+ [data-sketch] [class*="rounded-[var(--ds-radius-lg)"] {
593
+ border-radius: var(--ds-sketch-wobble-lg);
594
+ }
595
+
596
+ /* Buttons, inputs, badges — small surfaces */
597
+ [data-sketch] [class*="rounded-[var(--ds-radius-sm)"] {
598
+ border-radius: var(--ds-sketch-wobble-sm);
599
+ }
@@ -0,0 +1,46 @@
1
+ /* Gridsmith — Tailwind v4 theme bindings
2
+ Maps --ds-* design tokens to Tailwind utilities.
3
+ Import AFTER roots.css and your tokens file. */
4
+
5
+ @theme {
6
+ --font-sans: var(--ds-font-sans);
7
+ --font-mono: var(--ds-font-mono);
8
+ --font-display: var(--ds-font-display);
9
+ --default-transition-duration: var(--ds-transition-speed);
10
+ --default-transition-timing-function: var(--ds-transition-ease);
11
+
12
+ --spacing-ds-0_5: var(--ds-space-0\.5);
13
+ --spacing-ds-1: var(--ds-space-1);
14
+ --spacing-ds-1_5: var(--ds-space-1\.5);
15
+ --spacing-ds-2: var(--ds-space-2);
16
+ --spacing-ds-2_5: var(--ds-space-2\.5);
17
+ --spacing-ds-3: var(--ds-space-3);
18
+ --spacing-ds-4: var(--ds-space-4);
19
+ --spacing-ds-5: var(--ds-space-5);
20
+ --spacing-ds-6: var(--ds-space-6);
21
+ --spacing-ds-8: var(--ds-space-8);
22
+ --spacing-ds-10: var(--ds-space-10);
23
+ --spacing-ds-12: var(--ds-space-12);
24
+
25
+ --font-size-xs: var(--ds-font-size-xs);
26
+ --font-size-sm: var(--ds-font-size-sm);
27
+ --font-size-base: var(--ds-font-size-body);
28
+ --font-size-lg: var(--ds-font-size-lg);
29
+ --font-size-xl: var(--ds-font-size-xl);
30
+ --font-size-2xl: var(--ds-font-size-2xl);
31
+ --font-size-3xl: var(--ds-font-size-3xl);
32
+
33
+ --font-weight-normal: var(--ds-weight-base);
34
+ --font-weight-medium: var(--ds-weight-emphasis);
35
+ --font-weight-semibold: var(--ds-weight-strong);
36
+ --font-weight-bold: var(--ds-weight-heavy);
37
+
38
+ --opacity-disabled: var(--ds-opacity-disabled);
39
+
40
+ --color-accent-subtle: var(--ds-accent-subtle);
41
+ --color-sidebar-accent-subtle: var(--ds-sidebar-accent-subtle);
42
+ }
43
+
44
+ @utility text-2xs {
45
+ font-size: var(--ds-font-size-2xs);
46
+ }