@brightweblabs/theme 0.2.1 → 0.4.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/src/tokens.css CHANGED
@@ -1,11 +1,75 @@
1
1
  /* ── L0: brand primitives ─────────────────────────────────────────────── */
2
2
  :root {
3
3
  color-scheme: light;
4
- --font-body: "Mulish", "Mulish Fallback", "Segoe UI", Arial, sans-serif;
4
+ /* Font loaders expose these variables at the app root. Client themes only
5
+ override this family layer; component recipes never name a font. The system
6
+ fallback after the loaded-font var is REQUIRED: without it a missing
7
+ --font-geist-sans makes the whole var() chain "guaranteed-invalid" and
8
+ font-family silently reverts to the browser default (Times), instead of a
9
+ clean sans. */
10
+ --font-body: var(--font-geist-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);
5
11
  --font-heading: var(--font-body);
6
- --font-sans: var(--font-body);
7
- --font-display: var(--font-heading);
8
- --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", "Menlo", monospace;
12
+ --font-code: var(--font-geist-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace);
13
+
14
+ /* Typography primitives. These raw values live here—and only here—so a
15
+ maintainer can retune family, scale, weight, rhythm, or tracking globally. */
16
+ --type-weight-regular: 400;
17
+ --type-weight-medium: 600;
18
+ --type-weight-bold: 700;
19
+ --type-weight-heavy: 800;
20
+ --type-weight-black: 900;
21
+
22
+ --type-leading-090: 0.9;
23
+ --type-leading-092: 0.92;
24
+ --type-leading-095: 0.95;
25
+ --type-leading-096: 0.96;
26
+ --type-leading-none: 1;
27
+ --type-leading-102: 1.02;
28
+ --type-leading-104: 1.04;
29
+ --type-leading-105: 1.05;
30
+ --type-leading-110: 1.1;
31
+ --type-leading-115: 1.15;
32
+ --type-leading-120: 1.2;
33
+ --type-leading-124: 1.238;
34
+ --type-leading-tight: 1.25;
35
+ --type-leading-130: 1.3;
36
+ --type-leading-133: calc(1 / 0.75);
37
+ --type-leading-snug: 1.375;
38
+ --type-leading-140: 1.4;
39
+ --type-leading-143: calc(1.25 / 0.875);
40
+ --type-leading-145: 1.45;
41
+ --type-leading-normal: 1.5;
42
+ --type-leading-155: 1.55;
43
+ --type-leading-156: calc(1.75 / 1.125);
44
+ --type-leading-160: 1.6;
45
+ --type-leading-relaxed: 1.625;
46
+ --type-leading-165: 1.65;
47
+ --type-leading-166: 1.66;
48
+ --type-leading-172: 1.72;
49
+ --type-leading-loose: 2;
50
+
51
+ --type-tracking-n050: -0.05em;
52
+ --type-tracking-n045: -0.045em;
53
+ --type-tracking-n040: -0.04em;
54
+ --type-tracking-n035: -0.035em;
55
+ --type-tracking-n030: -0.03em;
56
+ --type-tracking-n025: -0.025em;
57
+ --type-tracking-n020: -0.02em;
58
+ --type-tracking-tight: -0.025em;
59
+ --type-tracking-n010: -0.01em;
60
+ --type-tracking-normal: 0;
61
+ --type-tracking-010: 0.01em;
62
+ --type-tracking-wide: 0.025em;
63
+ --type-tracking-040: 0.04em;
64
+ --type-tracking-wider: 0.05em;
65
+ --type-tracking-060: 0.06em;
66
+ --type-tracking-080: 0.08em;
67
+ --type-tracking-100: 0.1em;
68
+ --type-tracking-120: 0.12em;
69
+ --type-tracking-140: 0.14em;
70
+ --type-tracking-160: 0.16em;
71
+ --type-tracking-widest: 0.1em;
72
+ --type-tracking-180: 0.18em;
9
73
 
10
74
  --brand-accent: #4a7dbd;
11
75
  --brand-accent-soft: #7196c4;
@@ -34,6 +98,7 @@
34
98
  --secondary-foreground: var(--brand-ink);
35
99
  --muted: rgba(203, 213, 225, 0.25);
36
100
  --muted-foreground: var(--brand-neutral-500);
101
+ --foreground-muted-accessible: #5f6b7a;
37
102
  --foreground-inverse: var(--brand-white);
38
103
  --foreground-inverse-muted: rgba(255, 255, 255, 0.88);
39
104
  --foreground-inverse-subtle: rgba(255, 255, 255, 0.84);
@@ -60,6 +125,34 @@
60
125
  --semantic-neutral: #71717a;
61
126
  --semantic-neutral-strong: #52525b;
62
127
 
128
+ --project-state-planned: var(--semantic-info);
129
+ --project-state-planned-strong: var(--semantic-info-strong);
130
+ --project-state-active: var(--semantic-success);
131
+ --project-state-active-strong: var(--semantic-success-strong);
132
+ --project-state-blocked: var(--semantic-special);
133
+ --project-state-blocked-strong: var(--semantic-special-strong);
134
+ --project-state-completed: var(--semantic-success);
135
+ --project-state-completed-strong: var(--semantic-success-strong);
136
+ --project-state-canceled: var(--semantic-neutral);
137
+ --project-state-canceled-strong: var(--semantic-neutral-strong);
138
+ --project-risk-at-risk: var(--semantic-warning);
139
+ --project-risk-at-risk-strong: var(--semantic-warning-strong);
140
+ --project-risk-overdue: var(--semantic-danger);
141
+ --project-risk-overdue-strong: var(--semantic-danger-strong);
142
+ --project-risk-overdue-soft: var(--semantic-danger-soft);
143
+ /* Ink to use ON a solid health fill: light-mode fills are saturated so
144
+ ink flips per theme (see dark block). */
145
+ --project-risk-overdue-ink: #ffffff;
146
+ --project-risk-at-risk-ink: #3a2a05;
147
+ --project-state-completed-ink: #06281e;
148
+ --project-health-on-track: var(--project-state-active-strong);
149
+ --project-health-at-risk: var(--project-risk-at-risk);
150
+ --project-health-at-risk-strong: var(--project-risk-at-risk-strong);
151
+ --project-health-off-track: var(--project-risk-overdue);
152
+ --project-health-progress: var(--project-state-active);
153
+ --project-health-off-track-strong: var(--project-risk-overdue-strong);
154
+ --project-health-off-track-soft: var(--project-risk-overdue-soft);
155
+
63
156
  /* ── L3: experience tokens ─────────────────────────────────────────── */
64
157
  --space-2xs: 0.25rem;
65
158
  --space-xs: 0.5rem;
@@ -85,10 +178,20 @@
85
178
  --radius-control: 0.625rem;
86
179
  --radius-card: 0.75rem;
87
180
  --radius-panel: 1rem;
181
+ --radius-swatch: 0.125rem;
182
+ --radius-pill: 999px;
183
+ --radius-scrollbar: 9999px;
88
184
 
185
+ /* MQ-derived size scale. Aliases below retain the current rendered sizes. */
186
+ --text-ui-nano: 0.4375rem;
187
+ --text-ui-nano-lg: 0.5rem;
188
+ --text-ui-fine: 0.5625rem;
89
189
  --text-ui-micro: 0.625rem;
90
190
  --text-ui-label: 0.6875rem;
191
+ --text-ui-label-relaxed: 0.7rem;
91
192
  --text-ui-meta: 0.75rem;
193
+ --text-ui-chip: 0.78125rem;
194
+ --text-ui-action: 0.8125rem;
92
195
  --text-ui-body: 0.875rem;
93
196
  --text-ui-card-title: 0.9375rem;
94
197
  --text-ui-subhead: 1.125rem;
@@ -96,9 +199,29 @@
96
199
  --text-ui-heading: 1.5rem;
97
200
  --text-ui-title-sm: 1.875rem;
98
201
  --text-ui-title: clamp(1.75rem, 1.6rem + 0.7vw, 2rem);
202
+ --text-ui-shell-title: 1.3125rem;
203
+ --text-ui-report-title: 1.75rem;
204
+ --text-ui-report-title-lg: 2.25rem;
205
+ --text-ui-calendar: 0.8rem;
206
+ --text-ui-report-metric: 2.5rem;
99
207
  --text-ui-metric: 2.75rem;
100
208
  --text-ui-metric-xl: 3.5rem;
209
+ --text-ui-dashboard-card-title: 1.375rem;
210
+ --text-ui-dashboard-title: 2.125rem;
211
+ --text-ui-preview-card-title: 2.375rem;
212
+ --text-ui-dashboard-title-lg: 2.75rem;
213
+ --text-ui-dashboard-metric: 3.25rem;
214
+ --text-ui-preview-stat: clamp(2rem, 4vw, 3rem);
215
+ --text-ui-preview-title: clamp(2.4rem, 5.5vw, 4.8rem);
216
+ --text-ui-auth-title: clamp(2.4rem, 5vw, 4.75rem);
101
217
  --text-ui-metric-display: var(--text-ui-metric);
218
+ --portal-text-micro: 0.625rem;
219
+ --type-paragraph-large: 1.09375rem;
220
+ --type-heading-2: clamp(2rem, 4vw, 2.8125rem);
221
+ --type-paragraph: 1rem;
222
+ --type-paragraph-small: 0.875rem;
223
+ --type-paragraph-mini: 0.75rem;
224
+ --type-label: 0.625rem;
102
225
 
103
226
  --elevate-1: color-mix(in srgb, var(--foreground) 3%, transparent);
104
227
  --elevate-2: color-mix(in srgb, var(--foreground) 5%, transparent);
@@ -109,6 +232,133 @@
109
232
  --border-hairline-soft: color-mix(in srgb, var(--foreground) 12%, transparent);
110
233
  --border-strong: color-mix(in srgb, var(--foreground) 24%, transparent);
111
234
  --surface-hover: color-mix(in srgb, var(--foreground) 4%, var(--card) 96%);
235
+ --surface-overlay: color-mix(in srgb, var(--foreground) 50%, transparent);
236
+ --surface-overlay-strong: color-mix(in srgb, var(--foreground) 55%, transparent);
237
+ --surface-tooltip: color-mix(in srgb, var(--popover) 95%, transparent);
238
+ --surface-badge-tint: color-mix(in srgb, currentColor 14%, transparent);
239
+ --surface-button-soft: color-mix(in srgb, var(--foreground) 3.5%, var(--card));
240
+ --surface-button-soft-hover: color-mix(in srgb, var(--foreground) 7%, var(--card));
241
+ --border-button-soft-hover: color-mix(in srgb, var(--foreground) 16%, transparent);
242
+ --surface-button-brand: color-mix(in srgb, var(--brand-accent) 84%, var(--foreground));
243
+ --foreground-accent-link: color-mix(in srgb, var(--brand-accent) 45%, var(--foreground));
244
+ --surface-selection: color-mix(in srgb, var(--accent) 12%, var(--card));
245
+ --border-selection: color-mix(in srgb, var(--accent) 40%, var(--hairline));
246
+ --surface-pagination-active: color-mix(in srgb, var(--accent) 10%, var(--card));
247
+ --border-pagination-active: color-mix(in srgb, var(--accent) 36%, transparent);
248
+ --surface-danger-subtle: color-mix(in srgb, var(--semantic-danger) 10%, transparent);
249
+ --surface-account-team: color-mix(in srgb, var(--role-team) 20%, var(--card));
250
+ --surface-account-client: color-mix(in srgb, var(--role-client) 20%, var(--card));
251
+ --surface-account: color-mix(in srgb, var(--foreground) 3%, var(--card) 97%);
252
+ --surface-account-hover: color-mix(in srgb, var(--foreground) 5%, transparent);
253
+ --account-presence: #10b981;
254
+ --account-presence-size: 0.625rem;
255
+ --surface-status-success: color-mix(in srgb, var(--semantic-success) 14%, transparent);
256
+ --surface-status-warning: color-mix(in srgb, var(--semantic-warning) 14%, transparent);
257
+ --surface-status-danger: color-mix(in srgb, var(--semantic-danger) 12%, transparent);
258
+ --scrollbar-thumb: color-mix(in srgb, var(--foreground) 18%, transparent);
259
+ --scrollbar-thumb-hover: color-mix(in srgb, var(--foreground) 30%, transparent);
260
+
261
+ --toast-success-bg: color-mix(in srgb, var(--primary) 12%, var(--background));
262
+ --toast-success-border: color-mix(in srgb, var(--primary) 30%, var(--background));
263
+ --toast-warning-bg: color-mix(in srgb, var(--accent) 12%, var(--background));
264
+ --toast-warning-text: color-mix(in srgb, var(--accent) 80%, var(--foreground));
265
+ --toast-warning-border: color-mix(in srgb, var(--accent) 30%, var(--background));
266
+ --toast-error-bg: color-mix(in srgb, var(--destructive) 12%, var(--background));
267
+ --toast-error-border: color-mix(in srgb, var(--destructive) 30%, var(--background));
268
+ --toast-info-bg: color-mix(in srgb, var(--secondary) 15%, var(--background));
269
+ --toast-info-text: color-mix(in srgb, var(--secondary) 70%, var(--foreground));
270
+ --toast-info-border: color-mix(in srgb, var(--secondary) 30%, var(--background));
271
+
272
+ --shadow-accent-control: 0 4px 14px color-mix(in srgb, var(--brand-accent) 26%, transparent);
273
+ --shadow-toolbar-control: 0 4px 14px rgba(91, 197, 242, 0.26);
274
+ --shadow-toolbar-popover: 0 18px 44px rgba(10, 21, 26, 0.16), 0 2px 10px rgba(10, 21, 26, 0.08);
275
+ --shadow-tooltip: 0 14px 34px var(--elevate-3);
276
+ --shadow-dialog: 0 24px 64px var(--elevate-3);
277
+ --shadow-phone-dropdown: 0 12px 28px var(--elevate-3);
278
+
279
+ --report-hero-glow: radial-gradient(circle, color-mix(in srgb, var(--accent) 38%, transparent), transparent 70%);
280
+ --report-hero-rule: linear-gradient(90deg, transparent, color-mix(in srgb, var(--accent) 60%, transparent), transparent);
281
+
282
+ --shell-frame-offset: 0.75rem;
283
+ --shell-sidebar-width: 15rem;
284
+ --shell-sidebar-collapsed-width: 4rem;
285
+ --shell-sidebar-toggle-offset: 3.25rem;
286
+ --shell-sidebar-toggle-size: 1.625rem;
287
+ --shell-sidebar-toggle-inset: -0.8125rem;
288
+ --shell-brand-height: 2.25rem;
289
+ --shell-nav-item-height: 2.625rem;
290
+ --shell-nav-item-collapsed-size: 2.75rem;
291
+ --shell-nav-icon-well-size: 1.6875rem;
292
+ --shell-nav-icon-radius: 0.5rem;
293
+ --shell-nav-icon-size: 0.9375rem;
294
+ --shell-nav-divider-width: 2.25rem;
295
+ --shell-nav-child-height: 2.25rem;
296
+ --shell-nav-child-enter-offset: 0.25rem;
297
+ --shell-nav-active-indicator-inset: 0.5625rem;
298
+ --shell-nav-active-indicator-collapsed-inset: 0.6875rem;
299
+ --shell-nav-active-indicator-width: 0.1875rem;
300
+ --shell-nav-active-indicator-offset: -0.0625rem;
301
+ --shell-nav-context-dot-size: 0.5rem;
302
+ --shell-nav-context-dot-offset: -0.1875rem;
303
+ --shell-nav-context-dot-border: 0.125rem;
304
+ --shell-header-divider-height: 1.25rem;
305
+ --shell-account-gap: 0.6875rem;
306
+ --shell-account-padding-y: 0.4375rem;
307
+ --shell-surface-border: color-mix(in srgb, var(--foreground) 10%, transparent);
308
+ --shell-surface-hover: color-mix(in srgb, var(--card) 78%, var(--foreground) 3%);
309
+ --shell-surface-active: color-mix(in srgb, var(--accent) 11%, var(--card) 89%);
310
+ --shell-hairline: color-mix(in srgb, var(--foreground) 7%, transparent);
311
+ --shell-icon-bg: color-mix(in srgb, var(--foreground) 4.5%, var(--card) 95.5%);
312
+ --shell-group-open: color-mix(in srgb, var(--foreground) 2.6%, transparent);
313
+ --shell-shadow: 0 16px 38px rgba(10, 21, 26, 0.06), 0 2px 10px rgba(10, 21, 26, 0.04);
314
+ --shell-background: #f4f8fb;
315
+ --shell-sidebar-background: linear-gradient(180deg, color-mix(in srgb, var(--card) 94%, white 6%) 0%, color-mix(in srgb, var(--card) 98%, transparent) 100%);
316
+ --shell-control-muted: color-mix(in srgb, var(--foreground) 58%, transparent);
317
+ --shell-nav-foreground: color-mix(in srgb, var(--foreground) 70%, transparent);
318
+ --shell-nav-active-border: color-mix(in srgb, var(--accent) 28%, var(--shell-surface-border));
319
+ --shell-nav-active-icon-bg: color-mix(in srgb, var(--accent) 18%, var(--card) 82%);
320
+ --shell-nav-active-icon-fg: color-mix(in srgb, var(--accent) 82%, black 18%);
321
+ --shell-nav-context-icon-bg: color-mix(in srgb, var(--accent) 16%, var(--card) 84%);
322
+ --shell-nav-context-icon-fg: color-mix(in srgb, var(--accent) 80%, black 20%);
323
+ --shell-nav-child-fg: color-mix(in srgb, var(--foreground) 64%, transparent);
324
+ --shell-nav-child-icon-fg: color-mix(in srgb, var(--foreground) 48%, transparent);
325
+ --shell-nav-child-active-bg: color-mix(in srgb, var(--accent) 13%, var(--card) 87%);
326
+ --shell-nav-child-active-border: color-mix(in srgb, var(--accent) 26%, var(--shell-surface-border));
327
+ --shell-navbar-fg: #0a151a;
328
+ --shell-navbar-muted: #8e8f9a;
329
+ --shell-navbar-hairline: color-mix(in srgb, #0a151a 8%, transparent);
330
+
331
+ --toolbar-popover-width: 18.75rem;
332
+ --toolbar-chip-height: 1.875rem;
333
+ --toolbar-search-min-width: 13.125rem;
334
+ --toolbar-icon-size: 0.9375rem;
335
+ --radius-toolbar-popover: 0.875rem;
336
+ --crm-sidebar-gap: 1.125rem;
337
+ --crm-report-copy-max-width: 34rem;
338
+ --crm-report-metric-min-width: 6.5rem;
339
+ --timeline-list-inset: 0.625rem;
340
+ --timeline-line-offset: 0.28125rem;
341
+ --timeline-marker-offset: 0.3125rem;
342
+ --table-header-height: 2.25rem;
343
+ --table-cell-padding-x: 1rem;
344
+ --table-cell-padding-y: 0.5rem;
345
+ --crm-table-viewport-offset: 12rem;
346
+ --crm-table-min-height: 35rem;
347
+ --crm-table-empty-min-height: 26.25rem;
348
+ --report-stat-min-width: 9rem;
349
+ --dialog-width: 28rem;
350
+ --sheet-width: 24rem;
351
+ --crm-sheet-width: 32rem;
352
+ --menu-min-width: 8rem;
353
+ --chart-tooltip-min-width: 8rem;
354
+ --skeleton-line-height: 0.6rem;
355
+ --skeleton-line-height-lg: 0.7rem;
356
+ --skeleton-line-height-compact: 0.55rem;
357
+ --skeleton-line-height-xs: 0.5rem;
358
+ --section-icon-size: 1.875rem;
359
+ --surface-enter-offset: 0.625rem;
360
+ --space-eyebrow-y: 0.375rem;
361
+ --scrollbar-size: 0.375rem;
112
362
 
113
363
  --skeleton: color-mix(in srgb, var(--foreground) 7%, transparent);
114
364
  --skeleton-strong: color-mix(in srgb, var(--foreground) 11%, transparent);
@@ -125,6 +375,12 @@
125
375
 
126
376
  --badge-count-bg: var(--semantic-danger);
127
377
  --badge-count-fg: var(--brand-white);
378
+ --sheet-edit-border: color-mix(in srgb, var(--accent) 24%, var(--border));
379
+ --sheet-edit-surface: color-mix(in srgb, var(--accent) 4%, var(--card));
380
+ --sheet-edit-header: color-mix(in srgb, var(--accent) 20%, var(--card));
381
+ --sheet-edit-control-border: color-mix(in srgb, var(--accent) 22%, var(--border));
382
+ --sheet-edit-control-ring: color-mix(in srgb, var(--accent) 22%, transparent);
383
+ --sheet-edit-header-surface: linear-gradient(135deg, color-mix(in srgb, var(--accent) 16%, transparent), transparent 62%);
128
384
  --on-fill-danger: var(--brand-white);
129
385
  --on-fill-warning: #3a2a05;
130
386
  --on-fill-success: #06281e;
@@ -143,6 +399,47 @@
143
399
  --brand-panel-muted: color-mix(in srgb, var(--brand-white) 68%, transparent);
144
400
  --brand-panel-subtle: color-mix(in srgb, var(--brand-white) 48%, transparent);
145
401
  --brand-panel-border: color-mix(in srgb, var(--brand-accent) 22%, transparent);
402
+ --project-surface-primary: var(--card);
403
+ --project-surface-secondary: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
404
+ --project-surface-item: color-mix(in srgb, var(--card) 96%, transparent);
405
+ --project-hero-surface: var(--brand-panel-surface);
406
+ --project-hero-surface-raised: var(--brand-panel-surface-raised);
407
+ --project-hero-foreground: var(--brand-panel-foreground);
408
+ --project-hero-muted: var(--brand-panel-muted);
409
+ --project-hero-subtle: var(--brand-panel-subtle);
410
+ --project-hero-border: var(--brand-panel-border);
411
+ --project-hero-base: var(--brand-surface-dark);
412
+ --project-hero-shadow: var(--brand-shadow-soft);
413
+ --dashboard-shadow-sm: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent);
414
+ --dashboard-shadow-md: 0 8px 24px color-mix(in srgb, var(--foreground) 8%, transparent);
415
+ --dashboard-shadow-lg: 0 10px 30px color-mix(in srgb, var(--foreground) 8%, transparent);
416
+ --dashboard-hero-glow: radial-gradient(circle, color-mix(in srgb, var(--accent) 38%, transparent), transparent 70%);
417
+ --dashboard-hero-highlight: linear-gradient(90deg, transparent, color-mix(in srgb, var(--accent) 60%, transparent), transparent);
418
+ --dashboard-tab-hover: color-mix(in srgb, var(--foreground) 7%, transparent);
419
+ --dashboard-tab-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 45%, transparent);
420
+ --dashboard-breakdown-track: color-mix(in srgb, var(--foreground) 7%, transparent);
421
+ --dashboard-accent-soft: color-mix(in srgb, var(--accent) 16%, transparent);
422
+ --dashboard-neutral-rule: color-mix(in srgb, var(--foreground) 14%, transparent);
423
+ --dashboard-task-risk-bg: color-mix(in srgb, var(--project-risk-overdue) 11%, transparent);
424
+ --dashboard-task-risk-hover: color-mix(in srgb, var(--project-risk-overdue) 16%, transparent);
425
+ --dashboard-task-due-bg: color-mix(in srgb, var(--project-risk-at-risk) 13%, transparent);
426
+ --dashboard-task-due-hover: color-mix(in srgb, var(--project-risk-at-risk) 18%, transparent);
427
+ --dashboard-task-flight-bg: color-mix(in srgb, var(--foreground) 5%, transparent);
428
+ --dashboard-task-flight-hover: color-mix(in srgb, var(--foreground) 7%, transparent);
429
+ --dashboard-task-row-hover: color-mix(in srgb, var(--accent) 6%, transparent);
430
+ --dashboard-milestone-glow: radial-gradient(circle, color-mix(in srgb, var(--accent) 30%, transparent), transparent 70%);
431
+ --dashboard-milestone-icon: color-mix(in srgb, var(--accent) 18%, transparent);
432
+ --dashboard-milestone-skeleton: color-mix(in srgb, var(--project-hero-foreground) 12%, transparent);
433
+ --dashboard-milestone-empty: color-mix(in srgb, var(--project-hero-foreground) 10%, transparent);
434
+ --dashboard-milestone-date: color-mix(in srgb, var(--project-hero-foreground) 8%, transparent);
435
+ --dashboard-period-glow: color-mix(in srgb, var(--accent) 22%, transparent);
436
+ --dashboard-client-avatar: color-mix(in srgb, var(--role-client) 18%, var(--card));
437
+ --dashboard-local-muted-foreground: color-mix(in srgb, var(--foreground) 62%, transparent);
438
+ --dashboard-local-border: color-mix(in srgb, var(--foreground) 14%, transparent);
439
+ --dashboard-local-muted: color-mix(in srgb, var(--foreground) 6%, transparent);
440
+ --dashboard-danger-soft: color-mix(in srgb, var(--project-risk-overdue) 15%, transparent);
441
+ --dashboard-danger-border: color-mix(in srgb, var(--project-risk-overdue) 40%, transparent);
442
+ --project-surface-padding: 1.25rem;
146
443
  --row-sweep-tint: var(--foreground);
