@hemerson/design-system 0.0.0-stage → 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.
Files changed (35) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +78 -2
  3. package/dist/components/Badge/Badge.d.ts +14 -0
  4. package/dist/components/Button/Button.d.ts +17 -0
  5. package/dist/components/Button/index.d.ts +2 -0
  6. package/dist/components/Card/Card.d.ts +19 -0
  7. package/dist/components/Checkbox/Checkbox.d.ts +8 -0
  8. package/dist/components/Container/Container.d.ts +9 -0
  9. package/dist/components/Dialog/Dialog.d.ts +18 -0
  10. package/dist/components/FloatingButton/FloatingButton.d.ts +9 -0
  11. package/dist/components/GlassPanel/GlassPanel.d.ts +13 -0
  12. package/dist/components/GlowAvatar/GlowAvatar.d.ts +10 -0
  13. package/dist/components/Input/Input.d.ts +12 -0
  14. package/dist/components/Loading/Loading.d.ts +11 -0
  15. package/dist/components/Menu/Menu.d.ts +25 -0
  16. package/dist/components/NavBar/NavBar.d.ts +20 -0
  17. package/dist/components/ScrollArea/ScrollArea.d.ts +8 -0
  18. package/dist/components/SectionTitle/SectionTitle.d.ts +12 -0
  19. package/dist/components/SegmentedControl/SegmentedControl.d.ts +21 -0
  20. package/dist/components/Select/Select.d.ts +16 -0
  21. package/dist/components/Separator/Separator.d.ts +8 -0
  22. package/dist/components/Sidebar/Sidebar.d.ts +21 -0
  23. package/dist/components/Table/Table.d.ts +26 -0
  24. package/dist/components/Toast/Toast.d.ts +16 -0
  25. package/dist/glass/enableGlassRefraction.d.ts +9 -0
  26. package/dist/index.d.ts +42 -0
  27. package/dist/index.js +726 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/internal/Icon.d.ts +17 -0
  30. package/dist/internal/cx.d.ts +2 -0
  31. package/dist/internal/field.d.ts +16 -0
  32. package/dist/styles.css +1249 -0
  33. package/dist/tokens.css +184 -0
  34. package/dist/tokens.json +514 -0
  35. package/package.json +86 -4
