@paraxe/design 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3743 @@
1
+ /* ==========================================================================
2
+ @loba/design — components.css
3
+ Shared HTML/CSS component classes (framework-agnostic).
4
+
5
+ These classes consume the canonical Loba tokens:
6
+ - Structural tokens → tokens.css (--button-*, --card-*, etc.)
7
+ - Color tokens → themes/*.css (--button-primary-bg, etc.)
8
+ - Personality → presets/*.css (--button-radius, etc.)
9
+
10
+ They are the SINGLE source of truth for the framework-agnostic component
11
+ layer. `@loba/ui` consumers use the Vue components instead (no duplicate
12
+ class layer). Non-`@loba/ui` projects consume these classes directly.
13
+
14
+ ✅ DO put here:
15
+ - Button classes (.btn, .btn-primary, .btn-secondary, etc.)
16
+ - Card classes (.card, .card-hoverable)
17
+ - Badge class (.badge)
18
+ - Layout primitives (.container, .section, .stack, .inline, .grid)
19
+ - Navbar classes (.navbar, .nav-link, .nav-link-active)
20
+ - Form controls (.input, .textarea, .select)
21
+ - Animation utility classes (.animate-fade-in, etc.)
22
+
23
+ ❌ DO NOT put here:
24
+ - Token definitions (→ tokens.css / themes/*.css / presets/*.css)
25
+ - Base element styles (→ @loba/ui base.css / project globals)
26
+ - @keyframes definitions (→ project animations.css / typography.css)
27
+ ========================================================================== */
28
+
29
+ /* ==========================================================================
30
+ BUTTONS
31
+ ========================================================================== */
32
+
33
+ .btn {
34
+ display: inline-flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ gap: var(--button-gap);
38
+
39
+ min-height: var(--button-min-height);
40
+ padding: var(--button-padding-y) var(--button-padding-x);
41
+
42
+ border: 1px solid transparent;
43
+ border-radius: var(--button-radius);
44
+
45
+ font-family: var(--font-family-body);
46
+ font-size: var(--typography-button-size);
47
+ font-weight: var(--typography-button-weight);
48
+ line-height: var(--typography-button-lineheight);
49
+
50
+ text-decoration: none;
51
+ white-space: nowrap;
52
+ user-select: none;
53
+ cursor: pointer;
54
+
55
+ transition:
56
+ background-color var(--motion-duration-fast) var(--motion-ease-out),
57
+ border-color var(--motion-duration-fast) var(--motion-ease-out),
58
+ color var(--motion-duration-fast) var(--motion-ease-out),
59
+ transform var(--motion-duration-fast) var(--motion-ease-out),
60
+ box-shadow var(--motion-duration-fast) var(--motion-ease-out);
61
+ }
62
+
63
+ .btn:focus-visible {
64
+ outline: var(--focus-ring-width) solid var(--focus-ring-color);
65
+ outline-offset: var(--focus-ring-offset);
66
+ }
67
+
68
+ .btn:disabled {
69
+ cursor: not-allowed;
70
+ pointer-events: none;
71
+ }
72
+
73
+ /* --------------------------------------------------------------------------
74
+ VARIANTS
75
+ -------------------------------------------------------------------------- */
76
+
77
+ .btn-primary {
78
+ background: var(--button-primary-bg);
79
+ color: var(--button-primary-text);
80
+ border-color: var(--button-primary-border);
81
+ }
82
+
83
+ .btn-primary:hover {
84
+ background: var(--button-primary-hover-bg);
85
+ border-color: var(--button-primary-hover-border);
86
+ }
87
+
88
+ .btn-primary:active {
89
+ background: var(--button-primary-active-bg);
90
+ }
91
+
92
+ .btn-primary:disabled {
93
+ background: var(--button-primary-disabled-bg);
94
+ color: var(--button-primary-disabled-text);
95
+ border-color: var(--button-primary-disabled-border);
96
+ }
97
+
98
+
99
+ .btn-secondary {
100
+ background: var(--button-secondary-bg);
101
+ color: var(--button-secondary-text);
102
+ border-color: var(--button-secondary-border);
103
+ }
104
+
105
+ .btn-secondary:hover {
106
+ background: var(--button-secondary-hover-bg);
107
+ border-color: var(--button-secondary-hover-border);
108
+ }
109
+
110
+ .btn-secondary:active {
111
+ background: var(--button-secondary-active-bg);
112
+ }
113
+
114
+ .btn-secondary:disabled {
115
+ background: var(--button-secondary-disabled-bg);
116
+ color: var(--button-secondary-disabled-text);
117
+ border-color: var(--button-secondary-disabled-border);
118
+ }
119
+
120
+
121
+ .btn-destructive {
122
+ background: var(--button-destructive-bg);
123
+ color: var(--button-destructive-text);
124
+ border-color: var(--button-destructive-border);
125
+ }
126
+
127
+ .btn-destructive:hover {
128
+ background: var(--button-destructive-hover-bg);
129
+ border-color: var(--button-destructive-hover-border);
130
+ }
131
+
132
+ .btn-destructive:active {
133
+ background: var(--button-destructive-active-bg);
134
+ }
135
+
136
+ .btn-destructive:disabled {
137
+ background: var(--button-destructive-disabled-bg);
138
+ color: var(--button-destructive-disabled-text);
139
+ border-color: var(--button-destructive-disabled-border);
140
+ }
141
+
142
+
143
+ .btn-ghost {
144
+ background: var(--button-ghost-bg);
145
+ color: var(--button-ghost-text);
146
+ border-color: var(--button-ghost-border);
147
+ }
148
+
149
+ .btn-ghost:hover {
150
+ background: var(--button-ghost-hover-bg);
151
+ border-color: var(--button-ghost-hover-border);
152
+ }
153
+
154
+ .btn-ghost:active {
155
+ background: var(--button-ghost-active-bg);
156
+ }
157
+
158
+ .btn-ghost:disabled {
159
+ background: var(--button-ghost-disabled-bg);
160
+ color: var(--button-ghost-disabled-text);
161
+ border-color: var(--button-ghost-disabled-border);
162
+ }
163
+
164
+
165
+ /* --------------------------------------------------------------------------
166
+ SIZES
167
+ -------------------------------------------------------------------------- */
168
+
169
+ .btn-sm {
170
+ min-height: var(--button-min-height-sm);
171
+ padding: var(--button-padding-y-sm) var(--button-padding-x-sm);
172
+ font-size: var(--font-size-xs);
173
+ }
174
+
175
+ .btn-md {
176
+ min-height: var(--button-min-height);
177
+ padding: var(--button-padding-y) var(--button-padding-x);
178
+ font-size: var(--typography-button-size);
179
+ }
180
+
181
+ .btn-lg {
182
+ min-height: var(--button-min-height-lg);
183
+ padding: var(--button-padding-y-lg) var(--button-padding-x-lg);
184
+ font-size: var(--font-size-base);
185
+ }
186
+
187
+
188
+ /* --------------------------------------------------------------------------
189
+ WIDTH
190
+ -------------------------------------------------------------------------- */
191
+
192
+ .btn-full {
193
+ width: 100%;
194
+ }
195
+
196
+
197
+ /* --------------------------------------------------------------------------
198
+ ICON-ONLY
199
+ -------------------------------------------------------------------------- */
200
+
201
+ .btn-icon-only {
202
+ aspect-ratio: 1;
203
+ padding-inline: 0;
204
+ }
205
+
206
+
207
+ /* --------------------------------------------------------------------------
208
+ LOADING
209
+ -------------------------------------------------------------------------- */
210
+
211
+ .btn-loading {
212
+ cursor: wait;
213
+ pointer-events: none;
214
+ }
215
+
216
+
217
+ /* --------------------------------------------------------------------------
218
+ REDUCED MOTION
219
+ -------------------------------------------------------------------------- */
220
+
221
+ @media (prefers-reduced-motion: reduce) {
222
+ .btn {
223
+ transition: none;
224
+ }
225
+ }
226
+
227
+ /* ==========================================================================
228
+ EDITORIAL & COMPOSITION
229
+ Semantic composition primitives for marketing, editorial, and agency sites.
230
+ These are framework-agnostic and consume canonical Loba tokens.
231
+ ========================================================================== */
232
+ /* --------------------------------------------------------------------------
233
+ ACCORDION
234
+ -------------------------------------------------------------------------- */
235
+
236
+ .accordion {
237
+ width: 100%;
238
+ }
239
+
240
+
241
+ /* --------------------------------------------------------------------------
242
+ ACCORDION ITEM
243
+ -------------------------------------------------------------------------- */
244
+
245
+ .accordion-item {
246
+ width: 100%;
247
+ }
248
+
249
+
250
+ /* --------------------------------------------------------------------------
251
+ ACCORDION TRIGGER
252
+ -------------------------------------------------------------------------- */
253
+
254
+ .accordion-trigger {
255
+ width: 100%;
256
+ display: flex;
257
+ align-items: center;
258
+ justify-content: space-between;
259
+ gap: var(--space-4);
260
+
261
+ padding-block: var(--space-5);
262
+
263
+ background: none;
264
+ border: 0;
265
+ border-bottom: 1px solid var(--border-subtle);
266
+
267
+ color: var(--text-primary);
268
+ font-family: var(--font-family-body);
269
+ font-size: var(--font-size-base);
270
+ font-weight: var(--font-weight-semibold);
271
+ text-align: left;
272
+
273
+ cursor: pointer;
274
+ transition: var(--transition-fast);
275
+ }
276
+
277
+ .accordion-trigger:hover {
278
+ color: var(--text-accent);
279
+ }
280
+
281
+ .accordion-trigger:focus-visible {
282
+ outline: var(--focus-ring-width) solid var(--form-border-focus);
283
+ outline-offset: var(--focus-ring-offset);
284
+ }
285
+
286
+ .accordion-trigger:disabled {
287
+ color: var(--text-muted);
288
+ cursor: not-allowed;
289
+ }
290
+
291
+
292
+ /* --------------------------------------------------------------------------
293
+ ACCORDION CONTENT
294
+ -------------------------------------------------------------------------- */
295
+
296
+ .accordion-content {
297
+ padding-block: var(--space-5);
298
+ color: var(--text-secondary);
299
+ }
300
+ /* -------------------------------------------------------------------------
301
+ DIVIDER
302
+ --------------------------------------------------------------------------- */
303
+ .divider {
304
+ width: 100%;
305
+ border-top: 1px solid var(--border-subtle);
306
+ }
307
+ /* --------------------------------------------------------------------------
308
+ EYEBROW
309
+ -------------------------------------------------------------------------- */
310
+
311
+ .eyebrow {
312
+ display: inline-flex;
313
+ align-items: center;
314
+ gap: var(--space-2);
315
+ width: fit-content;
316
+
317
+ color: var(--text-accent);
318
+ font-family: var(--font-family-body);
319
+ font-size: var(--font-size-xs);
320
+ font-weight: var(--font-weight-semibold);
321
+ line-height: 1;
322
+ letter-spacing: var(--letter-spacing-wider);
323
+ text-transform: uppercase;
324
+ }
325
+
326
+ .eyebrow::before {
327
+ content: "";
328
+
329
+ width: 0.375rem;
330
+ height: 0.375rem;
331
+ flex: 0 0 auto;
332
+
333
+ border-radius: var(--radius-full);
334
+ background: var(--brand-primary);
335
+ }
336
+
337
+
338
+ /* --------------------------------------------------------------------------
339
+ LABEL
340
+ -------------------------------------------------------------------------- */
341
+
342
+ .label {
343
+ display: inline-block;
344
+
345
+ color: var(--text-muted);
346
+ font-family: var(--font-family-body);
347
+ font-size: var(--font-size-xs);
348
+ font-weight: var(--font-weight-semibold);
349
+ line-height: var(--line-height-snug);
350
+ letter-spacing: var(--letter-spacing-wide);
351
+ text-transform: uppercase;
352
+ }
353
+
354
+
355
+ /* --------------------------------------------------------------------------
356
+ SECTION HEADER
357
+ -------------------------------------------------------------------------- */
358
+
359
+ .section-header {
360
+ display: flex;
361
+ flex-direction: column;
362
+ align-items: flex-start;
363
+ gap: var(--stack-gap);
364
+
365
+ max-width: 45rem;
366
+ margin-bottom: var(--space-12);
367
+ }
368
+
369
+ .section-header--wide {
370
+ max-width: 62.5rem;
371
+ }
372
+
373
+ .section-header--center {
374
+ align-items: center;
375
+ margin-inline: auto;
376
+ text-align: center;
377
+ }
378
+
379
+ .section-header--center .section-description {
380
+ margin-inline: auto;
381
+ }
382
+
383
+
384
+ /* --------------------------------------------------------------------------
385
+ SECTION TITLE
386
+ -------------------------------------------------------------------------- */
387
+
388
+ .section-title {
389
+ margin: 0;
390
+
391
+ max-width: 18ch;
392
+
393
+ color: var(--text-primary);
394
+ font-family: var(--font-family-display);
395
+ font-size: clamp(
396
+ var(--font-size-3xl),
397
+ 4vw,
398
+ var(--font-size-5xl)
399
+ );
400
+ font-weight: var(--font-weight-bold);
401
+ line-height: var(--line-height-tight);
402
+ letter-spacing: var(--letter-spacing-tight);
403
+
404
+ text-wrap: balance;
405
+ }
406
+
407
+ .section-header--wide .section-title {
408
+ max-width: 24ch;
409
+ }
410
+
411
+
412
+ /* --------------------------------------------------------------------------
413
+ SECTION DESCRIPTION
414
+ -------------------------------------------------------------------------- */
415
+
416
+ .section-description {
417
+ max-width: var(--content-width-narrow);
418
+ margin: 0;
419
+
420
+ color: var(--text-secondary);
421
+ font-family: var(--font-family-body);
422
+ font-size: var(--font-size-base);
423
+ font-weight: var(--font-weight-regular);
424
+ line-height: var(--line-height-relaxed);
425
+
426
+ text-wrap: pretty;
427
+ }
428
+
429
+
430
+ /* --------------------------------------------------------------------------
431
+ LEAD / LARGE BODY
432
+ -------------------------------------------------------------------------- */
433
+
434
+ .lead {
435
+ max-width: 42rem;
436
+ margin: 0;
437
+
438
+ color: var(--text-secondary);
439
+ font-family: var(--font-family-body);
440
+ font-size: clamp(
441
+ var(--font-size-lg),
442
+ 2vw,
443
+ var(--font-size-xl)
444
+ );
445
+ font-weight: var(--font-weight-regular);
446
+ line-height: var(--line-height-relaxed);
447
+
448
+ text-wrap: pretty;
449
+ }
450
+
451
+ .body-large {
452
+ color: var(--text-secondary);
453
+ font-family: var(--font-family-body);
454
+ font-size: var(--font-size-lg);
455
+ line-height: var(--line-height-relaxed);
456
+ }
457
+
458
+
459
+ /* --------------------------------------------------------------------------
460
+ BUTTON GROUP
461
+ -------------------------------------------------------------------------- */
462
+
463
+ .button-group {
464
+ display: flex;
465
+ flex-wrap: wrap;
466
+ align-items: center;
467
+ gap: var(--inline-gap);
468
+ }
469
+
470
+ .button-group--center {
471
+ justify-content: center;
472
+ }
473
+
474
+ .button-group--end {
475
+ justify-content: flex-end;
476
+ }
477
+
478
+ .button-group--stack {
479
+ flex-direction: column;
480
+ align-items: stretch;
481
+ }
482
+
483
+
484
+ /* --------------------------------------------------------------------------
485
+ ARROW LINK
486
+ -------------------------------------------------------------------------- */
487
+
488
+ .link-arrow {
489
+ display: inline-flex;
490
+ align-items: center;
491
+ gap: var(--space-2);
492
+
493
+ width: fit-content;
494
+
495
+ color: var(--text-primary);
496
+ font-family: var(--font-family-body);
497
+ font-size: var(--font-size-sm);
498
+ font-weight: var(--font-weight-semibold);
499
+ line-height: 1;
500
+ text-decoration: none;
501
+
502
+ transition:
503
+ color var(--motion-duration-fast) var(--motion-ease-out),
504
+ gap var(--motion-duration-fast) var(--motion-ease-out);
505
+ }
506
+
507
+ .link-arrow::after {
508
+ content: "→";
509
+
510
+ transition:
511
+ transform var(--motion-duration-fast) var(--motion-ease-out);
512
+ }
513
+
514
+ .link-arrow:hover {
515
+ gap: var(--space-3);
516
+ color: var(--text-accent);
517
+ }
518
+
519
+ .link-arrow:hover::after {
520
+ transform: translateX(0.1875rem);
521
+ }
522
+
523
+ .link-arrow:focus-visible {
524
+ outline: var(--focus-ring-width) solid var(--focus-ring-color);
525
+ outline-offset: var(--focus-ring-offset);
526
+ border-radius: var(--radius-sm);
527
+ }
528
+
529
+
530
+ .media {
531
+ position: relative;
532
+ overflow: hidden;
533
+ }
534
+
535
+ .media img,
536
+ .media video {
537
+ display: block;
538
+ width: 100%;
539
+ height: 100%;
540
+ object-fit: cover;
541
+ border-radius: var(--media-radius);
542
+ }
543
+
544
+ .media-square {
545
+ aspect-ratio: 1 / 1;
546
+ }
547
+
548
+ .media-video {
549
+ aspect-ratio: 16 / 9;
550
+ }
551
+
552
+ .media-portrait {
553
+ aspect-ratio: 4 / 5;
554
+ }
555
+
556
+ .media-wide {
557
+ aspect-ratio: 21 / 9;
558
+ }
559
+
560
+ .media-contain img,
561
+ .media-contain video {
562
+ object-fit: contain;
563
+ }
564
+
565
+
566
+ /* --------------------------------------------------------------------------
567
+ PROSE
568
+ -------------------------------------------------------------------------- */
569
+
570
+ .prose {
571
+ max-width: var(--content-width-narrow);
572
+
573
+ color: var(--text-secondary);
574
+ font-family: var(--font-family-body);
575
+ font-size: var(--font-size-base);
576
+ line-height: var(--line-height-relaxed);
577
+ }
578
+
579
+ .prose > * + * {
580
+ margin-top: var(--space-6);
581
+ }
582
+
583
+ .prose h2,
584
+ .prose h3,
585
+ .prose h4 {
586
+ color: var(--text-primary);
587
+ font-family: var(--font-family-display);
588
+ letter-spacing: var(--letter-spacing-tight);
589
+ }
590
+
591
+ .prose h2 {
592
+ font-size: var(--font-size-3xl);
593
+ line-height: var(--line-height-tight);
594
+ }
595
+
596
+ .prose h3 {
597
+ font-size: var(--font-size-2xl);
598
+ line-height: var(--line-height-tight);
599
+ }
600
+
601
+ .prose h4 {
602
+ font-size: var(--font-size-xl);
603
+ line-height: var(--line-height-snug);
604
+ }
605
+
606
+ .prose a {
607
+ color: var(--text-link);
608
+ text-decoration: underline;
609
+ text-underline-offset: 0.2em;
610
+ }
611
+
612
+ .prose a:hover {
613
+ color: var(--text-link-hover);
614
+ }
615
+
616
+ .prose ul,
617
+ .prose ol {
618
+ padding-left: var(--space-6);
619
+ }
620
+
621
+ .prose li + li {
622
+ margin-top: var(--space-2);
623
+ }
624
+
625
+
626
+ /* --------------------------------------------------------------------------
627
+ RESPONSIVE
628
+ -------------------------------------------------------------------------- */
629
+
630
+ @media (max-width: 768px) {
631
+ .section-header {
632
+ margin-bottom: var(--space-8);
633
+ }
634
+
635
+ .section-title {
636
+ max-width: 100%;
637
+ font-size: var(--font-size-3xl);
638
+ }
639
+
640
+ .section-header--wide .section-title {
641
+ max-width: 100%;
642
+ }
643
+
644
+ .button-group--stack-mobile {
645
+ flex-direction: column;
646
+ align-items: stretch;
647
+ }
648
+
649
+ .button-group--stack-mobile > .btn {
650
+ width: 100%;
651
+ }
652
+ }
653
+
654
+ /* ==========================================================================
655
+ SURFACES
656
+ Visual layering / treatment.
657
+ Surface does not own content padding.
658
+ ========================================================================== */
659
+
660
+ .surface {
661
+ width: 100%;
662
+ }
663
+
664
+ .surface-base {
665
+ background: var(--surface-base);
666
+ }
667
+
668
+ .surface-raised {
669
+ background: var(--surface-raised);
670
+ }
671
+
672
+ .surface-card {
673
+ background: var(--surface-card);
674
+ }
675
+
676
+ .surface-elevated-1 {
677
+ background: var(--surface-elevated-1);
678
+ }
679
+
680
+ .surface-elevated-2 {
681
+ background: var(--surface-elevated-2);
682
+ }
683
+
684
+ .surface-elevated-3 {
685
+ background: var(--surface-elevated-3);
686
+ }
687
+
688
+
689
+ /* --------------------------------------------------------------------------
690
+ SURFACE EFFECTS
691
+ -------------------------------------------------------------------------- */
692
+
693
+ .surface-glass {
694
+ background: var(--glass-background);
695
+ border: 1px solid var(--glass-border);
696
+
697
+ backdrop-filter:
698
+ blur(var(--glass-blur))
699
+ saturate(var(--glass-saturate));
700
+
701
+ -webkit-backdrop-filter:
702
+ blur(var(--glass-blur))
703
+ saturate(var(--glass-saturate));
704
+
705
+ box-shadow:
706
+ var(
707
+ --card-highlight,
708
+ inset 0 1px 0 0 rgb(255 255 255 / 0.08)
709
+ );
710
+ }
711
+
712
+ .surface-glass-strong {
713
+ background: var(--surface-glass-strong);
714
+ border: 1px solid var(--glass-border);
715
+
716
+ backdrop-filter:
717
+ blur(var(--glass-blur))
718
+ saturate(var(--glass-saturate));
719
+
720
+ -webkit-backdrop-filter:
721
+ blur(var(--glass-blur))
722
+ saturate(var(--glass-saturate));
723
+
724
+ box-shadow:
725
+ var(
726
+ --card-highlight,
727
+ inset 0 1px 0 0 rgb(255 255 255 / 0.08)
728
+ );
729
+ }
730
+
731
+
732
+ /* ==========================================================================
733
+ CARDS
734
+ Content container / grouping primitive.
735
+ ========================================================================== */
736
+
737
+ .card {
738
+ width: 100%;
739
+ padding: var(--card-padding);
740
+ border-radius: var(--card-radius);
741
+
742
+ background: var(--card-background);
743
+ color: var(--text-primary);
744
+ }
745
+
746
+
747
+ /* --------------------------------------------------------------------------
748
+ VARIANTS
749
+ -------------------------------------------------------------------------- */
750
+
751
+ .card-default {
752
+ border: 1px solid transparent;
753
+ }
754
+
755
+ .card-outlined {
756
+ border: 1px solid var(--card-border);
757
+ }
758
+
759
+ .card-elevated {
760
+ border: 1px solid var(--card-border);
761
+ box-shadow: var(--shadow-elevation-medium);
762
+ }
763
+
764
+ .card-interactive {
765
+ border: 1px solid var(--card-border);
766
+
767
+ transition:
768
+ border-color
769
+ var(--motion-duration-normal)
770
+ var(--motion-ease-out),
771
+ box-shadow
772
+ var(--motion-duration-normal)
773
+ var(--motion-ease-out),
774
+ transform
775
+ var(--motion-duration-normal)
776
+ var(--motion-ease-out);
777
+ }
778
+
779
+ .card-interactive:hover {
780
+ border-color: var(--card-border-hover);
781
+ box-shadow: var(--shadow-elevation-medium);
782
+ transform: translateY(var(--interaction-lift));
783
+ }
784
+
785
+ .card-interactive:focus-visible {
786
+ outline:
787
+ var(--focus-ring-width)
788
+ solid
789
+ var(--focus-ring-color);
790
+
791
+ outline-offset: var(--focus-ring-offset);
792
+ }
793
+
794
+ .card-selected {
795
+ border: 1px solid var(--border-focus);
796
+ box-shadow: var(--shadow-elevation-low);
797
+ }
798
+
799
+
800
+ /* --------------------------------------------------------------------------
801
+ REDUCED MOTION
802
+ -------------------------------------------------------------------------- */
803
+
804
+ @media (prefers-reduced-motion: reduce) {
805
+ .card-interactive {
806
+ transition: none;
807
+ }
808
+
809
+ .card-interactive:hover {
810
+ transform: none;
811
+ }
812
+ }
813
+
814
+
815
+
816
+ /* ==========================================================================
817
+ BADGES
818
+ ========================================================================== */
819
+
820
+ .badge {
821
+ display: inline-flex;
822
+ align-items: center;
823
+ gap: var(--badge-gap);
824
+
825
+ min-height: var(--badge-min-height);
826
+ padding: var(--badge-padding-y) var(--badge-padding-x);
827
+
828
+ background: var(--badge-background);
829
+ border: 1px solid var(--badge-border);
830
+ border-radius: var(--badge-radius);
831
+
832
+ color: var(--badge-text);
833
+ font-family: var(--font-family-body);
834
+ font-size: var(--font-size-xs);
835
+ font-weight: var(--font-weight-medium);
836
+ line-height: 1;
837
+
838
+ white-space: nowrap;
839
+ }
840
+
841
+
842
+ /* --------------------------------------------------------------------------
843
+ VARIANTS
844
+ -------------------------------------------------------------------------- */
845
+
846
+ .badge-default {
847
+ background: var(--badge-default-background);
848
+ border-color: var(--badge-default-border);
849
+ color: var(--badge-default-text);
850
+ }
851
+
852
+ .badge-success {
853
+ background: var(--badge-success-background);
854
+ border-color: var(--badge-success-border);
855
+ color: var(--badge-success-text);
856
+ }
857
+
858
+ .badge-warning {
859
+ background: var(--badge-warning-background);
860
+ border-color: var(--badge-warning-border);
861
+ color: var(--badge-warning-text);
862
+ }
863
+
864
+ .badge-danger {
865
+ background: var(--badge-danger-background);
866
+ border-color: var(--badge-danger-border);
867
+ color: var(--badge-danger-text);
868
+ }
869
+
870
+ .badge-info {
871
+ background: var(--badge-info-background);
872
+ border-color: var(--badge-info-border);
873
+ color: var(--badge-info-text);
874
+ }
875
+
876
+ .badge-brand {
877
+ background: var(--badge-brand-background);
878
+ border-color: var(--badge-brand-border);
879
+ color: var(--badge-brand-text);
880
+ }
881
+ /* ========================================================================
882
+ TAGS
883
+ ======================================================================== */
884
+
885
+ .tag {
886
+ display: inline-flex;
887
+ align-items: center;
888
+ gap: var(--tag-gap);
889
+ width: fit-content;
890
+
891
+ min-height: var(--tag-min-height);
892
+ padding: var(--tag-padding-y) var(--tag-padding-x);
893
+
894
+ background: var(--tag-background);
895
+ border: 1px solid var(--tag-border);
896
+ border-radius: var(--tag-radius);
897
+
898
+ color: var(--tag-text);
899
+ font-family: var(--font-family-body);
900
+ font-size: var(--font-size-xs);
901
+ font-weight: var(--font-weight-medium);
902
+ line-height: 1;
903
+
904
+ white-space: nowrap;
905
+ }
906
+ /* ==========================================================================
907
+ NAVBAR
908
+ ========================================================================== */
909
+
910
+ .navbar {
911
+ position: fixed;
912
+ top: 0;
913
+ left: 0;
914
+ right: 0;
915
+ height: var(--nav-height);
916
+ background: var(--nav-background);
917
+ border-bottom: 1px solid var(--nav-border);
918
+ backdrop-filter: blur(var(--nav-blur));
919
+ -webkit-backdrop-filter: blur(var(--nav-blur));
920
+ z-index: var(--z-navbar);
921
+ display: flex;
922
+ align-items: center;
923
+ padding-inline: var(--container-padding);
924
+ }
925
+
926
+ .navbar-inner {
927
+ display: flex;
928
+ align-items: center;
929
+ justify-content: space-between;
930
+ width: 100%;
931
+ max-width: var(--container-max-width);
932
+ margin-inline: auto;
933
+ }
934
+
935
+ .nav-link {
936
+ color: var(--nav-link);
937
+ text-decoration: none;
938
+ font-size: var(--font-size-sm);
939
+ font-weight: var(--font-weight-medium);
940
+ transition: color var(--motion-duration-fast) ease;
941
+ padding: 0.5rem 0.75rem;
942
+ border-radius: var(--radius-md);
943
+ }
944
+
945
+ .nav-link:hover {
946
+ color: var(--nav-link-hover);
947
+ }
948
+
949
+ .nav-link-active {
950
+ color: var(--nav-link-active);
951
+ }
952
+ /* ==========================================================================
953
+ SIDEBAR
954
+ Premium application navigation
955
+ ========================================================================== */
956
+
957
+ .sidebar {
958
+ position: sticky;
959
+ top: 0;
960
+
961
+ display: flex;
962
+ flex-direction: column;
963
+
964
+ width: var(--sidebar-width, 16rem);
965
+ height: 100vh;
966
+
967
+ flex: 0 0 auto;
968
+
969
+ background: var(--surface-raised);
970
+ border-right: 1px solid var(--border-subtle);
971
+
972
+ color: var(--text-primary);
973
+ }
974
+
975
+ .sidebar--collapsed {
976
+ width: var(--sidebar-width-collapsed, 4.5rem);
977
+ }
978
+
979
+
980
+ /* ==========================================================================
981
+ SIDEBAR REGIONS
982
+ ========================================================================== */
983
+
984
+ .sidebar-header {
985
+ flex: 0 0 auto;
986
+
987
+ padding: var(--space-5);
988
+ }
989
+
990
+ .sidebar-navigation {
991
+ display: flex;
992
+ flex-direction: column;
993
+ gap: var(--space-2);
994
+
995
+ flex: 1 1 auto;
996
+ min-height: 0;
997
+
998
+ padding: var(--space-3) var(--space-3);
999
+
1000
+ overflow-y: auto;
1001
+ overflow-x: hidden;
1002
+
1003
+ scrollbar-width: thin;
1004
+ scrollbar-color:
1005
+ var(--border-default)
1006
+ transparent;
1007
+ }
1008
+
1009
+ .sidebar-footer {
1010
+ flex: 0 0 auto;
1011
+
1012
+ padding: var(--space-3);
1013
+
1014
+ border-top: 1px solid var(--border-subtle);
1015
+ }
1016
+
1017
+
1018
+ /* ==========================================================================
1019
+ SIDEBAR GROUP
1020
+ ========================================================================== */
1021
+
1022
+ .sidebar-group {
1023
+ display: flex;
1024
+ flex-direction: column;
1025
+
1026
+ width: 100%;
1027
+ }
1028
+
1029
+ .sidebar-group + .sidebar-group {
1030
+ margin-top: var(--space-4);
1031
+ }
1032
+
1033
+ .sidebar-group-label {
1034
+ padding:
1035
+ var(--space-2)
1036
+ var(--space-3)
1037
+ var(--space-2);
1038
+
1039
+ color: var(--text-muted);
1040
+
1041
+ font-family: var(--font-family-body);
1042
+ font-size: var(--font-size-xs);
1043
+ font-weight: var(--font-weight-semibold);
1044
+ line-height: var(--line-height-normal);
1045
+ letter-spacing: var(--letter-spacing-wide);
1046
+
1047
+ text-transform: uppercase;
1048
+ }
1049
+
1050
+ .sidebar-group-items {
1051
+ display: flex;
1052
+ flex-direction: column;
1053
+ gap: var(--space-1);
1054
+ }
1055
+
1056
+
1057
+ /* ==========================================================================
1058
+ SIDEBAR ITEM
1059
+ ========================================================================== */
1060
+
1061
+ .sidebar-item-wrapper {
1062
+ display: flex;
1063
+ flex-direction: column;
1064
+
1065
+ width: 100%;
1066
+ }
1067
+
1068
+ .sidebar-item {
1069
+ position: relative;
1070
+
1071
+ display: flex;
1072
+ align-items: center;
1073
+
1074
+ width: 100%;
1075
+ min-height: 2.625rem;
1076
+
1077
+ padding:
1078
+ var(--space-2)
1079
+ var(--space-3);
1080
+
1081
+ border: 1px solid transparent;
1082
+ border-radius: var(--radius-md);
1083
+
1084
+ background: transparent;
1085
+ color: var(--text-secondary);
1086
+
1087
+ font-family: var(--font-family-body);
1088
+ font-size: var(--font-size-sm);
1089
+ font-weight: var(--font-weight-medium);
1090
+ line-height: var(--line-height-normal);
1091
+
1092
+ text-align: left;
1093
+ text-decoration: none;
1094
+
1095
+ cursor: pointer;
1096
+
1097
+ transition:
1098
+ background-color var(--motion-duration-fast) var(--motion-ease-out),
1099
+ border-color var(--motion-duration-fast) var(--motion-ease-out),
1100
+ color var(--motion-duration-fast) var(--motion-ease-out),
1101
+ transform var(--motion-duration-fast) var(--motion-ease-out);
1102
+ }
1103
+
1104
+ .sidebar-item:hover {
1105
+ background: var(--surface-hover);
1106
+ color: var(--text-primary);
1107
+ }
1108
+
1109
+ .sidebar-item:focus-visible {
1110
+ outline:
1111
+ var(--focus-ring-width)
1112
+ solid
1113
+ var(--focus-ring-color);
1114
+
1115
+ outline-offset: var(--focus-ring-offset);
1116
+ }
1117
+
1118
+ .sidebar-item--active {
1119
+ background: var(--surface-card);
1120
+ border-color: var(--border-subtle);
1121
+
1122
+ color: var(--text-primary);
1123
+ }
1124
+
1125
+ .sidebar-item--active::before {
1126
+ content: "";
1127
+
1128
+ position: absolute;
1129
+ top: 50%;
1130
+ left: 0;
1131
+
1132
+ width: 0.1875rem;
1133
+ height: 1.35rem;
1134
+
1135
+ border-radius: var(--radius-full);
1136
+
1137
+ background: var(--brand-primary);
1138
+
1139
+ transform: translateY(-50%);
1140
+ }
1141
+
1142
+ .sidebar-item--active:hover {
1143
+ background: var(--surface-hover);
1144
+ }
1145
+
1146
+ .sidebar-item--disabled {
1147
+ opacity: var(--interaction-opacity-disabled);
1148
+ cursor: not-allowed;
1149
+ pointer-events: none;
1150
+ }
1151
+
1152
+
1153
+ /* ==========================================================================
1154
+ ITEM CONTENT
1155
+ ========================================================================== */
1156
+
1157
+ .sidebar-item-icon {
1158
+ display: inline-flex;
1159
+ align-items: center;
1160
+ justify-content: center;
1161
+
1162
+ width: 1.25rem;
1163
+ height: 1.25rem;
1164
+
1165
+ flex: 0 0 auto;
1166
+
1167
+ color: currentColor;
1168
+ }
1169
+
1170
+ .sidebar-item-label {
1171
+ min-width: 0;
1172
+
1173
+ flex: 1 1 auto;
1174
+
1175
+ overflow: hidden;
1176
+
1177
+ white-space: nowrap;
1178
+ text-overflow: ellipsis;
1179
+ }
1180
+
1181
+ .sidebar-item-chevron {
1182
+ display: inline-flex;
1183
+ align-items: center;
1184
+ justify-content: center;
1185
+
1186
+ width: 1.25rem;
1187
+ height: 1.25rem;
1188
+
1189
+ flex: 0 0 auto;
1190
+
1191
+ margin-left: var(--space-2);
1192
+
1193
+ color: var(--text-muted);
1194
+ }
1195
+
1196
+ .sidebar-item-chevron > span {
1197
+ display: inline-flex;
1198
+
1199
+ font-size: var(--font-size-lg);
1200
+ line-height: 1;
1201
+
1202
+ transform: rotate(0deg);
1203
+
1204
+ transition:
1205
+ transform var(--motion-duration-fast) var(--motion-ease-out),
1206
+ color var(--motion-duration-fast) var(--motion-ease-out);
1207
+ }
1208
+
1209
+ .sidebar-item:hover .sidebar-item-chevron {
1210
+ color: var(--text-primary);
1211
+ }
1212
+
1213
+ .sidebar-item-chevron--expanded {
1214
+ transform: rotate(90deg);
1215
+ }
1216
+
1217
+
1218
+ /* ==========================================================================
1219
+ NESTED ITEMS
1220
+ ========================================================================== */
1221
+
1222
+ .sidebar-item-children {
1223
+ display: flex;
1224
+ flex-direction: column;
1225
+
1226
+ gap: var(--space-1);
1227
+
1228
+ margin-top: var(--space-1);
1229
+ margin-left: var(--space-3);
1230
+
1231
+ padding-left: var(--space-3);
1232
+
1233
+ border-left: 1px solid var(--border-subtle);
1234
+ }
1235
+
1236
+ .sidebar-item-children .sidebar-item {
1237
+ min-height: 2.375rem;
1238
+
1239
+ padding:
1240
+ var(--space-2)
1241
+ var(--space-3);
1242
+
1243
+ font-size: var(--font-size-sm);
1244
+ }
1245
+
1246
+
1247
+ /* ==========================================================================
1248
+ COLLAPSED SIDEBAR
1249
+ ========================================================================== */
1250
+
1251
+ .sidebar--collapsed .sidebar-header {
1252
+ padding-inline: var(--space-3);
1253
+ }
1254
+
1255
+ .sidebar--collapsed .sidebar-navigation {
1256
+ padding-inline: var(--space-2);
1257
+ }
1258
+
1259
+ .sidebar--collapsed .sidebar-footer {
1260
+ padding-inline: var(--space-2);
1261
+ }
1262
+
1263
+ .sidebar--collapsed .sidebar-group-label {
1264
+ display: none;
1265
+ }
1266
+
1267
+ .sidebar--collapsed .sidebar-item {
1268
+ justify-content: center;
1269
+
1270
+ padding-inline: var(--space-2);
1271
+ }
1272
+
1273
+ .sidebar--collapsed .sidebar-item-label,
1274
+ .sidebar--collapsed .sidebar-item-chevron {
1275
+ display: none;
1276
+ }
1277
+
1278
+ .sidebar--collapsed .sidebar-item-icon {
1279
+ width: 1.5rem;
1280
+ height: 1.5rem;
1281
+ }
1282
+
1283
+ .sidebar--collapsed .sidebar-item-children {
1284
+ display: none;
1285
+ }
1286
+
1287
+
1288
+ /* ==========================================================================
1289
+ SCROLLBAR
1290
+ ========================================================================== */
1291
+
1292
+ .sidebar-navigation::-webkit-scrollbar {
1293
+ width: 0.35rem;
1294
+ }
1295
+
1296
+ .sidebar-navigation::-webkit-scrollbar-track {
1297
+ background: transparent;
1298
+ }
1299
+
1300
+ .sidebar-navigation::-webkit-scrollbar-thumb {
1301
+ background: var(--border-default);
1302
+ border-radius: var(--radius-full);
1303
+ }
1304
+
1305
+ .sidebar-navigation::-webkit-scrollbar-thumb:hover {
1306
+ background: var(--border-strong);
1307
+ }
1308
+
1309
+
1310
+ /* ==========================================================================
1311
+ REDUCED MOTION
1312
+ ========================================================================== */
1313
+
1314
+ @media (prefers-reduced-motion: reduce) {
1315
+ .sidebar-item,
1316
+ .sidebar-item-chevron > span {
1317
+ transition: none;
1318
+ }
1319
+ }
1320
+ /* ==========================================================================
1321
+ TABS
1322
+ ========================================================================== */
1323
+
1324
+ .tabs {
1325
+ width: 100%;
1326
+ }
1327
+
1328
+ .tabs-list {
1329
+ display: flex;
1330
+ align-items: center;
1331
+ gap: var(--space-1);
1332
+
1333
+ width: 100%;
1334
+
1335
+ border-bottom: 1px solid var(--border-subtle);
1336
+
1337
+ overflow-x: auto;
1338
+ scrollbar-width: none;
1339
+ }
1340
+
1341
+ .tabs-list::-webkit-scrollbar {
1342
+ display: none;
1343
+ }
1344
+
1345
+ .tab {
1346
+ position: relative;
1347
+
1348
+ display: inline-flex;
1349
+ align-items: center;
1350
+ justify-content: center;
1351
+
1352
+ min-height: 2.75rem;
1353
+ padding: var(--space-2) var(--space-3);
1354
+
1355
+ border: 0;
1356
+ border-bottom: 2px solid transparent;
1357
+
1358
+ background: transparent;
1359
+ color: var(--text-muted);
1360
+
1361
+ font-family: var(--font-family-body);
1362
+ font-size: var(--font-size-sm);
1363
+ font-weight: var(--font-weight-medium);
1364
+ line-height: var(--line-height-normal);
1365
+
1366
+ white-space: nowrap;
1367
+
1368
+ cursor: pointer;
1369
+
1370
+ transition:
1371
+ color var(--motion-duration-fast) var(--motion-ease-out),
1372
+ border-color var(--motion-duration-fast) var(--motion-ease-out),
1373
+ background-color var(--motion-duration-fast) var(--motion-ease-out);
1374
+ }
1375
+
1376
+ .tab:hover {
1377
+ color: var(--text-primary);
1378
+ background: var(--surface-hover);
1379
+ }
1380
+
1381
+ .tab:focus-visible {
1382
+ outline:
1383
+ var(--focus-ring-width)
1384
+ solid
1385
+ var(--focus-ring-color);
1386
+
1387
+ outline-offset: calc(var(--focus-ring-offset) * -1);
1388
+ }
1389
+
1390
+ .tab--active {
1391
+ color: var(--text-primary);
1392
+ border-bottom-color: var(--brand-primary);
1393
+ }
1394
+
1395
+ .tab--disabled {
1396
+ color: var(--text-muted);
1397
+ opacity: var(--interaction-opacity-disabled);
1398
+ cursor: not-allowed;
1399
+ pointer-events: none;
1400
+ }
1401
+
1402
+ .tab-panels {
1403
+ width: 100%;
1404
+ }
1405
+
1406
+ .tab-panel {
1407
+ width: 100%;
1408
+ }
1409
+
1410
+ @media (prefers-reduced-motion: reduce) {
1411
+ .tab {
1412
+ transition: none;
1413
+ }
1414
+ }
1415
+ /* ==========================================================================
1416
+ BREADCRUMBS
1417
+ ========================================================================== */
1418
+
1419
+ .breadcrumbs {
1420
+ display: flex;
1421
+ align-items: center;
1422
+
1423
+ width: 100%;
1424
+
1425
+ color: var(--text-muted);
1426
+
1427
+ font-family: var(--font-family-body);
1428
+ font-size: var(--font-size-sm);
1429
+ line-height: var(--line-height-normal);
1430
+
1431
+ overflow-x: auto;
1432
+ white-space: nowrap;
1433
+
1434
+ scrollbar-width: none;
1435
+ }
1436
+
1437
+ .breadcrumbs::-webkit-scrollbar {
1438
+ display: none;
1439
+ }
1440
+
1441
+ .breadcrumbs-list {
1442
+ display: inline-flex;
1443
+ align-items: center;
1444
+ gap: var(--space-2);
1445
+
1446
+ min-width: max-content;
1447
+ }
1448
+
1449
+ .breadcrumbs-item {
1450
+ display: inline-flex;
1451
+ align-items: center;
1452
+ gap: var(--space-2);
1453
+ }
1454
+
1455
+ .breadcrumbs-link {
1456
+ color: var(--text-muted);
1457
+ text-decoration: none;
1458
+
1459
+ transition:
1460
+ color var(--motion-duration-fast) var(--motion-ease-out);
1461
+ }
1462
+
1463
+ .breadcrumbs-link:hover {
1464
+ color: var(--text-primary);
1465
+ text-decoration: underline;
1466
+ text-underline-offset: 0.2em;
1467
+ }
1468
+
1469
+ .breadcrumbs-link:focus-visible {
1470
+ outline:
1471
+ var(--focus-ring-width)
1472
+ solid
1473
+ var(--focus-ring-color);
1474
+
1475
+ outline-offset: var(--focus-ring-offset);
1476
+ border-radius: var(--radius-sm);
1477
+ }
1478
+
1479
+ .breadcrumbs-separator {
1480
+ display: inline-flex;
1481
+ align-items: center;
1482
+ justify-content: center;
1483
+
1484
+ color: var(--text-muted);
1485
+
1486
+ user-select: none;
1487
+ }
1488
+
1489
+ .breadcrumbs-current {
1490
+ color: var(--text-primary);
1491
+ font-weight: var(--font-weight-medium);
1492
+
1493
+ overflow: hidden;
1494
+ text-overflow: ellipsis;
1495
+ }
1496
+
1497
+ .breadcrumbs-item:last-child .breadcrumbs-separator {
1498
+ display: none;
1499
+ }
1500
+ /* ==========================================================================
1501
+ LAYOUT PRIMITIVES
1502
+ Spacing system classes — use these instead of ad-hoc padding/margin/gap.
1503
+ ========================================================================== */
1504
+
1505
+ .container {
1506
+ max-width: var(--container-max-width);
1507
+ margin-inline: auto;
1508
+ padding-inline: var(--container-padding);
1509
+ }
1510
+
1511
+ .container-narrow {
1512
+ max-width: var(--container-narrow);
1513
+ margin-inline: auto;
1514
+ padding-inline: var(--container-padding);
1515
+ }
1516
+
1517
+ .section {
1518
+ padding-block: var(--section-spacing);
1519
+ }
1520
+
1521
+ .stack {
1522
+ display: flex;
1523
+ flex-direction: column;
1524
+ align-items: stretch;
1525
+ gap: var(--stack-gap);
1526
+ }
1527
+
1528
+ .stack-sm {
1529
+ display: flex;
1530
+ flex-direction: column;
1531
+ align-items: stretch;
1532
+ gap: var(--stack-gap-sm);
1533
+ }
1534
+
1535
+ .stack-lg {
1536
+ display: flex;
1537
+ flex-direction: column;
1538
+ align-items: stretch;
1539
+ gap: var(--stack-gap-lg);
1540
+ }
1541
+
1542
+ .stack-full {
1543
+ width: 100%;
1544
+ }
1545
+
1546
+ .inline {
1547
+ display: flex;
1548
+ flex-wrap: wrap;
1549
+ gap: var(--inline-gap);
1550
+ }
1551
+
1552
+ .inline-sm {
1553
+ display: flex;
1554
+ flex-wrap: wrap;
1555
+ gap: var(--inline-gap-sm);
1556
+ }
1557
+
1558
+ .inline-lg {
1559
+ display: flex;
1560
+ flex-wrap: wrap;
1561
+ gap: var(--inline-gap-lg);
1562
+ }
1563
+
1564
+ .grid {
1565
+ display: grid;
1566
+ gap: var(--grid-gap);
1567
+ }
1568
+
1569
+ .grid-sm {
1570
+ display: grid;
1571
+ gap: var(--grid-gap-sm);
1572
+ }
1573
+
1574
+ .grid-lg {
1575
+ display: grid;
1576
+ gap: var(--grid-gap-lg);
1577
+ }
1578
+
1579
+ .grid-cols-1 {
1580
+ grid-template-columns: repeat(1, minmax(0, 1fr));
1581
+ }
1582
+
1583
+ .grid-cols-2 {
1584
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1585
+ }
1586
+
1587
+ .grid-cols-3 {
1588
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1589
+ }
1590
+
1591
+ .grid-cols-4 {
1592
+ grid-template-columns: repeat(4, minmax(0, 1fr));
1593
+ }
1594
+
1595
+ .grid-cols-5 {
1596
+ grid-template-columns: repeat(5, minmax(0, 1fr));
1597
+ }
1598
+
1599
+ .grid-cols-6 {
1600
+ grid-template-columns: repeat(6, minmax(0, 1fr));
1601
+ }
1602
+
1603
+ .grid-rows-1 {
1604
+ grid-template-rows: repeat(1, minmax(0, 1fr));
1605
+ }
1606
+
1607
+ .grid-rows-2 {
1608
+ grid-template-rows: repeat(2, minmax(0, 1fr));
1609
+ }
1610
+
1611
+ .grid-rows-3 {
1612
+ grid-template-rows: repeat(3, minmax(0, 1fr));
1613
+ }
1614
+
1615
+ .grid-rows-4 {
1616
+ grid-template-rows: repeat(4, minmax(0, 1fr));
1617
+ }
1618
+
1619
+ .grid-rows-5 {
1620
+ grid-template-rows: repeat(5, minmax(0, 1fr));
1621
+ }
1622
+
1623
+ .grid-rows-6 {
1624
+ grid-template-rows: repeat(6, minmax(0, 1fr));
1625
+ }
1626
+
1627
+ /* ==========================================================================
1628
+ SPACING UTILITIES
1629
+ Gap + padding helpers for custom composition. Use these to elevate
1630
+ layouts without writing ad-hoc inline styles — matching the gap/padding
1631
+ ergonomics of hand-rolled HTML/CSS.
1632
+ ========================================================================== */
1633
+
1634
+ /* ---- Gap (flex / grid) ---- */
1635
+ .gap-0 { gap: 0; }
1636
+ .gap-1 { gap: var(--space-1); }
1637
+ .gap-2 { gap: var(--space-2); }
1638
+ .gap-3 { gap: var(--space-3); }
1639
+ .gap-4 { gap: var(--space-4); }
1640
+ .gap-5 { gap: var(--space-5); }
1641
+ .gap-6 { gap: var(--space-6); }
1642
+ .gap-8 { gap: var(--space-8); }
1643
+ .gap-10 { gap: var(--space-10); }
1644
+ .gap-12 { gap: var(--space-12); }
1645
+ .gap-16 { gap: var(--space-16); }
1646
+
1647
+ .gap-x-2 { column-gap: var(--space-2); }
1648
+ .gap-x-4 { column-gap: var(--space-4); }
1649
+ .gap-x-6 { column-gap: var(--space-6); }
1650
+ .gap-x-8 { column-gap: var(--space-8); }
1651
+
1652
+ .gap-y-2 { row-gap: var(--space-2); }
1653
+ .gap-y-4 { row-gap: var(--space-4); }
1654
+ .gap-y-6 { row-gap: var(--space-6); }
1655
+ .gap-y-8 { row-gap: var(--space-8); }
1656
+
1657
+ /* ---- Padding (all sides) ---- */
1658
+ .p-0 { padding: 0; }
1659
+ .p-1 { padding: var(--space-1); }
1660
+ .p-2 { padding: var(--space-2); }
1661
+ .p-3 { padding: var(--space-3); }
1662
+ .p-4 { padding: var(--space-4); }
1663
+ .p-5 { padding: var(--space-5); }
1664
+ .p-6 { padding: var(--space-6); }
1665
+ .p-8 { padding: var(--space-8); }
1666
+ .p-10 { padding: var(--space-10); }
1667
+ .p-12 { padding: var(--space-12); }
1668
+
1669
+ /* ---- Padding (block axis) ---- */
1670
+ .py-0 { padding-block: 0; }
1671
+ .py-1 { padding-block: var(--space-1); }
1672
+ .py-2 { padding-block: var(--space-2); }
1673
+ .py-3 { padding-block: var(--space-3); }
1674
+ .py-4 { padding-block: var(--space-4); }
1675
+ .py-5 { padding-block: var(--space-5); }
1676
+ .py-6 { padding-block: var(--space-6); }
1677
+ .py-8 { padding-block: var(--space-8); }
1678
+ .py-10 { padding-block: var(--space-10); }
1679
+ .py-12 { padding-block: var(--space-12); }
1680
+ .py-16 { padding-block: var(--space-16); }
1681
+ .py-20 { padding-block: var(--space-20); }
1682
+ .py-24 { padding-block: var(--space-24); }
1683
+
1684
+ /* ---- Padding (inline axis) ---- */
1685
+ .px-0 { padding-inline: 0; }
1686
+ .px-1 { padding-inline: var(--space-1); }
1687
+ .px-2 { padding-inline: var(--space-2); }
1688
+ .px-3 { padding-inline: var(--space-3); }
1689
+ .px-4 { padding-inline: var(--space-4); }
1690
+ .px-5 { padding-inline: var(--space-5); }
1691
+ .px-6 { padding-inline: var(--space-6); }
1692
+ .px-8 { padding-inline: var(--space-8); }
1693
+ .px-10 { padding-inline: var(--space-10); }
1694
+ .px-12 { padding-inline: var(--space-12); }
1695
+
1696
+
1697
+ /* ==========================================================================
1698
+ TYPOGRAPHY UTILITIES
1699
+ A composable text vocabulary so every consumer (plain HTML/CSS or Vue
1700
+ composition) can make type breathe. Each class consumes the canonical
1701
+ @loba/design tokens directly — no new tokens, just exposes the scale.
1702
+ ========================================================================== */
1703
+
1704
+ /* ---- Body text sizes (each step carries tuned line-height) ---- */
1705
+ .text-xs { font-size: var(--font-size-xs); line-height: var(--line-height-snug); }
1706
+ .text-sm { font-size: var(--font-size-sm); line-height: var(--line-height-snug); }
1707
+ .text-md { font-size: var(--font-size-base); line-height: var(--line-height-normal); }
1708
+ .text-base { font-size: var(--font-size-base); line-height: var(--line-height-normal); }
1709
+ .text-lg { font-size: var(--font-size-lg); line-height: var(--line-height-relaxed); }
1710
+ .text-xl { font-size: var(--font-size-xl); line-height: var(--line-height-relaxed); }
1711
+ .text-2xl { font-size: var(--font-size-2xl); line-height: var(--line-height-snug); }
1712
+ .text-3xl { font-size: var(--font-size-3xl); line-height: var(--line-height-tight); }
1713
+ .text-4xl { font-size: var(--font-size-4xl); line-height: var(--line-height-tight); }
1714
+ .text-5xl { font-size: var(--font-size-5xl); line-height: var(--line-height-tight); }
1715
+ .text-6xl { font-size: var(--font-size-6xl); line-height: 1.05; }
1716
+
1717
+ /* ---- Display / heading scale (mirrors the Heading component) ---- */
1718
+ .heading-xs {
1719
+ font-family: var(--font-family-display);
1720
+ font-size: var(--font-size-lg);
1721
+ font-weight: var(--font-weight-semibold);
1722
+ line-height: var(--line-height-tight);
1723
+ letter-spacing: var(--letter-spacing-tight);
1724
+ color: var(--text-primary);
1725
+ }
1726
+ .heading-sm {
1727
+ font-family: var(--font-family-display);
1728
+ font-size: var(--font-size-xl);
1729
+ font-weight: var(--font-weight-bold);
1730
+ line-height: var(--line-height-tight);
1731
+ letter-spacing: var(--letter-spacing-tight);
1732
+ color: var(--text-primary);
1733
+ }
1734
+ .heading-md {
1735
+ font-family: var(--font-family-display);
1736
+ font-size: clamp(var(--font-size-xl), 3vw, var(--font-size-2xl));
1737
+ font-weight: var(--font-weight-bold);
1738
+ line-height: var(--line-height-tight);
1739
+ letter-spacing: var(--letter-spacing-tight);
1740
+ color: var(--text-primary);
1741
+ }
1742
+ .heading-lg {
1743
+ font-family: var(--font-family-display);
1744
+ font-size: clamp(var(--font-size-2xl), 4vw, var(--font-size-4xl));
1745
+ font-weight: var(--font-weight-bold);
1746
+ line-height: var(--line-height-tight);
1747
+ letter-spacing: var(--letter-spacing-tight);
1748
+ color: var(--text-primary);
1749
+ }
1750
+ .heading-xl {
1751
+ font-family: var(--font-family-display);
1752
+ font-size: clamp(var(--font-size-4xl), 6vw, var(--font-size-6xl));
1753
+ font-weight: var(--font-weight-bold);
1754
+ line-height: 1.05;
1755
+ letter-spacing: var(--letter-spacing-tight);
1756
+ color: var(--text-primary);
1757
+ }
1758
+
1759
+ /* ---- Text tone / color ---- */
1760
+ .text-primary { color: var(--text-primary); }
1761
+ .text-secondary { color: var(--text-secondary); }
1762
+ .text-muted { color: var(--text-muted); }
1763
+ .text-accent { color: var(--text-accent); }
1764
+ .text-inverse { color: var(--text-inverse); }
1765
+ .text-brand { color: var(--brand-primary); }
1766
+
1767
+ /* ---- Text wrap ---- */
1768
+ .text-balance { text-wrap: balance; }
1769
+ .text-pretty { text-wrap: pretty; }
1770
+
1771
+ /* ---- Leading (line-height) ---- */
1772
+ .leading-tight { line-height: var(--line-height-tight); }
1773
+ .leading-snug { line-height: var(--line-height-snug); }
1774
+ .leading-normal { line-height: var(--line-height-normal); }
1775
+ .leading-relaxed { line-height: var(--line-height-relaxed); }
1776
+ .leading-loose { line-height: var(--line-height-loose); }
1777
+
1778
+ /* ---- Tracking (letter-spacing) ---- */
1779
+ .tracking-tight { letter-spacing: var(--letter-spacing-tight); }
1780
+ .tracking-normal { letter-spacing: var(--letter-spacing-normal); }
1781
+ .tracking-wide { letter-spacing: var(--letter-spacing-wide); }
1782
+ .tracking-wider { letter-spacing: var(--letter-spacing-wider); }
1783
+ .tracking-widest { letter-spacing: var(--letter-spacing-widest); }
1784
+
1785
+ /* ---- Weight ---- */
1786
+ .font-light { font-weight: var(--font-weight-light); }
1787
+ .font-regular { font-weight: var(--font-weight-regular); }
1788
+ .font-medium { font-weight: var(--font-weight-medium); }
1789
+ .font-semibold { font-weight: var(--font-weight-semibold); }
1790
+ .font-bold { font-weight: var(--font-weight-bold); }
1791
+ .font-extrabold { font-weight: var(--font-weight-extrabold); }
1792
+
1793
+ /* ---- Case & style ---- */
1794
+ .uppercase { text-transform: uppercase; }
1795
+ .lowercase { text-transform: lowercase; }
1796
+ .capitalize { text-transform: capitalize; }
1797
+ .italic { font-style: italic; }
1798
+
1799
+
1800
+ /* ==========================================================================
1801
+ FORMS
1802
+ ========================================================================== */
1803
+ .form-field {
1804
+ width: 100%;
1805
+ display: flex;
1806
+ flex-direction: column;
1807
+ gap: var(--stack-gap-sm);
1808
+ }
1809
+
1810
+ /* ==========================================================================
1811
+ CHECKBOXES
1812
+ ========================================================================== */
1813
+
1814
+ .checkbox {
1815
+ display: inline-flex;
1816
+ align-items: center;
1817
+ gap: var(--space-2);
1818
+
1819
+ width: fit-content;
1820
+
1821
+ color: var(--form-text);
1822
+
1823
+ font-family: var(--font-family-body);
1824
+ font-size: var(--font-size-sm);
1825
+ line-height: var(--line-height-normal);
1826
+
1827
+ cursor: pointer;
1828
+ user-select: none;
1829
+ }
1830
+
1831
+ .checkbox-control {
1832
+ position: relative;
1833
+
1834
+ display: inline-flex;
1835
+ align-items: center;
1836
+ justify-content: center;
1837
+
1838
+ width: var(--icon-button-size-sm);
1839
+ height: var(--icon-button-size-sm);
1840
+
1841
+ flex: 0 0 auto;
1842
+
1843
+ border: 1px solid var(--form-border);
1844
+ border-radius: var(--radius-sm);
1845
+
1846
+ background: var(--form-background);
1847
+ color: var(--text-on-brand);
1848
+
1849
+ transition: var(--transition-fast);
1850
+ }
1851
+
1852
+ .checkbox-control::after {
1853
+ content: "✓";
1854
+
1855
+ font-size: var(--font-size-xs);
1856
+ font-weight: var(--font-weight-bold);
1857
+
1858
+ opacity: 0;
1859
+ transform: scale(0.7);
1860
+
1861
+ transition: var(--transition-fast);
1862
+ }
1863
+
1864
+ .checkbox:hover .checkbox-control {
1865
+ border-color: var(--form-border-hover);
1866
+ }
1867
+
1868
+ .checkbox--checked .checkbox-control {
1869
+ background: var(--brand-primary);
1870
+ border-color: var(--brand-primary);
1871
+ }
1872
+
1873
+ .checkbox--checked .checkbox-control::after {
1874
+ opacity: 1;
1875
+ transform: scale(1);
1876
+ }
1877
+
1878
+ .checkbox--disabled {
1879
+ opacity: var(--interaction-opacity-disabled);
1880
+ cursor: not-allowed;
1881
+ }
1882
+
1883
+ .checkbox:focus-within .checkbox-control {
1884
+ outline:
1885
+ var(--focus-ring-width)
1886
+ solid
1887
+ var(--focus-ring-color);
1888
+
1889
+ outline-offset: var(--focus-ring-offset);
1890
+ }
1891
+
1892
+
1893
+ /* ==========================================================================
1894
+ RADIO
1895
+ ========================================================================== */
1896
+
1897
+ .radio {
1898
+ display: inline-flex;
1899
+ align-items: center;
1900
+ gap: var(--space-2);
1901
+
1902
+ width: fit-content;
1903
+
1904
+ color: var(--form-text);
1905
+
1906
+ font-family: var(--font-family-body);
1907
+ font-size: var(--font-size-sm);
1908
+ line-height: var(--line-height-normal);
1909
+
1910
+ cursor: pointer;
1911
+ user-select: none;
1912
+ }
1913
+
1914
+ .radio-control {
1915
+ position: relative;
1916
+
1917
+ display: inline-flex;
1918
+ align-items: center;
1919
+ justify-content: center;
1920
+
1921
+ width: var(--icon-button-size-sm);
1922
+ height: var(--icon-button-size-sm);
1923
+
1924
+ flex: 0 0 auto;
1925
+
1926
+ border: 1px solid var(--form-border);
1927
+ border-radius: var(--radius-full);
1928
+
1929
+ background: var(--form-background);
1930
+
1931
+ transition: var(--transition-fast);
1932
+ }
1933
+
1934
+ .radio-control::after {
1935
+ content: "";
1936
+
1937
+ width: 0.5rem;
1938
+ height: 0.5rem;
1939
+
1940
+ border-radius: var(--radius-full);
1941
+
1942
+ background: var(--brand-primary);
1943
+
1944
+ opacity: 0;
1945
+ transform: scale(0.5);
1946
+
1947
+ transition: var(--transition-fast);
1948
+ }
1949
+
1950
+ .radio:hover .radio-control {
1951
+ border-color: var(--form-border-hover);
1952
+ }
1953
+
1954
+ .radio--checked .radio-control {
1955
+ border-color: var(--brand-primary);
1956
+ }
1957
+
1958
+ .radio--checked .radio-control::after {
1959
+ opacity: 1;
1960
+ transform: scale(1);
1961
+ }
1962
+
1963
+ .radio--disabled {
1964
+ opacity: var(--interaction-opacity-disabled);
1965
+ cursor: not-allowed;
1966
+ }
1967
+
1968
+ .radio:focus-within .radio-control {
1969
+ outline:
1970
+ var(--focus-ring-width)
1971
+ solid
1972
+ var(--focus-ring-color);
1973
+
1974
+ outline-offset: var(--focus-ring-offset);
1975
+ }
1976
+
1977
+
1978
+ /* ==========================================================================
1979
+ SWITCH
1980
+ ========================================================================== */
1981
+
1982
+ .switch {
1983
+ display: inline-flex;
1984
+ align-items: center;
1985
+ gap: var(--space-3);
1986
+
1987
+ width: fit-content;
1988
+
1989
+ color: var(--form-text);
1990
+
1991
+ font-family: var(--font-family-body);
1992
+ font-size: var(--font-size-sm);
1993
+ line-height: var(--line-height-normal);
1994
+
1995
+ cursor: pointer;
1996
+ user-select: none;
1997
+ }
1998
+
1999
+ .switch-control {
2000
+ position: relative;
2001
+
2002
+ width: 2.75rem;
2003
+ height: 1.5rem;
2004
+
2005
+ flex: 0 0 auto;
2006
+
2007
+ border: 1px solid var(--form-border);
2008
+ border-radius: var(--radius-full);
2009
+
2010
+ background: var(--form-background);
2011
+
2012
+ transition: var(--transition-fast);
2013
+ }
2014
+
2015
+ .switch-control::after {
2016
+ content: "";
2017
+
2018
+ position: absolute;
2019
+ top: 50%;
2020
+ left: 0.2rem;
2021
+
2022
+ width: 1rem;
2023
+ height: 1rem;
2024
+
2025
+ border-radius: var(--radius-full);
2026
+
2027
+ background: var(--text-muted);
2028
+
2029
+ transform: translateY(-50%);
2030
+
2031
+ transition:
2032
+ left var(--motion-duration-fast) var(--motion-ease-out),
2033
+ background-color var(--motion-duration-fast) var(--motion-ease-out);
2034
+ }
2035
+
2036
+ .switch:hover .switch-control {
2037
+ border-color: var(--form-border-hover);
2038
+ }
2039
+
2040
+ .switch--checked .switch-control {
2041
+ background: var(--brand-primary);
2042
+ border-color: var(--brand-primary);
2043
+ }
2044
+
2045
+ .switch--checked .switch-control::after {
2046
+ left: calc(100% - 1.2rem);
2047
+ background: var(--text-on-brand);
2048
+ }
2049
+
2050
+ .switch--disabled {
2051
+ opacity: var(--interaction-opacity-disabled);
2052
+ cursor: not-allowed;
2053
+ }
2054
+
2055
+ .switch:focus-within .switch-control {
2056
+ outline:
2057
+ var(--focus-ring-width)
2058
+ solid
2059
+ var(--focus-ring-color);
2060
+
2061
+ outline-offset: var(--focus-ring-offset);
2062
+ }
2063
+
2064
+
2065
+ /* ==========================================================================
2066
+ CHOICE GROUP
2067
+ ========================================================================== */
2068
+
2069
+ .choice-group {
2070
+ display: grid;
2071
+ gap: var(--space-2);
2072
+
2073
+ width: 100%;
2074
+ }
2075
+
2076
+ .choice {
2077
+ display: flex;
2078
+ align-items: center;
2079
+ justify-content: flex-start;
2080
+
2081
+ width: 100%;
2082
+ min-height: var(--button-min-height);
2083
+
2084
+ padding: var(--space-3) var(--space-4);
2085
+
2086
+ border: 1px solid var(--form-border);
2087
+ border-radius: var(--radius-md);
2088
+
2089
+ background: var(--form-background);
2090
+ color: var(--form-text);
2091
+
2092
+ font-family: var(--font-family-body);
2093
+ font-size: var(--font-size-sm);
2094
+ font-weight: var(--font-weight-medium);
2095
+
2096
+ text-align: left;
2097
+
2098
+ cursor: pointer;
2099
+ user-select: none;
2100
+
2101
+ transition:
2102
+ background-color var(--motion-duration-fast) var(--motion-ease-out),
2103
+ border-color var(--motion-duration-fast) var(--motion-ease-out),
2104
+ color var(--motion-duration-fast) var(--motion-ease-out),
2105
+ transform var(--motion-duration-fast) var(--motion-ease-out);
2106
+ }
2107
+
2108
+ .choice:hover {
2109
+ border-color: var(--form-border-hover);
2110
+ color: var(--text-primary);
2111
+ transform: translateY(var(--interaction-lift-sm));
2112
+ }
2113
+
2114
+ .choice--selected {
2115
+ background: var(--surface-raised);
2116
+ border-color: var(--brand-primary);
2117
+ color: var(--text-primary);
2118
+ }
2119
+
2120
+ .choice--disabled {
2121
+ opacity: var(--interaction-opacity-disabled);
2122
+ cursor: not-allowed;
2123
+ pointer-events: none;
2124
+ }
2125
+
2126
+ .choice:focus-visible {
2127
+ outline:
2128
+ var(--focus-ring-width)
2129
+ solid
2130
+ var(--focus-ring-color);
2131
+
2132
+ outline-offset: var(--focus-ring-offset);
2133
+ }
2134
+
2135
+ .choice-group--multiple .choice--selected {
2136
+ background: var(--brand-primary-muted);
2137
+ }
2138
+
2139
+
2140
+ /* --------------------------------------------------------------------------
2141
+ CHOICE GROUP LAYOUT
2142
+ -------------------------------------------------------------------------- */
2143
+
2144
+ .choice-group--grid-2 {
2145
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2146
+ }
2147
+
2148
+ .choice-group--grid-3 {
2149
+ grid-template-columns: repeat(3, minmax(0, 1fr));
2150
+ }
2151
+
2152
+ .choice-group--grid-4 {
2153
+ grid-template-columns: repeat(4, minmax(0, 1fr));
2154
+ }
2155
+ /* ==========================================================================
2156
+ CUSTOM FORM CONTROL INPUTS
2157
+ Native inputs remain accessible but are visually hidden.
2158
+ ========================================================================== */
2159
+
2160
+ /* ==========================================================================
2161
+ CUSTOM FORM CONTROL INPUTS
2162
+ ========================================================================== */
2163
+
2164
+ .checkbox,
2165
+ .radio,
2166
+ .switch {
2167
+ position: relative;
2168
+ }
2169
+
2170
+ .checkbox > input,
2171
+ .radio > input,
2172
+ .switch > input {
2173
+ position: absolute;
2174
+
2175
+ width: 1px;
2176
+ height: 1px;
2177
+
2178
+ margin: 0;
2179
+ padding: 0;
2180
+
2181
+ opacity: 0;
2182
+
2183
+ appearance: none;
2184
+ -webkit-appearance: none;
2185
+
2186
+ pointer-events: none;
2187
+ }
2188
+ .checkbox,
2189
+ .radio,
2190
+ .switch {
2191
+ position: relative;
2192
+ }
2193
+
2194
+ .input,
2195
+ .textarea,
2196
+ .select {
2197
+ box-sizing: border-box;
2198
+ width: 100%;
2199
+ padding: var(--form-padding-y) var(--form-padding-x);
2200
+ background: var(--form-background);
2201
+ border: 1px solid var(--form-border);
2202
+ border-radius: var(--radius-md);
2203
+ color: var(--form-text);
2204
+ font-family: var(--font-family-body);
2205
+ font-size: var(--font-size-sm);
2206
+ line-height: 1.5;
2207
+ transition: var(--transition-fast);
2208
+ }
2209
+
2210
+ .input:hover,
2211
+ .textarea:hover,
2212
+ .select:hover {
2213
+ border-color: var(--form-border-hover);
2214
+ }
2215
+
2216
+ .input:focus,
2217
+ .textarea:focus,
2218
+ .select:focus {
2219
+ outline: var(--focus-ring-width) solid var(--form-border-focus);
2220
+ outline-offset: var(--focus-ring-offset);;
2221
+ border-color: var(--form-border-focus);
2222
+ }
2223
+
2224
+ .input::placeholder,
2225
+ .textarea::placeholder {
2226
+ color: var(--form-placeholder);
2227
+ }
2228
+
2229
+ .input:disabled,
2230
+ .textarea:disabled,
2231
+ .select:disabled {
2232
+ background: var(--form-bg-disabled);
2233
+ border-color: var(--form-border-disabled);
2234
+ color: var(--form-text-disabled);
2235
+ cursor: not-allowed;
2236
+ }
2237
+
2238
+ .textarea {
2239
+ min-height: 120px;
2240
+ resize: vertical;
2241
+ }
2242
+ /* Error */
2243
+ .input-error {
2244
+ border-color: var(--form-border-error);
2245
+ }
2246
+
2247
+ .input-error:hover {
2248
+ border-color: var(--form-border-error);
2249
+ }
2250
+
2251
+ .input-error:focus {
2252
+ outline: none;
2253
+ border-color: var(--form-border-error);
2254
+ box-shadow:
2255
+ 0 0 0 3px
2256
+ color-mix(
2257
+ in srgb,
2258
+ var(--form-border-error) 25%,
2259
+ transparent
2260
+ );
2261
+ }
2262
+
2263
+ /* Success */
2264
+ .input-success {
2265
+ border-color: var(--form-border-success);
2266
+ }
2267
+
2268
+ .input-success:hover {
2269
+ border-color: var(--form-border-success);
2270
+ }
2271
+
2272
+ .input-success:focus {
2273
+ outline: none;
2274
+ border-color: var(--form-border-success);
2275
+ box-shadow:
2276
+ 0 0 0 3px
2277
+ color-mix(
2278
+ in srgb,
2279
+ var(--form-border-success) 25%,
2280
+ transparent
2281
+ );
2282
+ }
2283
+ /* ==========================================================================
2284
+ DATA UI
2285
+ Application-oriented collection, list, pagination, and table patterns.
2286
+ Framework-agnostic. Consumes canonical Loba tokens.
2287
+ ========================================================================== */
2288
+
2289
+
2290
+ /* ==========================================================================
2291
+ EMPTY STATE
2292
+ ========================================================================== */
2293
+
2294
+ .empty-state {
2295
+ width: 100%;
2296
+ display: flex;
2297
+ flex-direction: column;
2298
+ align-items: center;
2299
+ justify-content: center;
2300
+
2301
+ gap: var(--stack-gap);
2302
+
2303
+ padding: var(--space-12);
2304
+ text-align: center;
2305
+ }
2306
+
2307
+ .empty-state-icon {
2308
+ display: flex;
2309
+ align-items: center;
2310
+ justify-content: center;
2311
+
2312
+ width: 3rem;
2313
+ height: 3rem;
2314
+
2315
+ color: var(--text-muted);
2316
+ }
2317
+
2318
+ .empty-state-content {
2319
+ display: flex;
2320
+ flex-direction: column;
2321
+ align-items: center;
2322
+ gap: var(--stack-gap-sm);
2323
+
2324
+ max-width: var(--text-max-width-sm);
2325
+ }
2326
+
2327
+ .empty-state-actions {
2328
+ display: flex;
2329
+ flex-wrap: wrap;
2330
+ align-items: center;
2331
+ justify-content: center;
2332
+ gap: var(--inline-gap);
2333
+
2334
+ margin-top: var(--space-2);
2335
+ }
2336
+
2337
+
2338
+ /* ==========================================================================
2339
+ LIST
2340
+ ========================================================================== */
2341
+
2342
+ .list {
2343
+ width: 100%;
2344
+ display: flex;
2345
+ flex-direction: column;
2346
+
2347
+ border-top: 1px solid var(--border-subtle);
2348
+ }
2349
+
2350
+ .list-item {
2351
+ position: relative;
2352
+
2353
+ display: flex;
2354
+ align-items: center;
2355
+
2356
+ width: 100%;
2357
+
2358
+ padding: var(--space-4) var(--space-5);
2359
+
2360
+ border-bottom: 1px solid var(--border-subtle);
2361
+
2362
+ background: transparent;
2363
+ color: var(--text-primary);
2364
+
2365
+ text-align: left;
2366
+
2367
+ transition:
2368
+ background-color var(--motion-duration-fast) var(--motion-ease-out),
2369
+ border-color var(--motion-duration-fast) var(--motion-ease-out),
2370
+ color var(--motion-duration-fast) var(--motion-ease-out);
2371
+ }
2372
+
2373
+
2374
+ /* --------------------------------------------------------------------------
2375
+ INTERACTIVE LIST ITEMS
2376
+ -------------------------------------------------------------------------- */
2377
+
2378
+ .list-item--selectable {
2379
+ cursor: pointer;
2380
+ }
2381
+
2382
+ .list-item--selectable:hover {
2383
+ background: var(--surface-hover);
2384
+ }
2385
+
2386
+ .list-item--selected {
2387
+ background: var(--surface-card);
2388
+ border-color: var(--border-default);
2389
+ }
2390
+
2391
+ .list-item--selected:hover {
2392
+ background: var(--surface-hover);
2393
+ }
2394
+
2395
+ .list-item--disabled {
2396
+ color: var(--text-muted);
2397
+ cursor: not-allowed;
2398
+ opacity: var(--interaction-opacity-disabled);
2399
+ }
2400
+
2401
+ .list-item--disabled:hover {
2402
+ background: transparent;
2403
+ }
2404
+
2405
+
2406
+ /* --------------------------------------------------------------------------
2407
+ LIST ITEM FOCUS
2408
+ -------------------------------------------------------------------------- */
2409
+
2410
+ .list-item--selectable:focus-visible {
2411
+ outline:
2412
+ var(--focus-ring-width)
2413
+ solid
2414
+ var(--focus-ring-color);
2415
+
2416
+ outline-offset: calc(var(--focus-ring-offset) * -1);
2417
+ z-index: 1;
2418
+ }
2419
+
2420
+
2421
+ /* ==========================================================================
2422
+ PAGINATION
2423
+ ========================================================================== */
2424
+
2425
+ .pagination {
2426
+ display: flex;
2427
+ align-items: center;
2428
+ gap: var(--space-4);
2429
+
2430
+ width: 100%;
2431
+ }
2432
+
2433
+ .pagination-controls {
2434
+ display: flex;
2435
+ align-items: center;
2436
+ gap: var(--space-1);
2437
+
2438
+ flex: 0 0 auto;
2439
+ }
2440
+
2441
+ .pagination-pages {
2442
+ display: flex;
2443
+ align-items: center;
2444
+ justify-content: center;
2445
+ gap: var(--space-1);
2446
+
2447
+ flex: 1 1 auto;
2448
+ }
2449
+ .pagination-item {
2450
+ display: inline-flex;
2451
+ align-items: center;
2452
+ justify-content: center;
2453
+
2454
+ min-width: var(--button-min-height);
2455
+ height: var(--button-min-height);
2456
+
2457
+ padding-inline: var(--space-3);
2458
+
2459
+ border: 1px solid transparent;
2460
+ border-radius: var(--radius-md);
2461
+
2462
+ background: transparent;
2463
+ color: var(--text-secondary);
2464
+
2465
+ font-family: var(--font-family-body);
2466
+ font-size: var(--font-size-sm);
2467
+ font-weight: var(--font-weight-medium);
2468
+
2469
+ cursor: pointer;
2470
+
2471
+ transition:
2472
+ background-color var(--motion-duration-fast) var(--motion-ease-out),
2473
+ border-color var(--motion-duration-fast) var(--motion-ease-out),
2474
+ color var(--motion-duration-fast) var(--motion-ease-out);
2475
+ }
2476
+
2477
+ .pagination-item:hover {
2478
+ background: var(--surface-hover);
2479
+ color: var(--text-primary);
2480
+ }
2481
+
2482
+ .pagination-item:focus-visible {
2483
+ outline:
2484
+ var(--focus-ring-width)
2485
+ solid
2486
+ var(--focus-ring-color);
2487
+
2488
+ outline-offset: var(--focus-ring-offset);
2489
+ }
2490
+
2491
+ .pagination-item--current {
2492
+ background: var(--surface-card);
2493
+ border-color: var(--border-default);
2494
+ color: var(--text-primary);
2495
+ }
2496
+
2497
+ .pagination-item--disabled {
2498
+ color: var(--text-muted);
2499
+ opacity: var(--interaction-opacity-disabled);
2500
+ cursor: not-allowed;
2501
+ pointer-events: none;
2502
+ }
2503
+
2504
+ .pagination-ellipsis {
2505
+ display: inline-flex;
2506
+ align-items: center;
2507
+ justify-content: center;
2508
+
2509
+ min-width: var(--button-min-height);
2510
+ height: var(--button-min-height);
2511
+
2512
+ color: var(--text-muted);
2513
+ user-select: none;
2514
+ }
2515
+
2516
+ .pagination-compact {
2517
+ gap: var(--space-2);
2518
+ }
2519
+
2520
+ .pagination-compact .pagination-item {
2521
+ min-width: var(--button-min-height-sm);
2522
+ height: var(--button-min-height-sm);
2523
+
2524
+ padding-inline: var(--space-2);
2525
+
2526
+ font-size: var(--font-size-xs);
2527
+ }
2528
+
2529
+
2530
+ /* ==========================================================================
2531
+ TABLE
2532
+ ========================================================================== */
2533
+
2534
+ .table {
2535
+ width: 100%;
2536
+ overflow-x: auto;
2537
+
2538
+ border: 1px solid var(--border-default);
2539
+ border-radius: var(--card-radius);
2540
+
2541
+ background: var(--surface-card);
2542
+ }
2543
+
2544
+ .table table {
2545
+ width: 100%;
2546
+ border-collapse: collapse;
2547
+
2548
+ color: var(--text-primary);
2549
+
2550
+ font-family: var(--font-family-body);
2551
+ font-size: var(--font-size-sm);
2552
+ }
2553
+
2554
+
2555
+ /* --------------------------------------------------------------------------
2556
+ TABLE HEADER
2557
+ -------------------------------------------------------------------------- */
2558
+
2559
+ .table th {
2560
+ padding: var(--space-4) var(--space-5);
2561
+
2562
+ border-bottom: 1px solid var(--border-default);
2563
+
2564
+ background: var(--surface-raised);
2565
+ color: var(--text-muted);
2566
+
2567
+ font-size: var(--font-size-xs);
2568
+ font-weight: var(--font-weight-semibold);
2569
+ line-height: var(--line-height-snug);
2570
+ letter-spacing: var(--letter-spacing-wide);
2571
+ text-align: left;
2572
+ text-transform: uppercase;
2573
+
2574
+ white-space: nowrap;
2575
+ }
2576
+
2577
+ .table th:first-child {
2578
+ border-top-left-radius: calc(var(--card-radius) - 1px);
2579
+ }
2580
+
2581
+ .table th:last-child {
2582
+ border-top-right-radius: calc(var(--card-radius) - 1px);
2583
+ }
2584
+
2585
+
2586
+ /* --------------------------------------------------------------------------
2587
+ SORTABLE HEADERS
2588
+ -------------------------------------------------------------------------- */
2589
+
2590
+ .table-header--sortable {
2591
+ cursor: pointer;
2592
+ user-select: none;
2593
+
2594
+ transition:
2595
+ background-color var(--motion-duration-fast) var(--motion-ease-out),
2596
+ color var(--motion-duration-fast) var(--motion-ease-out);
2597
+ }
2598
+
2599
+ .table-header--sortable:hover {
2600
+ background: var(--surface-hover);
2601
+ color: var(--text-primary);
2602
+ }
2603
+
2604
+ .table-header--sorted {
2605
+ color: var(--text-primary);
2606
+ }
2607
+
2608
+ .table-header--sortable:focus-visible {
2609
+ outline:
2610
+ var(--focus-ring-width)
2611
+ solid
2612
+ var(--focus-ring-color);
2613
+
2614
+ outline-offset: calc(var(--focus-ring-offset) * -1);
2615
+ }
2616
+
2617
+
2618
+ /* --------------------------------------------------------------------------
2619
+ TABLE BODY
2620
+ -------------------------------------------------------------------------- */
2621
+
2622
+ .table td {
2623
+ padding: var(--space-4) var(--space-5);
2624
+
2625
+ border-bottom: 1px solid var(--border-subtle);
2626
+
2627
+ color: var(--text-secondary);
2628
+
2629
+ vertical-align: middle;
2630
+ }
2631
+
2632
+ .table tbody tr {
2633
+ transition:
2634
+ background-color var(--motion-duration-fast) var(--motion-ease-out),
2635
+ color var(--motion-duration-fast) var(--motion-ease-out);
2636
+ }
2637
+
2638
+ .table tbody tr:hover {
2639
+ background: var(--surface-hover);
2640
+ }
2641
+
2642
+ .table tbody tr:last-child td {
2643
+ border-bottom: 0;
2644
+ }
2645
+
2646
+
2647
+ /* --------------------------------------------------------------------------
2648
+ TABLE SELECTED ROW
2649
+ -------------------------------------------------------------------------- */
2650
+
2651
+ .table-row--selected {
2652
+ background: var(--surface-raised);
2653
+ }
2654
+
2655
+ .table-row--selected:hover {
2656
+ background: var(--surface-hover);
2657
+ }
2658
+
2659
+
2660
+ /* --------------------------------------------------------------------------
2661
+ TABLE DISABLED ROW
2662
+ -------------------------------------------------------------------------- */
2663
+
2664
+ .table-row--disabled {
2665
+ opacity: var(--interaction-opacity-disabled);
2666
+ }
2667
+
2668
+ .table-row--disabled:hover {
2669
+ background: transparent;
2670
+ }
2671
+
2672
+
2673
+ /* --------------------------------------------------------------------------
2674
+ TABLE ALIGNMENT
2675
+ -------------------------------------------------------------------------- */
2676
+
2677
+ .table-cell--center {
2678
+ text-align: center;
2679
+ }
2680
+
2681
+ .table-cell--end {
2682
+ text-align: right;
2683
+ }
2684
+
2685
+
2686
+ /* --------------------------------------------------------------------------
2687
+ TABLE LOADING
2688
+ -------------------------------------------------------------------------- */
2689
+
2690
+ .table-loading {
2691
+ position: relative;
2692
+ min-height: 10rem;
2693
+ }
2694
+
2695
+ .table-loading::after {
2696
+ content: "";
2697
+
2698
+ position: absolute;
2699
+ inset: 0;
2700
+
2701
+ background: var(--surface-card);
2702
+
2703
+ opacity: 0.55;
2704
+
2705
+ pointer-events: none;
2706
+ }
2707
+
2708
+ /* --------------------------------------------------------------------------
2709
+ REDUCED MOTION
2710
+ -------------------------------------------------------------------------- */
2711
+
2712
+ @media (prefers-reduced-motion: reduce) {
2713
+ .list-item,
2714
+ .pagination-item,
2715
+ .table tbody tr,
2716
+ .table-header--sortable {
2717
+ transition: none;
2718
+ }
2719
+ }
2720
+ /* --------------------------------------------------------------------------
2721
+ OVERLAYS
2722
+ *---------------------------------------------------------------------------- */
2723
+ /* ==========================================================================
2724
+ DIALOG
2725
+ Focused task / decision overlay.
2726
+ ========================================================================== */
2727
+ .dialog {
2728
+ position: fixed;
2729
+ inset: 0;
2730
+ z-index: var(--z-modal);
2731
+
2732
+ display: flex;
2733
+ align-items: center;
2734
+ justify-content: center;
2735
+
2736
+ padding: var(--space-6);
2737
+
2738
+ pointer-events: none;
2739
+ }
2740
+
2741
+ .dialog-backdrop {
2742
+ position: absolute;
2743
+ inset: 0;
2744
+
2745
+ background: var(--overlay-scrim);
2746
+
2747
+ backdrop-filter: blur(3px);
2748
+ -webkit-backdrop-filter: blur(3px);
2749
+
2750
+ opacity: 0;
2751
+
2752
+ transition:
2753
+ opacity var(--motion-duration-normal)
2754
+ var(--motion-ease-out);
2755
+ }
2756
+
2757
+ .dialog--open {
2758
+ pointer-events: auto;
2759
+ }
2760
+
2761
+ .dialog--open .dialog-backdrop {
2762
+ opacity: 1;
2763
+ }
2764
+
2765
+ .dialog-content {
2766
+ position: relative;
2767
+ z-index: 1;
2768
+
2769
+ width: min(
2770
+ 100%,
2771
+ var(--dialog-width, 32rem)
2772
+ );
2773
+
2774
+ max-height: calc(100vh - var(--space-12));
2775
+
2776
+ overflow-y: auto;
2777
+
2778
+ padding: var(--card-padding);
2779
+
2780
+ border:
2781
+ 1px solid
2782
+ var(--card-border);
2783
+
2784
+ border-radius: var(--card-radius);
2785
+
2786
+ background: var(--card-background);
2787
+ color: var(--text-primary);
2788
+
2789
+ box-shadow: var(--shadow-elevation-high);
2790
+
2791
+ opacity: 0;
2792
+ transform: translateY(
2793
+ var(--space-2)
2794
+ ) scale(0.98);
2795
+
2796
+ transition:
2797
+ opacity var(--motion-duration-normal)
2798
+ var(--motion-ease-out),
2799
+ transform var(--motion-duration-normal)
2800
+ var(--motion-ease-out);
2801
+ }
2802
+
2803
+ .dialog--open .dialog-content {
2804
+ opacity: 1;
2805
+ transform: translateY(0) scale(1);
2806
+ }
2807
+
2808
+
2809
+ /* ==========================================================================
2810
+ DIALOG CLOSE
2811
+ ========================================================================== */
2812
+
2813
+ .dialog-close {
2814
+ position: absolute;
2815
+ top: var(--space-4);
2816
+ right: var(--space-4);
2817
+
2818
+ display: inline-flex;
2819
+ align-items: center;
2820
+ justify-content: center;
2821
+
2822
+ width: var(--button-min-height);
2823
+ height: var(--button-min-height);
2824
+
2825
+ padding: 0;
2826
+
2827
+ border: 0;
2828
+ border-radius: var(--radius-md);
2829
+
2830
+ background: transparent;
2831
+ color: var(--text-muted);
2832
+
2833
+ cursor: pointer;
2834
+
2835
+ transition:
2836
+ background-color var(--motion-duration-fast)
2837
+ var(--motion-ease-out),
2838
+ color var(--motion-duration-fast)
2839
+ var(--motion-ease-out);
2840
+ }
2841
+
2842
+ .dialog-close:hover {
2843
+ background: var(--surface-hover);
2844
+ color: var(--text-primary);
2845
+ }
2846
+
2847
+ .dialog-close:focus-visible {
2848
+ outline:
2849
+ var(--focus-ring-width)
2850
+ solid
2851
+ var(--focus-ring-color);
2852
+
2853
+ outline-offset: var(--focus-ring-offset);
2854
+ }
2855
+
2856
+
2857
+ /* ==========================================================================
2858
+ DIALOG RESPONSIVE
2859
+ ========================================================================== */
2860
+
2861
+ @media (max-width: 40rem) {
2862
+ .dialog {
2863
+ align-items: flex-end;
2864
+
2865
+ padding:
2866
+ var(--space-3);
2867
+ }
2868
+
2869
+ .dialog-content {
2870
+ width: 100%;
2871
+ max-height: calc(100vh - var(--space-6));
2872
+
2873
+ border-radius:
2874
+ var(--card-radius)
2875
+ var(--card-radius)
2876
+ 0
2877
+ 0;
2878
+
2879
+ transform: translateY(
2880
+ var(--space-4)
2881
+ );
2882
+ }
2883
+
2884
+ .dialog--open .dialog-content {
2885
+ transform: translateY(0);
2886
+ }
2887
+ }
2888
+
2889
+
2890
+ /* ==========================================================================
2891
+ REDUCED MOTION
2892
+ ========================================================================== */
2893
+
2894
+ @media (prefers-reduced-motion: reduce) {
2895
+ .dialog-backdrop,
2896
+ .dialog-content {
2897
+ transition: none;
2898
+ }
2899
+ }
2900
+ /* ==========================================================================
2901
+ DRAWER
2902
+ Large contextual workspace overlay.
2903
+ ========================================================================== */
2904
+
2905
+ .drawer {
2906
+ position: fixed;
2907
+ inset: 0;
2908
+ z-index: var(--z-overlay);
2909
+
2910
+ pointer-events: none;
2911
+ }
2912
+
2913
+ .drawer--open {
2914
+ pointer-events: auto;
2915
+ }
2916
+
2917
+
2918
+ /* ==========================================================================
2919
+ BACKDROP
2920
+ ========================================================================== */
2921
+
2922
+ .drawer-backdrop {
2923
+ position: absolute;
2924
+ inset: 0;
2925
+
2926
+ border: 0;
2927
+ padding: 0;
2928
+
2929
+ background: var(--overlay-scrim);
2930
+
2931
+ backdrop-filter: blur(3px);
2932
+ -webkit-backdrop-filter: blur(3px);
2933
+
2934
+ opacity: 0;
2935
+
2936
+ cursor: default;
2937
+
2938
+ transition:
2939
+ opacity var(--motion-duration-normal)
2940
+ var(--motion-ease-out);
2941
+ }
2942
+
2943
+ .drawer--open .drawer-backdrop {
2944
+ opacity: 1;
2945
+ }
2946
+
2947
+
2948
+ /* ==========================================================================
2949
+ PANEL
2950
+ ========================================================================== */
2951
+
2952
+ .drawer-panel {
2953
+ position: absolute;
2954
+ top: 0;
2955
+ bottom: 0;
2956
+
2957
+ display: flex;
2958
+ flex-direction: column;
2959
+
2960
+ width: min(
2961
+ var(--drawer-width, 28rem),
2962
+ 100vw
2963
+ );
2964
+
2965
+ background: var(--card-background);
2966
+ color: var(--text-primary);
2967
+
2968
+ border-color: var(--border-subtle);
2969
+ border-style: solid;
2970
+
2971
+ box-shadow: var(--shadow-elevation-high);
2972
+
2973
+ overflow: hidden;
2974
+
2975
+ transition:
2976
+ transform var(--motion-duration-normal)
2977
+ var(--motion-ease-out);
2978
+ }
2979
+
2980
+
2981
+ /* ==========================================================================
2982
+ SIDES
2983
+ ========================================================================== */
2984
+
2985
+ .drawer--right .drawer-panel {
2986
+ right: 0;
2987
+
2988
+ border-left-width: 1px;
2989
+
2990
+ transform: translateX(100%);
2991
+ }
2992
+
2993
+ .drawer--left .drawer-panel {
2994
+ left: 0;
2995
+
2996
+ border-right-width: 1px;
2997
+
2998
+ transform: translateX(-100%);
2999
+ }
3000
+
3001
+ .drawer--open .drawer-panel {
3002
+ transform: translateX(0);
3003
+ }
3004
+
3005
+
3006
+ /* ==========================================================================
3007
+ CONTENT
3008
+ ========================================================================== */
3009
+
3010
+ .drawer-content {
3011
+ flex: 1 1 auto;
3012
+ min-height: 0;
3013
+
3014
+ padding: var(--card-padding);
3015
+
3016
+ overflow-y: auto;
3017
+ }
3018
+
3019
+
3020
+ /* ==========================================================================
3021
+ CLOSE
3022
+ ========================================================================== */
3023
+
3024
+ .drawer-close {
3025
+ display: inline-flex;
3026
+ align-items: center;
3027
+ justify-content: center;
3028
+
3029
+ width: var(--button-min-height);
3030
+ height: var(--button-min-height);
3031
+
3032
+ flex: 0 0 auto;
3033
+
3034
+ padding: 0;
3035
+
3036
+ border: 0;
3037
+ border-radius: var(--radius-md);
3038
+
3039
+ background: transparent;
3040
+ color: var(--text-muted);
3041
+
3042
+ cursor: pointer;
3043
+
3044
+ transition:
3045
+ background-color var(--motion-duration-fast)
3046
+ var(--motion-ease-out),
3047
+ color var(--motion-duration-fast)
3048
+ var(--motion-ease-out);
3049
+ }
3050
+
3051
+ .drawer-close:hover {
3052
+ background: var(--surface-hover);
3053
+ color: var(--text-primary);
3054
+ }
3055
+
3056
+ .drawer-close:focus-visible {
3057
+ outline:
3058
+ var(--focus-ring-width)
3059
+ solid
3060
+ var(--focus-ring-color);
3061
+
3062
+ outline-offset: var(--focus-ring-offset);
3063
+ }
3064
+
3065
+
3066
+ /* ==========================================================================
3067
+ MOBILE
3068
+ ========================================================================== */
3069
+
3070
+ @media (max-width: 40rem) {
3071
+ .drawer-panel {
3072
+ width: 100%;
3073
+ }
3074
+ }
3075
+
3076
+
3077
+ /* ==========================================================================
3078
+ REDUCED MOTION
3079
+ ========================================================================== */
3080
+
3081
+ @media (prefers-reduced-motion: reduce) {
3082
+ .drawer-backdrop,
3083
+ .drawer-panel {
3084
+ transition: none;
3085
+ }
3086
+ }
3087
+ /* ==========================================================================
3088
+ POPOVER
3089
+ Contextual interactive content
3090
+ ========================================================================== */
3091
+
3092
+ .popover {
3093
+ position: relative;
3094
+ display: inline-block;
3095
+ }
3096
+
3097
+ .popover-trigger {
3098
+ display: inline-flex;
3099
+ }
3100
+
3101
+ .popover-content {
3102
+ position: absolute;
3103
+ z-index: var(--z-popover);
3104
+
3105
+ width: max-content;
3106
+ max-width: min(
3107
+ 22rem,
3108
+ calc(100vw - var(--space-8))
3109
+ );
3110
+
3111
+ padding: var(--space-4);
3112
+
3113
+ border: 1px solid var(--border-subtle);
3114
+ border-radius: var(--radius-md);
3115
+
3116
+ background: var(--surface-card);
3117
+ color: var(--text-primary);
3118
+
3119
+ box-shadow: var(--shadow-elevation-medium);
3120
+
3121
+ opacity: 0;
3122
+ visibility: hidden;
3123
+ transform: translateY(-0.25rem) scale(0.98);
3124
+
3125
+ transition:
3126
+ opacity var(--motion-duration-fast) var(--motion-ease-out),
3127
+ transform var(--motion-duration-fast) var(--motion-ease-out),
3128
+ visibility var(--motion-duration-fast) var(--motion-ease-out);
3129
+ }
3130
+
3131
+ .popover--open .popover-content {
3132
+ opacity: 1;
3133
+ visibility: visible;
3134
+ transform: translateY(0) scale(1);
3135
+ }
3136
+
3137
+ .popover--bottom .popover-content {
3138
+ top: calc(100% + var(--space-2));
3139
+ left: 0;
3140
+ }
3141
+
3142
+ .popover--top .popover-content {
3143
+ bottom: calc(100% + var(--space-2));
3144
+ left: 0;
3145
+
3146
+ transform: translateY(0.25rem) scale(0.98);
3147
+ }
3148
+
3149
+ .popover--top.popover--open .popover-content {
3150
+ transform: translateY(0) scale(1);
3151
+ }
3152
+
3153
+ .popover--right .popover-content {
3154
+ top: 0;
3155
+ left: calc(100% + var(--space-2));
3156
+ }
3157
+
3158
+ .popover--left .popover-content {
3159
+ top: 0;
3160
+ right: calc(100% + var(--space-2));
3161
+ }
3162
+
3163
+
3164
+ /* ==========================================================================
3165
+ TOOLTIP
3166
+ ========================================================================== */
3167
+
3168
+ .tooltip {
3169
+ position: relative;
3170
+ display: inline-flex;
3171
+ }
3172
+
3173
+ .tooltip-trigger {
3174
+ display: inline-flex;
3175
+ }
3176
+
3177
+ .tooltip-content {
3178
+ position: absolute;
3179
+ z-index: var(--z-tooltip);
3180
+
3181
+ width: max-content;
3182
+ max-width: 18rem;
3183
+
3184
+ padding:
3185
+ var(--space-2)
3186
+ var(--space-3);
3187
+
3188
+ border: 1px solid var(--border-subtle);
3189
+ border-radius: var(--radius-sm);
3190
+
3191
+ background: var(--surface-elevated-2);
3192
+ color: var(--text-primary);
3193
+
3194
+ font-family: var(--font-family-body);
3195
+ font-size: var(--font-size-xs);
3196
+ font-weight: var(--font-weight-medium);
3197
+ line-height: var(--line-height-normal);
3198
+
3199
+ box-shadow: var(--shadow-elevation-low);
3200
+
3201
+ white-space: normal;
3202
+ text-align: left;
3203
+
3204
+ pointer-events: none;
3205
+
3206
+ opacity: 0;
3207
+ visibility: hidden;
3208
+ transform: translateY(-0.2rem);
3209
+
3210
+ transition:
3211
+ opacity var(--motion-duration-fast) var(--motion-ease-out),
3212
+ transform var(--motion-duration-fast) var(--motion-ease-out),
3213
+ visibility var(--motion-duration-fast) var(--motion-ease-out);
3214
+ }
3215
+
3216
+ .tooltip--visible .tooltip-content {
3217
+ opacity: 1;
3218
+ visibility: visible;
3219
+ transform: translateY(0);
3220
+ }
3221
+
3222
+ .tooltip--bottom .tooltip-content {
3223
+ top: calc(100% + var(--space-2));
3224
+ left: 50%;
3225
+
3226
+ transform: translate(-50%, -0.2rem);
3227
+ }
3228
+
3229
+ .tooltip--bottom.tooltip--visible .tooltip-content {
3230
+ transform: translate(-50%, 0);
3231
+ }
3232
+
3233
+ .tooltip--top .tooltip-content {
3234
+ bottom: calc(100% + var(--space-2));
3235
+ left: 50%;
3236
+
3237
+ transform: translate(-50%, 0.2rem);
3238
+ }
3239
+
3240
+ .tooltip--top.tooltip--visible .tooltip-content {
3241
+ transform: translate(-50%, 0);
3242
+ }
3243
+
3244
+ .tooltip--right .tooltip-content {
3245
+ top: 50%;
3246
+ left: calc(100% + var(--space-2));
3247
+
3248
+ transform: translate(0.2rem, -50%);
3249
+ }
3250
+
3251
+ .tooltip--right.tooltip--visible .tooltip-content {
3252
+ transform: translate(0, -50%);
3253
+ }
3254
+
3255
+ .tooltip--left .tooltip-content {
3256
+ top: 50%;
3257
+ right: calc(100% + var(--space-2));
3258
+
3259
+ transform: translate(-0.2rem, -50%);
3260
+ }
3261
+
3262
+ .tooltip--left.tooltip--visible .tooltip-content {
3263
+ transform: translate(0, -50%);
3264
+ }
3265
+
3266
+
3267
+ /* ==========================================================================
3268
+ REDUCED MOTION
3269
+ ========================================================================== */
3270
+
3271
+ @media (prefers-reduced-motion: reduce) {
3272
+ .popover-content,
3273
+ .tooltip-content {
3274
+ transition: none;
3275
+ }
3276
+ }
3277
+ /* ==========================================================================
3278
+ ALERT
3279
+ Persistent in-flow feedback message.
3280
+ ========================================================================== */
3281
+
3282
+ .alert {
3283
+ display: flex;
3284
+ align-items: flex-start;
3285
+ gap: var(--space-3);
3286
+
3287
+ width: 100%;
3288
+
3289
+ padding: var(--space-4);
3290
+
3291
+ border: 1px solid transparent;
3292
+ border-radius: var(--radius-md);
3293
+
3294
+ background: var(--surface-card);
3295
+ color: var(--text-primary);
3296
+ }
3297
+
3298
+
3299
+ /* --------------------------------------------------------------------------
3300
+ CONTENT
3301
+ -------------------------------------------------------------------------- */
3302
+
3303
+ .alert-content {
3304
+ display: flex;
3305
+ flex-direction: column;
3306
+ gap: var(--space-1);
3307
+
3308
+ min-width: 0;
3309
+ flex: 1 1 auto;
3310
+ }
3311
+
3312
+ .alert-message {
3313
+ color: var(--text-secondary);
3314
+ line-height: var(--line-height-normal);
3315
+ }
3316
+
3317
+ .alert-actions {
3318
+ display: inline-flex;
3319
+ align-items: center;
3320
+
3321
+ flex: 0 0 auto;
3322
+
3323
+ margin-top: var(--space-3);
3324
+ }
3325
+
3326
+
3327
+ /* --------------------------------------------------------------------------
3328
+ VARIANTS
3329
+ -------------------------------------------------------------------------- */
3330
+
3331
+ .alert-info {
3332
+ border-color: var(--alert-info-border);
3333
+ background: var(--alert-info-background);
3334
+ color: var(--alert-info-text);
3335
+ }
3336
+
3337
+ .alert-success {
3338
+ border-color: var(--alert-success-border);
3339
+ background: var(--alert-success-background);
3340
+ color: var(--alert-success-text);
3341
+ }
3342
+
3343
+ .alert-warning {
3344
+ border-color: var(--alert-warning-border);
3345
+ background: var(--alert-warning-background);
3346
+ color: var(--alert-warning-text);
3347
+ }
3348
+
3349
+ .alert-danger {
3350
+ border-color: var(--alert-danger-border);
3351
+ background: var(--alert-danger-background);
3352
+ color: var(--alert-danger-text);
3353
+ }
3354
+
3355
+
3356
+ /* --------------------------------------------------------------------------
3357
+ DISMISS
3358
+ -------------------------------------------------------------------------- */
3359
+
3360
+ .alert-close {
3361
+ display: inline-flex;
3362
+ align-items: center;
3363
+ justify-content: center;
3364
+
3365
+ width: var(--button-min-height-sm);
3366
+ height: var(--button-min-height-sm);
3367
+
3368
+ flex: 0 0 auto;
3369
+
3370
+ padding: 0;
3371
+
3372
+ border: 0;
3373
+ border-radius: var(--radius-md);
3374
+
3375
+ background: transparent;
3376
+ color: var(--text-muted);
3377
+
3378
+ cursor: pointer;
3379
+
3380
+ transition:
3381
+ background-color var(--motion-duration-fast) var(--motion-ease-out),
3382
+ color var(--motion-duration-fast) var(--motion-ease-out);
3383
+ }
3384
+
3385
+ .alert-close:hover {
3386
+ background: var(--surface-hover);
3387
+ color: var(--text-primary);
3388
+ }
3389
+
3390
+ .alert-close:focus-visible {
3391
+ outline:
3392
+ var(--focus-ring-width)
3393
+ solid
3394
+ var(--focus-ring-color);
3395
+
3396
+ outline-offset: var(--focus-ring-offset);
3397
+ }
3398
+
3399
+
3400
+ /* --------------------------------------------------------------------------
3401
+ REDUCED MOTION
3402
+ -------------------------------------------------------------------------- */
3403
+
3404
+ @media (prefers-reduced-motion: reduce) {
3405
+ .alert-close {
3406
+ transition: none;
3407
+ }
3408
+ }
3409
+ /* ==========================================================================
3410
+ PROGRESS
3411
+ Shows completion of an operation.
3412
+ ========================================================================== */
3413
+
3414
+ .progress {
3415
+ display: flex;
3416
+ flex-direction: column;
3417
+ gap: var(--space-2);
3418
+
3419
+ width: 100%;
3420
+ }
3421
+
3422
+ .progress-track {
3423
+ position: relative;
3424
+
3425
+ width: 100%;
3426
+ height: 0.5rem;
3427
+
3428
+ overflow: hidden;
3429
+
3430
+ border-radius: var(--radius-full);
3431
+
3432
+ background: var(--surface-raised);
3433
+ }
3434
+
3435
+ .progress-value {
3436
+ height: 100%;
3437
+ width: 0;
3438
+
3439
+ border-radius: inherit;
3440
+
3441
+ background: var(--brand-primary);
3442
+
3443
+ transition:
3444
+ width var(--motion-duration-normal)
3445
+ var(--motion-ease-out);
3446
+ }
3447
+
3448
+ .progress--success .progress-value {
3449
+ background: var(--color-success);
3450
+ }
3451
+
3452
+ .progress--warning .progress-value {
3453
+ background: var(--color-warning);
3454
+ }
3455
+
3456
+ .progress--danger .progress-value {
3457
+ background: var(--color-danger);
3458
+ }
3459
+
3460
+ .progress--indeterminate .progress-value {
3461
+ width: 40%;
3462
+
3463
+ animation:
3464
+ progress-indeterminate
3465
+ 1.4s
3466
+ var(--motion-ease-in-out)
3467
+ infinite;
3468
+ }
3469
+
3470
+ .progress-label {
3471
+ display: flex;
3472
+ align-items: center;
3473
+ justify-content: space-between;
3474
+ gap: var(--space-3);
3475
+
3476
+ color: var(--text-secondary);
3477
+
3478
+ font-size: var(--font-size-sm);
3479
+ line-height: var(--line-height-normal);
3480
+ }
3481
+
3482
+ @keyframes progress-indeterminate {
3483
+ 0% {
3484
+ transform: translateX(-100%);
3485
+ }
3486
+
3487
+ 50% {
3488
+ transform: translateX(150%);
3489
+ }
3490
+
3491
+ 100% {
3492
+ transform: translateX(300%);
3493
+ }
3494
+ }
3495
+
3496
+
3497
+ /* ==========================================================================
3498
+ SKELETON
3499
+ Placeholder for loading content.
3500
+ ========================================================================== */
3501
+
3502
+ .skeleton {
3503
+ display: block;
3504
+
3505
+ width: 100%;
3506
+ min-height: 1rem;
3507
+
3508
+ border-radius: var(--radius-md);
3509
+
3510
+ background:
3511
+ linear-gradient(
3512
+ 90deg,
3513
+ var(--surface-raised) 25%,
3514
+ var(--surface-hover) 50%,
3515
+ var(--surface-raised) 75%
3516
+ );
3517
+
3518
+ background-size: 200% 100%;
3519
+
3520
+ animation:
3521
+ skeleton-shimmer
3522
+ 1.6s
3523
+ var(--motion-ease-in-out)
3524
+ infinite;
3525
+ }
3526
+
3527
+ .skeleton--text {
3528
+ height: 1rem;
3529
+ min-height: 1rem;
3530
+ }
3531
+
3532
+ .skeleton--heading {
3533
+ height: 2rem;
3534
+ min-height: 2rem;
3535
+
3536
+ max-width: 70%;
3537
+ }
3538
+
3539
+ .skeleton--avatar {
3540
+ width: 2.75rem;
3541
+ min-width: 2.75rem;
3542
+
3543
+ height: 2.75rem;
3544
+ min-height: 2.75rem;
3545
+
3546
+ border-radius: var(--radius-full);
3547
+ }
3548
+
3549
+ .skeleton--circle {
3550
+ border-radius: var(--radius-full);
3551
+ }
3552
+
3553
+ .skeleton--button {
3554
+ width: 7rem;
3555
+ min-height: var(--button-min-height);
3556
+
3557
+ border-radius: var(--button-radius);
3558
+ }
3559
+
3560
+ @keyframes skeleton-shimmer {
3561
+ 0% {
3562
+ background-position: 200% 0;
3563
+ }
3564
+
3565
+ 100% {
3566
+ background-position: -200% 0;
3567
+ }
3568
+ }
3569
+
3570
+
3571
+ /* ==========================================================================
3572
+ TOAST
3573
+ Temporary floating feedback.
3574
+ ========================================================================== */
3575
+
3576
+ .toast {
3577
+ position: fixed;
3578
+ right: var(--space-6);
3579
+ bottom: var(--space-6);
3580
+
3581
+ z-index: var(--z-tooltip);
3582
+
3583
+ display: flex;
3584
+ align-items: flex-start;
3585
+ gap: var(--space-3);
3586
+
3587
+ width: min(
3588
+ 24rem,
3589
+ calc(100vw - var(--space-8))
3590
+ );
3591
+
3592
+ padding: var(--space-4);
3593
+
3594
+ border: 1px solid var(--border-default);
3595
+ border-radius: var(--radius-md);
3596
+
3597
+ background: var(--surface-card);
3598
+ color: var(--text-primary);
3599
+
3600
+ box-shadow: var(--shadow-elevation-high);
3601
+
3602
+ transform: translateY(var(--space-3));
3603
+ opacity: 0;
3604
+
3605
+ transition:
3606
+ opacity var(--motion-duration-normal)
3607
+ var(--motion-ease-out),
3608
+ transform var(--motion-duration-normal)
3609
+ var(--motion-ease-out);
3610
+ }
3611
+
3612
+ .toast--visible {
3613
+ opacity: 1;
3614
+ transform: translateY(0);
3615
+ }
3616
+
3617
+ .toast-info {
3618
+ border-color: var(--alert-info-border);
3619
+ }
3620
+
3621
+ .toast-success {
3622
+ border-color: var(--alert-success-border);
3623
+ }
3624
+
3625
+ .toast-warning {
3626
+ border-color: var(--alert-warning-border);
3627
+ }
3628
+
3629
+ .toast-danger {
3630
+ border-color: var(--alert-danger-border);
3631
+ }
3632
+
3633
+ .toast-content {
3634
+ display: flex;
3635
+ flex-direction: column;
3636
+ gap: var(--space-1);
3637
+
3638
+ min-width: 0;
3639
+
3640
+ flex: 1 1 auto;
3641
+ }
3642
+
3643
+ .toast-title {
3644
+ color: var(--text-primary);
3645
+ font-weight: var(--font-weight-semibold);
3646
+ }
3647
+
3648
+ .toast-message {
3649
+ color: var(--text-secondary);
3650
+ line-height: var(--line-height-normal);
3651
+ }
3652
+
3653
+ .toast-close {
3654
+ display: inline-flex;
3655
+ align-items: center;
3656
+ justify-content: center;
3657
+
3658
+ width: var(--button-min-height-sm);
3659
+ height: var(--button-min-height-sm);
3660
+
3661
+ flex: 0 0 auto;
3662
+
3663
+ padding: 0;
3664
+
3665
+ border: 0;
3666
+ border-radius: var(--radius-md);
3667
+
3668
+ background: transparent;
3669
+ color: var(--text-muted);
3670
+
3671
+ cursor: pointer;
3672
+
3673
+ transition:
3674
+ background-color var(--motion-duration-fast)
3675
+ var(--motion-ease-out),
3676
+ color var(--motion-duration-fast)
3677
+ var(--motion-ease-out);
3678
+ }
3679
+
3680
+ .toast-close:hover {
3681
+ background: var(--surface-hover);
3682
+ color: var(--text-primary);
3683
+ }
3684
+
3685
+ .toast-close:focus-visible {
3686
+ outline:
3687
+ var(--focus-ring-width)
3688
+ solid
3689
+ var(--focus-ring-color);
3690
+
3691
+ outline-offset: var(--focus-ring-offset);
3692
+ }
3693
+
3694
+ @media (max-width: 40rem) {
3695
+ .toast {
3696
+ right: var(--space-3);
3697
+ bottom: var(--space-3);
3698
+
3699
+ width: calc(100vw - var(--space-6));
3700
+ }
3701
+ }
3702
+
3703
+
3704
+ /* ==========================================================================
3705
+ REDUCED MOTION
3706
+ ========================================================================== */
3707
+
3708
+ @media (prefers-reduced-motion: reduce) {
3709
+ .progress-value,
3710
+ .skeleton,
3711
+ .toast {
3712
+ animation: none;
3713
+ transition: none;
3714
+ }
3715
+
3716
+ .toast {
3717
+ transform: none;
3718
+ }
3719
+ }
3720
+ /* ==========================================================================
3721
+ ANIMATION UTILITY CLASSES
3722
+ Consume @keyframes from the project's animations.css / typography.css.
3723
+ ========================================================================== */
3724
+
3725
+ .animate-fade-in {
3726
+ animation: fade-in var(--motion-duration-normal) var(--motion-ease-smooth) forwards;
3727
+ }
3728
+
3729
+ .animate-fade-in-up {
3730
+ animation: fade-in-up var(--motion-duration-normal) var(--motion-ease-smooth) forwards;
3731
+ }
3732
+
3733
+ .animate-slide-in-left {
3734
+ animation: slide-in-left var(--motion-duration-slow) var(--motion-ease-smooth) forwards;
3735
+ }
3736
+
3737
+ .animate-slide-in-right {
3738
+ animation: slide-in-right var(--motion-duration-slow) var(--motion-ease-smooth) forwards;
3739
+ }
3740
+
3741
+ .animate-scale-in {
3742
+ animation: scale-in var(--motion-duration-fast) var(--motion-ease-spring) forwards;
3743
+ }