147
444
  --surface-card: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
148
445
  --surface-card-light: var(--card);
@@ -150,6 +447,26 @@
150
447
  --stat-cell-padding: 1rem;
151
448
  }
152
449
 
450
+ /* Dynamic tint recipes resolve where components provide --tint. */
451
+ @layer components {
452
+ .row-hover-sweep {
453
+ --row-hover-sweep: linear-gradient(90deg, transparent, color-mix(in srgb, var(--row-sweep-tint, var(--foreground)) 9%, transparent) 50%, transparent);
454
+ }
455
+
456
+ .tint-soft {
457
+ --tint-soft-border: color-mix(in srgb, var(--tint) 34%, transparent);
458
+ --tint-soft-bg: color-mix(in srgb, var(--tint) 10%, var(--card));
459
+ --tint-soft-hover: color-mix(in srgb, var(--tint) 14%, var(--card));
460
+ }
461
+
462
+ .tint-hero {
463
+ --tint-hero-border: color-mix(in srgb, var(--tint) 46%, transparent);
464
+ --tint-hero-bg: color-mix(in srgb, var(--tint) 16%, transparent);
465
+ --tint-hero-fg: color-mix(in srgb, var(--tint) 18%, white);
466
+ --tint-hero-hover: color-mix(in srgb, var(--tint) 24%, transparent);
467
+ }
468
+ }
469
+
153
470
  /* Dark mode redefines the primitives and semantic base before re-deriving L1. */