@@ -0,0 +1,1249 @@
1
+ /* Raleway for text, JetBrains Mono for numerals. Projects that self-host the
2
+ fonts can import tokens.css and components.css instead of styles.css. */
3
+ @import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@500;700&family=Raleway:wght@400;500;600;700&display=swap");
4
+
5
+ /* Generated from tokens/tokens.json by scripts/build-tokens.mjs. Do not edit. */
6
+
7
+ :root,
8
+ [data-theme="dark"] {
9
+ color-scheme: dark;
10
+ --dark-900: #1b1b1b;
11
+ --light-200: #e4e3de;
12
+ --light-400: #c4c6bb;
13
+ --primary-500: #7ea8a7;
14
+ --secondary-500: #78718e;
15
+ --surface: var(--dark-900);
16
+ --surface-raised: #262626;
17
+ --surface-sunken: #141414;
18
+ --ink: var(--light-200);
19
+ --ink-muted: var(--light-400);
20
+ --accent: var(--primary-500);
21
+ --accent-fill: var(--primary-500);
22
+ --on-accent: var(--dark-900);
23
+ --accent-soft: #7ea8a71f;
24
+ --secondary: #a49dba;
25
+ --secondary-fill: var(--secondary-500);
26
+ --on-secondary: #ffffff;
27
+ --line: #ffffff26;
28
+ --line-strong: var(--secondary-500);
29
+ --focus-ring: var(--accent);
30
+ --glass-regular-tint: #1b1b1bcc;
31
+ --glass-thick-tint: #1b1b1bf0;
32
+ --glass-solid: var(--surface-raised);
33
+ --glass-clear-tint: #e4e3de12;
34
+ --glass-sheen: #ffffff24;
35
+ --glass-rim: #ffffff59;
36
+ --glass-accent-tint: #7ea8a71f;
37
+ --glass-accent-sheen: #b9d8d759;
38
+ --success: #8ab4d8;
39
+ --warning: #e3c47b;
40
+ --danger: #f19b90;
41
+ --on-danger: var(--dark-900);
42
+ --scrim: #0000008c;
43
+ --shadow-glass: inset 0 1px 0 0 rgba(255,255,255,0.35), 0 8px 30px -6px rgba(0,0,0,0.5);
44
+ --shadow-glow: 0 0 14px rgba(126,168,167,0.55);
45
+ --shadow-raised: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1);
46
+ }
47
+
48
+ [data-theme="light"] {
49
+ color-scheme: light;
50
+ --dark-900: #1b1b1b;
51
+ --light-200: #e4e3de;
52
+ --light-400: #c4c6bb;
53
+ --primary-500: #7ea8a7;
54
+ --secondary-500: #78718e;
55
+ --surface: #f2f1ec;
56
+ --surface-raised: #faf9f6;
57
+ --surface-sunken: var(--light-200);
58
+ --ink: var(--dark-900);
59
+ --ink-muted: #55574f;
60
+ --accent: #3f6b6a;
61
+ --accent-fill: var(--primary-500);
62
+ --on-accent: var(--dark-900);
63
+ --accent-soft: #3f6b6a1f;
64
+ --secondary: #5a5374;
65
+ --secondary-fill: var(--secondary-500);
66
+ --on-secondary: #ffffff;
67
+ --line: #1b1b1b26;
68
+ --line-strong: var(--secondary-500);
69
+ --focus-ring: var(--accent);
70
+ --glass-regular-tint: #f2f1eccc;
71
+ --glass-thick-tint: #f2f1ecf0;
72
+ --glass-solid: var(--surface-raised);
73
+ --glass-clear-tint: #ffffff8c;
74
+ --glass-sheen: #ffffffb3;
75
+ --glass-rim: #ffffffcc;
76
+ --glass-accent-tint: #7ea8a71f;
77
+ --glass-accent-sheen: #b9d8d759;
78
+ --success: #2d5b86;
79
+ --warning: #765811;
80
+ --danger: #a1342a;
81
+ --on-danger: #ffffff;
82
+ --scrim: #1b1b1b59;
83
+ --shadow-glass: inset 0 1px 0 0 rgba(255,255,255,0.8), 0 8px 30px -6px rgba(27,27,27,0.18);
84
+ --shadow-glow: 0 0 14px rgba(63,107,106,0.35);
85
+ --shadow-raised: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1);
86
+ }
87
+
88
+ :root {
89
+ --space-1: 4px;
90
+ --space-2: 8px;
91
+ --space-3: 12px;
92
+ --space-4: 16px;
93
+ --space-6: 24px;
94
+ --space-8: 32px;
95
+ --space-10: 40px;
96
+ --space-20: 80px;
97
+ --radius-sm: 2px;
98
+ --radius-md: 6px;
99
+ --radius-lg: 8px;
100
+ --radius-xl: 12px;
101
+ --radius-full: 9999px;
102
+ --radius-2xl: 24px;
103
+ --content-max: 1152px;
104
+ --sidebar-width: 64px;
105
+ --glass-blur: blur(16px) saturate(180%);
106
+ --glass-thick-blur: blur(20px) saturate(150%);
107
+ --glass-accent-blur: blur(10px) saturate(180%);
108
+ --font-sans: Raleway, "Segoe UI", system-ui, sans-serif;
109
+ --font-mono: "JetBrains Mono", ui-monospace, Consolas, monospace;
110
+ }
111
+
112
+ .hds-text-title-xl {
113
+ font-family: var(--font-sans);
114
+ font-size: 36px;
115
+ line-height: 40px;
116
+ font-weight: 700;
117
+ }
118
+
119
+ .hds-text-title-lg {
120
+ font-family: var(--font-sans);
121
+ font-size: 24px;
122
+ line-height: 32px;
123
+ font-weight: 700;
124
+ }
125
+
126
+ .hds-text-title-md {
127
+ font-family: var(--font-sans);
128
+ font-size: 20px;
129
+ line-height: 28px;
130
+ font-weight: 600;
131
+ }
132
+
133
+ .hds-text-body-lg {
134
+ font-family: var(--font-sans);
135
+ font-size: 18px;
136
+ line-height: 28px;
137
+ font-weight: 500;
138
+ }
139
+
140
+ .hds-text-body {
141
+ font-family: var(--font-sans);
142
+ font-size: 16px;
143
+ line-height: 24px;
144
+ font-weight: 400;
145
+ }
146
+
147
+ .hds-text-body-sm {
148
+ font-family: var(--font-sans);
149
+ font-size: 14px;
150
+ line-height: 20px;
151
+ font-weight: 400;
152
+ }
153
+
154
+ .hds-text-caption {
155
+ font-family: var(--font-sans);
156
+ font-size: 12px;
157
+ line-height: 16px;
158
+ font-weight: 500;
159
+ }
160
+
161
+ .hds-text-button {
162
+ font-family: var(--font-sans);
163
+ font-size: 16px;
164
+ line-height: 24px;
165
+ font-weight: 700;
166
+ }
167
+
168
+ .hds-text-eyebrow {
169
+ font-family: var(--font-sans);
170
+ font-size: 14px;
171
+ line-height: 20px;
172
+ font-weight: 700;
173
+ letter-spacing: 0.025em;
174
+ }
175
+
176
+ .hds-text-section-index {
177
+ font-family: var(--font-mono);
178
+ font-size: 20px;
179
+ line-height: 28px;
180
+ font-weight: 700;
181
+ }
182
+
183
+ .hds-text-mono-sm {
184
+ font-family: var(--font-mono);
185
+ font-size: 14px;
186
+ line-height: 20px;
187
+ font-weight: 500;
188
+ }
189
+
190
+ /* Hemerson Design System: component styles. Every color, length and shadow
191
+ comes from tokens.css; the only literals are the -webkit-backdrop-filter
192
+ values, because Safari does not resolve custom properties there. */
193
+
194
+ /* ---------- Base ---------- */
195
+
196
+ .hds-root {
197
+ font-family: var(--font-sans);
198
+ color: var(--ink);
199
+ background: var(--surface);
200
+ }
201
+
202
+ :where([class^="hds-"], [class*=" hds-"]) {
203
+ box-sizing: border-box;
204
+ }
205
+
206
+ :where(.hds-btn, .hds-input, .hds-select, .hds-checkbox-input, .hds-segmented-option,
207
+ .hds-menu-item, .hds-sidebar-item, .hds-navbar-link, .hds-scroll):focus-visible {
208
+ outline: 2px solid var(--focus-ring);
209
+ outline-offset: 2px;
210
+ }
211
+
212
+ .hds-visually-hidden {
213
+ position: absolute;
214
+ width: 1px;
215
+ height: 1px;
216
+ margin: -1px;
217
+ padding: 0;
218
+ overflow: hidden;
219
+ clip: rect(0 0 0 0);
220
+ white-space: nowrap;
221
+ border: 0;
222
+ }
223
+
224
+ .hds-icon {
225
+ flex: none;
226
+ width: 1em;
227
+ height: 1em;
228
+ }
229
+
230
+ /* ---------- Glass material ----------
231
+ Layer 1: solid, always readable. Layer 2: frosted glass where
232
+ backdrop-filter works. Layer 3: refraction, only when
233
+ enableGlassRefraction() marks <html data-glass-refraction> (Chromium). */
234
+
235
+ .hds-glass {
236
+ position: relative;
237
+ color: var(--ink);
238
+ background: var(--glass-solid);
239
+ border: 1px solid var(--line);
240
+ border-top-color: var(--glass-rim);
241
+ box-shadow: var(--shadow-glass);
242
+ }
243
+
244
+ @supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
245
+ .hds-glass {
246
+ background: linear-gradient(135deg, var(--glass-sheen), transparent 45%), var(--glass-regular-tint);
247
+ -webkit-backdrop-filter: blur(16px) saturate(180%);
248
+ backdrop-filter: var(--glass-blur);
249
+ }
250
+
251
+ .hds-glass--clear {
252
+ background: linear-gradient(135deg, var(--glass-sheen), transparent 45%), var(--glass-clear-tint);
253
+ }
254
+
255
+ .hds-glass--thick {
256
+ background: linear-gradient(135deg, var(--glass-sheen), transparent 45%), var(--glass-thick-tint);
257
+ -webkit-backdrop-filter: blur(20px) saturate(150%);
258
+ backdrop-filter: var(--glass-thick-blur);
259
+ }
260
+
261
+ .hds-glass--accent {
262
+ background: linear-gradient(135deg, var(--glass-accent-sheen), transparent 60%), var(--glass-accent-tint), var(--glass-regular-tint);
263
+ -webkit-backdrop-filter: blur(10px) saturate(180%);
264
+ backdrop-filter: var(--glass-accent-blur);
265
+ }
266
+ }
267
+
268
+ .hds-glass--accent {
269
+ border-color: var(--accent);
270
+ box-shadow: var(--shadow-glass), var(--shadow-glow);
271
+ }
272
+
273
+ html[data-glass-refraction] .hds-glass:not(.hds-glass--thick) {
274
+ backdrop-filter: blur(10px) url(#hds-glass-distortion) saturate(180%);
275
+ }
276
+
277
+ html[data-glass-refraction] .hds-glass--accent {
278
+ backdrop-filter: blur(6px) url(#hds-glass-distortion) saturate(200%);
279
+ }
280
+
281
+ /* Reduced transparency: the system setting, or the app's own setting */
282
+ @media (prefers-reduced-transparency: reduce) {
283
+ html .hds-glass,
284
+ html[data-glass-refraction] .hds-glass:not(.hds-glass--thick) {
285
+ background: var(--glass-solid);
286
+ -webkit-backdrop-filter: none;
287
+ backdrop-filter: none;
288
+ }
289
+ }
290
+
291
+ html[data-transparency="reduced"] .hds-glass,
292
+ html[data-transparency="reduced"][data-glass-refraction] .hds-glass:not(.hds-glass--thick) {
293
+ background: var(--glass-solid);
294
+ -webkit-backdrop-filter: none;
295
+ backdrop-filter: none;
296
+ }
297
+
298
+ @media (prefers-contrast: more) {
299
+ .hds-glass {
300
+ border: 2px solid currentColor;
301
+ }
302
+ }
303
+
304
+ /* ---------- Button ---------- */
305
+
306
+ .hds-btn {
307
+ display: inline-flex;
308
+ align-items: center;
309
+ justify-content: center;
310
+ gap: var(--space-2);
311
+ min-height: 40px;
312
+ padding: var(--space-2) var(--space-4);
313
+ border: 1px solid transparent;
314
+ border-radius: var(--radius-md);
315
+ font-family: var(--font-sans);
316
+ font-size: 16px;
317
+ line-height: 24px;
318
+ font-weight: 700;
319
+ text-transform: uppercase;
320
+ white-space: nowrap;
321
+ text-decoration: none;
322
+ cursor: pointer;
323
+ transition: opacity 150ms, background-color 150ms, color 150ms, filter 150ms;
324
+ }
325
+
326
+ .hds-btn .hds-icon {
327
+ font-size: 20px;
328
+ }
329
+
330
+ .hds-btn--sm {
331
+ min-height: 32px;
332
+ padding: var(--space-1) var(--space-3);
333
+ font-size: 14px;
334
+ line-height: 20px;
335
+ }
336
+
337
+ .hds-btn--sm .hds-icon {
338
+ font-size: 16px;
339
+ }
340
+
341
+ .hds-btn--lg {
342
+ min-height: 56px;
343
+ padding: var(--space-4);
344
+ }
345
+
346
+ .hds-btn--icon {
347
+ padding: 0;
348
+ aspect-ratio: 1;
349
+ }
350
+
351
+ .hds-btn--primary {
352
+ background: var(--accent-fill);
353
+ color: var(--on-accent);
354
+ }
355
+
356
+ .hds-btn--secondary {
357
+ background: var(--secondary-fill);
358
+ color: var(--on-secondary);
359
+ }
360
+
361
+ .hds-btn--danger {
362
+ background: var(--danger);
363
+ color: var(--on-danger);
364
+ }
365
+
366
+ .hds-btn--primary:hover,
367
+ .hds-btn--secondary:hover,
368
+ .hds-btn--danger:hover {
369
+ opacity: 0.8;
370
+ }
371
+
372
+ .hds-btn--ghost {
373
+ background: transparent;
374
+ color: var(--ink);
375
+ }
376
+
377
+ .hds-btn--ghost:hover {
378
+ background: var(--accent-soft);
379
+ color: var(--accent);
380
+ }
381
+
382
+ .hds-btn--glass {
383
+ border-radius: var(--radius-full);
384
+ }
385
+
386
+ .hds-btn--glass:hover {
387
+ filter: brightness(1.15);
388
+ }
389
+
390
+ .hds-btn:disabled,
391
+ .hds-btn[aria-disabled="true"] {
392
+ opacity: 0.5;
393
+ cursor: not-allowed;
394
+ }
395
+
396
+ .hds-btn[aria-busy="true"] {
397
+ cursor: progress;
398
+ }
399
+
400
+ /* ---------- Loading ---------- */
401
+
402
+ .hds-loading {
403
+ display: inline-flex;
404
+ align-items: center;
405
+ gap: var(--space-2);
406
+ color: var(--accent);
407
+ }
408
+
409
+ .hds-loading .hds-icon,
410
+ .hds-spin {
411
+ animation: hds-spin 0.8s linear infinite;
412
+ }
413
+
414
+ .hds-loading--sm .hds-icon { font-size: 16px; }
415
+ .hds-loading--md .hds-icon { font-size: 24px; }
416
+ .hds-loading--lg .hds-icon { font-size: 32px; }
417
+
418
+ @keyframes hds-spin {
419
+ to { transform: rotate(360deg); }
420
+ }
421
+
422
+ /* ---------- NavBar ---------- */
423
+
424
+ .hds-navbar {
425
+ position: sticky;
426
+ top: var(--space-4);
427
+ z-index: 20;
428
+ display: flex;
429
+ align-items: center;
430
+ gap: var(--space-4);
431
+ width: 100%;
432
+ max-width: var(--content-max);
433
+ min-height: 56px;
434
+ margin-inline: auto;
435
+ padding: var(--space-2) var(--space-2) var(--space-2) var(--space-6);
436
+ border-radius: var(--radius-full);
437
+ }
438
+
439
+ .hds-navbar-title {
440
+ margin: 0;
441
+ font-size: 20px;
442
+ line-height: 28px;
443
+ font-weight: 600;
444
+ white-space: nowrap;
445
+ }
446
+
447
+ .hds-navbar-nav {
448
+ display: flex;
449
+ flex: 1;
450
+ gap: var(--space-1);
451
+ min-width: 0;
452
+ overflow-x: auto;
453
+ }
454
+
455
+ .hds-navbar-actions {
456
+ display: flex;
457
+ align-items: center;
458
+ gap: var(--space-2);
459
+ margin-left: auto;
460
+ }
461
+
462
+ .hds-navbar-link {
463
+ display: inline-flex;
464
+ align-items: center;
465
+ min-height: 40px;
466
+ padding: 0 var(--space-4);
467
+ border-radius: var(--radius-full);
468
+ color: var(--ink);
469
+ font-size: 14px;
470
+ line-height: 20px;
471
+ font-weight: 600;
472
+ text-decoration: none;
473
+ white-space: nowrap;
474
+ transition: background-color 150ms, color 150ms;
475
+ }
476
+
477
+ .hds-navbar-link:hover {
478
+ color: var(--accent);
479
+ }
480
+
481
+ .hds-navbar-link[aria-current="page"] {
482
+ background: var(--accent-soft);
483
+ color: var(--accent);
484
+ }
485
+
486
+ /* ---------- Sidebar ---------- */
487
+
488
+ .hds-sidebar {
489
+ display: flex;
490
+ flex-direction: column;
491
+ align-items: center;
492
+ gap: var(--space-2);
493
+ width: var(--sidebar-width);
494
+ height: 100%;
495
+ padding: var(--space-3) 0;
496
+ border-width: 0 1px 0 0;
497
+ }
498
+
499
+ .hds-sidebar--floating {
500
+ height: auto;
501
+ border-width: 1px;
502
+ border-radius: var(--radius-full);
503
+ }
504
+
505
+ .hds-sidebar-items {
506
+ display: flex;
507
+ flex-direction: column;
508
+ gap: var(--space-2);
509
+ margin: 0;
510
+ padding: 0;
511
+ list-style: none;
512
+ }
513
+
514
+ .hds-sidebar-footer {
515
+ margin-top: auto;
516
+ }
517
+
518
+ .hds-sidebar-item {
519
+ display: grid;
520
+ place-items: center;
521
+ width: 40px;
522
+ height: 40px;
523
+ border: 0;
524
+ border-radius: var(--radius-full);
525
+ background: transparent;
526
+ color: var(--ink);
527
+ font-size: 20px;
528
+ cursor: pointer;
529
+ text-decoration: none;
530
+ transition: background-color 150ms, color 150ms;
531
+ }
532
+
533
+ .hds-sidebar-item:hover {
534
+ color: var(--accent);
535
+ }
536
+
537
+ .hds-sidebar-item[aria-current="page"] {
538
+ background: var(--accent-soft);
539
+ color: var(--accent);
540
+ }
541
+
542
+ /* ---------- SegmentedControl ---------- */
543
+
544
+ .hds-segmented {
545
+ display: inline-flex;
546
+ position: relative;
547
+ padding: var(--space-1);
548
+ border-radius: var(--radius-full);
549
+ }
550
+
551
+ /* The thumb looks like accent glass but adds no second backdrop-filter:
552
+ glass is never stacked on glass. */
553
+ .hds-segmented-thumb {
554
+ position: absolute;
555
+ top: var(--space-1);
556
+ bottom: var(--space-1);
557
+ left: var(--space-1);
558
+ border: 1px solid var(--accent);
559
+ border-radius: var(--radius-full);
560
+ background: linear-gradient(135deg, var(--glass-accent-sheen), transparent 60%), var(--glass-accent-tint);
561
+ box-shadow: var(--shadow-glow);
562
+ transition: transform 300ms ease-out;
563
+ pointer-events: none;
564
+ }
565
+
566
+ .hds-segmented-option {
567
+ position: relative;
568
+ z-index: 1;
569
+ display: inline-flex;
570
+ align-items: center;
571
+ justify-content: center;
572
+ gap: var(--space-1);
573
+ min-height: 32px;
574
+ padding: 0 var(--space-3);
575
+ border: 0;
576
+ border-radius: var(--radius-full);
577
+ background: transparent;
578
+ color: var(--ink);
579
+ font-family: var(--font-sans);
580
+ font-size: 14px;
581
+ line-height: 20px;
582
+ font-weight: 600;
583
+ cursor: pointer;
584
+ opacity: 0.75;
585
+ transition: opacity 300ms ease-out;
586
+ }
587
+
588
+ .hds-segmented-option:hover,
589
+ .hds-segmented-option[aria-checked="true"] {
590
+ opacity: 1;
591
+ }
592
+
593
+ /* ---------- FloatingButton ---------- */
594
+
595
+ .hds-fab {
596
+ position: fixed;
597
+ z-index: 10;
598
+ display: grid;
599
+ place-items: center;
600
+ width: 56px;
601
+ height: 56px;
602
+ padding: 0;
603
+ border-radius: var(--radius-full);
604
+ color: var(--ink);
605
+ font-size: 24px;
606
+ cursor: pointer;
607
+ transition: filter 150ms;
608
+ }
609
+
610
+ .hds-fab:hover {
611
+ filter: brightness(1.25);
612
+ }
613
+
614
+ .hds-fab--bottom-right {
615
+ right: calc(var(--space-6) + env(safe-area-inset-right, 0px));
616
+ bottom: calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
617
+ }
618
+
619
+ .hds-fab--bottom-left {
620
+ left: calc(var(--space-6) + env(safe-area-inset-left, 0px));
621
+ bottom: calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
622
+ }
623
+
624
+ .hds-fab--top-right {
625
+ right: calc(var(--space-6) + env(safe-area-inset-right, 0px));
626
+ top: calc(var(--space-6) + env(safe-area-inset-top, 0px));
627
+ }
628
+
629
+ .hds-fab--top-left {
630
+ left: calc(var(--space-6) + env(safe-area-inset-left, 0px));
631
+ top: calc(var(--space-6) + env(safe-area-inset-top, 0px));
632
+ }
633
+
634
+ /* ---------- Menu ---------- */
635
+
636
+ .hds-menu {
637
+ position: relative;
638
+ display: inline-block;
639
+ }
640
+
641
+ .hds-menu-panel {
642
+ position: absolute;
643
+ top: calc(100% + var(--space-2));
644
+ z-index: 30;
645
+ min-width: 176px;
646
+ padding: var(--space-1);
647
+ border-radius: var(--radius-lg);
648
+ }
649
+
650
+ .hds-menu-panel--start { left: 0; }
651
+ .hds-menu-panel--end { right: 0; }
652
+
653
+ .hds-menu-item {
654
+ display: flex;
655
+ align-items: center;
656
+ gap: var(--space-2);
657
+ width: 100%;
658
+ min-height: 36px;
659
+ padding: var(--space-2) var(--space-3);
660
+ border: 0;
661
+ border-radius: var(--space-1);
662
+ background: transparent;
663
+ color: var(--ink);
664
+ font-family: var(--font-sans);
665
+ font-size: 14px;
666
+ line-height: 20px;
667
+ font-weight: 500;
668
+ text-align: left;
669
+ cursor: pointer;
670
+ }
671
+
672
+ .hds-menu-item .hds-icon {
673
+ font-size: 16px;
674
+ }
675
+
676
+ .hds-menu-item:hover,
677
+ .hds-menu-item:focus-visible {
678
+ background: var(--accent-soft);
679
+ }
680
+
681
+ .hds-menu-item--danger {
682
+ color: var(--danger);
683
+ }
684
+
685
+ .hds-menu-separator {
686
+ height: 1px;
687
+ margin: var(--space-1) var(--space-2);
688
+ background: var(--line);
689
+ }
690
+
691
+ /* ---------- Dialog ---------- */
692
+
693
+ .hds-scrim {
694
+ position: fixed;
695
+ inset: 0;
696
+ z-index: 50;
697
+ display: grid;
698
+ place-items: center;
699
+ padding: var(--space-4);
700
+ background: var(--scrim);
701
+ }
702
+
703
+ .hds-dialog {
704
+ display: flex;
705
+ flex-direction: column;
706
+ gap: var(--space-4);
707
+ width: 100%;
708
+ max-width: 560px;
709
+ max-height: calc(100% - var(--space-8));
710
+ overflow: auto;
711
+ padding: var(--space-6);
712
+ border-radius: var(--radius-2xl);
713
+ }
714
+
715
+ .hds-dialog-header {
716
+ display: flex;
717
+ align-items: flex-start;
718
+ justify-content: space-between;
719
+ gap: var(--space-4);
720
+ }
721
+
722
+ .hds-dialog-title {
723
+ margin: 0;
724
+ font-size: 20px;
725
+ line-height: 28px;
726
+ font-weight: 600;
727
+ }
728
+
729
+ .hds-dialog-description {
730
+ margin: var(--space-1) 0 0;
731
+ color: var(--ink-muted);
732
+ font-size: 14px;
733
+ line-height: 20px;
734
+ }
735
+
736
+ .hds-dialog-footer {
737
+ display: flex;
738
+ flex-wrap: wrap;
739
+ justify-content: flex-end;
740
+ gap: var(--space-2);
741
+ }
742
+
743
+ /* ---------- Toast ---------- */
744
+
745
+ .hds-toast-region {
746
+ position: fixed;
747
+ left: 50%;
748
+ bottom: calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
749
+ z-index: 60;
750
+ display: flex;
751
+ flex-direction: column;
752
+ gap: var(--space-2);
753
+ width: min(420px, calc(100% - var(--space-8)));
754
+ transform: translateX(-50%);
755
+ }
756
+
757
+ .hds-toast {
758
+ display: flex;
759
+ align-items: flex-start;
760
+ gap: var(--space-3);
761
+ padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
762
+ border-radius: var(--radius-2xl);
763
+ animation: hds-toast-in 300ms ease-out;
764
+ }
765
+
766
+ .hds-toast > .hds-icon {
767
+ margin-top: 2px;
768
+ font-size: 20px;
769
+ }
770
+
771
+ .hds-toast--success > .hds-icon { color: var(--success); }
772
+ .hds-toast--warning > .hds-icon { color: var(--warning); }
773
+ .hds-toast--danger > .hds-icon { color: var(--danger); }
774
+ .hds-toast--neutral > .hds-icon { color: var(--accent); }
775
+
776
+ .hds-toast-body {
777
+ flex: 1;
778
+ min-width: 0;
779
+ font-size: 14px;
780
+ line-height: 20px;
781
+ }
782
+
783
+ .hds-toast-title {
784
+ margin: 0;
785
+ font-weight: 700;
786
+ }
787
+
788
+ .hds-toast-description {
789
+ margin: 0;
790
+ }
791
+
792
+ @keyframes hds-toast-in {
793
+ from { opacity: 0; transform: translateY(var(--space-2)); }
794
+ }
795
+
796
+ /* ---------- Forms ---------- */
797
+
798
+ .hds-field {
799
+ display: flex;
800
+ flex-direction: column;
801
+ gap: var(--space-1);
802
+ min-width: 0;
803
+ }
804
+
805
+ .hds-label {
806
+ color: var(--ink);
807
+ font-size: 14px;
808
+ line-height: 20px;
809
+ font-weight: 600;
810
+ }
811
+
812
+ .hds-hint {
813
+ margin: 0;
814
+ color: var(--ink-muted);
815
+ font-size: 14px;
816
+ line-height: 20px;
817
+ }
818
+
819
+ .hds-error {
820
+ display: flex;
821
+ align-items: center;
822
+ gap: var(--space-1);
823
+ margin: 0;
824
+ color: var(--danger);
825
+ font-size: 14px;
826
+ line-height: 20px;
827
+ font-weight: 600;
828
+ }
829
+
830
+ .hds-input,
831
+ .hds-select {
832
+ width: 100%;
833
+ min-height: 40px;
834
+ padding: var(--space-2) var(--space-3);
835
+ border: 1px solid var(--line-strong);
836
+ border-radius: var(--radius-md);
837
+ background: var(--surface-sunken);
838
+ color: var(--ink);
839
+ font-family: var(--font-sans);
840
+ font-size: 16px;
841
+ line-height: 24px;
842
+ transition: border-color 150ms;
843
+ }
844
+
845
+ .hds-input::placeholder {
846
+ color: var(--ink-muted);
847
+ opacity: 1;
848
+ }
849
+
850
+ .hds-input:hover,
851
+ .hds-select:hover {
852
+ border-color: var(--accent);
853
+ }
854
+
855
+ .hds-input[aria-invalid="true"],
856
+ .hds-select[aria-invalid="true"] {
857
+ border-color: var(--danger);
858
+ }
859
+
860
+ .hds-input:disabled,
861
+ .hds-select:disabled {
862
+ opacity: 0.5;
863
+ cursor: not-allowed;
864
+ }
865
+
866
+ .hds-input--numeric {
867
+ font-family: var(--font-mono);
868
+ font-variant-numeric: tabular-nums;
869
+ }
870
+
871
+ .hds-select-wrap {
872
+ position: relative;
873
+ }
874
+
875
+ .hds-select {
876
+ -webkit-appearance: none;
877
+ appearance: none;
878
+ padding-right: var(--space-10);
879
+ cursor: pointer;
880
+ }
881
+
882
+ .hds-select-wrap > .hds-icon {
883
+ position: absolute;
884
+ top: 50%;
885
+ right: var(--space-3);
886
+ font-size: 16px;
887
+ color: var(--ink-muted);
888
+ transform: translateY(-50%);
889
+ pointer-events: none;
890
+ }
891
+
892
+ .hds-checkbox {
893
+ display: inline-flex;
894
+ align-items: flex-start;
895
+ gap: var(--space-2);
896
+ color: var(--ink);
897
+ font-size: 16px;
898
+ line-height: 24px;
899
+ cursor: pointer;
900
+ }
901
+
902
+ .hds-checkbox-control {
903
+ position: relative;
904
+ display: inline-grid;
905
+ flex: none;
906
+ width: 20px;
907
+ height: 20px;
908
+ margin-top: 2px;
909
+ }
910
+
911
+ .hds-checkbox-input {
912
+ position: absolute;
913
+ inset: 0;
914
+ width: 100%;
915
+ height: 100%;
916
+ margin: 0;
917
+ opacity: 0;
918
+ cursor: pointer;
919
+ }
920
+
921
+ .hds-checkbox-box {
922
+ display: grid;
923
+ place-items: center;
924
+ border: 1.5px solid var(--line-strong);
925
+ border-radius: var(--radius-sm);
926
+ background: var(--surface-sunken);
927
+ color: var(--on-accent);
928
+ font-size: 14px;
929
+ pointer-events: none;
930
+ transition: background-color 150ms, border-color 150ms;
931
+ }
932
+
933
+ .hds-checkbox-box .hds-icon {
934
+ opacity: 0;
935
+ }
936
+
937
+ .hds-checkbox-input:checked + .hds-checkbox-box {
938
+ border-color: var(--accent-fill);
939
+ background: var(--accent-fill);
940
+ }
941
+
942
+ .hds-checkbox-input:checked + .hds-checkbox-box .hds-icon {
943
+ opacity: 1;
944
+ }
945
+
946
+ .hds-checkbox-input:focus-visible + .hds-checkbox-box {
947
+ outline: 2px solid var(--focus-ring);
948
+ outline-offset: 2px;
949
+ }
950
+
951
+ .hds-checkbox-input:disabled + .hds-checkbox-box {
952
+ opacity: 0.5;
953
+ }
954
+
955
+ .hds-checkbox-text {
956
+ display: flex;
957
+ flex-direction: column;
958
+ }
959
+
960
+ /* ---------- Card ---------- */
961
+
962
+ .hds-card {
963
+ display: flex;
964
+ flex-direction: column;
965
+ overflow: hidden;
966
+ border: 1px solid var(--line);
967
+ border-radius: var(--radius-lg);
968
+ background: var(--surface-raised);
969
+ color: var(--ink);
970
+ box-shadow: var(--shadow-raised);
971
+ }
972
+
973
+ .hds-card--interactive {
974
+ transition: transform 200ms ease-out;
975
+ }
976
+
977
+ .hds-card--interactive:hover {
978
+ transform: scale(1.02);
979
+ }
980
+
981
+ .hds-card-media {
982
+ display: block;
983
+ width: 100%;
984
+ aspect-ratio: 16 / 9;
985
+ object-fit: cover;
986
+ }
987
+
988
+ .hds-card-body {
989
+ display: flex;
990
+ flex-direction: column;
991
+ gap: var(--space-2);
992
+ padding: var(--space-6);
993
+ }
994
+
995
+ .hds-card-eyebrow {
996
+ margin: 0;
997
+ color: var(--secondary);
998
+ font-size: 14px;
999
+ line-height: 20px;
1000
+ font-weight: 700;
1001
+ letter-spacing: 0.025em;
1002
+ text-transform: uppercase;
1003
+ }
1004
+
1005
+ .hds-card-title {
1006
+ margin: 0;
1007
+ font-size: 20px;
1008
+ line-height: 28px;
1009
+ font-weight: 600;
1010
+ }
1011
+
1012
+ .hds-card-text {
1013
+ color: var(--ink-muted);
1014
+ font-size: 14px;
1015
+ line-height: 20px;
1016
+ }
1017
+
1018
+ .hds-card-footer {
1019
+ display: flex;
1020
+ flex-wrap: wrap;
1021
+ gap: var(--space-3);
1022
+ padding: 0 var(--space-6) var(--space-6);
1023
+ }
1024
+
1025
+ /* ---------- Badge ---------- */
1026
+
1027
+ .hds-badge {
1028
+ display: inline-flex;
1029
+ align-items: center;
1030
+ gap: var(--space-1);
1031
+ padding: 2px var(--space-2);
1032
+ border-radius: var(--radius-full);
1033
+ color: var(--ink);
1034
+ font-size: 12px;
1035
+ line-height: 16px;
1036
+ font-weight: 600;
1037
+ white-space: nowrap;
1038
+ }
1039
+
1040
+ .hds-badge .hds-icon {
1041
+ font-size: 14px;
1042
+ }
1043
+
1044
+ .hds-badge--neutral {
1045
+ background: color-mix(in srgb, var(--ink) 8%, transparent);
1046
+ }
1047
+
1048
+ .hds-badge--neutral .hds-icon { color: var(--ink-muted); }
1049
+ .hds-badge--accent { background: color-mix(in srgb, var(--accent) 14%, transparent); }
1050
+ .hds-badge--accent .hds-icon { color: var(--accent); }
1051
+ .hds-badge--success { background: color-mix(in srgb, var(--success) 14%, transparent); }
1052
+ .hds-badge--success .hds-icon { color: var(--success); }
1053
+ .hds-badge--warning { background: color-mix(in srgb, var(--warning) 14%, transparent); }
1054
+ .hds-badge--warning .hds-icon { color: var(--warning); }
1055
+ .hds-badge--danger { background: color-mix(in srgb, var(--danger) 14%, transparent); }
1056
+ .hds-badge--danger .hds-icon { color: var(--danger); }
1057
+
1058
+ /* ---------- Table ---------- */
1059
+
1060
+ .hds-table-wrap {
1061
+ overflow-x: auto;
1062
+ border: 1px solid var(--line);
1063
+ border-radius: var(--radius-lg);
1064
+ background: var(--surface-raised);
1065
+ }
1066
+
1067
+ .hds-table {
1068
+ width: 100%;
1069
+ border-collapse: separate;
1070
+ border-spacing: 0;
1071
+ color: var(--ink);
1072
+ font-size: 14px;
1073
+ line-height: 20px;
1074
+ }
1075
+
1076
+ .hds-table caption {
1077
+ padding: var(--space-3) var(--space-4);
1078
+ color: var(--ink-muted);
1079
+ text-align: left;
1080
+ }
1081
+
1082
+ .hds-table th {
1083
+ position: sticky;
1084
+ top: 0;
1085
+ padding: var(--space-3) var(--space-4);
1086
+ background: var(--surface-sunken);
1087
+ color: var(--ink-muted);
1088
+ font-weight: 600;
1089
+ text-align: left;
1090
+ white-space: nowrap;
1091
+ }
1092
+
1093
+ .hds-table td {
1094
+ padding: var(--space-3) var(--space-4);
1095
+ border-top: 1px solid var(--line);
1096
+ vertical-align: middle;
1097
+ }
1098
+
1099
+ .hds-table tbody tr {
1100
+ transition: background-color 150ms;
1101
+ }
1102
+
1103
+ .hds-table tbody tr:hover {
1104
+ background: var(--accent-soft);
1105
+ }
1106
+
1107
+ .hds-table .hds-cell--numeric {
1108
+ font-family: var(--font-mono);
1109
+ font-weight: 500;
1110
+ font-variant-numeric: tabular-nums;
1111
+ text-align: right;
1112
+ white-space: nowrap;
1113
+ }
1114
+
1115
+ .hds-table th.hds-cell--numeric {
1116
+ font-family: var(--font-sans);
1117
+ font-weight: 600;
1118
+ }
1119
+
1120
+ .hds-table .hds-cell--center {
1121
+ text-align: center;
1122
+ }
1123
+
1124
+ .hds-table-empty {
1125
+ padding: var(--space-8) var(--space-4);
1126
+ color: var(--ink-muted);
1127
+ text-align: center;
1128
+ }
1129
+
1130
+ /* ---------- Layout and typography ---------- */
1131
+
1132
+ .hds-container {
1133
+ width: 100%;
1134
+ max-width: var(--content-max);
1135
+ margin-inline: auto;
1136
+ padding: var(--space-20) var(--space-4);
1137
+ }
1138
+
1139
+ @media (min-width: 768px) {
1140
+ .hds-container--with-sidebar {
1141
+ padding-left: calc(var(--sidebar-width) + var(--space-4));
1142
+ }
1143
+ }
1144
+
1145
+ .hds-section-title {
1146
+ display: flex;
1147
+ align-items: center;
1148
+ gap: var(--space-3);
1149
+ margin: 0;
1150
+ color: var(--ink);
1151
+ font-size: 36px;
1152
+ line-height: 40px;
1153
+ font-weight: 700;
1154
+ text-wrap: balance;
1155
+ }
1156
+
1157
+ .hds-section-index {
1158
+ color: color-mix(in srgb, var(--accent) 30%, transparent);
1159
+ font-family: var(--font-mono);
1160
+ font-size: 20px;
1161
+ line-height: 28px;
1162
+ font-weight: 700;
1163
+ filter: drop-shadow(0 0 10px var(--accent));
1164
+ }
1165
+
1166
+ .hds-separator {
1167
+ flex: none;
1168
+ background: var(--line-strong);
1169
+ }
1170
+
1171
+ .hds-separator--horizontal {
1172
+ width: 100%;
1173
+ height: 1px;
1174
+ }
1175
+
1176
+ .hds-separator--vertical {
1177
+ width: 1px;
1178
+ align-self: stretch;
1179
+ }
1180
+
1181
+ .hds-scroll {
1182
+ overflow: auto;
1183
+ scrollbar-width: thin;
1184
+ scrollbar-color: var(--secondary-500) transparent;
1185
+ }
1186
+
1187
+ .hds-scroll::-webkit-scrollbar {
1188
+ width: 10px;
1189
+ height: 10px;
1190
+ }
1191
+
1192
+ .hds-scroll::-webkit-scrollbar-track {
1193
+ background: transparent;
1194
+ }
1195
+
1196
+ .hds-scroll::-webkit-scrollbar-thumb {
1197
+ border: 2px solid var(--surface);
1198
+ border-radius: var(--radius-full);
1199
+ background-color: var(--secondary-500);
1200
+ }
1201
+
1202
+ .hds-scroll::-webkit-scrollbar-thumb:hover {
1203
+ background-color: var(--primary-500);
1204
+ }
1205
+
1206
+ .hds-avatar {
1207
+ position: relative;
1208
+ display: inline-block;
1209
+ flex: none;
1210
+ isolation: isolate;
1211
+ }
1212
+
1213
+ .hds-avatar-glow {
1214
+ position: absolute;
1215
+ inset: 0;
1216
+ z-index: -1;
1217
+ border-radius: var(--radius-full);
1218
+ background: var(--accent-fill);
1219
+ opacity: 0.7;
1220
+ filter: blur(24px);
1221
+ }
1222
+
1223
+ .hds-avatar-image {
1224
+ display: block;
1225
+ width: 100%;
1226
+ height: 100%;
1227
+ border: 4px solid var(--accent-fill);
1228
+ border-radius: var(--radius-full);
1229
+ object-fit: cover;
1230
+ }
1231
+
1232
+ /* ---------- Motion preferences ---------- */
1233
+
1234
+ @media (prefers-reduced-motion: reduce) {
1235
+ .hds-card--interactive:hover {
1236
+ transform: none;
1237
+ }
1238
+
1239
+ .hds-segmented-thumb,
1240
+ .hds-toast {
1241
+ transition: none;
1242
+ animation: none;
1243
+ }
1244
+
1245
+ .hds-loading .hds-icon,
1246
+ .hds-spin {
1247
+ animation-duration: 2.4s;
1248
+ }
1249
+ }