@invisibleloop/pulse 0.14.1 → 0.14.2

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.
@@ -0,0 +1,4031 @@
1
+ /**
2
+ * Pulse UI — Component stylesheet
3
+ *
4
+ * Import this file in your page spec:
5
+ * meta: { styles: ['/pulse-ui.css', '/app.css'] }
6
+ *
7
+ * Theming: override these custom properties in :root in your app.css.
8
+ * Do not edit this file — extend via new CSS modifier classes only.
9
+ *
10
+ * Token fallback chain: project token → ui default
11
+ * e.g. --ui-accent falls back to --accent, then to a hardcoded default.
12
+ */
13
+
14
+ /* ─── UI tokens ─────────────────────────────────────────────────────────────
15
+ All component styles reference --ui-* tokens only.
16
+ Override these in :root to retheme the entire library at once. */
17
+ :root {
18
+ --ui-bg: var(--bg, #0d0d10);
19
+ --ui-surface: var(--surface, #111116);
20
+ --ui-surface-2: var(--surface-2, #18181f);
21
+ --ui-border: var(--border, #38383f);
22
+ --ui-text: var(--text, #e2e2ea);
23
+ --ui-muted: var(--muted, #9090a0);
24
+ --ui-accent: var(--accent, #9b8dff);
25
+ --ui-accent-hover: var(--accent-hover, #b5aaff);
26
+ --ui-accent-dim: var(--accent-dim, rgba(155,141,255,.12));
27
+ --ui-accent-text: var(--accent-text, #0d0a20);
28
+ /* Inline code in dark theme — accent passes WCAG AA on surface-2 by default */
29
+ --ui-code-color: var(--code-color, var(--ui-accent));
30
+ --ui-green: var(--green, #3dd68c);
31
+ --ui-green-dim: rgba(61, 214, 140, .12);
32
+ --ui-red: var(--red, #ff6b6b);
33
+ --ui-red-dim: rgba(255, 107, 107, .12);
34
+ --ui-yellow: #f5a623;
35
+ --ui-yellow-dim: rgba(245, 166, 35, .12);
36
+ --ui-blue: #60a5fa;
37
+ --ui-blue-dim: rgba( 96, 165, 250, .12);
38
+ --ui-radius: var(--radius, 8px);
39
+ --ui-radius-sm: 4px;
40
+ --ui-font: var(--font, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
41
+ --ui-font-display: var(--font-display, var(--ui-font));
42
+ --ui-mono: var(--mono, 'Fira Code', 'Cascadia Code', monospace);
43
+ --ui-letter-spacing-display: var(--letter-spacing-display, -0.025em);
44
+
45
+ /* Touch target minimum per WCAG 2.5.5 */
46
+ --ui-touch-min: 44px;
47
+
48
+ /* ── Spacing scale ── */
49
+ --ui-space-1: 0.25rem; /* 4px */
50
+ --ui-space-2: 0.5rem; /* 8px */
51
+ --ui-space-3: 0.75rem; /* 12px */
52
+ --ui-space-4: 1rem; /* 16px */
53
+ --ui-space-5: 1.25rem; /* 20px */
54
+ --ui-space-6: 1.5rem; /* 24px */
55
+ --ui-space-8: 2rem; /* 32px */
56
+ --ui-space-10: 2.5rem; /* 40px */
57
+ --ui-space-12: 3rem; /* 48px */
58
+ --ui-space-16: 4rem; /* 64px */
59
+ --ui-space-20: 5rem; /* 80px */
60
+ --ui-space-24: 6rem; /* 96px */
61
+
62
+ /* ── Type scale ── */
63
+ --ui-text-xs: 0.75rem; /* 12px */
64
+ --ui-text-sm: 0.875rem; /* 14px */
65
+ --ui-text-base: 1rem; /* 16px */
66
+ --ui-text-lg: 1.125rem; /* 18px */
67
+ --ui-text-xl: 1.25rem; /* 20px */
68
+ --ui-text-2xl: 1.5rem; /* 24px */
69
+ --ui-text-3xl: 1.875rem; /* 30px */
70
+ --ui-text-4xl: 2.25rem; /* 36px */
71
+ }
72
+
73
+ /* ─── Base reset ─────────────────────────────────────────────────────────────
74
+ Apply the dark background and text colour to the document root so the page
75
+ background matches the component surface colours out of the box.
76
+ Projects can opt into a light theme via meta.theme: 'light' (sets
77
+ data-theme="light" on <body>) or override :root tokens in app.css. */
78
+ *, *::before, *::after { box-sizing: border-box; }
79
+ h1, h2, h3, h4, h5, h6, p, ul, ol, li { margin: 0; }
80
+ ul, ol { list-style: none; }
81
+
82
+ html, body {
83
+ margin: 0;
84
+ background-color: var(--ui-bg);
85
+ color: var(--ui-text);
86
+ font-family: var(--ui-font);
87
+ min-height: 100dvh;
88
+ }
89
+
90
+ /* ─── Focus style ────────────────────────────────────────────────────────────
91
+ Applied via :focus-visible to avoid showing on mouse click.
92
+ All interactive components inherit this. */
93
+ .ui-btn:focus-visible,
94
+ .ui-input:focus-visible,
95
+ .ui-select:focus-visible,
96
+ .ui-textarea:focus-visible {
97
+ outline: 2px solid var(--ui-accent);
98
+ outline-offset: 2px;
99
+ }
100
+
101
+ /* ─── Button ─────────────────────────────────────────────────────────────── */
102
+ .ui-btn {
103
+ box-sizing: border-box;
104
+ display: inline-flex;
105
+ align-items: center;
106
+ justify-content: center;
107
+ gap: .45rem;
108
+ padding: 0 1.2rem;
109
+ height: var(--ui-touch-min);
110
+ min-width: var(--ui-touch-min);
111
+ border: 1px solid transparent;
112
+ border-radius: var(--ui-radius);
113
+ font-family: var(--ui-font);
114
+ font-size: .9rem;
115
+ font-weight: 600;
116
+ line-height: 1;
117
+ text-decoration: none;
118
+ white-space: nowrap;
119
+ cursor: pointer;
120
+ transition: background .15s, color .15s, border-color .15s, opacity .15s;
121
+ -webkit-font-smoothing: antialiased;
122
+ }
123
+
124
+ /* Variants */
125
+ .ui-btn--primary {
126
+ background: var(--ui-accent);
127
+ color: var(--ui-bg);
128
+ }
129
+ .ui-btn--primary:hover:not(.ui-btn--disabled):not([disabled]) {
130
+ background: var(--ui-accent-hover);
131
+ }
132
+
133
+ .ui-btn--secondary {
134
+ background: var(--ui-surface-2);
135
+ color: var(--ui-text);
136
+ border-color: var(--ui-muted);
137
+ }
138
+ .ui-btn--secondary:hover:not(.ui-btn--disabled):not([disabled]) {
139
+ background: var(--ui-surface);
140
+ border-color: var(--ui-text);
141
+ }
142
+
143
+ .ui-btn--ghost {
144
+ background: transparent;
145
+ color: var(--ui-muted);
146
+ border: none;
147
+ }
148
+ .ui-btn--ghost:hover:not(.ui-btn--disabled):not([disabled]) {
149
+ background: var(--ui-surface-2);
150
+ color: var(--ui-text);
151
+ }
152
+
153
+ .ui-btn--danger {
154
+ background: var(--ui-red-dim);
155
+ color: var(--ui-red);
156
+ border-color: var(--ui-red);
157
+ }
158
+ .ui-btn--danger:hover:not(.ui-btn--disabled):not([disabled]) {
159
+ background: var(--ui-red);
160
+ color: var(--ui-bg);
161
+ }
162
+
163
+ /* Sizes */
164
+ .ui-btn--sm {
165
+ height: 36px;
166
+ padding: 0 .85rem;
167
+ font-size: .82rem;
168
+ min-width: 36px;
169
+ }
170
+ .ui-btn--lg {
171
+ height: 52px;
172
+ padding: 0 1.75rem;
173
+ font-size: 1rem;
174
+ }
175
+
176
+ /* Modifiers */
177
+ .ui-btn--full { width: 100%; }
178
+ .ui-btn--disabled,
179
+ .ui-btn[disabled] {
180
+ opacity: .45;
181
+ cursor: not-allowed;
182
+ pointer-events: none;
183
+ }
184
+
185
+ .ui-btn-icon {
186
+ display: inline-flex;
187
+ align-items: center;
188
+ flex-shrink: 0;
189
+ }
190
+
191
+ /* ─── Badge ──────────────────────────────────────────────────────────────── */
192
+ .ui-badge {
193
+ display: inline-flex;
194
+ align-items: center;
195
+ align-self: flex-start;
196
+ padding: .3em .55em;
197
+ border-radius: var(--ui-radius-sm);
198
+ font-family: var(--ui-font);
199
+ font-size: .72rem;
200
+ font-weight: 600;
201
+ line-height: 1;
202
+ white-space: nowrap;
203
+ letter-spacing: .02em;
204
+ }
205
+
206
+ .ui-badge--default { background: var(--ui-surface-2); color: var(--ui-muted); }
207
+ .ui-badge--success { background: var(--ui-green-dim); color: var(--ui-green); }
208
+ .ui-badge--warning { background: var(--ui-yellow-dim);color: var(--ui-yellow); }
209
+ .ui-badge--error { background: var(--ui-red-dim); color: var(--ui-red); }
210
+ .ui-badge--info { background: var(--ui-blue-dim); color: var(--ui-blue); }
211
+
212
+ /* ─── Card ───────────────────────────────────────────────────────────────── */
213
+ .ui-card {
214
+ background: var(--ui-surface);
215
+ border: 1px solid var(--ui-border);
216
+ border-radius: var(--ui-radius);
217
+ overflow: hidden;
218
+ }
219
+
220
+ .ui-card-header {
221
+ padding: 1rem 1.25rem;
222
+ border-bottom: 1px solid var(--ui-border);
223
+ }
224
+
225
+ .ui-card-title {
226
+ margin: 0;
227
+ font-size: .95rem;
228
+ font-weight: 600;
229
+ color: var(--ui-text);
230
+ line-height: 1.4;
231
+ }
232
+
233
+ .ui-card-body { padding: 1.25rem; }
234
+
235
+ .ui-card--flush .ui-card-body { padding: 0; }
236
+
237
+ /* Card variants */
238
+ .ui-card--elevated {
239
+ box-shadow: 0 4px 24px rgba(0,0,0,.22), 0 1px 4px rgba(0,0,0,.12);
240
+ border-color: transparent;
241
+ }
242
+ .ui-card--bordered {
243
+ box-shadow: none;
244
+ border-width: 2px;
245
+ }
246
+ .ui-card--flat {
247
+ box-shadow: none;
248
+ border-color: transparent;
249
+ }
250
+ .ui-card--glass {
251
+ background: rgba(255,255,255,.06);
252
+ border-color: rgba(255,255,255,.12);
253
+ box-shadow: 0 4px 24px rgba(0,0,0,.18);
254
+ backdrop-filter: blur(12px);
255
+ -webkit-backdrop-filter: blur(12px);
256
+ }
257
+ [data-theme="light"] .ui-card--glass {
258
+ background: rgba(255,255,255,.72);
259
+ border-color: rgba(0,0,0,.08);
260
+ }
261
+ .ui-card--tinted {
262
+ background: var(--ui-accent-dim, rgba(99,102,241,.1));
263
+ border-color: var(--ui-accent-dim, rgba(99,102,241,.2));
264
+ box-shadow: none;
265
+ }
266
+
267
+ .ui-card-footer {
268
+ padding: 1rem 1.25rem;
269
+ border-top: 1px solid var(--ui-border);
270
+ background: var(--ui-surface-2);
271
+ }
272
+
273
+ /* ============================================================
274
+ Fieldset
275
+ ============================================================ */
276
+
277
+ .ui-fieldset {
278
+ border: 1px solid var(--ui-border);
279
+ border-radius: var(--ui-radius);
280
+ padding: 0;
281
+ margin: 0;
282
+ }
283
+
284
+ .ui-fieldset-legend {
285
+ margin-left: 1rem;
286
+ padding: 0 0.375rem;
287
+ font-size: 0.75rem;
288
+ font-weight: 600;
289
+ letter-spacing: 0.06em;
290
+ text-transform: uppercase;
291
+ color: var(--ui-muted);
292
+ line-height: 1;
293
+ }
294
+
295
+ .ui-fieldset-body {
296
+ display: flex;
297
+ flex-direction: column;
298
+ gap: 1rem;
299
+ padding: 1.25rem;
300
+ }
301
+
302
+ .ui-fieldset--gap-xs .ui-fieldset-body { gap: 0.375rem; }
303
+ .ui-fieldset--gap-sm .ui-fieldset-body { gap: 0.625rem; }
304
+ .ui-fieldset--gap-lg .ui-fieldset-body { gap: 1.5rem; }
305
+
306
+ /* ─── Form fields (shared base) ──────────────────────────────────────────── */
307
+ .ui-field {
308
+ display: flex;
309
+ flex-direction: column;
310
+ gap: .4rem;
311
+ }
312
+
313
+ .ui-label {
314
+ font-family: var(--ui-font);
315
+ font-size: .85rem;
316
+ font-weight: 600;
317
+ color: var(--ui-text);
318
+ line-height: 1.4;
319
+ }
320
+
321
+ .ui-required {
322
+ color: var(--ui-red);
323
+ margin-left: .15rem;
324
+ }
325
+
326
+ .ui-hint {
327
+ font-size: .8rem;
328
+ color: var(--ui-muted);
329
+ margin: 0;
330
+ line-height: 1.5;
331
+ }
332
+
333
+ .ui-error {
334
+ font-size: .8rem;
335
+ color: var(--ui-red);
336
+ margin: 0;
337
+ line-height: 1.5;
338
+ }
339
+
340
+ /* ─── Input ──────────────────────────────────────────────────────────────── */
341
+ .ui-input {
342
+ width: 100%;
343
+ height: var(--ui-touch-min);
344
+ padding: 0 .85rem;
345
+ background: var(--ui-surface);
346
+ border: 1px solid var(--ui-border);
347
+ border-radius: var(--ui-radius);
348
+ font-family: var(--ui-font);
349
+ font-size: .9rem;
350
+ color: var(--ui-text);
351
+ transition: border-color .15s;
352
+ appearance: none;
353
+ -webkit-appearance: none;
354
+ }
355
+
356
+ .ui-input::placeholder { color: var(--ui-muted); }
357
+
358
+ .ui-input:hover:not(:disabled) { border-color: var(--ui-muted); }
359
+
360
+ .ui-input:disabled {
361
+ opacity: .5;
362
+ cursor: not-allowed;
363
+ }
364
+
365
+ .ui-field--error .ui-input {
366
+ border-color: var(--ui-red);
367
+ }
368
+
369
+ /* ─── Search ─────────────────────────────────────────────────────────────── */
370
+ .ui-search-wrap {
371
+ position: relative;
372
+ display: flex;
373
+ align-items: center;
374
+ }
375
+
376
+ .ui-search-icon {
377
+ position: absolute;
378
+ left: .75rem;
379
+ display: flex;
380
+ align-items: center;
381
+ color: var(--ui-muted);
382
+ pointer-events: none;
383
+ }
384
+
385
+ .ui-search-input {
386
+ width: 100%;
387
+ height: var(--ui-touch-min);
388
+ padding: 0 2.5rem 0 2.5rem;
389
+ background: var(--ui-surface);
390
+ border: 1px solid var(--ui-border);
391
+ border-radius: var(--ui-radius);
392
+ font-family: var(--ui-font);
393
+ font-size: .9rem;
394
+ color: var(--ui-text);
395
+ transition: border-color .15s;
396
+ appearance: none;
397
+ -webkit-appearance: none;
398
+ }
399
+
400
+ .ui-search-input::placeholder { color: var(--ui-muted); }
401
+
402
+ .ui-search-input:hover:not(:disabled) { border-color: var(--ui-muted); }
403
+
404
+ .ui-search-input:disabled { opacity: .5; cursor: not-allowed; }
405
+
406
+ /* Hide native browser cancel button — the component provides its own */
407
+ .ui-search-input::-webkit-search-cancel-button { display: none; }
408
+
409
+ .ui-search-clear {
410
+ position: absolute;
411
+ right: .5rem;
412
+ display: flex;
413
+ align-items: center;
414
+ justify-content: center;
415
+ width: 1.75rem;
416
+ height: 1.75rem;
417
+ padding: 0;
418
+ background: transparent;
419
+ border: none;
420
+ border-radius: var(--ui-radius-sm);
421
+ color: var(--ui-muted);
422
+ cursor: pointer;
423
+ transition: color .15s, background .15s;
424
+ }
425
+
426
+ .ui-search-clear:hover { color: var(--ui-text); background: var(--ui-surface-2); }
427
+
428
+ /* ─── Select ─────────────────────────────────────────────────────────────── */
429
+ .ui-select-wrap {
430
+ position: relative;
431
+ display: flex;
432
+ }
433
+
434
+ .ui-select {
435
+ width: 100%;
436
+ height: var(--ui-touch-min);
437
+ padding: 0 2.5rem 0 .85rem;
438
+ background: var(--ui-surface);
439
+ border: 1px solid var(--ui-border);
440
+ border-radius: var(--ui-radius);
441
+ font-family: var(--ui-font);
442
+ font-size: .9rem;
443
+ color: var(--ui-text);
444
+ cursor: pointer;
445
+ appearance: none;
446
+ -webkit-appearance: none;
447
+ transition: border-color .15s;
448
+ }
449
+
450
+ .ui-select:hover:not(:disabled) { border-color: var(--ui-muted); }
451
+
452
+ .ui-select:disabled {
453
+ opacity: .5;
454
+ cursor: not-allowed;
455
+ }
456
+
457
+ .ui-field--error .ui-select { border-color: var(--ui-red); }
458
+
459
+ .ui-select-chevron {
460
+ position: absolute;
461
+ right: .85rem;
462
+ top: 50%;
463
+ transform: translateY(-50%);
464
+ pointer-events: none;
465
+ color: var(--ui-muted);
466
+ display: flex;
467
+ align-items: center;
468
+ }
469
+
470
+ /* ─── Textarea ───────────────────────────────────────────────────────────── */
471
+ .ui-textarea {
472
+ width: 100%;
473
+ padding: .65rem .85rem;
474
+ background: var(--ui-surface);
475
+ border: 1px solid var(--ui-border);
476
+ border-radius: var(--ui-radius);
477
+ font-family: var(--ui-font);
478
+ font-size: .9rem;
479
+ color: var(--ui-text);
480
+ resize: vertical;
481
+ transition: border-color .15s;
482
+ min-height: calc(var(--ui-touch-min) * 2);
483
+ appearance: none;
484
+ }
485
+
486
+ .ui-textarea::placeholder { color: var(--ui-muted); }
487
+
488
+ .ui-textarea:hover:not(:disabled) { border-color: var(--ui-muted); }
489
+
490
+ .ui-textarea:disabled {
491
+ opacity: .5;
492
+ cursor: not-allowed;
493
+ }
494
+
495
+ .ui-field--error .ui-textarea { border-color: var(--ui-red); }
496
+
497
+ /* ─── Alert ──────────────────────────────────────────────────────────────── */
498
+ .ui-alert {
499
+ display: flex;
500
+ align-items: flex-start;
501
+ gap: .75rem;
502
+ padding: .85rem 1rem;
503
+ border-radius: var(--ui-radius);
504
+ border: 1px solid transparent;
505
+ font-size: .88rem;
506
+ line-height: 1.6;
507
+ }
508
+
509
+ .ui-alert--info { background: var(--ui-blue-dim); border-color: var(--ui-blue); color: var(--ui-blue); }
510
+ .ui-alert--success { background: var(--ui-green-dim); border-color: var(--ui-green); color: var(--ui-green); }
511
+ .ui-alert--warning { background: var(--ui-yellow-dim);border-color: var(--ui-yellow); color: var(--ui-yellow);}
512
+ .ui-alert--error { background: var(--ui-red-dim); border-color: var(--ui-red); color: var(--ui-red); }
513
+
514
+ .ui-alert-icon {
515
+ display: flex;
516
+ align-items: center;
517
+ flex-shrink: 0;
518
+ margin-top: .1rem;
519
+ }
520
+
521
+ .ui-alert-body { color: var(--ui-text); }
522
+
523
+ .ui-alert-title { font-weight: 600; }
524
+
525
+ /* ─── Stat ───────────────────────────────────────────────────────────────── */
526
+ .ui-stat {
527
+ display: flex;
528
+ flex-direction: column;
529
+ gap: .3rem;
530
+ }
531
+
532
+ .ui-stat-label {
533
+ font-size: .8rem;
534
+ color: var(--ui-muted);
535
+ font-weight: 500;
536
+ margin: 0;
537
+ }
538
+
539
+ .ui-stat-value {
540
+ font-size: 2rem;
541
+ font-weight: 700;
542
+ color: var(--ui-text);
543
+ line-height: 1;
544
+ margin: 0;
545
+ letter-spacing: -.02em;
546
+ }
547
+
548
+ .ui-stat-change {
549
+ display: inline-flex;
550
+ align-items: center;
551
+ gap: .3rem;
552
+ font-size: .8rem;
553
+ font-weight: 600;
554
+ margin: 0;
555
+ }
556
+
557
+ .ui-stat-change--up { color: var(--ui-green); }
558
+ .ui-stat-change--down { color: var(--ui-red); }
559
+ .ui-stat-change--neutral { color: var(--ui-muted); }
560
+
561
+ .ui-stat--center { align-items: center; text-align: center; }
562
+ .ui-stat--center .ui-stat-change { margin-inline: auto; }
563
+
564
+ /* Stat sizes */
565
+ .ui-stat--sm .ui-stat-value { font-size: 1.25rem; letter-spacing: -.01em; }
566
+ .ui-stat--sm .ui-stat-label { font-size: .72rem; }
567
+ .ui-stat--lg .ui-stat-value { font-size: 3.5rem; letter-spacing: -.04em; line-height: .9; }
568
+ .ui-stat--lg .ui-stat-label { font-size: .9rem; }
569
+
570
+ /* ─── Avatar ─────────────────────────────────────────────────────────────── */
571
+ .ui-avatar {
572
+ display: inline-flex;
573
+ align-items: center;
574
+ justify-content: center;
575
+ border-radius: 50%;
576
+ overflow: hidden;
577
+ background: var(--ui-accent-dim);
578
+ color: var(--ui-accent);
579
+ font-family: var(--ui-font);
580
+ font-weight: 700;
581
+ flex-shrink: 0;
582
+ object-fit: cover;
583
+ }
584
+
585
+ .ui-avatar--sm { width: 28px; height: 28px; font-size: .65rem; }
586
+ .ui-avatar--md { width: 40px; height: 40px; font-size: .85rem; }
587
+ .ui-avatar--lg { width: 56px; height: 56px; font-size: 1.1rem; }
588
+ .ui-avatar--xl { width: 80px; height: 80px; font-size: 1.5rem; }
589
+
590
+ /* ─── Empty state ────────────────────────────────────────────────────────── */
591
+ .ui-empty {
592
+ display: flex;
593
+ flex-direction: column;
594
+ align-items: center;
595
+ text-align: center;
596
+ gap: .75rem;
597
+ padding: 3rem 1.5rem;
598
+ }
599
+
600
+ .ui-empty-title {
601
+ font-size: 1.05rem;
602
+ font-weight: 600;
603
+ color: var(--ui-text);
604
+ margin: 0;
605
+ }
606
+
607
+ .ui-empty-desc {
608
+ font-size: .88rem;
609
+ color: var(--ui-muted);
610
+ max-width: 36ch;
611
+ margin: 0;
612
+ line-height: 1.6;
613
+ }
614
+
615
+ /* ─── Table ──────────────────────────────────────────────────────────────── */
616
+ .ui-table-wrap {
617
+ overflow-x: auto;
618
+ border: 1px solid var(--ui-border);
619
+ border-radius: var(--ui-radius);
620
+ /* Explicit outline for keyboard-scrollable region */
621
+ }
622
+
623
+ .ui-table-wrap:focus-visible {
624
+ outline: 2px solid var(--ui-accent);
625
+ outline-offset: 2px;
626
+ }
627
+
628
+ .ui-table {
629
+ width: 100%;
630
+ border-collapse: collapse;
631
+ font-size: .88rem;
632
+ }
633
+
634
+ .ui-table-caption {
635
+ caption-side: top;
636
+ text-align: left;
637
+ padding: .75rem 1rem;
638
+ font-size: .8rem;
639
+ font-weight: 600;
640
+ color: var(--ui-muted);
641
+ text-transform: uppercase;
642
+ letter-spacing: .06em;
643
+ border-bottom: 1px solid var(--ui-border);
644
+ }
645
+
646
+ .ui-table thead th {
647
+ padding: .65rem 1rem;
648
+ text-align: left;
649
+ font-size: .78rem;
650
+ font-weight: 600;
651
+ color: var(--ui-muted);
652
+ text-transform: uppercase;
653
+ letter-spacing: .06em;
654
+ border-bottom: 1px solid var(--ui-border);
655
+ background: var(--ui-surface-2);
656
+ white-space: nowrap;
657
+ }
658
+
659
+ .ui-table tbody td {
660
+ padding: .75rem 1rem;
661
+ border-bottom: 1px solid var(--ui-border);
662
+ color: var(--ui-text);
663
+ vertical-align: top;
664
+ line-height: 1.5;
665
+ }
666
+
667
+ .ui-table tbody tr:last-child td { border-bottom: none; }
668
+
669
+ .ui-table tbody tr:nth-child(even) { background: var(--ui-surface-2); }
670
+
671
+ /* ─── Container ──────────────────────────────────────────────────────────── */
672
+ .ui-container { width: 100%; margin-left: auto; margin-right: auto; padding-left: 1.5rem; padding-right: 1.5rem; }
673
+ .ui-container--sm { max-width: 640px; }
674
+ .ui-container--md { max-width: 768px; }
675
+ .ui-container--lg { max-width: 1100px; }
676
+ .ui-container--xl { max-width: 1280px; }
677
+
678
+ /* ─── Section ────────────────────────────────────────────────────────────── */
679
+ .ui-section { padding-top: 5rem; padding-bottom: 5rem; }
680
+ .ui-section--sm { padding-top: 3rem; padding-bottom: 3rem; }
681
+ .ui-section--lg { padding-top: 7rem; padding-bottom: 7rem; }
682
+ .ui-section--alt { background: var(--ui-surface, var(--surface, #111116)); }
683
+ .ui-section--dark { background: var(--ui-surface-2, var(--surface-2, #18181f)); }
684
+
685
+ /* diagonal — tapered bottom edge; follow with a section that starts flush */
686
+ .ui-section--diagonal {
687
+ background: var(--ui-surface, var(--surface, #111116));
688
+ padding-bottom: calc(5rem + 3.5rem);
689
+ clip-path: polygon(0 0, 100% 0, 100% calc(100% - 3.5rem), 0 100%);
690
+ }
691
+ /* paper — subtle dot-grid texture on a raised surface */
692
+ .ui-section--paper {
693
+ position: relative;
694
+ background-color: var(--ui-surface, var(--surface, #111116));
695
+ background-image: radial-gradient(circle, var(--ui-border) 1px, transparent 0);
696
+ background-size: 22px 22px;
697
+ }
698
+ /* spotlight — accent glow from center top */
699
+ .ui-section--spotlight {
700
+ background: radial-gradient(ellipse 70% 60% at 50% 30%, var(--ui-accent-dim, rgba(155,141,255,.15)), var(--ui-surface, #111116) 80%);
701
+ }
702
+
703
+ /* ─── Grid ───────────────────────────────────────────────────────────────── */
704
+ .ui-grid { display: grid; gap: 2rem; }
705
+
706
+ .ui-grid--cols-1 { grid-template-columns: 1fr; }
707
+ .ui-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
708
+ .ui-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }
709
+ .ui-grid--cols-4 { grid-template-columns: repeat(4, 1fr); }
710
+
711
+ .ui-grid--gap-sm { gap: 1rem; }
712
+ .ui-grid--gap-lg { gap: 3rem; }
713
+
714
+ /* ─── Stack ──────────────────────────────────────────────────────────────── */
715
+ .ui-stack { display: flex; flex-direction: column; gap: 1rem; }
716
+
717
+ .ui-stack--gap-xs { gap: .25rem; }
718
+ .ui-stack--gap-sm { gap: .5rem; }
719
+ .ui-stack--gap-lg { gap: 2rem; }
720
+ .ui-stack--gap-xl { gap: 3rem; }
721
+
722
+ .ui-stack--align-start { align-items: flex-start; }
723
+ .ui-stack--align-center { align-items: center; }
724
+ .ui-stack--align-end { align-items: flex-end; }
725
+
726
+ /* ─── Cluster ────────────────────────────────────────────────────────────── */
727
+ .ui-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; }
728
+
729
+ .ui-cluster--gap-xs { gap: .25rem; }
730
+ .ui-cluster--gap-sm { gap: .5rem; }
731
+ .ui-cluster--gap-lg { gap: 2rem; }
732
+
733
+ .ui-cluster--justify-center { justify-content: center; }
734
+ .ui-cluster--justify-end { justify-content: flex-end; }
735
+ .ui-cluster--justify-between { justify-content: space-between; }
736
+
737
+ .ui-cluster--align-start { align-items: flex-start; }
738
+ .ui-cluster--align-end { align-items: flex-end; }
739
+
740
+ .ui-cluster--nowrap { flex-wrap: nowrap; }
741
+
742
+ /* ─── Divider ────────────────────────────────────────────────────────────── */
743
+ hr.ui-divider {
744
+ border: none;
745
+ border-top: 1px solid var(--ui-border, var(--border, #222228));
746
+ margin: 0;
747
+ }
748
+
749
+ .ui-divider--label {
750
+ display: flex;
751
+ align-items: center;
752
+ gap: .75rem;
753
+ }
754
+
755
+ .ui-divider-line {
756
+ flex: 1;
757
+ height: 1px;
758
+ background: var(--ui-border, var(--border, #222228));
759
+ display: block;
760
+ }
761
+
762
+ .ui-divider-text {
763
+ font-size: .8rem;
764
+ color: var(--ui-muted, var(--muted, #9090a0));
765
+ white-space: nowrap;
766
+ flex-shrink: 0;
767
+ }
768
+
769
+ /* ─── Banner ─────────────────────────────────────────────────────────────── */
770
+ .ui-banner {
771
+ padding: .625rem 1.5rem;
772
+ text-align: center;
773
+ font-size: .875rem;
774
+ font-weight: 500;
775
+ line-height: 1.5;
776
+ }
777
+
778
+ .ui-banner--info {
779
+ background: var(--ui-accent-dim, rgba(155,141,255,.12));
780
+ color: var(--ui-accent, var(--accent, #9b8dff));
781
+ }
782
+
783
+ .ui-banner--promo {
784
+ background: var(--ui-accent, var(--accent, #9b8dff));
785
+ color: #fff;
786
+ }
787
+
788
+ .ui-banner--warning {
789
+ background: rgba(255, 193, 7, .12);
790
+ color: #ffc107;
791
+ }
792
+
793
+ .ui-banner--bottom {
794
+ position: fixed;
795
+ bottom: 0;
796
+ left: 0;
797
+ right: 0;
798
+ z-index: 200;
799
+ display: flex;
800
+ align-items: center;
801
+ justify-content: center;
802
+ gap: 1rem;
803
+ }
804
+
805
+ .ui-banner-close {
806
+ position: absolute;
807
+ right: 1rem;
808
+ top: 50%;
809
+ transform: translateY(-50%);
810
+ background: none;
811
+ border: none;
812
+ cursor: pointer;
813
+ color: inherit;
814
+ font-size: 1.1rem;
815
+ line-height: 1;
816
+ padding: 0.25rem 0.5rem;
817
+ opacity: 0.7;
818
+ transition: opacity 0.15s;
819
+ }
820
+ .ui-banner-close:hover { opacity: 1; }
821
+
822
+ /* ─── Media ──────────────────────────────────────────────────────────────── */
823
+ .ui-media {
824
+ display: grid;
825
+ grid-template-columns: 1fr 1fr;
826
+ gap: 3rem;
827
+ align-items: center;
828
+ }
829
+
830
+ .ui-media--reverse { direction: rtl; }
831
+ .ui-media--reverse > * { direction: ltr; }
832
+
833
+ .ui-media--align-start { align-items: flex-start; }
834
+
835
+ .ui-media--gap-sm { gap: 1.5rem; }
836
+ .ui-media--gap-lg { gap: 5rem; }
837
+
838
+ .ui-media-image { min-width: 0; }
839
+ .ui-media-content { min-width: 0; }
840
+
841
+ .ui-media-image img {
842
+ width: 100%;
843
+ height: auto;
844
+ border-radius: var(--ui-radius, 8px);
845
+ display: block;
846
+ }
847
+
848
+ /* ─── Hero ───────────────────────────────────────────────────────────────── */
849
+ .ui-hero { padding: 5rem 1.5rem; text-align: center; }
850
+ .ui-hero--left { text-align: left; }
851
+ .ui-hero--sm { padding-top: 2.5rem; padding-bottom: 0; }
852
+ .ui-hero--gradient,
853
+ .ui-hero--gradient--purple {
854
+ background:
855
+ radial-gradient(ellipse 70% 80% at 75% 50%, #2d1b6e 0%, #1a0f45 45%, transparent 75%),
856
+ radial-gradient(ellipse 60% 60% at 20% 80%, #1c1060 0%, transparent 65%),
857
+ #0d0a1e;
858
+ }
859
+
860
+ .ui-hero--gradient--blue {
861
+ background:
862
+ radial-gradient(ellipse 70% 80% at 75% 50%, #0e2d6b 0%, #071840 45%, transparent 75%),
863
+ radial-gradient(ellipse 60% 60% at 20% 80%, #0a1f5c 0%, transparent 65%),
864
+ #060d1e;
865
+ }
866
+
867
+ .ui-hero--gradient--green {
868
+ background:
869
+ radial-gradient(ellipse 70% 80% at 75% 50%, #0d3d28 0%, #052218 45%, transparent 75%),
870
+ radial-gradient(ellipse 60% 60% at 20% 80%, #083020 0%, transparent 65%),
871
+ #020e09;
872
+ }
873
+
874
+ .ui-hero--gradient--rose {
875
+ background:
876
+ radial-gradient(ellipse 70% 80% at 75% 50%, #6b0e35 0%, #400720 45%, transparent 75%),
877
+ radial-gradient(ellipse 60% 60% at 20% 80%, #5c0a2a 0%, transparent 65%),
878
+ #1e0610;
879
+ }
880
+
881
+ .ui-hero--gradient--orange {
882
+ background:
883
+ radial-gradient(ellipse 70% 80% at 75% 50%, #6b2e0e 0%, #401807 45%, transparent 75%),
884
+ radial-gradient(ellipse 60% 60% at 20% 80%, #5c2208 0%, transparent 65%),
885
+ #1e0e04;
886
+ }
887
+
888
+ .ui-hero-inner { max-width: 720px; margin: 0 auto; }
889
+ .ui-hero--left .ui-hero-inner { margin: 0; }
890
+
891
+ .ui-hero-eyebrow {
892
+ font-size: .78rem;
893
+ font-weight: 600;
894
+ letter-spacing: .08em;
895
+ text-transform: uppercase;
896
+ color: var(--ui-accent, var(--accent, #9b8dff));
897
+ margin: 0 0 .75rem;
898
+ }
899
+
900
+ .ui-hero-title {
901
+ font-size: clamp(2.2rem, 6vw, 3.5rem);
902
+ font-weight: 800;
903
+ line-height: 1.1;
904
+ letter-spacing: var(--ui-letter-spacing-display, -.02em);
905
+ font-family: var(--ui-font-display, var(--ui-font));
906
+ color: var(--ui-text, var(--text, #e2e2ea));
907
+ margin: 0 0 1.25rem;
908
+ }
909
+
910
+ .ui-hero-subtitle {
911
+ font-size: 1.125rem;
912
+ color: var(--ui-muted, var(--muted, #9090a0));
913
+ line-height: 1.65;
914
+ margin: 0 0 2rem;
915
+ }
916
+
917
+ .ui-hero-actions {
918
+ display: flex;
919
+ gap: .75rem;
920
+ flex-wrap: wrap;
921
+ justify-content: center;
922
+ }
923
+ .ui-hero--left .ui-hero-actions { justify-content: flex-start; }
924
+
925
+ /* Split (text + image, 50/50) */
926
+ .ui-hero--split { text-align: left; }
927
+ .ui-hero--split .ui-hero-inner {
928
+ max-width: 1100px;
929
+ margin: 0 auto;
930
+ display: grid;
931
+ grid-template-columns: 1fr 1fr;
932
+ gap: 3rem;
933
+ align-items: center;
934
+ }
935
+ .ui-hero--split .ui-hero-actions { justify-content: flex-start; }
936
+ .ui-hero--split .ui-hero-media { display: flex; align-items: center; justify-content: center; }
937
+ .ui-hero--split .ui-hero-media img { width: 100%; height: auto; border-radius: var(--ui-radius, 8px); display: block; }
938
+ .ui-hero--media-left .ui-hero-media { order: -1; }
939
+
940
+ /* Asymmetric (text 60%, image 40%) */
941
+ .ui-hero--asymmetric { text-align: left; }
942
+ .ui-hero--asymmetric .ui-hero-inner {
943
+ max-width: 1100px;
944
+ margin: 0 auto;
945
+ display: grid;
946
+ grid-template-columns: 3fr 2fr;
947
+ gap: 3rem;
948
+ align-items: center;
949
+ }
950
+ .ui-hero--asymmetric .ui-hero-actions { justify-content: flex-start; }
951
+ .ui-hero--asymmetric .ui-hero-media { display: flex; align-items: center; justify-content: center; }
952
+ .ui-hero--asymmetric .ui-hero-media img { width: 100%; height: auto; border-radius: var(--ui-radius, 8px); display: block; }
953
+ .ui-hero--asymmetric.ui-hero--media-left .ui-hero-media { order: -1; }
954
+ .ui-hero--asymmetric.ui-hero--media-left .ui-hero-inner { grid-template-columns: 2fr 3fr; }
955
+
956
+ /* Overlap (image fills section, text overlaid) */
957
+ .ui-hero--overlap {
958
+ position: relative;
959
+ min-height: 60vh;
960
+ overflow: hidden;
961
+ padding: 0;
962
+ display: flex;
963
+ align-items: flex-end;
964
+ text-align: left;
965
+ }
966
+ .ui-hero--overlap .ui-hero-overlap-media {
967
+ position: absolute;
968
+ inset: 0;
969
+ z-index: 0;
970
+ }
971
+ .ui-hero--overlap .ui-hero-overlap-media img,
972
+ .ui-hero--overlap .ui-hero-overlap-media video {
973
+ width: 100%;
974
+ height: 100%;
975
+ object-fit: cover;
976
+ display: block;
977
+ }
978
+ .ui-hero--overlap .ui-hero-inner {
979
+ position: relative;
980
+ z-index: 1;
981
+ width: 100%;
982
+ max-width: none;
983
+ padding: 4rem 2rem;
984
+ background: linear-gradient(to top, rgba(0,0,0,.75) 0%, rgba(0,0,0,.3) 60%, transparent 100%);
985
+ }
986
+ .ui-hero--overlap .ui-hero-content { max-width: 600px; }
987
+ .ui-hero--overlap .ui-hero-eyebrow { color: rgba(255,255,255,.75); }
988
+ .ui-hero--overlap .ui-hero-title { color: #fff; text-shadow: 0 2px 8px rgba(0,0,0,.4); }
989
+ .ui-hero--overlap .ui-hero-subtitle{ color: rgba(255,255,255,.8); }
990
+ .ui-hero--overlap .ui-hero-actions { justify-content: flex-start; }
991
+
992
+ /* ─── Testimonial ────────────────────────────────────────────────────────── */
993
+ .ui-testimonial {
994
+ background: var(--ui-surface, var(--surface, #111116));
995
+ border: 1px solid var(--ui-border, var(--border, #222228));
996
+ border-radius: var(--ui-radius, 8px);
997
+ padding: 1.5rem;
998
+ margin: 0;
999
+ }
1000
+
1001
+ .ui-testimonial-rating {
1002
+ color: #f5a623;
1003
+ font-size: 1rem;
1004
+ letter-spacing: .1em;
1005
+ margin: 0 0 .75rem;
1006
+ }
1007
+
1008
+ .ui-testimonial-quote { margin: 0 0 1.25rem; }
1009
+ .ui-testimonial-quote p {
1010
+ font-size: .95rem;
1011
+ line-height: 1.65;
1012
+ color: var(--ui-text, var(--text, #e2e2ea));
1013
+ font-style: italic;
1014
+ margin: 0;
1015
+ }
1016
+
1017
+ .ui-testimonial-author { display: flex; align-items: center; gap: .75rem; }
1018
+
1019
+ .ui-testimonial-avatar {
1020
+ width: 40px;
1021
+ height: 40px;
1022
+ border-radius: 50%;
1023
+ object-fit: cover;
1024
+ flex-shrink: 0;
1025
+ }
1026
+
1027
+ .ui-testimonial-avatar--initials {
1028
+ background: var(--ui-muted-bg, rgba(128,128,128,.2));
1029
+ color: var(--ui-text, var(--text, #e2e2ea));
1030
+ font-size: .8rem;
1031
+ font-weight: 700;
1032
+ display: flex;
1033
+ align-items: center;
1034
+ justify-content: center;
1035
+ }
1036
+
1037
+ .ui-testimonial-meta { display: flex; flex-direction: column; gap: .1rem; }
1038
+ .ui-testimonial-name { font-size: .875rem; font-weight: 600; color: var(--ui-text, var(--text, #e2e2ea)); margin: 0; }
1039
+ .ui-testimonial-role { font-size: .78rem; color: var(--ui-muted, var(--muted, #9090a0)); margin: 0; }
1040
+
1041
+ /* ─── Feature ────────────────────────────────────────────────────────────── */
1042
+ .ui-feature { display: flex; flex-direction: column; gap: .75rem; }
1043
+ .ui-feature-image { width: 100%; border-radius: var(--ui-radius-sm); overflow: hidden; }
1044
+ .ui-feature-image img { width: 100%; height: auto; display: block; }
1045
+
1046
+ .ui-feature-icon {
1047
+ display: block;
1048
+ flex-shrink: 0;
1049
+ line-height: 1;
1050
+ }
1051
+
1052
+ .ui-feature-title { font-size: 1rem; font-weight: 600; color: var(--ui-text, var(--text, #e2e2ea)); margin: 0; }
1053
+ .ui-feature-desc { font-size: .9rem; color: var(--ui-muted, var(--muted, #9090a0)); line-height: 1.6; margin: 0; }
1054
+
1055
+ .ui-feature--center { align-items: center; text-align: center; }
1056
+
1057
+ /* ─── Pricing ────────────────────────────────────────────────────────────── */
1058
+ .ui-pricing {
1059
+ box-sizing: border-box;
1060
+ background: var(--ui-surface, var(--surface, #111116));
1061
+ border: 1px solid var(--ui-border, var(--border, #222228));
1062
+ border-radius: var(--ui-radius, 8px);
1063
+ padding: 2rem;
1064
+ display: flex;
1065
+ flex-direction: column;
1066
+ gap: 1.25rem;
1067
+ position: relative;
1068
+ width: 100%;
1069
+ }
1070
+
1071
+ .ui-pricing--highlighted {
1072
+ border-color: var(--ui-accent, var(--accent, #9b8dff));
1073
+ box-shadow: 0 0 0 1px var(--ui-accent, var(--accent, #9b8dff));
1074
+ }
1075
+
1076
+ .ui-pricing-badge {
1077
+ position: absolute;
1078
+ top: -12px;
1079
+ left: 50%;
1080
+ transform: translateX(-50%);
1081
+ background: var(--ui-accent, var(--accent, #9b8dff));
1082
+ color: var(--ui-accent-text, #0d0a20);
1083
+ font-size: .72rem;
1084
+ font-weight: 700;
1085
+ letter-spacing: .05em;
1086
+ text-transform: uppercase;
1087
+ padding: .25rem .75rem;
1088
+ border-radius: 99px;
1089
+ margin: 0;
1090
+ white-space: nowrap;
1091
+ }
1092
+
1093
+ .ui-pricing-header { display: flex; flex-direction: column; gap: .25rem; }
1094
+ .ui-pricing-name { font-size: 1.1rem; font-weight: 700; color: var(--ui-text, var(--text, #e2e2ea)); margin: 0; }
1095
+ .ui-pricing-desc { font-size: .875rem; color: var(--ui-muted, var(--muted, #9090a0)); margin: 0; }
1096
+
1097
+ .ui-pricing-price { display: flex; align-items: baseline; gap: .3rem; }
1098
+ .ui-pricing-amount { font-size: 2.25rem; font-weight: 800; color: var(--ui-text, var(--text, #e2e2ea)); line-height: 1; letter-spacing: -.02em; }
1099
+ .ui-pricing-period { font-size: .875rem; color: var(--ui-muted, var(--muted, #9090a0)); }
1100
+
1101
+ .ui-pricing-features { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: .6rem; }
1102
+ .ui-pricing-feature { font-size: .875rem; color: var(--ui-text, var(--text, #e2e2ea)); display: flex; align-items: flex-start; gap: .5rem; width: 100%; }
1103
+ .ui-pricing-check { color: var(--ui-green, var(--green, #3dd68c)); font-weight: 700; flex-shrink: 0; }
1104
+
1105
+ /* ─── Pricing grid (responsive) ─────────────────────────────────────────── */
1106
+ .ui-pricing-grid {
1107
+ display: grid;
1108
+ gap: 1.5rem;
1109
+ align-items: start;
1110
+ grid-template-columns: 1fr;
1111
+ width: 100%;
1112
+ }
1113
+ @media (min-width: 640px) {
1114
+ .ui-pricing-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
1115
+ .ui-pricing-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }
1116
+ }
1117
+ .ui-pricing-action { margin-top: auto; }
1118
+
1119
+ /* ─── Accordion ──────────────────────────────────────────────────────────── */
1120
+ .ui-accordion { display: flex; flex-direction: column; gap: .5rem; width: 100%; }
1121
+
1122
+ .ui-accordion-item {
1123
+ background: var(--ui-surface, var(--surface, #111116));
1124
+ border: 1px solid var(--ui-border, var(--border, #222228));
1125
+ border-radius: var(--ui-radius, 8px);
1126
+ overflow: hidden;
1127
+ }
1128
+
1129
+ .ui-accordion-summary {
1130
+ display: flex;
1131
+ justify-content: space-between;
1132
+ align-items: center;
1133
+ padding: 1rem 1.25rem;
1134
+ cursor: pointer;
1135
+ font-size: .95rem;
1136
+ font-weight: 500;
1137
+ color: var(--ui-text, var(--text, #e2e2ea));
1138
+ list-style: none;
1139
+ user-select: none;
1140
+ gap: 1rem;
1141
+ }
1142
+ .ui-accordion-summary::-webkit-details-marker { display: none; }
1143
+ .ui-accordion-summary:hover { color: var(--ui-accent, var(--accent, #9b8dff)); }
1144
+
1145
+ .ui-accordion-icon {
1146
+ width: 16px;
1147
+ height: 16px;
1148
+ position: relative;
1149
+ flex-shrink: 0;
1150
+ }
1151
+ .ui-accordion-icon::before,
1152
+ .ui-accordion-icon::after {
1153
+ content: '';
1154
+ position: absolute;
1155
+ background: currentColor;
1156
+ border-radius: 2px;
1157
+ transition: transform .2s;
1158
+ }
1159
+ .ui-accordion-icon::before { width: 10px; height: 1.5px; top: 7px; left: 3px; }
1160
+ .ui-accordion-icon::after { width: 1.5px; height: 10px; top: 3px; left: 7px; }
1161
+ .ui-accordion-item[open] .ui-accordion-icon::after { transform: rotate(90deg); }
1162
+
1163
+ .ui-accordion-body { padding: 0 1.25rem 1rem; }
1164
+ .ui-accordion-body p { font-size: .9rem; color: var(--ui-muted, var(--muted, #9090a0)); line-height: 1.7; margin: 0; }
1165
+
1166
+ /* ─── Tooltip ────────────────────────────────────────────────────────────── */
1167
+ .ui-tooltip {
1168
+ position: relative;
1169
+ display: inline-block;
1170
+ }
1171
+
1172
+ .ui-tooltip::after {
1173
+ content: attr(data-tip);
1174
+ position: absolute;
1175
+ bottom: calc(100% + 8px);
1176
+ left: 50%;
1177
+ transform: translateX(-50%) translateY(4px);
1178
+ background: var(--ui-surface-2, var(--surface-2, #1a1a26));
1179
+ color: var(--ui-text, var(--text, #e2e2ea));
1180
+ font-size: .78rem;
1181
+ font-weight: 500;
1182
+ line-height: 1.4;
1183
+ white-space: nowrap;
1184
+ padding: .35rem .7rem;
1185
+ border-radius: 6px;
1186
+ border: 1px solid var(--ui-border, var(--border, #2a2a38));
1187
+ pointer-events: none;
1188
+ opacity: 0;
1189
+ transition: opacity .15s, transform .15s;
1190
+ z-index: var(--ui-z-tooltip, 200);
1191
+ }
1192
+
1193
+ .ui-tooltip::before {
1194
+ content: '';
1195
+ position: absolute;
1196
+ bottom: calc(100% + 2px);
1197
+ left: 50%;
1198
+ transform: translateX(-50%);
1199
+ border: 5px solid transparent;
1200
+ border-top-color: var(--ui-border, var(--border, #2a2a38));
1201
+ pointer-events: none;
1202
+ opacity: 0;
1203
+ transition: opacity .15s;
1204
+ z-index: var(--ui-z-tooltip, 200);
1205
+ }
1206
+
1207
+ .ui-tooltip:hover::after,
1208
+ .ui-tooltip:focus-within::after {
1209
+ opacity: 1;
1210
+ transform: translateX(-50%) translateY(0);
1211
+ }
1212
+ .ui-tooltip:hover::before,
1213
+ .ui-tooltip:focus-within::before { opacity: 1; }
1214
+
1215
+ /* bottom */
1216
+ .ui-tooltip--bottom::after { bottom: auto; top: calc(100% + 8px); transform: translateX(-50%) translateY(-4px); }
1217
+ .ui-tooltip--bottom::before { bottom: auto; top: calc(100% + 2px); border-top-color: transparent; border-bottom-color: var(--ui-border, var(--border, #2a2a38)); }
1218
+ .ui-tooltip--bottom:hover::after,
1219
+ .ui-tooltip--bottom:focus-within::after { transform: translateX(-50%) translateY(0); }
1220
+
1221
+ /* left */
1222
+ .ui-tooltip--left::after { bottom: auto; top: 50%; left: auto; right: calc(100% + 8px); transform: translateY(-50%) translateX(4px); }
1223
+ .ui-tooltip--left::before { bottom: auto; top: 50%; left: auto; right: calc(100% + 2px); transform: translateY(-50%); border-top-color: transparent; border-left-color: var(--ui-border, var(--border, #2a2a38)); }
1224
+ .ui-tooltip--left:hover::after,
1225
+ .ui-tooltip--left:focus-within::after { transform: translateY(-50%) translateX(0); }
1226
+
1227
+ /* right */
1228
+ .ui-tooltip--right::after { bottom: auto; top: 50%; left: calc(100% + 8px); transform: translateY(-50%) translateX(-4px); }
1229
+ .ui-tooltip--right::before { bottom: auto; top: 50%; left: calc(100% + 2px); transform: translateY(-50%); border-top-color: transparent; border-right-color: var(--ui-border, var(--border, #2a2a38)); }
1230
+ .ui-tooltip--right:hover::after,
1231
+ .ui-tooltip--right:focus-within::after { transform: translateY(-50%) translateX(0); }
1232
+
1233
+ /* ─── Modal ──────────────────────────────────────────────────────────────── */
1234
+ .ui-modal {
1235
+ position: fixed;
1236
+ inset: 0;
1237
+ margin: auto;
1238
+ width: min(560px, calc(100vw - 2rem));
1239
+ max-height: min(80vh, calc(100dvh - 2rem));
1240
+ padding: 0;
1241
+ background: var(--ui-surface, var(--surface, #13131e));
1242
+ border: 1px solid var(--ui-border, var(--border, #2a2a38));
1243
+ border-radius: var(--ui-radius, 12px);
1244
+ overflow: hidden;
1245
+ box-shadow: 0 20px 60px rgba(0, 0, 0, .5);
1246
+ }
1247
+
1248
+ .ui-modal--sm { width: min(400px, calc(100vw - 2rem)); }
1249
+ .ui-modal--lg { width: min(760px, calc(100vw - 2rem)); }
1250
+ .ui-modal--xl { width: min(1000px, calc(100vw - 2rem)); }
1251
+
1252
+ .ui-modal::backdrop {
1253
+ background: rgba(0, 0, 0, .6);
1254
+ backdrop-filter: blur(2px);
1255
+ }
1256
+
1257
+ .ui-modal-inner {
1258
+ display: flex;
1259
+ flex-direction: column;
1260
+ max-height: inherit;
1261
+ margin: 0;
1262
+ border: none;
1263
+ padding: 0;
1264
+ background: transparent;
1265
+ }
1266
+
1267
+ .ui-modal-header {
1268
+ display: flex;
1269
+ align-items: center;
1270
+ gap: 1rem;
1271
+ padding: 1.25rem 1.5rem;
1272
+ border-bottom: 1px solid var(--ui-border, var(--border, #2a2a38));
1273
+ flex-shrink: 0;
1274
+ }
1275
+
1276
+ .ui-modal-title {
1277
+ flex: 1;
1278
+ font-size: 1.1rem;
1279
+ font-weight: 700;
1280
+ color: var(--ui-text, var(--text, #e2e2ea));
1281
+ margin: 0;
1282
+ }
1283
+
1284
+ .ui-modal-close {
1285
+ display: flex;
1286
+ align-items: center;
1287
+ justify-content: center;
1288
+ width: 32px;
1289
+ height: 32px;
1290
+ padding: 0;
1291
+ background: transparent;
1292
+ border: none;
1293
+ border-radius: 6px;
1294
+ color: var(--ui-muted, var(--muted, #9090a0));
1295
+ cursor: pointer;
1296
+ transition: color .15s, background .15s;
1297
+ flex-shrink: 0;
1298
+ }
1299
+ .ui-modal-close:hover {
1300
+ color: var(--ui-text, var(--text, #e2e2ea));
1301
+ background: var(--ui-surface-2, var(--surface-2, #1a1a26));
1302
+ }
1303
+
1304
+ .ui-modal-body {
1305
+ flex: 1;
1306
+ overflow-y: auto;
1307
+ padding: 1.5rem;
1308
+ color: var(--ui-text, var(--text, #e2e2ea));
1309
+ }
1310
+
1311
+ .ui-modal-footer {
1312
+ display: flex;
1313
+ align-items: center;
1314
+ justify-content: flex-end;
1315
+ gap: .75rem;
1316
+ padding: 1rem 1.5rem;
1317
+ border-top: 1px solid var(--ui-border, var(--border, #2a2a38));
1318
+ flex-shrink: 0;
1319
+ }
1320
+
1321
+ /* ─── Carousel ───────────────────────────────────────────────────────────── */
1322
+ .ui-carousel {
1323
+ position: relative;
1324
+ width: 100%;
1325
+ border-radius: var(--ui-radius, 12px);
1326
+ overflow: hidden;
1327
+ }
1328
+
1329
+ .ui-carousel-track {
1330
+ display: flex;
1331
+ overflow-x: auto;
1332
+ scroll-snap-type: x mandatory;
1333
+ scroll-behavior: smooth;
1334
+ -webkit-overflow-scrolling: touch;
1335
+ scrollbar-width: none;
1336
+ }
1337
+ .ui-carousel-track::-webkit-scrollbar { display: none; }
1338
+
1339
+ .ui-carousel-slide {
1340
+ flex: 0 0 100%;
1341
+ scroll-snap-align: start;
1342
+ }
1343
+
1344
+ .ui-carousel-btn {
1345
+ position: absolute;
1346
+ top: 50%;
1347
+ transform: translateY(-50%);
1348
+ z-index: 2;
1349
+ display: flex;
1350
+ align-items: center;
1351
+ justify-content: center;
1352
+ width: 40px;
1353
+ height: 40px;
1354
+ padding: 0;
1355
+ background: var(--ui-surface, var(--surface, #13131e));
1356
+ border: 1px solid var(--ui-border, var(--border, #2a2a38));
1357
+ border-radius: 50%;
1358
+ color: var(--ui-text, var(--text, #e2e2ea));
1359
+ cursor: pointer;
1360
+ transition: background .15s, opacity .15s;
1361
+ }
1362
+ .ui-carousel-btn:hover { background: var(--ui-surface-2, var(--surface-2, #1a1a26)); }
1363
+ .ui-carousel-btn[hidden] { display: none; }
1364
+ .ui-carousel-prev { left: .75rem; }
1365
+ .ui-carousel-next { right: .75rem; }
1366
+
1367
+ .ui-carousel-dots {
1368
+ display: flex;
1369
+ justify-content: center;
1370
+ gap: .5rem;
1371
+ padding: .75rem 0 .5rem;
1372
+ }
1373
+
1374
+ .ui-carousel-dot {
1375
+ width: 8px;
1376
+ height: 8px;
1377
+ padding: 0;
1378
+ background: var(--ui-border, var(--border, #2a2a38));
1379
+ border: none;
1380
+ border-radius: 50%;
1381
+ cursor: pointer;
1382
+ transition: background .15s, transform .15s;
1383
+ }
1384
+ .ui-carousel-dot.active,
1385
+ .ui-carousel-dot:hover { background: var(--ui-accent, var(--accent, #9b8dff)); }
1386
+ .ui-carousel-dot.active { transform: scale(1.35); }
1387
+
1388
+ /* ─── Nav ────────────────────────────────────────────────────────────────── */
1389
+ .ui-nav {
1390
+ position: relative;
1391
+ background: var(--ui-bg, var(--bg, #0d0d10));
1392
+ border-bottom: 1px solid var(--ui-border, var(--border, #222228));
1393
+ padding-inline: 1.5rem;
1394
+ }
1395
+
1396
+ .ui-nav--sticky {
1397
+ position: sticky;
1398
+ top: 0;
1399
+ z-index: 100;
1400
+ backdrop-filter: blur(12px);
1401
+ -webkit-backdrop-filter: blur(12px);
1402
+ background: var(--ui-nav-sticky-bg, rgba(13, 13, 16, .85));
1403
+ }
1404
+
1405
+ .ui-nav-inner {
1406
+ max-width: 1100px;
1407
+ margin: 0 auto;
1408
+ padding: .875rem 0;
1409
+ display: flex;
1410
+ align-items: center;
1411
+ gap: 2rem;
1412
+ }
1413
+
1414
+ .ui-nav-logo {
1415
+ font-size: 1rem;
1416
+ font-weight: 700;
1417
+ color: var(--ui-text, var(--text, #e2e2ea));
1418
+ text-decoration: none;
1419
+ display: flex;
1420
+ align-items: center;
1421
+ gap: .5rem;
1422
+ flex-shrink: 0;
1423
+ }
1424
+ .ui-nav-logo:hover { color: var(--ui-accent, var(--accent, #9b8dff)); }
1425
+
1426
+ .ui-nav-links { display: flex; gap: 1.5rem; align-items: center; flex: 1; }
1427
+ .ui-nav-utility { flex: 0; margin-left: auto; }
1428
+
1429
+ .ui-nav-link {
1430
+ font-size: .875rem;
1431
+ color: var(--ui-muted, var(--muted, #9090a0));
1432
+ text-decoration: none;
1433
+ transition: color .15s;
1434
+ min-height: 44px;
1435
+ display: flex;
1436
+ align-items: center;
1437
+ }
1438
+ .ui-nav-link:hover { color: var(--ui-text, var(--text, #e2e2ea)); }
1439
+
1440
+ .ui-nav-action { margin-left: auto; }
1441
+
1442
+ .ui-nav--burger-left .ui-nav-burger { order: -1; margin-left: 0; margin-right: auto; }
1443
+
1444
+ .ui-nav-burger {
1445
+ display: none;
1446
+ margin-left: auto;
1447
+ padding: .35rem;
1448
+ background: none;
1449
+ border: none;
1450
+ color: var(--ui-text, var(--text, #e2e2ea));
1451
+ cursor: pointer;
1452
+ align-items: center;
1453
+ justify-content: center;
1454
+ border-radius: var(--ui-radius-sm, 6px);
1455
+ transition: background .15s;
1456
+ }
1457
+ .ui-nav-burger:hover { background: var(--ui-surface, var(--surface, #111116)); }
1458
+ .ui-nav-burger-close { display: none; }
1459
+ .ui-nav--open .ui-nav-burger-open { display: none; }
1460
+ .ui-nav--open .ui-nav-burger-close { display: block; }
1461
+
1462
+ .ui-nav-mobile {
1463
+ display: none;
1464
+ position: absolute;
1465
+ top: 100%;
1466
+ left: 0;
1467
+ right: 0;
1468
+ z-index: 99;
1469
+ background: var(--ui-bg, var(--bg, #0d0d10));
1470
+ border-bottom: 1px solid var(--ui-border, var(--border, #222228));
1471
+ padding: 1rem 1.5rem;
1472
+ flex-direction: column;
1473
+ gap: .25rem;
1474
+ }
1475
+ .ui-nav--open .ui-nav-mobile { display: flex; }
1476
+
1477
+ .ui-nav-mobile nav {
1478
+ display: flex;
1479
+ flex-direction: column;
1480
+ }
1481
+ .ui-nav-mobile .ui-nav-link {
1482
+ padding: .6rem 0;
1483
+ border-bottom: 1px solid var(--ui-border, var(--border, #222228));
1484
+ }
1485
+ .ui-nav-mobile .ui-nav-link:last-child { border-bottom: none; }
1486
+ .ui-nav-mobile-action { padding-top: .75rem; }
1487
+ .ui-nav-mobile-section {
1488
+ font-size: .7rem;
1489
+ font-weight: 600;
1490
+ text-transform: uppercase;
1491
+ letter-spacing: .08em;
1492
+ color: var(--ui-muted, var(--muted, #6b6b80));
1493
+ margin: .75rem 0 .25rem;
1494
+ padding: 0;
1495
+ }
1496
+
1497
+ /* ─── Mega nav ───────────────────────────────────────────────────────────── */
1498
+ .ui-nav-mega-wrap { position: relative; }
1499
+
1500
+ .ui-nav-mega-trigger {
1501
+ background: none;
1502
+ border: none;
1503
+ cursor: pointer;
1504
+ display: inline-flex;
1505
+ align-items: center;
1506
+ gap: .3rem;
1507
+ padding: 0;
1508
+ font: inherit;
1509
+ font-size: .875rem;
1510
+ }
1511
+
1512
+ .ui-nav-mega-chevron { transition: transform .2s ease; flex-shrink: 0; }
1513
+ .ui-nav-mega-wrap--open .ui-nav-mega-chevron { transform: rotate(180deg); }
1514
+
1515
+ .ui-nav-mega-panel {
1516
+ position: absolute;
1517
+ top: calc(100% + .875rem);
1518
+ left: 50%;
1519
+ transform: translateX(-50%);
1520
+ background: var(--ui-bg, var(--bg, #0d0d10));
1521
+ border: 1px solid var(--ui-border, var(--border, #232329));
1522
+ border-radius: var(--ui-radius, 8px);
1523
+ box-shadow: 0 8px 40px rgba(0,0,0,.35);
1524
+ padding: 1.5rem;
1525
+ z-index: 200;
1526
+ min-width: 360px;
1527
+ }
1528
+ .ui-nav-mega-panel[hidden] { display: none !important; }
1529
+
1530
+ .ui-nav-mega-inner { display: flex; gap: 2rem; }
1531
+
1532
+ .ui-nav-mega-col { flex: 1; min-width: 140px; }
1533
+
1534
+ .ui-nav-mega-heading {
1535
+ font-size: .7rem;
1536
+ font-weight: 600;
1537
+ text-transform: uppercase;
1538
+ letter-spacing: .08em;
1539
+ color: var(--ui-muted, var(--muted, #6b6b80));
1540
+ margin: 0 0 .5rem;
1541
+ padding: 0 .5rem;
1542
+ }
1543
+
1544
+ .ui-nav-mega-item {
1545
+ display: flex;
1546
+ flex-direction: column;
1547
+ gap: .15rem;
1548
+ padding: .5rem;
1549
+ border-radius: calc(var(--ui-radius, 8px) * .65);
1550
+ transition: background .15s;
1551
+ }
1552
+ .ui-nav-mega-item:hover { background: var(--ui-surface, var(--surface, #111116)); }
1553
+ .ui-nav-mega-item-label {
1554
+ font-size: .875rem;
1555
+ font-weight: 500;
1556
+ color: var(--ui-text, var(--text, #e2e2ea));
1557
+ text-decoration: none;
1558
+ }
1559
+ .ui-nav-mega-item-label:hover { color: var(--ui-accent, var(--accent, #9b8dff)); }
1560
+ .ui-nav-mega-item-desc { font-size: .75rem; color: var(--ui-muted, var(--muted, #6b6b80)); }
1561
+
1562
+ [data-theme="light"] .ui-nav-mega-panel { box-shadow: 0 8px 40px rgba(0,0,0,.12); }
1563
+
1564
+ /* ─── App Badge ──────────────────────────────────────────────────────────── */
1565
+ .ui-app-badge {
1566
+ display: inline-flex;
1567
+ align-items: center;
1568
+ gap: .625rem;
1569
+ background: var(--ui-text, var(--text, #e2e2ea));
1570
+ color: var(--ui-bg, var(--bg, #0d0d10));
1571
+ border-radius: 10px;
1572
+ padding: .625rem 1.25rem;
1573
+ text-decoration: none;
1574
+ transition: opacity .15s;
1575
+ min-width: 148px;
1576
+ }
1577
+ .ui-app-badge:hover { opacity: .85; }
1578
+
1579
+ .ui-app-badge-text { display: flex; flex-direction: column; gap: .05rem; }
1580
+ .ui-app-badge-line1 { font-size: .65rem; font-weight: 400; line-height: 1; }
1581
+ .ui-app-badge-line2 { font-size: .95rem; font-weight: 700; line-height: 1; }
1582
+
1583
+ /* ─── Mobile ─────────────────────────────────────────────────────────────── */
1584
+ @media (max-width: 640px) {
1585
+ .ui-btn--lg {
1586
+ height: 48px;
1587
+ padding: 0 1.25rem;
1588
+ font-size: .95rem;
1589
+ }
1590
+
1591
+ .ui-stat-value { font-size: 1.6rem; }
1592
+
1593
+ /* Full-width buttons in narrow containers */
1594
+ .ui-btn--full { font-size: .9rem; }
1595
+
1596
+ /* Layout */
1597
+ .ui-section { padding-top: 3rem; padding-bottom: 3rem; }
1598
+ .ui-section--sm { padding-top: 2rem; padding-bottom: 2rem; }
1599
+ .ui-section--lg { padding-top: 4rem; padding-bottom: 4rem; }
1600
+
1601
+ .ui-grid--cols-2,
1602
+ .ui-grid--cols-3,
1603
+ .ui-grid--cols-4 { grid-template-columns: 1fr; }
1604
+
1605
+ .ui-media { grid-template-columns: 1fr; }
1606
+ .ui-media--reverse { direction: ltr; }
1607
+
1608
+ .ui-hero { padding: 3rem 1.25rem; }
1609
+ .ui-hero-title { font-size: 2rem; }
1610
+ .ui-hero-subtitle { font-size: 1rem; }
1611
+ .ui-hero--split .ui-hero-inner { grid-template-columns: 1fr; }
1612
+ .ui-hero--media-left .ui-hero-media { order: 0; }
1613
+
1614
+ .ui-nav-links { display: none; }
1615
+ .ui-nav-burger { display: flex; }
1616
+ .ui-nav-inner { gap: .75rem; }
1617
+ }
1618
+
1619
+ /* ─── Utilities ──────────────────────────────────────────────────────────────
1620
+ Single-purpose helpers for spacing, typography, and layout.
1621
+ Use these in page HTML instead of writing custom CSS for common patterns.
1622
+ Prefix: u- (distinct from component classes which use ui-) */
1623
+
1624
+ /* Screen-reader only — visually hidden but accessible to assistive tech */
1625
+ /* u-visually-hidden is an alias — use either */
1626
+ .ui-sr-only,
1627
+ .u-visually-hidden {
1628
+ position: absolute;
1629
+ width: 1px; height: 1px;
1630
+ padding: 0; margin: -1px;
1631
+ overflow: hidden;
1632
+ clip: rect(0,0,0,0);
1633
+ white-space: nowrap;
1634
+ border: 0;
1635
+ }
1636
+
1637
+ /* Spacing scale: 1=4px 2=8px 3=12px 4=16px 5=20px 6=24px 8=32px 10=40px 12=48px 16=64px */
1638
+
1639
+ /* Margin top */
1640
+ .u-mt-0 { margin-top: 0; }
1641
+ .u-mt-1 { margin-top: .25rem; }
1642
+ .u-mt-2 { margin-top: .5rem; }
1643
+ .u-mt-3 { margin-top: .75rem; }
1644
+ .u-mt-4 { margin-top: 1rem; }
1645
+ .u-mt-5 { margin-top: 1.25rem; }
1646
+ .u-mt-6 { margin-top: 1.5rem; }
1647
+ .u-mt-8 { margin-top: 2rem; }
1648
+ .u-mt-10 { margin-top: 2.5rem; }
1649
+ .u-mt-12 { margin-top: 3rem; }
1650
+ .u-mt-16 { margin-top: 4rem; }
1651
+
1652
+ /* Margin bottom */
1653
+ .u-mb-0 { margin-bottom: 0; }
1654
+ .u-mb-1 { margin-bottom: .25rem; }
1655
+ .u-mb-2 { margin-bottom: .5rem; }
1656
+ .u-mb-3 { margin-bottom: .75rem; }
1657
+ .u-mb-4 { margin-bottom: 1rem; }
1658
+ .u-mb-5 { margin-bottom: 1.25rem; }
1659
+ .u-mb-6 { margin-bottom: 1.5rem; }
1660
+ .u-mb-8 { margin-bottom: 2rem; }
1661
+ .u-mb-10 { margin-bottom: 2.5rem; }
1662
+ .u-mb-12 { margin-bottom: 3rem; }
1663
+ .u-mb-16 { margin-bottom: 4rem; }
1664
+
1665
+ /* Margin left / right / auto */
1666
+ .u-ml-auto { margin-left: auto; }
1667
+ .u-mr-auto { margin-right: auto; }
1668
+ .u-mx-auto { margin-left: auto; margin-right: auto; }
1669
+
1670
+ /* Padding */
1671
+ .u-p-0 { padding: 0; }
1672
+ .u-p-1 { padding: .25rem; }
1673
+ .u-p-2 { padding: .5rem; }
1674
+ .u-p-3 { padding: .75rem; }
1675
+ .u-p-4 { padding: 1rem; }
1676
+ .u-p-5 { padding: 1.25rem; }
1677
+ .u-p-6 { padding: 1.5rem; }
1678
+ .u-p-8 { padding: 2rem; }
1679
+
1680
+ .u-px-0 { padding-left: 0; padding-right: 0; }
1681
+ .u-px-2 { padding-left: .5rem; padding-right: .5rem; }
1682
+ .u-px-3 { padding-left: .75rem; padding-right: .75rem; }
1683
+ .u-px-4 { padding-left: 1rem; padding-right: 1rem; }
1684
+ .u-px-5 { padding-left: 1.25rem;padding-right: 1.25rem; }
1685
+ .u-px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
1686
+ .u-px-8 { padding-left: 2rem; padding-right: 2rem; }
1687
+
1688
+ .u-py-0 { padding-top: 0; padding-bottom: 0; }
1689
+ .u-py-2 { padding-top: .5rem; padding-bottom: .5rem; }
1690
+ .u-py-3 { padding-top: .75rem; padding-bottom: .75rem; }
1691
+ .u-py-4 { padding-top: 1rem; padding-bottom: 1rem; }
1692
+ .u-py-5 { padding-top: 1.25rem;padding-bottom: 1.25rem; }
1693
+ .u-py-6 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
1694
+ .u-py-8 { padding-top: 2rem; padding-bottom: 2rem; }
1695
+
1696
+ /* Typography — size */
1697
+ .u-text-xs { font-size: .75rem; line-height: 1.4; }
1698
+ .u-text-sm { font-size: .875rem; line-height: 1.5; }
1699
+ .u-text-base { font-size: 1rem; line-height: 1.6; }
1700
+ .u-text-lg { font-size: 1.125rem;line-height: 1.5; }
1701
+ .u-text-xl { font-size: 1.25rem; line-height: 1.4; }
1702
+ .u-text-2xl { font-size: 1.5rem; line-height: 1.3; }
1703
+ .u-text-3xl { font-size: 1.875rem;line-height: 1.2; }
1704
+ .u-text-4xl { font-size: 2.25rem; line-height: 1.15; }
1705
+ .u-text-5xl { font-size: 3rem; line-height: 1.1; }
1706
+ .u-text-6xl { font-size: 4rem; line-height: 1.05; }
1707
+ .u-text-7xl { font-size: 5rem; line-height: 1; }
1708
+
1709
+ /* Typography — weight */
1710
+ .u-font-normal { font-weight: 400; }
1711
+ .u-font-medium { font-weight: 500; }
1712
+ .u-font-semibold { font-weight: 600; }
1713
+ .u-font-bold { font-weight: 700; }
1714
+
1715
+ /* Typography — alignment */
1716
+ .u-text-left { text-align: left; }
1717
+ .u-text-center { text-align: center; }
1718
+ .u-text-right { text-align: right; }
1719
+ .u-text-balance { text-wrap: balance; }
1720
+
1721
+ /* Typography — color (uses tokens so theme overrides apply) */
1722
+ .u-text-default { color: var(--ui-text); }
1723
+ .u-text-muted { color: var(--ui-muted); }
1724
+ .u-text-accent { color: var(--ui-accent); }
1725
+ .u-text-green { color: var(--ui-green); }
1726
+ .u-text-red { color: var(--ui-red); }
1727
+ .u-text-yellow { color: var(--ui-yellow); }
1728
+ .u-text-blue { color: var(--ui-blue); }
1729
+
1730
+ /* Typography — line height */
1731
+ .u-leading-tight { line-height: 1.25; }
1732
+ .u-leading-snug { line-height: 1.375; }
1733
+ .u-leading-normal { line-height: 1.5; }
1734
+ .u-leading-relaxed { line-height: 1.625; }
1735
+ .u-leading-loose { line-height: 2; }
1736
+
1737
+ /* Width */
1738
+ .u-w-full { width: 100%; }
1739
+ .u-w-auto { width: auto; }
1740
+ .u-max-w-xs { max-width: 320px; }
1741
+ .u-max-w-sm { max-width: 480px; }
1742
+ .u-max-w-md { max-width: 640px; }
1743
+ .u-max-w-lg { max-width: 800px; }
1744
+ .u-max-w-xl { max-width: 1024px; }
1745
+ .u-max-w-prose { max-width: 65ch; }
1746
+
1747
+ /* Display */
1748
+ .u-block { display: block; }
1749
+ .u-inline { display: inline; }
1750
+ .u-inline-block { display: inline-block; }
1751
+ .u-hidden { display: none; }
1752
+
1753
+ /* Flexbox */
1754
+ .u-flex { display: flex; }
1755
+ .u-flex-col { display: flex; flex-direction: column; }
1756
+ .u-flex-wrap { flex-wrap: wrap; }
1757
+ .u-flex-1 { flex: 1; }
1758
+ .u-shrink-0 { flex-shrink: 0; }
1759
+
1760
+ .u-items-start { align-items: flex-start; }
1761
+ .u-items-center { align-items: center; }
1762
+ .u-items-end { align-items: flex-end; }
1763
+ .u-items-stretch { align-items: stretch; }
1764
+
1765
+ .u-justify-start { justify-content: flex-start; }
1766
+ .u-justify-center { justify-content: center; }
1767
+ .u-justify-end { justify-content: flex-end; }
1768
+ .u-justify-between { justify-content: space-between; }
1769
+
1770
+ .u-gap-1 { gap: .25rem; }
1771
+ .u-gap-2 { gap: .5rem; }
1772
+ .u-gap-3 { gap: .75rem; }
1773
+ .u-gap-4 { gap: 1rem; }
1774
+ .u-gap-5 { gap: 1.25rem; }
1775
+ .u-gap-6 { gap: 1.5rem; }
1776
+ .u-gap-8 { gap: 2rem; }
1777
+
1778
+ /* Border radius */
1779
+ .u-rounded { border-radius: var(--ui-radius-sm); }
1780
+ .u-rounded-md { border-radius: var(--ui-radius); }
1781
+ .u-rounded-lg { border-radius: calc(var(--ui-radius) * 1.5); }
1782
+ .u-rounded-xl { border-radius: calc(var(--ui-radius) * 2); }
1783
+ .u-rounded-full { border-radius: 9999px; }
1784
+
1785
+ /* Border */
1786
+ .u-border { border: 1px solid var(--ui-border); }
1787
+ .u-border-t { border-top: 1px solid var(--ui-border); }
1788
+ .u-border-b { border-bottom: 1px solid var(--ui-border); }
1789
+
1790
+ /* Background */
1791
+ .u-bg-surface { background: var(--ui-surface); }
1792
+ .u-bg-surface2 { background: var(--ui-surface-2); }
1793
+ .u-bg-accent { background: var(--ui-accent); }
1794
+
1795
+ /* Overflow */
1796
+ .u-overflow-hidden { overflow: hidden; }
1797
+ .u-overflow-auto { overflow: auto; }
1798
+
1799
+ /* Position */
1800
+ .u-relative { position: relative; }
1801
+ .u-absolute { position: absolute; }
1802
+
1803
+ /* Opacity */
1804
+ .u-opacity-50 { opacity: .5; }
1805
+ .u-opacity-75 { opacity: .75; }
1806
+
1807
+ /* Numeric formatting */
1808
+ .u-tabular-nums { font-variant-numeric: tabular-nums; }
1809
+
1810
+ /* ─── Section header ─────────────────────────────────────────────────────────
1811
+ Optional heading block prepended to section() when eyebrow/title/subtitle
1812
+ props are supplied. Sits above the content slot. */
1813
+ .ui-section-header { width: 100%; max-width: 1100px; margin: 0 auto 2.5rem; padding-left: 1.5rem; padding-right: 1.5rem; }
1814
+ .ui-section-header--center { text-align: center; }
1815
+ .ui-section-header--gap-none { margin-bottom: 0; }
1816
+ .ui-section-header--gap-sm { margin-bottom: 1.25rem; }
1817
+ .ui-section-header--gap-lg { margin-bottom: 4rem; }
1818
+
1819
+ .ui-section-eyebrow {
1820
+ display: block;
1821
+ font-size: .75rem;
1822
+ font-weight: 600;
1823
+ letter-spacing: .08em;
1824
+ text-transform: uppercase;
1825
+ color: var(--ui-accent);
1826
+ margin: 0 0 2rem;
1827
+ }
1828
+
1829
+ .ui-section-title {
1830
+ font-size: 2rem;
1831
+ font-weight: 700;
1832
+ line-height: 1.15;
1833
+ letter-spacing: var(--ui-letter-spacing-display, -0.025em);
1834
+ font-family: var(--ui-font-display, var(--ui-font));
1835
+ color: var(--ui-text);
1836
+ margin: 0 0 1.25rem;
1837
+ }
1838
+
1839
+ .ui-section-subtitle {
1840
+ font-size: 1rem;
1841
+ color: var(--ui-muted);
1842
+ line-height: 1.65;
1843
+ margin: 0;
1844
+ max-width: 58ch;
1845
+ }
1846
+
1847
+ .ui-section-header--center .ui-section-subtitle { margin-left: auto; margin-right: auto; }
1848
+
1849
+ @media (max-width: 640px) {
1850
+ .ui-section-title { font-size: 1.5rem; }
1851
+ .ui-section-header { margin-bottom: 2rem; }
1852
+ }
1853
+
1854
+ /* ─── CTA ────────────────────────────────────────────────────────────────────
1855
+ Call-to-action block. Sits inside section() + container(). */
1856
+ .ui-cta { text-align: center; }
1857
+ .ui-cta--left { text-align: left; }
1858
+
1859
+ .ui-cta-eyebrow {
1860
+ display: block;
1861
+ font-size: .75rem;
1862
+ font-weight: 600;
1863
+ letter-spacing: .08em;
1864
+ text-transform: uppercase;
1865
+ color: var(--ui-accent);
1866
+ margin: 0 0 .75rem;
1867
+ }
1868
+
1869
+ .ui-cta-title {
1870
+ font-size: 2.5rem;
1871
+ font-weight: 700;
1872
+ line-height: 1.1;
1873
+ color: var(--ui-text);
1874
+ margin: 0 0 1rem;
1875
+ }
1876
+
1877
+ .ui-cta-subtitle {
1878
+ font-size: 1.05rem;
1879
+ color: var(--ui-muted);
1880
+ line-height: 1.65;
1881
+ max-width: 56ch;
1882
+ margin: 0 auto 2rem;
1883
+ }
1884
+
1885
+ .ui-cta--left .ui-cta-subtitle { margin-left: 0; }
1886
+
1887
+ .ui-cta-actions {
1888
+ display: flex;
1889
+ gap: 1rem;
1890
+ flex-wrap: wrap;
1891
+ justify-content: center;
1892
+ }
1893
+
1894
+ .ui-cta--left .ui-cta-actions { justify-content: flex-start; }
1895
+
1896
+ @media (max-width: 640px) {
1897
+ .ui-cta-title { font-size: 1.75rem; }
1898
+ .ui-cta-actions { flex-direction: column; align-items: stretch; }
1899
+ }
1900
+
1901
+ /* ─── Code Window ────────────────────────────────────────────────────────────
1902
+ macOS-style window chrome around a <pre><code> block. */
1903
+ .ui-code-window {
1904
+ background: var(--ui-surface-2);
1905
+ border: 1px solid var(--ui-border);
1906
+ border-radius: var(--ui-radius);
1907
+ overflow: hidden;
1908
+ }
1909
+
1910
+ .ui-code-window-chrome {
1911
+ display: flex;
1912
+ align-items: center;
1913
+ gap: .4rem;
1914
+ padding: .6rem 1rem;
1915
+ background: var(--ui-surface);
1916
+ border-bottom: 1px solid var(--ui-border);
1917
+ }
1918
+
1919
+ .ui-code-window-dot {
1920
+ width: 10px;
1921
+ height: 10px;
1922
+ border-radius: 50%;
1923
+ flex-shrink: 0;
1924
+ }
1925
+
1926
+ .ui-code-window-dot:nth-child(1) { background: #ff5f57; }
1927
+ .ui-code-window-dot:nth-child(2) { background: #febc2e; }
1928
+ .ui-code-window-dot:nth-child(3) { background: #28c840; }
1929
+
1930
+ .ui-code-window-filename {
1931
+ font-size: .75rem;
1932
+ font-family: var(--ui-mono);
1933
+ color: #9898b2;
1934
+ margin-left: .35rem;
1935
+ }
1936
+
1937
+ .ui-code-window-lang {
1938
+ font-size: .7rem;
1939
+ font-family: var(--ui-mono);
1940
+ color: #9898b2;
1941
+ margin-left: auto;
1942
+ }
1943
+
1944
+ .ui-code-window-pre {
1945
+ margin: 0;
1946
+ padding: 1.25rem 1.5rem;
1947
+ overflow-x: auto;
1948
+ font-family: var(--ui-mono);
1949
+ font-size: .85rem;
1950
+ line-height: 1.7;
1951
+ color: var(--ui-text);
1952
+ tab-size: 2;
1953
+ }
1954
+
1955
+ .ui-code-window-code { font-family: inherit; }
1956
+
1957
+ /* ─── Phone Frame ────────────────────────────────────────────────────────────
1958
+ Realistic CSS mobile phone frame — body, dynamic island, side buttons,
1959
+ home indicator. Drop any HTML into the content slot. */
1960
+ .ui-phone {
1961
+ position: relative;
1962
+ display: inline-flex;
1963
+ width: 260px;
1964
+ background: linear-gradient(160deg, #1e1e28 0%, #141418 100%);
1965
+ border-radius: 3rem;
1966
+ border: 1.5px solid rgba(255, 255, 255, 0.1);
1967
+ box-shadow:
1968
+ 0 0 0 1px rgba(0, 0, 0, 0.8),
1969
+ 0 2px 0 1px rgba(255, 255, 255, 0.05) inset,
1970
+ 0 48px 96px rgba(0, 0, 0, 0.55),
1971
+ 0 12px 32px rgba(0, 0, 0, 0.4);
1972
+ padding: 12px;
1973
+ }
1974
+
1975
+ /* Side buttons */
1976
+ .ui-phone-btn {
1977
+ position: absolute;
1978
+ background: linear-gradient(90deg, #1a1a22 0%, #26262e 100%);
1979
+ border-radius: 2px;
1980
+ }
1981
+ .ui-phone-btn--mute { left: -3px; top: 88px; width: 3px; height: 28px; }
1982
+ .ui-phone-btn--vol-up { left: -3px; top: 128px; width: 3px; height: 48px; }
1983
+ .ui-phone-btn--vol-down { left: -3px; top: 186px; width: 3px; height: 48px; }
1984
+ .ui-phone-btn--power { right: -3px; top: 140px; width: 3px; height: 64px; }
1985
+
1986
+ /* Phone inner — holds screen + chrome */
1987
+ .ui-phone-inner {
1988
+ width: 100%;
1989
+ background: #000;
1990
+ border-radius: 2.5rem;
1991
+ overflow: hidden;
1992
+ display: flex;
1993
+ flex-direction: column;
1994
+ }
1995
+
1996
+ /* Dynamic island */
1997
+ .ui-phone-island {
1998
+ flex-shrink: 0;
1999
+ display: flex;
2000
+ align-items: center;
2001
+ justify-content: center;
2002
+ height: 32px;
2003
+ background: #000;
2004
+ }
2005
+ .ui-phone-camera {
2006
+ display: block;
2007
+ width: 10px;
2008
+ height: 10px;
2009
+ background: radial-gradient(circle at 35% 35%, #2a2a3a, #0a0a0a);
2010
+ border-radius: 50%;
2011
+ box-shadow: 0 0 0 1px rgba(255,255,255,0.06);
2012
+ }
2013
+
2014
+ /* Screen */
2015
+ .ui-phone-screen {
2016
+ flex: 1;
2017
+ overflow: hidden;
2018
+ }
2019
+
2020
+ /* Home indicator */
2021
+ .ui-phone-home {
2022
+ flex-shrink: 0;
2023
+ display: flex;
2024
+ align-items: center;
2025
+ justify-content: center;
2026
+ height: 24px;
2027
+ background: #000;
2028
+ }
2029
+ .ui-phone-home::after {
2030
+ content: '';
2031
+ display: block;
2032
+ width: 80px;
2033
+ height: 4px;
2034
+ background: rgba(255, 255, 255, 0.25);
2035
+ border-radius: 2px;
2036
+ }
2037
+
2038
+ /* Hover tilt — enabled by .ui-phone--tilt */
2039
+ .ui-phone--tilt {
2040
+ transform-style: preserve-3d;
2041
+ transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), box-shadow 0.4s ease;
2042
+ will-change: transform;
2043
+ }
2044
+ .ui-phone--tilt:hover {
2045
+ transform: perspective(900px) rotateY(-8deg) rotateX(3deg);
2046
+ box-shadow:
2047
+ 0 0 0 1px rgba(0, 0, 0, 0.8),
2048
+ 0 2px 0 1px rgba(255, 255, 255, 0.07) inset,
2049
+ 8px 56px 120px rgba(0, 0, 0, 0.65),
2050
+ 4px 16px 40px rgba(0, 0, 0, 0.5);
2051
+ }
2052
+
2053
+ /* ─── Footer ─────────────────────────────────────────────────────────────────
2054
+ Site footer — logo, nav links, legal text. Stacks on mobile. */
2055
+ .ui-footer {
2056
+ padding: 3rem 1.5rem;
2057
+ border-top: 1px solid var(--ui-border);
2058
+ }
2059
+
2060
+ .ui-footer-inner {
2061
+ max-width: 1200px;
2062
+ margin: 0 auto;
2063
+ display: flex;
2064
+ align-items: center;
2065
+ gap: 2rem;
2066
+ flex-wrap: wrap;
2067
+ }
2068
+
2069
+ .ui-footer-logo {
2070
+ font-size: 1rem;
2071
+ font-weight: 600;
2072
+ color: var(--ui-text);
2073
+ text-decoration: none;
2074
+ flex-shrink: 0;
2075
+ transition: color .15s;
2076
+ }
2077
+
2078
+ .ui-footer-logo:hover { color: var(--ui-accent); }
2079
+ .ui-footer-logo:focus-visible {
2080
+ outline: 2px solid var(--ui-accent);
2081
+ outline-offset: 2px;
2082
+ border-radius: 2px;
2083
+ }
2084
+
2085
+ .ui-footer-links {
2086
+ display: flex;
2087
+ gap: 1.5rem;
2088
+ flex-wrap: wrap;
2089
+ flex: 1;
2090
+ }
2091
+
2092
+ .ui-footer-link {
2093
+ font-size: .875rem;
2094
+ color: var(--ui-muted);
2095
+ text-decoration: none;
2096
+ transition: color .15s;
2097
+ }
2098
+
2099
+ .ui-footer-link:hover { color: var(--ui-text); }
2100
+ .ui-footer-link:focus-visible {
2101
+ outline: 2px solid var(--ui-accent);
2102
+ outline-offset: 2px;
2103
+ border-radius: 2px;
2104
+ }
2105
+
2106
+ .ui-footer-legal {
2107
+ font-size: .8rem;
2108
+ color: var(--ui-muted);
2109
+ margin: 0 0 0 auto;
2110
+ }
2111
+
2112
+ @media (max-width: 640px) {
2113
+ .ui-footer-inner { flex-direction: column; align-items: flex-start; gap: 1.25rem; }
2114
+ .ui-footer-legal { margin-left: 0; }
2115
+ .ui-footer-links { gap: 1rem; }
2116
+ }
2117
+
2118
+ /* ─── Footer — Rich variant ─────────────────────────────────────────────── */
2119
+ .ui-footer--rich {
2120
+ padding: 0;
2121
+ border-top: none;
2122
+ }
2123
+
2124
+ .ui-footer--rich .ui-footer-top {
2125
+ display: flex;
2126
+ justify-content: space-between;
2127
+ align-items: flex-start;
2128
+ gap: 2rem;
2129
+ padding: 3rem 2rem 2rem;
2130
+ flex-wrap: wrap;
2131
+ }
2132
+
2133
+ .ui-footer--rich .ui-footer-logo {
2134
+ font-size: 1.5rem;
2135
+ }
2136
+
2137
+ .ui-footer--rich .ui-footer-subscribe {
2138
+ max-width: 480px;
2139
+ flex: 1;
2140
+ }
2141
+
2142
+ .ui-footer-columns {
2143
+ display: grid;
2144
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
2145
+ gap: 2rem;
2146
+ padding: 2rem 2rem;
2147
+ border-top: 1px solid currentcolor;
2148
+ opacity-on-border: 0.15;
2149
+ }
2150
+
2151
+ .ui-footer-col-title {
2152
+ font-size: 0.6875rem;
2153
+ font-weight: 600;
2154
+ letter-spacing: 0.1em;
2155
+ text-transform: uppercase;
2156
+ margin: 0 0 1rem;
2157
+ color: var(--ui-muted, currentcolor);
2158
+ }
2159
+
2160
+ .ui-footer-col-links {
2161
+ list-style: none;
2162
+ margin: 0;
2163
+ padding: 0;
2164
+ display: flex;
2165
+ flex-direction: column;
2166
+ gap: 0.6rem;
2167
+ }
2168
+
2169
+ .ui-footer-col-links a {
2170
+ display: block;
2171
+ padding: 0.3rem 0;
2172
+ min-height: 24px;
2173
+ font-size: 0.9375rem;
2174
+ color: var(--ui-muted, inherit);
2175
+ text-decoration: none;
2176
+ transition: color 0.15s;
2177
+ }
2178
+ .ui-footer-col-links a:hover { color: var(--ui-text, currentcolor); }
2179
+
2180
+ .ui-footer-wordmark {
2181
+ padding: 1rem 1.5rem 0;
2182
+ overflow: hidden;
2183
+ }
2184
+ .ui-footer-wordmark::after {
2185
+ content: attr(data-wordmark);
2186
+ display: block;
2187
+ font-size: clamp(4rem, 16vw, 14rem);
2188
+ font-weight: 700;
2189
+ letter-spacing: -0.03em;
2190
+ line-height: 0.9;
2191
+ word-break: break-all;
2192
+ }
2193
+
2194
+ .ui-footer-legal-row {
2195
+ display: flex;
2196
+ gap: 1.5rem;
2197
+ align-items: center;
2198
+ flex-wrap: wrap;
2199
+ padding: 1.5rem 2rem;
2200
+ font-size: 0.8125rem;
2201
+ color: var(--ui-muted, currentcolor);
2202
+ border-top: 1px solid var(--ui-border, currentcolor);
2203
+ }
2204
+
2205
+ .ui-footer-legal-row a {
2206
+ color: inherit;
2207
+ text-decoration: none;
2208
+ }
2209
+ .ui-footer-legal-row a:hover { text-decoration: underline; }
2210
+
2211
+ @media (max-width: 640px) {
2212
+ .ui-footer--rich .ui-footer-top { flex-direction: column; }
2213
+ .ui-footer-columns { grid-template-columns: repeat(2, 1fr); }
2214
+ }
2215
+
2216
+ /* ─── Icon wrapper ───────────────────────────────────────────────────────────
2217
+ Wraps any icon in a tinted background shape.
2218
+ bg: 'circle' → border-radius: 50% | bg: 'square' → var(--ui-radius) */
2219
+
2220
+ .ui-icon-wrap {
2221
+ display: inline-flex;
2222
+ align-items: center;
2223
+ justify-content: center;
2224
+ padding: .55em;
2225
+ flex-shrink: 0;
2226
+ line-height: 1;
2227
+ }
2228
+
2229
+ .ui-icon-wrap--circle { border-radius: 50%; }
2230
+ .ui-icon-wrap--square { border-radius: var(--ui-radius); }
2231
+
2232
+ .ui-icon-wrap--accent { background: var(--ui-accent-dim); color: var(--ui-accent); }
2233
+ .ui-icon-wrap--success { background: var(--ui-green-dim); color: var(--ui-green); }
2234
+ .ui-icon-wrap--warning { background: var(--ui-yellow-dim); color: var(--ui-yellow); }
2235
+ .ui-icon-wrap--error { background: var(--ui-red-dim); color: var(--ui-red); }
2236
+ .ui-icon-wrap--muted { background: var(--ui-surface-2); color: var(--ui-muted); }
2237
+
2238
+ /* ─── Timeline ───────────────────────────────────────────────────────────────
2239
+ Shared rules (dot, label, body) apply to both orientations. */
2240
+
2241
+ /* Shared base */
2242
+ .ui-timeline {
2243
+ list-style: none;
2244
+ padding: 0;
2245
+ margin: 0;
2246
+ }
2247
+
2248
+ .ui-timeline-dot {
2249
+ width: 10px;
2250
+ height: 10px;
2251
+ border-radius: 50%;
2252
+ flex-shrink: 0;
2253
+ display: flex;
2254
+ align-items: center;
2255
+ justify-content: center;
2256
+ position: relative;
2257
+ z-index: 1;
2258
+ }
2259
+
2260
+ /* Icon dot — larger, with dim background */
2261
+ .ui-timeline-dot--icon {
2262
+ width: 2rem;
2263
+ height: 2rem;
2264
+ border-radius: 50%;
2265
+ font-size: 1rem;
2266
+ }
2267
+
2268
+ /* Dot colour variants */
2269
+ .ui-timeline-dot--accent { background: var(--ui-accent); }
2270
+ .ui-timeline-dot--success { background: var(--ui-green); }
2271
+ .ui-timeline-dot--warning { background: var(--ui-yellow); }
2272
+ .ui-timeline-dot--error { background: var(--ui-red); }
2273
+ .ui-timeline-dot--muted { background: var(--ui-surface-2); outline: 2px solid var(--ui-border); outline-offset: 0; }
2274
+
2275
+ /* Icon dot: dim background + coloured icon */
2276
+ .ui-timeline-dot--icon.ui-timeline-dot--accent { background: var(--ui-accent-dim); color: var(--ui-accent); }
2277
+ .ui-timeline-dot--icon.ui-timeline-dot--success { background: var(--ui-green-dim); color: var(--ui-green); }
2278
+ .ui-timeline-dot--icon.ui-timeline-dot--warning { background: var(--ui-yellow-dim); color: var(--ui-yellow); }
2279
+ .ui-timeline-dot--icon.ui-timeline-dot--error { background: var(--ui-red-dim); color: var(--ui-red); }
2280
+ .ui-timeline-dot--icon.ui-timeline-dot--muted { background: var(--ui-surface-2); color: var(--ui-muted); }
2281
+
2282
+ .ui-timeline-label {
2283
+ display: block;
2284
+ font-size: .72rem;
2285
+ font-weight: 600;
2286
+ color: var(--ui-muted);
2287
+ letter-spacing: .05em;
2288
+ text-transform: uppercase;
2289
+ margin-bottom: .35rem;
2290
+ }
2291
+
2292
+ /* ── Vertical ── */
2293
+ .ui-timeline--vertical {
2294
+ display: flex;
2295
+ flex-direction: column;
2296
+ }
2297
+
2298
+ .ui-timeline--vertical .ui-timeline-item {
2299
+ display: flex;
2300
+ gap: 1rem;
2301
+ }
2302
+
2303
+ .ui-timeline--vertical .ui-timeline-side {
2304
+ display: flex;
2305
+ flex-direction: column;
2306
+ align-items: center;
2307
+ flex-shrink: 0;
2308
+ }
2309
+
2310
+ /* Connecting line segments run above and below the dot */
2311
+ .ui-timeline--vertical .ui-timeline-connector {
2312
+ width: 2px;
2313
+ background: var(--ui-border);
2314
+ flex: 1;
2315
+ min-height: .75rem;
2316
+ }
2317
+
2318
+ /* No line above the first item or below the last */
2319
+ .ui-timeline--vertical .ui-timeline-item:first-child .ui-timeline-connector--before,
2320
+ .ui-timeline--vertical .ui-timeline-item:last-child .ui-timeline-connector--after {
2321
+ visibility: hidden;
2322
+ }
2323
+
2324
+ .ui-timeline--vertical .ui-timeline-main {
2325
+ flex: 1;
2326
+ padding-bottom: 1.75rem;
2327
+ }
2328
+
2329
+ .ui-timeline--vertical .ui-timeline-item:last-child .ui-timeline-main {
2330
+ padding-bottom: 0;
2331
+ }
2332
+
2333
+ /* ── Horizontal ── */
2334
+ .ui-timeline--horizontal {
2335
+ display: flex;
2336
+ align-items: flex-start;
2337
+ overflow-x: auto;
2338
+ }
2339
+
2340
+ .ui-timeline--horizontal .ui-timeline-item {
2341
+ flex: 1;
2342
+ min-width: 0;
2343
+ display: flex;
2344
+ flex-direction: column;
2345
+ align-items: center;
2346
+ }
2347
+
2348
+ .ui-timeline--horizontal .ui-timeline-side {
2349
+ display: flex;
2350
+ align-items: center;
2351
+ width: 100%;
2352
+ margin-bottom: .75rem;
2353
+ }
2354
+
2355
+ .ui-timeline--horizontal .ui-timeline-connector {
2356
+ flex: 1;
2357
+ height: 2px;
2358
+ background: var(--ui-border);
2359
+ }
2360
+
2361
+ /* No line before the first item or after the last */
2362
+ .ui-timeline--horizontal .ui-timeline-item:first-child .ui-timeline-connector--before,
2363
+ .ui-timeline--horizontal .ui-timeline-item:last-child .ui-timeline-connector--after {
2364
+ visibility: hidden;
2365
+ }
2366
+
2367
+ .ui-timeline--horizontal .ui-timeline-main {
2368
+ text-align: center;
2369
+ padding: 0 .5rem;
2370
+ width: 100%;
2371
+ }
2372
+
2373
+ /* ─── Switch ─────────────────────────────────────────────────────────────── */
2374
+ .ui-switch-input {
2375
+ position: absolute;
2376
+ width: 1px;
2377
+ height: 1px;
2378
+ padding: 0;
2379
+ margin: -1px;
2380
+ overflow: hidden;
2381
+ clip: rect(0,0,0,0);
2382
+ border: 0;
2383
+ }
2384
+
2385
+ .ui-switch-label {
2386
+ display: inline-flex;
2387
+ align-items: center;
2388
+ gap: .65rem;
2389
+ cursor: pointer;
2390
+ user-select: none;
2391
+ }
2392
+
2393
+ .ui-switch-label--disabled {
2394
+ opacity: .5;
2395
+ cursor: not-allowed;
2396
+ }
2397
+
2398
+ .ui-switch-track {
2399
+ position: relative;
2400
+ display: inline-flex;
2401
+ align-items: center;
2402
+ width: 3rem;
2403
+ height: 1.75rem;
2404
+ border-radius: 999px;
2405
+ background: var(--ui-border);
2406
+ transition: background .2s;
2407
+ flex-shrink: 0;
2408
+ }
2409
+
2410
+ .ui-switch-thumb {
2411
+ position: absolute;
2412
+ left: .2rem;
2413
+ width: 1.35rem;
2414
+ height: 1.35rem;
2415
+ border-radius: 50%;
2416
+ background: #fff;
2417
+ box-shadow: 0 1px 3px rgba(0,0,0,.3);
2418
+ transition: transform .2s cubic-bezier(.34,1.56,.64,1), background .2s;
2419
+ }
2420
+
2421
+ .ui-switch-input:checked + .ui-switch-track {
2422
+ background: var(--ui-accent);
2423
+ }
2424
+
2425
+ .ui-switch-input:checked + .ui-switch-track .ui-switch-thumb {
2426
+ transform: translateX(1.25rem);
2427
+ }
2428
+
2429
+ .ui-switch-input:focus-visible + .ui-switch-track {
2430
+ outline: 2px solid var(--ui-accent);
2431
+ outline-offset: 2px;
2432
+ }
2433
+
2434
+ .ui-switch-text {
2435
+ font-family: var(--ui-font);
2436
+ font-size: .9rem;
2437
+ color: var(--ui-text);
2438
+ line-height: 1.4;
2439
+ }
2440
+
2441
+ /* ─── Radio ──────────────────────────────────────────────────────────────── */
2442
+ .ui-radio-group {
2443
+ border: 1px solid var(--ui-border);
2444
+ border-radius: var(--ui-radius);
2445
+ padding: 0;
2446
+ margin: 0;
2447
+ }
2448
+
2449
+ .ui-radio-group-body {
2450
+ display: flex;
2451
+ flex-direction: column;
2452
+ gap: var(--radio-gap, .75rem);
2453
+ padding: 1.25rem;
2454
+ }
2455
+
2456
+ /* ─── Checkbox ───────────────────────────────────────────────────────────── */
2457
+ .ui-checkbox {
2458
+ display: inline-flex;
2459
+ align-items: flex-start;
2460
+ gap: .6rem;
2461
+ cursor: pointer;
2462
+ user-select: none;
2463
+ }
2464
+
2465
+ .ui-checkbox--disabled {
2466
+ opacity: .5;
2467
+ cursor: not-allowed;
2468
+ }
2469
+
2470
+ .ui-checkbox-input {
2471
+ position: absolute;
2472
+ width: 1px;
2473
+ height: 1px;
2474
+ padding: 0;
2475
+ margin: -1px;
2476
+ overflow: hidden;
2477
+ clip: rect(0,0,0,0);
2478
+ border: 0;
2479
+ }
2480
+
2481
+ .ui-checkbox-box {
2482
+ position: relative;
2483
+ display: inline-flex;
2484
+ align-items: center;
2485
+ justify-content: center;
2486
+ width: 1.125rem;
2487
+ height: 1.125rem;
2488
+ border-radius: .25rem;
2489
+ border: 2px solid var(--ui-border);
2490
+ background: var(--ui-surface);
2491
+ flex-shrink: 0;
2492
+ margin-top: .125rem;
2493
+ transition: border-color .15s, background .15s;
2494
+ }
2495
+
2496
+ .ui-checkbox-box::after {
2497
+ content: '';
2498
+ position: absolute;
2499
+ width: .3rem;
2500
+ height: .55rem;
2501
+ border-right: 2px solid var(--ui-bg);
2502
+ border-bottom: 2px solid var(--ui-bg);
2503
+ transform: rotate(45deg) scale(0);
2504
+ transform-origin: center;
2505
+ margin-top: -.1rem;
2506
+ opacity: 0;
2507
+ transition: opacity .1s, transform .15s cubic-bezier(.34, 1.56, .64, 1);
2508
+ }
2509
+
2510
+ .ui-checkbox-input:checked + .ui-checkbox-box {
2511
+ border-color: var(--ui-accent);
2512
+ background: var(--ui-accent);
2513
+ }
2514
+
2515
+ .ui-checkbox-input:checked + .ui-checkbox-box::after {
2516
+ opacity: 1;
2517
+ transform: rotate(45deg) scale(1);
2518
+ }
2519
+
2520
+ .ui-checkbox-input:focus-visible + .ui-checkbox-box {
2521
+ outline: 2px solid var(--ui-accent);
2522
+ outline-offset: 2px;
2523
+ }
2524
+
2525
+ .ui-checkbox--error .ui-checkbox-box {
2526
+ border-color: var(--ui-red);
2527
+ }
2528
+
2529
+ .ui-checkbox-label {
2530
+ font-family: var(--ui-font);
2531
+ font-size: .9rem;
2532
+ color: var(--ui-text);
2533
+ line-height: 1.4;
2534
+ }
2535
+
2536
+ /* ─── Radio ──────────────────────────────────────────────────────────────── */
2537
+ .ui-radio {
2538
+ display: inline-flex;
2539
+ align-items: center;
2540
+ gap: .6rem;
2541
+ cursor: pointer;
2542
+ user-select: none;
2543
+ }
2544
+
2545
+ .ui-radio--disabled {
2546
+ opacity: .5;
2547
+ cursor: not-allowed;
2548
+ }
2549
+
2550
+ .ui-radio-input {
2551
+ position: absolute;
2552
+ width: 1px;
2553
+ height: 1px;
2554
+ padding: 0;
2555
+ margin: -1px;
2556
+ overflow: hidden;
2557
+ clip: rect(0,0,0,0);
2558
+ border: 0;
2559
+ }
2560
+
2561
+ .ui-radio-dot {
2562
+ position: relative;
2563
+ display: inline-flex;
2564
+ align-items: center;
2565
+ justify-content: center;
2566
+ width: 1.25rem;
2567
+ height: 1.25rem;
2568
+ border-radius: 50%;
2569
+ border: 2px solid var(--ui-border);
2570
+ background: var(--ui-surface);
2571
+ flex-shrink: 0;
2572
+ transition: border-color .15s, background .15s;
2573
+ }
2574
+
2575
+ .ui-radio-dot::after {
2576
+ content: '';
2577
+ width: .5rem;
2578
+ height: .5rem;
2579
+ border-radius: 50%;
2580
+ background: var(--ui-bg);
2581
+ opacity: 0;
2582
+ transform: scale(0);
2583
+ transition: opacity .15s, transform .2s cubic-bezier(.34,1.56,.64,1);
2584
+ }
2585
+
2586
+ .ui-radio-input:checked + .ui-radio-dot {
2587
+ border-color: var(--ui-accent);
2588
+ background: var(--ui-accent);
2589
+ }
2590
+
2591
+ .ui-radio-input:checked + .ui-radio-dot::after {
2592
+ opacity: 1;
2593
+ transform: scale(1);
2594
+ }
2595
+
2596
+ .ui-radio-input:focus-visible + .ui-radio-dot {
2597
+ outline: 2px solid var(--ui-accent);
2598
+ outline-offset: 2px;
2599
+ }
2600
+
2601
+ .ui-radio-label {
2602
+ font-family: var(--ui-font);
2603
+ font-size: .9rem;
2604
+ color: var(--ui-text);
2605
+ line-height: 1.4;
2606
+ }
2607
+
2608
+ .ui-radio-group--error .ui-radio-dot {
2609
+ border-color: var(--ui-red);
2610
+ }
2611
+
2612
+ /* ─── Rating ─────────────────────────────────────────────────────────────── */
2613
+ .ui-rating {
2614
+ display: inline-flex;
2615
+ align-items: center;
2616
+ gap: .1em;
2617
+ font-size: var(--rating-size, 1.5rem);
2618
+ color: var(--ui-muted);
2619
+ line-height: 1;
2620
+ }
2621
+
2622
+ /* Read-only stars */
2623
+ .ui-rating-star--filled,
2624
+ .ui-rating-star--half { color: var(--ui-yellow); }
2625
+
2626
+ /* Interactive stars container — row-reverse makes high→low DOM order appear as 1…max */
2627
+ .ui-rating-stars {
2628
+ display: inline-flex;
2629
+ flex-direction: row-reverse;
2630
+ gap: .1em;
2631
+ font-size: var(--rating-size, 1.5rem);
2632
+ line-height: 1;
2633
+ }
2634
+
2635
+ /* Each input is nested inside its label — hidden but in the tab order */
2636
+ .ui-rating-input {
2637
+ position: absolute;
2638
+ width: 1px;
2639
+ height: 1px;
2640
+ padding: 0;
2641
+ margin: -1px;
2642
+ overflow: hidden;
2643
+ clip: rect(0,0,0,0);
2644
+ border: 0;
2645
+ }
2646
+
2647
+ /* Star labels — only flex items, no invisible elements between them */
2648
+ .ui-rating-stars .ui-rating-star {
2649
+ color: var(--ui-muted);
2650
+ cursor: pointer;
2651
+ transition: color .1s;
2652
+ user-select: none;
2653
+ }
2654
+
2655
+ /* Checked: colour the label containing the checked input + all DOM-subsequent
2656
+ labels (= visually lower-numbered stars due to row-reverse) */
2657
+ .ui-rating-stars .ui-rating-star:has(input:checked),
2658
+ .ui-rating-stars .ui-rating-star:has(input:checked) ~ .ui-rating-star {
2659
+ color: var(--ui-yellow);
2660
+ }
2661
+
2662
+ /* Hover: reset everything, then re-highlight up to the hovered star */
2663
+ .ui-rating-stars:hover .ui-rating-star { color: var(--ui-muted); }
2664
+ .ui-rating-stars .ui-rating-star:hover,
2665
+ .ui-rating-stars .ui-rating-star:hover ~ .ui-rating-star { color: var(--ui-yellow); }
2666
+
2667
+ /* Focus ring on the label when its input is keyboard-focused */
2668
+ .ui-rating-star:focus-within {
2669
+ outline: 2px solid var(--ui-accent);
2670
+ outline-offset: 2px;
2671
+ border-radius: 2px;
2672
+ }
2673
+
2674
+ /* Disabled */
2675
+ fieldset[disabled] .ui-rating-star {
2676
+ cursor: not-allowed;
2677
+ opacity: .5;
2678
+ }
2679
+ fieldset[disabled] .ui-rating-stars:hover .ui-rating-star { color: revert; }
2680
+ fieldset[disabled] .ui-rating-stars .ui-rating-star:hover,
2681
+ fieldset[disabled] .ui-rating-stars .ui-rating-star:hover ~ .ui-rating-star { color: revert; }
2682
+
2683
+ /* ─── Spinner ────────────────────────────────────────────────────────────── */
2684
+ @keyframes ui-spin {
2685
+ to { transform: rotate(360deg); }
2686
+ }
2687
+
2688
+ .ui-spinner {
2689
+ display: inline-block;
2690
+ width: var(--spinner-size, 1.5rem);
2691
+ height: var(--spinner-size, 1.5rem);
2692
+ border: 2px solid color-mix(in srgb, var(--spinner-color, var(--ui-accent)) 20%, transparent);
2693
+ border-top-color: var(--spinner-color, var(--ui-accent));
2694
+ border-radius: 50%;
2695
+ animation: ui-spin .7s linear infinite;
2696
+ flex-shrink: 0;
2697
+ }
2698
+
2699
+ /* ─── Progress ───────────────────────────────────────────────────────────── */
2700
+ .ui-progress { width: 100%; }
2701
+
2702
+ .ui-progress-header {
2703
+ display: flex;
2704
+ justify-content: space-between;
2705
+ align-items: baseline;
2706
+ margin-bottom: .4rem;
2707
+ gap: 1rem;
2708
+ }
2709
+
2710
+ .ui-progress-label {
2711
+ font-size: .8rem;
2712
+ font-weight: 600;
2713
+ color: var(--ui-text);
2714
+ }
2715
+
2716
+ .ui-progress-value {
2717
+ font-size: .8rem;
2718
+ color: var(--ui-muted);
2719
+ font-variant-numeric: tabular-nums;
2720
+ }
2721
+
2722
+ .ui-progress-track {
2723
+ width: 100%;
2724
+ height: var(--progress-height, .5rem);
2725
+ background: var(--ui-border);
2726
+ border-radius: 999px;
2727
+ overflow: hidden;
2728
+ }
2729
+
2730
+ .ui-progress-fill {
2731
+ height: 100%;
2732
+ border-radius: 999px;
2733
+ transition: width .3s ease;
2734
+ }
2735
+
2736
+ /* Variants */
2737
+ .ui-progress--accent .ui-progress-fill { background: var(--ui-accent); }
2738
+ .ui-progress--success .ui-progress-fill { background: var(--ui-green); }
2739
+ .ui-progress--warning .ui-progress-fill { background: var(--ui-yellow); }
2740
+ .ui-progress--error .ui-progress-fill { background: var(--ui-red); }
2741
+
2742
+ /* Indeterminate — animates a fill bar back and forth */
2743
+ @keyframes ui-progress-indeterminate {
2744
+ 0% { transform: translateX(-100%) scaleX(.4); }
2745
+ 50% { transform: translateX( 60%) scaleX(.6); }
2746
+ 100% { transform: translateX( 200%) scaleX(.4); }
2747
+ }
2748
+
2749
+ .ui-progress--indeterminate .ui-progress-fill {
2750
+ width: 50%;
2751
+ animation: ui-progress-indeterminate 1.4s ease infinite;
2752
+ transform-origin: left center;
2753
+ }
2754
+
2755
+ /* ─── Slider ─────────────────────────────────────────────────────────────── */
2756
+ .ui-slider {
2757
+ width: 100%;
2758
+ height: var(--ui-touch-min);
2759
+ -webkit-appearance: none;
2760
+ appearance: none;
2761
+ background: transparent;
2762
+ cursor: pointer;
2763
+ padding: 0;
2764
+ margin: 0;
2765
+ }
2766
+ .ui-slider::-webkit-slider-runnable-track {
2767
+ height: 4px;
2768
+ border-radius: 999px;
2769
+ background: linear-gradient(
2770
+ to right,
2771
+ var(--ui-accent) 0% var(--slider-fill, 50%),
2772
+ var(--ui-border) var(--slider-fill, 50%) 100%
2773
+ );
2774
+ }
2775
+ .ui-slider::-moz-range-track {
2776
+ height: 4px;
2777
+ border-radius: 999px;
2778
+ background: var(--ui-border);
2779
+ }
2780
+ .ui-slider::-moz-range-progress {
2781
+ height: 4px;
2782
+ border-radius: 999px;
2783
+ background: var(--ui-accent);
2784
+ }
2785
+ .ui-slider::-webkit-slider-thumb {
2786
+ -webkit-appearance: none;
2787
+ width: 20px;
2788
+ height: 20px;
2789
+ border-radius: 50%;
2790
+ background: var(--ui-accent);
2791
+ margin-top: -8px;
2792
+ box-shadow: 0 1px 4px rgba(0,0,0,.3);
2793
+ transition: transform .15s;
2794
+ }
2795
+ .ui-slider::-moz-range-thumb {
2796
+ width: 20px;
2797
+ height: 20px;
2798
+ border-radius: 50%;
2799
+ background: var(--ui-accent);
2800
+ border: none;
2801
+ box-shadow: 0 1px 4px rgba(0,0,0,.3);
2802
+ }
2803
+ .ui-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }
2804
+ .ui-slider:focus-visible { outline: none; }
2805
+ .ui-slider:focus-visible::-webkit-slider-thumb {
2806
+ outline: 2px solid var(--ui-accent);
2807
+ outline-offset: 3px;
2808
+ }
2809
+ .ui-slider:disabled { opacity: .5; cursor: not-allowed; }
2810
+
2811
+ .ui-label--row {
2812
+ display: flex;
2813
+ justify-content: space-between;
2814
+ align-items: baseline;
2815
+ }
2816
+ .ui-slider-output {
2817
+ font-size: .8125rem;
2818
+ color: var(--ui-muted);
2819
+ font-variant-numeric: tabular-nums;
2820
+ min-width: 3ch;
2821
+ text-align: right;
2822
+ }
2823
+
2824
+ /* ─── File Upload ────────────────────────────────────────────────────────── */
2825
+
2826
+ .ui-upload {
2827
+ position: relative;
2828
+ display: flex;
2829
+ align-items: center;
2830
+ justify-content: center;
2831
+ padding: 2rem 1.5rem;
2832
+ background: var(--ui-surface);
2833
+ border: 1.5px dashed var(--ui-border);
2834
+ border-radius: var(--ui-radius);
2835
+ cursor: pointer;
2836
+ transition: border-color .15s, background .15s;
2837
+ outline: none;
2838
+ user-select: none;
2839
+ }
2840
+
2841
+ .ui-upload:hover:not(.ui-upload--disabled),
2842
+ .ui-upload:focus-visible {
2843
+ border-color: var(--ui-accent);
2844
+ background: color-mix(in srgb, var(--ui-accent) 5%, var(--ui-surface));
2845
+ }
2846
+
2847
+ .ui-upload--active {
2848
+ border-color: var(--ui-accent);
2849
+ background: color-mix(in srgb, var(--ui-accent) 8%, var(--ui-surface));
2850
+ }
2851
+
2852
+ .ui-upload--error { border-color: var(--ui-red); }
2853
+ .ui-upload--selected { border-color: var(--ui-accent); }
2854
+ .ui-upload--selected .ui-upload-text { color: var(--ui-text); font-weight: 500; }
2855
+
2856
+ .ui-upload--disabled {
2857
+ opacity: .5;
2858
+ cursor: not-allowed;
2859
+ }
2860
+
2861
+ .ui-upload-body {
2862
+ display: flex;
2863
+ flex-direction: column;
2864
+ align-items: center;
2865
+ gap: .6rem;
2866
+ pointer-events: none;
2867
+ }
2868
+
2869
+ .ui-upload-icon { color: var(--ui-muted); display: block; }
2870
+
2871
+ .ui-upload:hover:not(.ui-upload--disabled) .ui-upload-icon,
2872
+ .ui-upload--active .ui-upload-icon { color: var(--ui-accent); }
2873
+
2874
+ .ui-upload-text {
2875
+ font-size: .875rem;
2876
+ color: var(--ui-muted);
2877
+ text-align: center;
2878
+ line-height: 1.5;
2879
+ }
2880
+
2881
+ .ui-upload-browse {
2882
+ color: var(--ui-accent);
2883
+ text-decoration: underline;
2884
+ text-underline-offset: 2px;
2885
+ }
2886
+
2887
+ .ui-upload-input {
2888
+ display: none;
2889
+ }
2890
+
2891
+ /* ─── Segmented ─────────────────────────────────────────────────────────── */
2892
+ .ui-segmented {
2893
+ display: inline-flex;
2894
+ background: var(--ui-surface-2);
2895
+ border-radius: var(--ui-radius);
2896
+ padding: 3px;
2897
+ gap: 2px;
2898
+ }
2899
+ .ui-segmented-input {
2900
+ position: absolute;
2901
+ width: 1px; height: 1px;
2902
+ padding: 0; margin: -1px;
2903
+ overflow: hidden; clip: rect(0,0,0,0); border: 0;
2904
+ }
2905
+ .ui-segmented-label {
2906
+ display: inline-flex;
2907
+ align-items: center;
2908
+ padding: .4rem .9rem;
2909
+ border-radius: calc(var(--ui-radius) - 2px);
2910
+ font-size: .85rem;
2911
+ font-weight: 500;
2912
+ color: var(--ui-muted);
2913
+ cursor: pointer;
2914
+ user-select: none;
2915
+ white-space: nowrap;
2916
+ transition: background .15s, color .15s, box-shadow .15s;
2917
+ }
2918
+ .ui-segmented--sm .ui-segmented-label { font-size: .75rem; padding: .25rem .65rem; }
2919
+ .ui-segmented--lg .ui-segmented-label { font-size: .95rem; padding: .55rem 1.1rem; }
2920
+ .ui-segmented-input:checked + .ui-segmented-label {
2921
+ background: var(--ui-surface);
2922
+ color: var(--ui-text);
2923
+ box-shadow: 0 1px 3px rgba(0,0,0,.25);
2924
+ }
2925
+ .ui-segmented-input:focus-visible + .ui-segmented-label {
2926
+ outline: 2px solid var(--ui-accent);
2927
+ outline-offset: 1px;
2928
+ }
2929
+
2930
+ /* ─── Breadcrumbs ────────────────────────────────────────────────────────── */
2931
+ .ui-breadcrumbs-list {
2932
+ display: flex;
2933
+ flex-wrap: wrap;
2934
+ align-items: center;
2935
+ gap: .25rem;
2936
+ list-style: none;
2937
+ padding: 0;
2938
+ margin: 0;
2939
+ font-size: .85rem;
2940
+ }
2941
+ .ui-breadcrumbs-item {
2942
+ display: flex;
2943
+ align-items: center;
2944
+ gap: .25rem;
2945
+ }
2946
+ .ui-breadcrumbs-link {
2947
+ color: var(--ui-muted);
2948
+ text-decoration: none;
2949
+ transition: color .15s;
2950
+ }
2951
+ .ui-breadcrumbs-link:hover { color: var(--ui-text); }
2952
+ .ui-breadcrumbs-current { color: var(--ui-text); }
2953
+ .ui-breadcrumbs-sep { color: var(--ui-border); user-select: none; }
2954
+
2955
+ /* ─── Stepper ────────────────────────────────────────────────────────────── */
2956
+ .ui-stepper {
2957
+ display: flex;
2958
+ align-items: flex-start;
2959
+ width: 100%;
2960
+ }
2961
+ .ui-stepper-item {
2962
+ flex: 1;
2963
+ display: flex;
2964
+ flex-direction: column;
2965
+ align-items: center;
2966
+ position: relative;
2967
+ }
2968
+ .ui-stepper-item:not(:last-child)::after {
2969
+ content: '';
2970
+ position: absolute;
2971
+ top: 13px;
2972
+ left: 50%;
2973
+ width: 100%;
2974
+ height: 2px;
2975
+ background: var(--ui-border);
2976
+ }
2977
+ .ui-stepper-item--complete:not(:last-child)::after { background: var(--ui-accent); }
2978
+ .ui-stepper-dot {
2979
+ position: relative;
2980
+ z-index: 1;
2981
+ width: 28px;
2982
+ height: 28px;
2983
+ border-radius: 50%;
2984
+ display: flex;
2985
+ align-items: center;
2986
+ justify-content: center;
2987
+ font-size: .75rem;
2988
+ font-weight: 700;
2989
+ background: var(--ui-surface-2);
2990
+ border: 2px solid var(--ui-border);
2991
+ color: var(--ui-muted);
2992
+ transition: background .2s, border-color .2s, color .2s;
2993
+ }
2994
+ .ui-stepper-item--complete .ui-stepper-dot {
2995
+ background: var(--ui-accent);
2996
+ border-color: var(--ui-accent);
2997
+ color: var(--ui-bg);
2998
+ }
2999
+ .ui-stepper-item--active .ui-stepper-dot {
3000
+ border-color: var(--ui-accent);
3001
+ color: var(--ui-accent);
3002
+ }
3003
+ .ui-stepper-label {
3004
+ margin-top: .5rem;
3005
+ font-size: .72rem;
3006
+ color: var(--ui-muted);
3007
+ text-align: center;
3008
+ line-height: 1.3;
3009
+ padding: 0 .25rem;
3010
+ }
3011
+ .ui-stepper-item--active .ui-stepper-label { color: var(--ui-text); font-weight: 600; }
3012
+ .ui-stepper-item--complete .ui-stepper-label { color: var(--ui-muted); }
3013
+
3014
+ /* ─── Image ──────────────────────────────────────────────────────────────── */
3015
+ .ui-image {
3016
+ display: block;
3017
+ }
3018
+ .ui-image-crop {
3019
+ overflow: hidden;
3020
+ border-radius: var(--ui-radius);
3021
+ }
3022
+ .ui-image-wrap {
3023
+ display: block;
3024
+ overflow: hidden;
3025
+ border-radius: var(--ui-radius);
3026
+ }
3027
+ .ui-image-img--cover {
3028
+ display: block;
3029
+ width: 100%;
3030
+ height: 100%;
3031
+ object-fit: cover;
3032
+ }
3033
+ .ui-image-img {
3034
+ display: block;
3035
+ max-width: 100%;
3036
+ height: auto;
3037
+ }
3038
+ .ui-image--rounded .ui-image-crop { border-radius: var(--ui-radius-lg, 1rem); }
3039
+ .ui-image--rounded .ui-image-wrap { border-radius: var(--ui-radius-lg, 1rem); }
3040
+ .ui-image--pill .ui-image-crop { border-radius: 999px; }
3041
+ .ui-image--pill .ui-image-wrap { border-radius: 999px; }
3042
+ .ui-image-caption {
3043
+ margin: .5rem 0 0;
3044
+ font-size: .8rem;
3045
+ color: var(--ui-muted);
3046
+ line-height: 1.5;
3047
+ }
3048
+
3049
+ /* ─── Pullquote ──────────────────────────────────────────────────────────── */
3050
+ .ui-pullquote {
3051
+ border-left: 3px solid var(--ui-accent);
3052
+ padding: .75rem 0 .75rem 1.5rem;
3053
+ margin: 0;
3054
+ }
3055
+ .ui-pullquote blockquote { margin: 0; padding: 0; }
3056
+ .ui-pullquote-text {
3057
+ font-size: 1.15rem;
3058
+ line-height: 1.6;
3059
+ color: var(--ui-text);
3060
+ font-style: italic;
3061
+ margin: 0;
3062
+ }
3063
+ .ui-pullquote--lg .ui-pullquote-text { font-size: 1.5rem; }
3064
+ .ui-pullquote-cite {
3065
+ display: block;
3066
+ margin-top: .75rem;
3067
+ font-size: .85rem;
3068
+ color: var(--ui-muted);
3069
+ font-style: normal;
3070
+ }
3071
+
3072
+ /* Editorial variant — centred large serif, no left border */
3073
+ .ui-pullquote--editorial {
3074
+ border-left: none;
3075
+ padding: 4rem 1.5rem;
3076
+ text-align: center;
3077
+ }
3078
+ .ui-pullquote--editorial .ui-pullquote-text {
3079
+ font-size: clamp(1.5rem, 3.5vw, 2.25rem);
3080
+ line-height: 1.4;
3081
+ font-style: italic;
3082
+ font-weight: 400;
3083
+ max-width: 640px;
3084
+ margin-left: auto;
3085
+ margin-right: auto;
3086
+ }
3087
+ .ui-pullquote--editorial.ui-pullquote--lg .ui-pullquote-text {
3088
+ font-size: clamp(1.75rem, 4vw, 3rem);
3089
+ }
3090
+ .ui-pullquote--editorial .ui-pullquote-cite {
3091
+ text-align: center;
3092
+ margin-top: 1.25rem;
3093
+ font-size: 0.9375rem;
3094
+ }
3095
+
3096
+ /* ─── List ───────────────────────────────────────────────────────────────────
3097
+ Styled list component. Use instead of raw <ul>/<ol>. */
3098
+ .ui-list {
3099
+ display: flex;
3100
+ flex-direction: column;
3101
+ padding-left: 1.5em;
3102
+ color: var(--ui-text);
3103
+ }
3104
+ .ui-list--unordered { list-style-type: disc; }
3105
+ .ui-list--ordered { list-style-type: decimal; }
3106
+ .ui-list-item { line-height: 1.6; }
3107
+
3108
+ /* ─── Prose ──────────────────────────────────────────────────────────────────
3109
+ Typography wrapper for rich text: CMS output, markdown-rendered HTML,
3110
+ blog/article bodies. Styles all descendant elements without class names. */
3111
+ .ui-prose {
3112
+ color: var(--ui-text);
3113
+ line-height: 1.75;
3114
+ font-size: 1rem;
3115
+ }
3116
+ .ui-prose--sm { font-size: .875rem; }
3117
+ .ui-prose--lg { font-size: 1.125rem; }
3118
+
3119
+ .ui-prose h1,
3120
+ .ui-prose h2,
3121
+ .ui-prose h3,
3122
+ .ui-prose h4,
3123
+ .ui-prose h5,
3124
+ .ui-prose h6 {
3125
+ color: var(--ui-text);
3126
+ font-weight: 700;
3127
+ line-height: 1.3;
3128
+ margin-top: 2em;
3129
+ margin-bottom: .6em;
3130
+ }
3131
+ .ui-prose h1 { font-size: 2rem; }
3132
+ .ui-prose h2 { font-size: 1.5rem; }
3133
+ .ui-prose h3 { font-size: 1.25rem; font-weight: 600; }
3134
+ .ui-prose h4 { font-size: 1rem; font-weight: 600; }
3135
+ .ui-prose h5 { font-size: .875rem; font-weight: 600; }
3136
+ .ui-prose h6 { font-size: .875rem; font-weight: 600; color: var(--ui-muted); }
3137
+
3138
+ .ui-prose :is(h1, h2, h3, h4, h5, h6):first-child { margin-top: 0; }
3139
+
3140
+ .ui-prose p { margin-bottom: 1.25em; }
3141
+ .ui-prose p:last-child { margin-bottom: 0; }
3142
+
3143
+ .ui-prose a {
3144
+ color: var(--ui-accent);
3145
+ text-decoration: underline;
3146
+ text-underline-offset: 2px;
3147
+ }
3148
+ .ui-prose a:hover { color: var(--ui-accent-hover); }
3149
+
3150
+ .ui-prose strong { font-weight: 700; }
3151
+ .ui-prose em { font-style: italic; }
3152
+
3153
+ .ui-prose ul,
3154
+ .ui-prose ol {
3155
+ padding-left: 1.5em;
3156
+ margin-bottom: 1.25em;
3157
+ }
3158
+ .ui-prose ul { list-style-type: disc; }
3159
+ .ui-prose ol { list-style-type: decimal; }
3160
+ .ui-prose ul ul { list-style-type: circle; }
3161
+ .ui-prose ul.contains-task-list { list-style: none; padding-left: 0; }
3162
+ .ui-prose li.task-list-item input[type="checkbox"] { margin-right: .4em; }
3163
+ .ui-prose li { margin-bottom: .375em; }
3164
+ .ui-prose li > ul,
3165
+ .ui-prose li > ol { margin-top: .375em; margin-bottom: .375em; }
3166
+
3167
+ .ui-prose blockquote {
3168
+ border-left: 3px solid var(--ui-border);
3169
+ padding: .5em 0 .5em 1.25em;
3170
+ margin: 1.5em 0;
3171
+ color: var(--ui-muted);
3172
+ font-style: italic;
3173
+ }
3174
+ .ui-prose blockquote p { margin-bottom: 0; }
3175
+
3176
+ .ui-prose code {
3177
+ background: var(--ui-surface-2);
3178
+ color: var(--ui-code-color);
3179
+ padding: .1em .35em;
3180
+ border-radius: var(--ui-radius-sm);
3181
+ font-size: .875em;
3182
+ font-family: var(--ui-mono);
3183
+ }
3184
+ .ui-prose pre {
3185
+ background: var(--ui-surface-2);
3186
+ border: 1px solid var(--ui-border);
3187
+ border-radius: var(--ui-radius);
3188
+ padding: 1em 1.25em;
3189
+ overflow-x: auto;
3190
+ margin-bottom: 1.25em;
3191
+ font-family: var(--ui-mono);
3192
+ font-size: .875em;
3193
+ line-height: 1.7;
3194
+ }
3195
+ .ui-prose pre code {
3196
+ background: none;
3197
+ color: inherit;
3198
+ padding: 0;
3199
+ font-size: inherit;
3200
+ }
3201
+
3202
+ .ui-prose hr {
3203
+ border: none;
3204
+ border-top: 1px solid var(--ui-border);
3205
+ margin: 2em 0;
3206
+ }
3207
+
3208
+ .ui-prose img {
3209
+ max-width: 100%;
3210
+ border-radius: var(--ui-radius);
3211
+ height: auto;
3212
+ }
3213
+ .ui-prose figure { margin: 1.5em 0; }
3214
+ .ui-prose figcaption {
3215
+ font-size: .875em;
3216
+ color: var(--ui-muted);
3217
+ margin-top: .5em;
3218
+ text-align: center;
3219
+ }
3220
+
3221
+ .ui-prose table {
3222
+ width: 100%;
3223
+ border-collapse: collapse;
3224
+ margin-bottom: 1.25em;
3225
+ font-size: .9375em;
3226
+ }
3227
+ .ui-prose th {
3228
+ text-align: left;
3229
+ padding: .5em .75em;
3230
+ border-bottom: 2px solid var(--ui-border);
3231
+ font-weight: 600;
3232
+ color: var(--ui-text);
3233
+ }
3234
+ .ui-prose td {
3235
+ padding: .5em .75em;
3236
+ border-bottom: 1px solid var(--ui-border);
3237
+ color: var(--ui-text);
3238
+ }
3239
+
3240
+ /* ─── Syntax highlighting tokens ────────────────────────────────────────────
3241
+ Used by ui-prose pre code blocks rendered via @invisibleloop/pulse/md.
3242
+ Dark theme defaults; light theme overrides below. */
3243
+ :root {
3244
+ --tok-kw: #c792ea;
3245
+ --tok-str: #c3e88d;
3246
+ --tok-cmt: #7a8a9a;
3247
+ --tok-num: #f78c6c;
3248
+ --tok-fn: #82aaff;
3249
+ --tok-op: #89ddff;
3250
+ --tok-punct: #7e8899;
3251
+ }
3252
+ .tok-kw { color: var(--tok-kw); }
3253
+ .tok-str { color: var(--tok-str); }
3254
+ .tok-cmt { color: var(--tok-cmt); font-style: italic; }
3255
+ .tok-num { color: var(--tok-num); }
3256
+ .tok-fn { color: var(--tok-fn); }
3257
+ .tok-op { color: var(--tok-op); }
3258
+ .tok-punct { color: var(--tok-punct); }
3259
+
3260
+ /* ─── Light theme ────────────────────────────────────────────────────────────
3261
+ Apply to any ancestor element: <body data-theme="light"> or .ui-theme-light
3262
+ All --ui-* tokens are overridden; component markup stays identical. */
3263
+ [data-theme="light"],
3264
+ .ui-theme-light {
3265
+ --ui-bg: var(--bg, #ffffff);
3266
+ --ui-surface: var(--surface, #f8f8fc);
3267
+ --ui-surface-2: var(--surface-2, #f0f0f8);
3268
+ --ui-border: var(--border, #d8d8e8);
3269
+ --ui-text: var(--text, #111118);
3270
+ --ui-muted: var(--muted, #60607a);
3271
+ --ui-accent: var(--accent, #6b5ce7);
3272
+ --ui-accent-hover: var(--accent-hover, #5847d6);
3273
+ --ui-accent-dim: var(--accent-dim, rgba(107, 92, 231, .12));
3274
+ --ui-accent-text: var(--accent-text, #ffffff);
3275
+ /* Inline code uses a slightly darker accent so it passes WCAG AA on --ui-surface-2 */
3276
+ --ui-code-color: var(--code-color, #4a3db5);
3277
+ --ui-green: var(--green, #166534);
3278
+ --ui-green-dim: rgba(22, 163, 74, .12);
3279
+ --ui-red: var(--red, #991b1b);
3280
+ --ui-red-dim: rgba(220, 38, 38, .12);
3281
+ --ui-yellow: #92400e;
3282
+ --ui-yellow-dim: rgba(217, 119, 6, .12);
3283
+ --ui-blue: #1e40af;
3284
+ --ui-blue-dim: rgba( 30, 64, 175, .12);
3285
+ --ui-nav-sticky-bg: rgba(255, 255, 255, .85);
3286
+ --ui-muted-bg: var(--muted-bg, rgba(0, 0, 0, .04));
3287
+ --ui-shadow: var(--shadow, 0 1px 3px rgba(0,0,0,.10), 0 1px 2px rgba(0,0,0,.06));
3288
+ --tok-kw: #7c3aed;
3289
+ --tok-str: #15803d;
3290
+ --tok-cmt: #6b7280;
3291
+ --tok-num: #c2410c;
3292
+ --tok-fn: #1d4ed8;
3293
+ --tok-op: #0891b2;
3294
+ --tok-punct: #6b7280;
3295
+ }
3296
+
3297
+ /* ─── Vibe presets ────────────────────────────────────────────────────────────
3298
+ meta.vibe sets data-vibe on <body>. Each vibe adjusts geometry and type
3299
+ tokens without touching colour — pair with a custom theme.css for full
3300
+ personality. All agents: set meta.vibe to get instant personality.
3301
+
3302
+ warm — rounded, friendly, inviting (local businesses, wellness)
3303
+ editorial — sharp, serif display, tight tracking (blogs, publications)
3304
+ playful — very rounded, loose, energetic (kids, lifestyle, food)
3305
+ minimal — razor-sharp, no shadows, refined (portfolios, luxury)
3306
+ bold — impact headings, strong presence (agencies, startups)
3307
+ brutalist — zero radius, oversized type, raw (art, fashion, counter-culture)
3308
+ retro — slab serif, medium radius, warm (vintage, craft, nostalgia)
3309
+ corporate — conservative geometry, tight tracking (B2B, finance, legal)
3310
+ neon — futuristic mono headline, glow-ready (tech, gaming, crypto)
3311
+ paper — organic radius, soft shadows, tactile (journals, bookshops) */
3312
+
3313
+ [data-vibe="warm"] {
3314
+ --ui-radius: 14px;
3315
+ --ui-radius-sm: 8px;
3316
+ --ui-letter-spacing-display: -0.01em;
3317
+ }
3318
+
3319
+ [data-vibe="editorial"] {
3320
+ --ui-radius: 0px;
3321
+ --ui-radius-sm: 0px;
3322
+ --ui-font-display: Georgia, 'Times New Roman', serif;
3323
+ --ui-letter-spacing-display: -0.04em;
3324
+ }
3325
+
3326
+ [data-vibe="playful"] {
3327
+ --ui-radius: 22px;
3328
+ --ui-radius-sm: 14px;
3329
+ --ui-letter-spacing-display: 0em;
3330
+ }
3331
+
3332
+ [data-vibe="minimal"] {
3333
+ --ui-radius: 2px;
3334
+ --ui-radius-sm: 1px;
3335
+ --ui-letter-spacing-display: 0.02em;
3336
+ }
3337
+
3338
+ [data-vibe="bold"] {
3339
+ --ui-radius: 6px;
3340
+ --ui-letter-spacing-display: -0.05em;
3341
+ }
3342
+
3343
+ [data-vibe="brutalist"] {
3344
+ --ui-radius: 0px;
3345
+ --ui-radius-sm: 0px;
3346
+ --ui-font-display: 'Arial Black', 'Impact', sans-serif;
3347
+ --ui-letter-spacing-display: -0.02em;
3348
+ }
3349
+
3350
+ [data-vibe="retro"] {
3351
+ --ui-radius: 8px;
3352
+ --ui-radius-sm: 4px;
3353
+ --ui-font-display: 'Rockwell', 'Courier New', Georgia, serif;
3354
+ --ui-letter-spacing-display: 0.01em;
3355
+ }
3356
+
3357
+ [data-vibe="corporate"] {
3358
+ --ui-radius: 4px;
3359
+ --ui-radius-sm: 2px;
3360
+ --ui-letter-spacing-display: -0.01em;
3361
+ }
3362
+
3363
+ [data-vibe="neon"] {
3364
+ --ui-radius: 3px;
3365
+ --ui-radius-sm: 2px;
3366
+ --ui-font-display: 'Courier New', 'Lucida Console', monospace;
3367
+ --ui-letter-spacing-display: -0.03em;
3368
+ }
3369
+
3370
+ [data-vibe="paper"] {
3371
+ --ui-radius: 10px;
3372
+ --ui-radius-sm: 6px;
3373
+ --ui-font-display: Georgia, 'Palatino Linotype', serif;
3374
+ --ui-letter-spacing-display: -0.02em;
3375
+ }
3376
+
3377
+ /* ─── Gallery ────────────────────────────────────────────────────────────── */
3378
+ .ui-gallery { display: grid; gap: 1rem; }
3379
+ .ui-gallery--cols-1 { grid-template-columns: 1fr; }
3380
+ .ui-gallery--cols-2 { grid-template-columns: repeat(2, 1fr); }
3381
+ .ui-gallery--cols-3 { grid-template-columns: repeat(3, 1fr); }
3382
+ .ui-gallery--cols-4 { grid-template-columns: repeat(4, 1fr); }
3383
+ .ui-gallery--gap-sm { gap: .5rem; }
3384
+ .ui-gallery--gap-lg { gap: 1.5rem; }
3385
+ .ui-gallery-item { margin: 0; }
3386
+ .ui-gallery-crop { overflow: hidden; }
3387
+ .ui-gallery-img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .3s ease; }
3388
+ .ui-gallery--rounded .ui-gallery-crop { border-radius: var(--ui-radius); }
3389
+ .ui-gallery-item:hover .ui-gallery-img { transform: scale(1.03); }
3390
+ .ui-gallery-link { display: block; }
3391
+ .ui-gallery-caption { font-size: .8125rem; color: var(--ui-muted); padding: .5rem 0 0; }
3392
+
3393
+ /* strip: horizontal scroll row */
3394
+ .ui-gallery--strip { grid-template-columns: none; display: flex; overflow-x: auto; gap: 1rem; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
3395
+ .ui-gallery--strip .ui-gallery-item { flex: 0 0 auto; width: 280px; scroll-snap-align: start; }
3396
+ .ui-gallery--strip .ui-gallery-crop { aspect-ratio: 3/4; }
3397
+
3398
+ /* masonry: CSS column layout */
3399
+ .ui-gallery--masonry { display: block; columns: 3; column-gap: 1rem; }
3400
+ .ui-gallery--masonry.ui-gallery--cols-2 { columns: 2; }
3401
+ .ui-gallery--masonry.ui-gallery--cols-4 { columns: 4; }
3402
+ .ui-gallery--masonry .ui-gallery-item { break-inside: avoid; margin-bottom: 1rem; }
3403
+ .ui-gallery--masonry .ui-gallery-crop { aspect-ratio: unset; }
3404
+ .ui-gallery--masonry .ui-gallery-img { height: auto; }
3405
+
3406
+ @media (max-width: 640px) {
3407
+ .ui-gallery--cols-3,
3408
+ .ui-gallery--cols-4 { grid-template-columns: repeat(2, 1fr); }
3409
+ .ui-gallery--masonry.ui-gallery--cols-3,
3410
+ .ui-gallery--masonry.ui-gallery--cols-4 { columns: 2; }
3411
+ }
3412
+
3413
+ /* ─── PhotoCard ──────────────────────────────────────────────────────────── */
3414
+ .ui-photo-card {
3415
+ margin: 0;
3416
+ display: inline-flex;
3417
+ flex-direction: column;
3418
+ background: var(--ui-surface);
3419
+ padding: .75rem .75rem .5rem;
3420
+ border: 1px solid var(--ui-border);
3421
+ box-shadow: 0 4px 12px rgba(0,0,0,.25);
3422
+ rotate: var(--photo-tilt, 0deg);
3423
+ transition: rotate .2s ease, box-shadow .2s ease;
3424
+ }
3425
+ .ui-photo-card:hover { box-shadow: 0 8px 24px rgba(0,0,0,.35); }
3426
+ .ui-photo-card--rounded .ui-photo-card-crop { border-radius: var(--ui-radius); overflow: hidden; }
3427
+ .ui-photo-card-crop { overflow: hidden; }
3428
+ .ui-photo-card-img { width: 100%; height: 100%; object-fit: cover; display: block; }
3429
+ .ui-photo-card-caption {
3430
+ font-size: .8125rem;
3431
+ color: var(--ui-muted);
3432
+ padding: .5rem .25rem .25rem;
3433
+ text-align: center;
3434
+ font-family: var(--ui-mono);
3435
+ }
3436
+
3437
+ /* ─── Marquee ────────────────────────────────────────────────────────────── */
3438
+ @keyframes ui-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
3439
+
3440
+ .ui-marquee { overflow: hidden; }
3441
+ .ui-marquee--fade {
3442
+ mask-image: linear-gradient(to right, transparent 0%, #000 10%, #000 90%, transparent 100%);
3443
+ -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 10%, #000 90%, transparent 100%);
3444
+ }
3445
+ .ui-marquee-track {
3446
+ display: flex;
3447
+ width: max-content;
3448
+ animation: ui-marquee var(--marquee-speed, 30s) linear infinite;
3449
+ animation-direction: var(--marquee-dir, normal);
3450
+ list-style: none;
3451
+ margin: 0;
3452
+ padding: 0;
3453
+ gap: 3rem;
3454
+ }
3455
+ .ui-marquee--gap-sm .ui-marquee-track { gap: 1rem; }
3456
+ .ui-marquee--gap-md .ui-marquee-track { gap: 2rem; }
3457
+ .ui-marquee--pause:hover .ui-marquee-track { animation-play-state: paused; }
3458
+ .ui-marquee-item { flex: 0 0 auto; display: flex; align-items: center; }
3459
+
3460
+ @media (prefers-reduced-motion: reduce) {
3461
+ .ui-marquee-track { animation: none; }
3462
+ .ui-marquee { overflow-x: auto; }
3463
+ }
3464
+
3465
+ /* ─── Decorate (SVG pattern overlay) ────────────────────────────────────── */
3466
+ .ui-decorate { pointer-events: none; }
3467
+
3468
+ /* ─── Product Card ───────────────────────────────────────────────────────── */
3469
+ .ui-product-card {
3470
+ position: relative;
3471
+ display: block;
3472
+ overflow: hidden;
3473
+ text-decoration: none;
3474
+ color: inherit;
3475
+ }
3476
+ .ui-product-card-crop {
3477
+ overflow: hidden;
3478
+ }
3479
+ .ui-product-card-img {
3480
+ width: 100%;
3481
+ height: 100%;
3482
+ object-fit: cover;
3483
+ display: block;
3484
+ transition: transform 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94);
3485
+ }
3486
+ .ui-product-card:hover .ui-product-card-img { transform: scale(1.04); }
3487
+ .ui-product-card:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: 2px; }
3488
+
3489
+ .ui-product-card-overlay {
3490
+ position: absolute;
3491
+ inset: 0;
3492
+ display: flex;
3493
+ flex-direction: column;
3494
+ justify-content: flex-end;
3495
+ padding: 1.25rem;
3496
+ background: linear-gradient(to top, rgba(0,0,0,0.55) 0%, transparent 55%);
3497
+ opacity: 0;
3498
+ transition: opacity 0.3s ease;
3499
+ }
3500
+ .ui-product-card:hover .ui-product-card-overlay { opacity: 1; }
3501
+
3502
+ /* Always-visible overlay for reduced-motion users */
3503
+ @media (prefers-reduced-motion: reduce) {
3504
+ .ui-product-card-img { transition: none; }
3505
+ .ui-product-card-overlay { opacity: 1; }
3506
+ }
3507
+
3508
+ .ui-product-card-name {
3509
+ font-size: 1rem;
3510
+ font-weight: 500;
3511
+ color: #fff;
3512
+ margin: 0;
3513
+ letter-spacing: 0.02em;
3514
+ }
3515
+ .ui-product-card-price {
3516
+ font-size: 0.875rem;
3517
+ color: rgba(255,255,255,0.75);
3518
+ margin: 0.3rem 0 0;
3519
+ }
3520
+
3521
+ .ui-product-card-badge {
3522
+ position: absolute;
3523
+ top: 1rem;
3524
+ left: 1rem;
3525
+ background: var(--ui-text);
3526
+ color: var(--ui-bg);
3527
+ font-size: 0.6875rem;
3528
+ font-weight: 600;
3529
+ letter-spacing: 0.08em;
3530
+ text-transform: uppercase;
3531
+ padding: 0.2em 0.6em;
3532
+ z-index: 1;
3533
+ }
3534
+ .ui-product-card--badge-right .ui-product-card-badge { left: auto; right: 1rem; }
3535
+
3536
+ /* Below layout — caption sits under the image, always visible */
3537
+ .ui-product-card--below {
3538
+ overflow: visible;
3539
+ }
3540
+ .ui-product-card-caption {
3541
+ text-align: center;
3542
+ padding: 0.75rem 0.5rem 0.25rem;
3543
+ background: var(--ui-surface);
3544
+ }
3545
+ .ui-product-card--below .ui-product-card-name {
3546
+ font-size: 1rem;
3547
+ font-weight: 400;
3548
+ color: var(--ui-text);
3549
+ margin: 0 0 0.25rem;
3550
+ font-style: normal;
3551
+ }
3552
+ .ui-product-card--below .ui-product-card-price {
3553
+ font-size: 0.875rem;
3554
+ color: var(--ui-muted);
3555
+ margin: 0;
3556
+ }
3557
+
3558
+ /* ─── Editorial Hero ─────────────────────────────────────────────────────── */
3559
+ .ui-editorial-hero {
3560
+ position: relative;
3561
+ overflow: hidden;
3562
+ }
3563
+
3564
+ .ui-editorial-hero-heading {
3565
+ position: absolute;
3566
+ width: 1px;
3567
+ height: 1px;
3568
+ overflow: hidden;
3569
+ clip: rect(0,0,0,0);
3570
+ margin: -1px;
3571
+ padding: 0;
3572
+ border: 0;
3573
+ }
3574
+
3575
+ .ui-editorial-hero-images {
3576
+ display: grid;
3577
+ grid-template-columns: 1fr 1fr;
3578
+ width: 100%;
3579
+ }
3580
+ .ui-editorial-hero-img {
3581
+ overflow: hidden;
3582
+ }
3583
+ .ui-editorial-hero-img img {
3584
+ width: 100%;
3585
+ height: 100%;
3586
+ object-fit: cover;
3587
+ display: block;
3588
+ }
3589
+
3590
+ .ui-editorial-hero-overlay {
3591
+ position: absolute;
3592
+ inset: 0;
3593
+ display: flex;
3594
+ flex-direction: column;
3595
+ justify-content: center;
3596
+ align-items: center;
3597
+ pointer-events: none;
3598
+ color: var(--ui-accent);
3599
+ mix-blend-mode: multiply;
3600
+ }
3601
+ .ui-editorial-hero-overlay span {
3602
+ display: block;
3603
+ font-size: clamp(3rem, 12vw, 11rem);
3604
+ font-weight: 700;
3605
+ letter-spacing: -0.04em;
3606
+ line-height: 0.9;
3607
+ text-transform: uppercase;
3608
+ white-space: nowrap;
3609
+ }
3610
+
3611
+ .ui-editorial-hero-cta {
3612
+ position: absolute;
3613
+ bottom: 1.5rem;
3614
+ left: 50%;
3615
+ transform: translateX(-50%);
3616
+ font-size: 0.75rem;
3617
+ letter-spacing: 0.1em;
3618
+ text-transform: uppercase;
3619
+ text-decoration: none;
3620
+ color: var(--ui-text);
3621
+ white-space: nowrap;
3622
+ }
3623
+
3624
+ @media (max-width: 640px) {
3625
+ .ui-editorial-hero-overlay span { font-size: clamp(2rem, 10vw, 4rem); }
3626
+ }
3627
+
3628
+ /* ─── Image Pair ─────────────────────────────────────────────────────────── */
3629
+ .ui-image-pair {
3630
+ display: grid;
3631
+ grid-template-columns: 1fr 1fr;
3632
+ width: 100%;
3633
+ }
3634
+ .ui-image-pair--gap-sm { gap: 0.5rem; }
3635
+ .ui-image-pair--gap-md { gap: 1.5rem; }
3636
+
3637
+ .ui-image-pair-col { overflow: hidden; }
3638
+ .ui-image-pair-img { overflow: hidden; }
3639
+ .ui-image-pair-crop { overflow: hidden; }
3640
+ .ui-image-pair-crop img {
3641
+ width: 100%;
3642
+ height: 100%;
3643
+ object-fit: cover;
3644
+ display: block;
3645
+ }
3646
+ .ui-image-pair--captioned .ui-image-pair-col { overflow: visible; }
3647
+
3648
+ .ui-image-pair-link {
3649
+ display: inline-block;
3650
+ margin-top: 0.75rem;
3651
+ font-size: 0.9375rem;
3652
+ text-decoration: none;
3653
+ color: var(--ui-text);
3654
+ }
3655
+ .ui-image-pair-link:hover { opacity: 0.6; }
3656
+
3657
+ @media (max-width: 480px) {
3658
+ .ui-image-pair { grid-template-columns: 1fr; }
3659
+ }
3660
+
3661
+ /* ─── Brand Statement ────────────────────────────────────────────────────── */
3662
+ .ui-brand-statement {
3663
+ padding: 5rem 1.5rem;
3664
+ text-align: center;
3665
+ }
3666
+ .ui-brand-statement--left { text-align: left; }
3667
+ .ui-brand-statement--right { text-align: right; }
3668
+
3669
+ .ui-brand-statement-inner {
3670
+ max-width: 860px;
3671
+ margin: 0 auto;
3672
+ }
3673
+
3674
+ .ui-brand-statement-text {
3675
+ font-size: clamp(1.5rem, 4vw, 2.5rem);
3676
+ line-height: 1.25;
3677
+ font-weight: 400;
3678
+ font-style: italic;
3679
+ margin: 0;
3680
+ color: var(--ui-text);
3681
+ }
3682
+
3683
+ .ui-brand-statement--display .ui-brand-statement-text {
3684
+ font-style: normal;
3685
+ font-weight: 700;
3686
+ }
3687
+
3688
+ .ui-brand-statement--sans .ui-brand-statement-text {
3689
+ font-style: normal;
3690
+ }
3691
+
3692
+ .ui-brand-statement--sm .ui-brand-statement-text { font-size: clamp(1.1rem, 2.5vw, 1.5rem); }
3693
+ .ui-brand-statement--lg .ui-brand-statement-text { font-size: clamp(2rem, 5vw, 3.5rem); }
3694
+
3695
+ .ui-brand-statement-attr {
3696
+ margin-top: 1.5rem;
3697
+ font-size: 0.9375rem;
3698
+ color: var(--ui-muted);
3699
+ font-style: italic;
3700
+ }
3701
+
3702
+ /* ------------------------------------------------------------------ */
3703
+ /* ServiceCard */
3704
+ /* ------------------------------------------------------------------ */
3705
+
3706
+ .ui-service-card {
3707
+ display: block;
3708
+ padding: var(--ui-space-5, 1.25rem);
3709
+ border: 1px solid var(--ui-border);
3710
+ border-radius: var(--ui-radius-md);
3711
+ background: var(--ui-surface);
3712
+ text-decoration: none;
3713
+ color: inherit;
3714
+ }
3715
+
3716
+ .ui-service-card--linked {
3717
+ transition: border-color 0.15s, box-shadow 0.15s;
3718
+ }
3719
+
3720
+ .ui-service-card--linked:hover {
3721
+ border-color: var(--ui-accent);
3722
+ box-shadow: 0 2px 12px var(--ui-shadow, rgba(0,0,0,.08));
3723
+ }
3724
+
3725
+ .ui-service-card-icon {
3726
+ display: inline-flex;
3727
+ align-items: center;
3728
+ justify-content: center;
3729
+ width: 2.5rem;
3730
+ height: 2.5rem;
3731
+ border-radius: var(--ui-radius);
3732
+ background: var(--ui-accent-tint);
3733
+ color: var(--ui-accent);
3734
+ margin-block-end: var(--ui-space-4, 1rem);
3735
+ }
3736
+
3737
+ .ui-service-card-title {
3738
+ font-size: var(--ui-text-md, 1rem);
3739
+ font-weight: 600;
3740
+ margin: 0 0 var(--ui-space-2, 0.5rem);
3741
+ color: var(--ui-text);
3742
+ }
3743
+
3744
+ .ui-service-card-desc {
3745
+ margin: 0;
3746
+ font-size: var(--ui-text-sm, 0.875rem);
3747
+ color: var(--ui-muted);
3748
+ line-height: 1.6;
3749
+ }
3750
+
3751
+ /* ------------------------------------------------------------------ */
3752
+ /* ContactRow */
3753
+ /* ------------------------------------------------------------------ */
3754
+
3755
+ .ui-contact-row {
3756
+ display: flex;
3757
+ flex-wrap: wrap;
3758
+ gap: var(--ui-space-3, 0.75rem) var(--ui-space-6, 1.5rem);
3759
+ list-style: none;
3760
+ margin: 0;
3761
+ padding: 0;
3762
+ }
3763
+
3764
+ .ui-contact-row--sm { font-size: var(--ui-text-sm, 0.875rem); }
3765
+
3766
+ .ui-contact-row-item {
3767
+ display: flex;
3768
+ align-items: center;
3769
+ gap: var(--ui-space-2, 0.5rem);
3770
+ color: var(--ui-muted);
3771
+ }
3772
+
3773
+ .ui-contact-row-item a {
3774
+ color: inherit;
3775
+ text-decoration: none;
3776
+ }
3777
+
3778
+ .ui-contact-row-item a:hover { color: var(--ui-accent); }
3779
+
3780
+ .ui-contact-row-icon {
3781
+ flex-shrink: 0;
3782
+ color: var(--ui-accent);
3783
+ line-height: 0;
3784
+ }
3785
+
3786
+ /* ------------------------------------------------------------------ */
3787
+ /* TrustList */
3788
+ /* ------------------------------------------------------------------ */
3789
+
3790
+ .ui-trust-list {
3791
+ display: flex;
3792
+ flex-wrap: wrap;
3793
+ gap: var(--ui-space-2, 0.5rem) var(--ui-space-5, 1.25rem);
3794
+ list-style: none;
3795
+ margin: 0;
3796
+ padding: 0;
3797
+ }
3798
+
3799
+ .ui-trust-list--md { font-size: var(--ui-text-md, 1rem); }
3800
+
3801
+ .ui-trust-list-item {
3802
+ display: flex;
3803
+ align-items: center;
3804
+ gap: var(--ui-space-2, 0.5rem);
3805
+ font-size: var(--ui-text-sm, 0.875rem);
3806
+ color: var(--ui-muted);
3807
+ }
3808
+
3809
+ .ui-trust-list-icon {
3810
+ flex-shrink: 0;
3811
+ color: var(--ui-accent);
3812
+ line-height: 0;
3813
+ }
3814
+
3815
+ /* ------------------------------------------------------------------ */
3816
+ /* TopStrip */
3817
+ /* ------------------------------------------------------------------ */
3818
+
3819
+ .ui-top-strip {
3820
+ display: flex;
3821
+ align-items: center;
3822
+ justify-content: space-between;
3823
+ padding: var(--ui-space-2, 0.5rem) var(--ui-space-6, 1.5rem);
3824
+ background: var(--ui-surface-raised, var(--ui-surface));
3825
+ font-size: var(--ui-text-xs, 0.75rem);
3826
+ color: var(--ui-muted);
3827
+ gap: var(--ui-space-4, 1rem);
3828
+ }
3829
+
3830
+ .ui-top-strip-content,
3831
+ .ui-top-strip-left,
3832
+ .ui-top-strip-right {
3833
+ display: flex;
3834
+ align-items: center;
3835
+ gap: var(--ui-space-4, 1rem);
3836
+ flex-wrap: wrap;
3837
+ }
3838
+
3839
+ @media (max-width: 640px) {
3840
+ .ui-top-strip {
3841
+ flex-direction: column;
3842
+ align-items: flex-start;
3843
+ gap: var(--ui-space-1, 0.25rem);
3844
+ }
3845
+ }
3846
+
3847
+ /* ------------------------------------------------------------------ */
3848
+ /* StatGrid */
3849
+ /* ------------------------------------------------------------------ */
3850
+
3851
+ .ui-stat-grid {
3852
+ display: grid;
3853
+ gap: var(--ui-space-4, 1rem);
3854
+ grid-template-columns: repeat(var(--stat-cols, 2), 1fr);
3855
+ padding: var(--ui-space-6, 1.5rem);
3856
+ border-radius: var(--ui-radius-md);
3857
+ }
3858
+
3859
+ .ui-stat-grid .ui-stat-value {
3860
+ font-size: clamp(1.5rem, 3vw, 2.25rem);
3861
+ line-height: 1.1;
3862
+ }
3863
+
3864
+ /* Stat suffix — icon/rating appended to the value */
3865
+ .ui-stat-suffix {
3866
+ display: inline-flex;
3867
+ align-items: center;
3868
+ margin-left: 0.2em;
3869
+ font-size: 0.6em;
3870
+ vertical-align: middle;
3871
+ line-height: 0;
3872
+ }
3873
+
3874
+ /* ─── Editorial Components ───────────────────────────────────────────────────
3875
+ Components for editorial/typographic layouts: entryList, displayHeading,
3876
+ sectionLabel, dropCap, colophon. */
3877
+
3878
+ /* Entry List — tabular list for backlists, release notes, changelogs */
3879
+ .ui-entry-list {
3880
+ display: flex;
3881
+ flex-direction: column;
3882
+ gap: 1.5rem;
3883
+ }
3884
+
3885
+ .ui-entry-list-item {
3886
+ display: grid;
3887
+ grid-template-columns: minmax(4rem, max-content) 1fr;
3888
+ gap: 2rem;
3889
+ align-items: baseline;
3890
+ }
3891
+
3892
+ @media (max-width: 640px) {
3893
+ .ui-entry-list-item {
3894
+ grid-template-columns: 1fr;
3895
+ gap: 0.5rem;
3896
+ }
3897
+ }
3898
+
3899
+ .ui-entry-list-meta {
3900
+ font-size: 0.9rem;
3901
+ color: var(--ui-muted);
3902
+ font-weight: 600;
3903
+ text-transform: uppercase;
3904
+ letter-spacing: 0.05em;
3905
+ font-variant-numeric: tabular-nums;
3906
+ }
3907
+
3908
+ .ui-entry-list-content {
3909
+ display: flex;
3910
+ flex-direction: column;
3911
+ gap: 0.5rem;
3912
+ }
3913
+
3914
+ .ui-entry-list-title {
3915
+ font-size: 1.1rem;
3916
+ font-weight: 600;
3917
+ color: var(--ui-text);
3918
+ line-height: 1.4;
3919
+ margin: 0;
3920
+ }
3921
+
3922
+ .ui-entry-list-description {
3923
+ font-size: 0.9rem;
3924
+ color: var(--ui-muted);
3925
+ line-height: 1.6;
3926
+ margin: 0;
3927
+ }
3928
+
3929
+ /* Display Heading — large typographic moments */
3930
+ .ui-display-heading {
3931
+ font-size: clamp(2.5rem, 6vw, 5rem);
3932
+ font-weight: 800;
3933
+ color: var(--ui-text);
3934
+ line-height: 1.1;
3935
+ margin: 0;
3936
+ }
3937
+
3938
+ /* Section Label — eyebrow + h2 + rule */
3939
+ .ui-section-label {
3940
+ display: flex;
3941
+ flex-direction: column;
3942
+ gap: 0.75rem;
3943
+ margin-bottom: 2rem;
3944
+ }
3945
+
3946
+ .ui-section-label--center {
3947
+ align-items: center;
3948
+ text-align: center;
3949
+ }
3950
+
3951
+ .ui-section-label-eyebrow {
3952
+ font-size: 0.85rem;
3953
+ color: var(--ui-muted);
3954
+ font-weight: 600;
3955
+ text-transform: uppercase;
3956
+ letter-spacing: 0.08em;
3957
+ margin: 0;
3958
+ }
3959
+
3960
+ .ui-section-label-heading {
3961
+ font-size: 1.75rem;
3962
+ font-weight: 700;
3963
+ color: var(--ui-text);
3964
+ line-height: 1.2;
3965
+ margin: 0;
3966
+ }
3967
+
3968
+ .ui-section-label-rule {
3969
+ width: 100%;
3970
+ max-width: 8rem;
3971
+ height: 2px;
3972
+ background: var(--ui-border);
3973
+ border: none;
3974
+ margin: 0;
3975
+ }
3976
+
3977
+ .ui-section-label--center .ui-section-label-rule {
3978
+ margin-left: auto;
3979
+ margin-right: auto;
3980
+ }
3981
+
3982
+ /* Drop Cap — first-letter treatment */
3983
+ .ui-drop-cap {
3984
+ margin: 0;
3985
+ line-height: 1.75;
3986
+ color: var(--ui-text);
3987
+ }
3988
+
3989
+ .ui-drop-cap-letter {
3990
+ font-weight: 700;
3991
+ color: var(--ui-text);
3992
+ }
3993
+
3994
+ /* Colophon — minimal footer for editorial pages */
3995
+ .ui-colophon {
3996
+ padding: 3rem 1.5rem 2rem;
3997
+ border-top: 1px solid var(--ui-border);
3998
+ margin-top: 4rem;
3999
+ text-align: center;
4000
+ }
4001
+
4002
+ .ui-colophon--left {
4003
+ text-align: left;
4004
+ }
4005
+
4006
+ .ui-colophon-inner {
4007
+ max-width: 640px;
4008
+ margin: 0 auto;
4009
+ font-size: 0.85rem;
4010
+ color: var(--ui-muted);
4011
+ line-height: 1.6;
4012
+ }
4013
+
4014
+ .ui-colophon-inner p {
4015
+ margin: 0.5em 0;
4016
+ }
4017
+
4018
+ .ui-colophon-inner p:last-child {
4019
+ margin-bottom: 0;
4020
+ }
4021
+
4022
+ .ui-colophon-inner a {
4023
+ color: var(--ui-muted);
4024
+ text-decoration: underline;
4025
+ text-underline-offset: 2px;
4026
+ transition: color 0.15s;
4027
+ }
4028
+
4029
+ .ui-colophon-inner a:hover {
4030
+ color: var(--ui-text);
4031
+ }