154
471
  :root.dark,
155
472
  :root[data-theme="dark"],
@@ -181,6 +498,7 @@
181
498
  --secondary-foreground: #dce5f0;
182
499
  --muted: rgba(148, 163, 184, 0.16);
183
500
  --muted-foreground: #a6b4c6;
501
+ --foreground-muted-accessible: #a6b4c6;
184
502
  --foreground-inverse: #f8fafc;
185
503
  --foreground-inverse-muted: rgba(248, 250, 252, 0.9);
186
504
  --foreground-inverse-subtle: rgba(248, 250, 252, 0.84);
@@ -206,6 +524,19 @@
206
524
  --semantic-neutral: #a1a1aa;
207
525
  --semantic-neutral-strong: #d4d4d8;
208
526
 
527
+ --project-risk-overdue-soft: var(--semantic-danger-soft);
528
+ /* Dark-mode health fills are light pastels, so on-fill ink stays dark. */
529
+ --project-risk-overdue-ink: #350a11;
530
+ --project-risk-at-risk-ink: #3a2a05;
531
+ --project-state-completed-ink: #06281e;
532
+ --project-health-on-track: var(--project-state-active-strong);
533
+ --project-health-at-risk: var(--project-risk-at-risk);
534
+ --project-health-at-risk-strong: var(--project-risk-at-risk-strong);
535
+ --project-health-off-track: var(--project-risk-overdue);
536
+ --project-health-progress: var(--project-state-active);
537
+ --project-health-off-track-strong: var(--project-risk-overdue);
538
+ --project-health-off-track-soft: var(--project-risk-overdue-soft);
539
+
209
540
  --skeleton: color-mix(in srgb, var(--foreground) 9%, transparent);
210
541
  --skeleton-strong: color-mix(in srgb, var(--foreground) 14%, transparent);
211
542
  --skeleton-highlight: color-mix(in srgb, var(--brand-white) 12%, transparent);
@@ -235,6 +566,19 @@
235
566
  --brand-panel-surface-raised: color-mix(in srgb, var(--card) 72%, var(--brand-accent));
236
567
  --surface-card: color-mix(in srgb, var(--foreground) 2%, var(--card) 98%);
237
568
  --surface-card-light: color-mix(in srgb, var(--card) 92%, var(--brand-white) 8%);
569
+
570
+ --shell-surface-border: rgba(255, 255, 255, 0.11);
571
+ --shell-surface-hover: rgba(19, 37, 52, 0.96);
572
+ --shell-surface-active: rgba(24, 62, 82, 0.82);
573
+ --shell-hairline: rgba(255, 255, 255, 0.08);
574
+ --shell-icon-bg: rgba(255, 255, 255, 0.055);
575
+ --shell-group-open: rgba(255, 255, 255, 0.025);
576
+ --shell-shadow: 0 22px 46px rgba(0, 0, 0, 0.3), 0 4px 16px rgba(0, 0, 0, 0.2);
577
+ --shell-background: #06121b;
578
+ --shell-sidebar-background: linear-gradient(180deg, rgba(7, 18, 28, 0.92) 0%, rgba(10, 23, 33, 0.94) 100%);
579
+ --shell-navbar-fg: #f6fbff;
580
+ --shell-navbar-muted: #8da3b0;
581
+ --shell-navbar-hairline: rgba(255, 255, 255, 0.08);
238
582
  }
239
583
 
240
584
  /* Explicit light scope wins when a theme class/attribute is toggled at runtime. */
@@ -254,6 +598,7 @@
254
598
  --secondary-foreground: var(--brand-ink);
255
599
  --muted: rgba(203, 213, 225, 0.25);
256
600
  --muted-foreground: var(--brand-neutral-500);
601
+ --foreground-muted-accessible: #5f6b7a;
257
602
  --foreground-inverse: var(--brand-white);
258
603
  --foreground-inverse-muted: rgba(255, 255, 255, 0.88);
259
604
  --foreground-inverse-subtle: rgba(255, 255, 255, 0.84);
@@ -1,97 +1,108 @@
1
- :root {
2
- --font-weight-regular: 400;
3
- /* Mulish weight 500 is not loaded; medium deliberately resolves to 600. */
4
- --font-weight-medium: 600;
5
- --font-weight-bold: 700;
6
- --font-weight-heavy: 800;
7
- }
8
-
9
1
  @utility text-ui-micro {
10
- font-family: var(--font-body), sans-serif;
2
+ font-family: var(--font-body);
11
3
  font-size: var(--text-ui-micro);
12
4
  font-weight: var(--font-weight-medium);
13
- line-height: 1.3;
14
- color: var(--muted-foreground);
5
+ line-height: var(--type-leading-130);
15
6
  }
16
7
 
17
8
  @utility text-ui-label {
18
- font-family: var(--font-body), sans-serif;
9
+ font-family: var(--font-body);
19
10
  font-size: var(--text-ui-label);
20
11
  font-weight: var(--font-weight-medium);
21
- line-height: 1;
12
+ line-height: var(--type-leading-none);
22
13
  text-transform: uppercase;
23
- letter-spacing: 0.14em;
24
- color: var(--muted-foreground);
14
+ letter-spacing: var(--type-tracking-140);
25
15
  }
26
16
 
27
17
  @utility text-ui-meta {
28
- font-family: var(--font-body), sans-serif;
18
+ font-family: var(--font-body);
29
19
  font-size: var(--text-ui-meta);
30
20
  font-weight: var(--font-weight-regular);
31
- line-height: 1.4;
32
- color: var(--muted-foreground);
21
+ line-height: var(--type-leading-140);
22
+ }
23
+
24
+ /* Size-only utilities for component recipes that supply their own weight and rhythm. */
25
+ @utility text-ui-chip {
26
+ font-size: var(--text-ui-chip);
27
+ }
28
+
29
+ @utility text-ui-action {
30
+ font-size: var(--text-ui-action);
31
+ }
32
+
33
+ @utility text-ui-calendar {
34
+ font-size: var(--text-ui-calendar);
35
+ }
36
+
37
+ @utility text-ui-shell-title {
38
+ font-size: var(--text-ui-shell-title);
39
+ }
40
+
41
+ @utility text-ui-report-title {
42
+ font-size: var(--text-ui-report-title);
43
+ }
44
+
45
+ @utility text-ui-report-title-lg {
46
+ font-size: var(--text-ui-report-title-lg);
47
+ }
48
+
49
+ @utility text-ui-report-metric {
50
+ font-size: var(--text-ui-report-metric);
33
51
  }
34
52
 
35
53
  @utility text-ui-body {
36
- font-family: var(--font-body), sans-serif;
54
+ font-family: var(--font-body);
37
55
  font-size: var(--text-ui-body);
38
56
  font-weight: var(--font-weight-regular);
39
- line-height: 1.5;
40
- color: var(--foreground);
57
+ line-height: var(--type-leading-normal);
41
58
  }
42
59
 
43
60
  @utility text-ui-card-title {
44
- font-family: var(--font-body), sans-serif;
61
+ font-family: var(--font-body);
45
62
  font-size: var(--text-ui-card-title);
46
63
  font-weight: var(--font-weight-medium);
47
- line-height: 1.3;
48
- letter-spacing: -0.025em;
49
- color: var(--foreground);
64
+ line-height: var(--type-leading-130);
65
+ letter-spacing: var(--type-tracking-n025);
50
66
  }
51
67
 
52
68
  @utility text-ui-subhead {
53
- font-family: var(--font-display), sans-serif;
69
+ font-family: var(--font-display);
54
70
  font-size: var(--text-ui-subhead);
55
71
  font-weight: var(--font-weight-bold);
56
- line-height: 1.25;
57
- letter-spacing: -0.02em;
58
- color: var(--foreground);
72
+ line-height: var(--type-leading-tight);
73
+ letter-spacing: var(--type-tracking-n020);
59
74
  }
60
75
 
61
76
  @utility text-ui-panel-title {
62
- font-family: var(--font-display), sans-serif;
77
+ font-family: var(--font-display);
63
78
  font-size: var(--text-ui-panel-title);
64
79
  font-weight: var(--font-weight-bold);
65
- line-height: 1.2;
66
- letter-spacing: -0.02em;
67
- color: var(--foreground);
80
+ line-height: var(--type-leading-120);
81
+ letter-spacing: var(--type-tracking-n020);
68
82
  }
69
83
 
70
84
  @utility text-ui-heading {
71
- font-family: var(--font-display), sans-serif;
85
+ font-family: var(--font-display);
72
86
  font-size: var(--text-ui-heading);
73
87
  font-weight: var(--font-weight-bold);
74
- line-height: 1.15;
75
- letter-spacing: -0.02em;
76
- color: var(--foreground);
88
+ line-height: var(--type-leading-115);
89
+ letter-spacing: var(--type-tracking-n020);
77
90
  }
78
91
 
79
92
  @utility text-ui-title-sm {
80
- font-family: var(--font-display), sans-serif;
93
+ font-family: var(--font-display);
81
94
  font-size: var(--text-ui-title-sm);
82
95
  font-weight: var(--font-weight-heavy);
83
- line-height: 1.1;
84
- letter-spacing: -0.03em;
85
- color: var(--foreground);
96
+ line-height: var(--type-leading-110);
97
+ letter-spacing: var(--type-tracking-n030);
86
98
  }
87
99
 
88
100
  @utility text-ui-title {
89
- font-family: var(--font-display), sans-serif;
101
+ font-family: var(--font-display);
90
102
  font-size: var(--text-ui-title);
91
103
  font-weight: var(--font-weight-heavy);
92
- line-height: 1.05;
93
- letter-spacing: -0.03em;
94
- color: var(--foreground);
104
+ line-height: var(--type-leading-105);
105
+ letter-spacing: var(--type-tracking-n030);
95
106
  }
96
107
 
97
108
  @utility text-ui-metric {
@@ -99,29 +110,26 @@
99
110
  font-variant-numeric: tabular-nums;
100
111
  font-size: var(--text-ui-metric);
101
112
  font-weight: var(--font-weight-heavy);
102
- line-height: 1;
103
- letter-spacing: -0.04em;
104
- color: var(--foreground);
113
+ line-height: var(--type-leading-none);
114
+ letter-spacing: var(--type-tracking-n040);
105
115
  }
106
116
 
107
117
  @utility text-ui-metric-xl {
108
- font-family: var(--font-display), sans-serif;
118
+ font-family: var(--font-display);
109
119
  font-variant-numeric: tabular-nums;
110
120
  font-size: var(--text-ui-metric-xl);
111
121
  font-weight: var(--font-weight-heavy);
112
- line-height: 0.95;
113
- letter-spacing: -0.04em;
114
- color: var(--foreground);
122
+ line-height: var(--type-leading-095);
123
+ letter-spacing: var(--type-tracking-n040);
115
124
  }
116
125
 
117
126
  @utility text-ui-metric-display {
118
- font-family: var(--font-display), sans-serif;
127
+ font-family: var(--font-display);
119
128
  font-variant-numeric: tabular-nums;
120
129
  font-size: var(--text-ui-metric-display);
121
130
  font-weight: var(--font-weight-heavy);
122
- line-height: 1;
123
- letter-spacing: -0.04em;
124
- color: var(--foreground);
131
+ line-height: var(--type-leading-none);
132
+ letter-spacing: var(--type-tracking-n040);
125
133
  }
126
134
 
127
135
  /* Thin scrollbar for bounded surface lists. */
@@ -130,20 +138,20 @@
130
138
  overflow-y: overlay;
131
139
  overflow-x: hidden;
132
140
  scrollbar-width: thin;
133
- scrollbar-color: color-mix(in srgb, var(--foreground) 18%, transparent) transparent;
141
+ scrollbar-color: var(--scrollbar-thumb) transparent;
134
142
 
135
143
  &::-webkit-scrollbar {
136
- width: 6px;
137
- height: 6px;
144
+ width: var(--scrollbar-size);
145
+ height: var(--scrollbar-size);
138
146
  }
139
147
  &::-webkit-scrollbar-track {
140
148
  background: transparent;
141
149
  }
142
150
  &::-webkit-scrollbar-thumb {
143
- background-color: color-mix(in srgb, var(--foreground) 18%, transparent);
144
- border-radius: 9999px;
151
+ background-color: var(--scrollbar-thumb);
152
+ border-radius: var(--radius-scrollbar);
145
153
  }
146
154
  &::-webkit-scrollbar-thumb:hover {
147
- background-color: color-mix(in srgb, var(--foreground) 30%, transparent);
155
+ background-color: var(--scrollbar-thumb-hover);
148
156
  }
149
157
  }