@attrus-ds/core 1.0.6 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/css/components/action-bar.css +93 -0
  2. package/dist/css/components/ambient.css +97 -0
  3. package/dist/css/components/animated-bg.css +261 -0
  4. package/dist/css/components/buttons.css +4 -4
  5. package/dist/css/components/callout.css +4 -3
  6. package/dist/css/components/cards.css +4 -3
  7. package/dist/css/components/combobox.css +16 -13
  8. package/dist/css/components/inputs.css +99 -15
  9. package/dist/css/components/number-input.css +6 -3
  10. package/dist/css/components/primitives.css +20 -15
  11. package/dist/css/components/sel-card.css +212 -0
  12. package/dist/css/components/sidebar.css +11 -9
  13. package/dist/css/components/smart-search.css +13 -11
  14. package/dist/css/components/status-pills.css +1 -1
  15. package/dist/css/components/stepper.css +81 -4
  16. package/dist/css/components/table.css +168 -7
  17. package/dist/css/components/tabs.css +4 -3
  18. package/dist/css/components/toast.css +2 -2
  19. package/dist/css/components/toggle-chip.css +137 -0
  20. package/dist/css/components/tooltip.css +8 -5
  21. package/dist/css/components/topbar.css +8 -7
  22. package/dist/css/index.css +5 -0
  23. package/dist/css/tokens.css +126 -22
  24. package/dist/react/ActionBar/ActionBar.d.ts +19 -0
  25. package/dist/react/ActionBar/ActionBar.tsx +54 -0
  26. package/dist/react/AmbientBackdrop/AmbientBackdrop.d.ts +17 -0
  27. package/dist/react/AmbientBackdrop/AmbientBackdrop.tsx +53 -0
  28. package/dist/react/AnimatedBackdrop/AnimatedBackdrop.d.ts +22 -0
  29. package/dist/react/AnimatedBackdrop/AnimatedBackdrop.tsx +317 -0
  30. package/dist/react/Callout/Callout.d.ts +1 -1
  31. package/dist/react/Callout/Callout.tsx +1 -1
  32. package/dist/react/Combobox/Combobox.d.ts +2 -0
  33. package/dist/react/Combobox/Combobox.tsx +85 -39
  34. package/dist/react/DataTable/DataTable.tsx +3 -3
  35. package/dist/react/Drawer/Drawer.tsx +7 -1
  36. package/dist/react/Input/Input.d.ts +1 -1
  37. package/dist/react/Input/Input.tsx +1 -1
  38. package/dist/react/Modal/Modal.tsx +8 -1
  39. package/dist/react/SelectableCard/SelectableCard.d.ts +39 -0
  40. package/dist/react/SelectableCard/SelectableCard.tsx +94 -0
  41. package/dist/react/SmartSearch/SmartSearch.tsx +2 -2
  42. package/dist/react/Stepper/Stepper.d.ts +3 -0
  43. package/dist/react/Stepper/Stepper.tsx +7 -0
  44. package/dist/react/Toast/Toast.d.ts +1 -1
  45. package/dist/react/Toast/Toast.tsx +1 -1
  46. package/dist/react/ToggleChip/ToggleChip.d.ts +29 -0
  47. package/dist/react/ToggleChip/ToggleChip.tsx +76 -0
  48. package/dist/react/Tooltip/Tooltip.d.ts +1 -1
  49. package/dist/react/Tooltip/Tooltip.tsx +1 -1
  50. package/package.json +1 -1
@@ -55,7 +55,7 @@
55
55
  .field > label {
56
56
  font-family: var(--font-sans);
57
57
  font-size: var(--fs-sm);
58
- font-weight: var(--w-semibold);
58
+ font-weight: var(--w-regular);
59
59
  color: var(--color-foreground-default);
60
60
  letter-spacing: var(--ls-body);
61
61
  }
@@ -260,6 +260,7 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
260
260
  background: var(--color-background-subtle);
261
261
  color: var(--color-foreground-muted);
262
262
  font-family: var(--font-mono);
263
+ font-size-adjust: var(--font-mono-adjust);
263
264
  font-size: var(--fs-sm);
264
265
  flex-shrink: 0;
265
266
  }
@@ -326,8 +327,9 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
326
327
  display: inline-flex;
327
328
  align-items: center;
328
329
  font-family: var(--font-mono);
330
+ font-size-adjust: var(--font-mono-adjust);
329
331
  font-size: var(--fs-xxs);
330
- font-weight: var(--w-semibold);
332
+ font-weight: var(--w-regular);
331
333
  color: var(--color-foreground-muted);
332
334
  background: var(--color-background-subtle);
333
335
  border: 1px solid var(--color-border-default);
@@ -389,7 +391,7 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
389
391
  border-radius: var(--radius-xs);
390
392
  font-family: var(--font-sans);
391
393
  font-size: var(--fs-xs);
392
- font-weight: var(--w-medium);
394
+ font-weight: var(--w-regular);
393
395
  line-height: 1;
394
396
  white-space: nowrap;
395
397
  flex-shrink: 0;
@@ -466,8 +468,9 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
466
468
  height: 48px;
467
469
  text-align: center;
468
470
  font-family: var(--font-mono);
471
+ font-size-adjust: var(--font-mono-adjust);
469
472
  font-size: var(--fs-xl);
470
- font-weight: var(--w-semibold);
473
+ font-weight: var(--w-regular);
471
474
  border: 1px solid var(--color-border-default);
472
475
  border-radius: var(--shape-control);
473
476
  outline: none;
@@ -513,7 +516,21 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
513
516
  .switch input:checked ~ .switch-track { background: var(--color-brand-solid); }
514
517
  .switch input:checked ~ .switch-track .switch-thumb { transform: translateX(16px); }
515
518
  .switch input:focus-visible ~ .switch-track { box-shadow: var(--shadow-focus); }
516
- .switch input:disabled ~ .switch-track { opacity: 0.5; cursor: not-allowed; }
519
+ /* Disabled — explicit tokens, never opacity (it composes with the surface into an
520
+ off-palette malva, kills the white thumb, and makes checked indistinguishable). */
521
+ .switch:has(input:disabled) { cursor: not-allowed; }
522
+ .switch:has(input:disabled) .switch-label { color: var(--color-foreground-disabled); }
523
+ .switch input:disabled ~ .switch-track {
524
+ background: var(--color-background-sunken);
525
+ box-shadow: inset 0 0 0 1px var(--color-border-default);
526
+ }
527
+ .switch input:disabled ~ .switch-track .switch-thumb {
528
+ background: var(--color-neutral-100);
529
+ box-shadow: none;
530
+ }
531
+ .switch input:checked:disabled ~ .switch-track {
532
+ background: color-mix(in srgb, var(--color-brand-solid) 32%, var(--color-background-sunken));
533
+ }
517
534
  .switch-label {
518
535
  font-family: var(--font-sans);
519
536
  font-size: var(--fs-sm);
@@ -570,7 +587,20 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
570
587
  }
571
588
  .check input:indeterminate ~ .check-box svg { display: none; }
572
589
  .check input:focus-visible ~ .check-box { box-shadow: var(--shadow-focus); }
573
- .check input:disabled ~ .check-box { opacity: 0.5; cursor: not-allowed; }
590
+ /* Disabled — explicit tokens (see .switch rationale) */
591
+ .check:has(input:disabled) { cursor: not-allowed; }
592
+ .check:has(input:disabled) .check-label { color: var(--color-foreground-disabled); }
593
+ .check input:disabled ~ .check-box {
594
+ background: var(--color-background-sunken);
595
+ border-color: var(--color-border-default);
596
+ }
597
+ .check input:disabled ~ .check-box svg { color: var(--color-foreground-disabled); }
598
+ .check input:checked:disabled ~ .check-box,
599
+ .check input:indeterminate:disabled ~ .check-box {
600
+ background: color-mix(in srgb, var(--color-brand-solid) 32%, var(--color-background-sunken));
601
+ border-color: transparent;
602
+ }
603
+ .check input:checked:disabled ~ .check-box svg { color: var(--color-neutral-100); }
574
604
  .check.is-error .check-box { border-color: var(--color-border-danger); }
575
605
 
576
606
 
@@ -614,7 +644,19 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
614
644
  .radio input:checked ~ .radio-dot { border-color: var(--color-brand-solid); }
615
645
  .radio input:checked ~ .radio-dot::after { transform: scale(1); }
616
646
  .radio input:focus-visible ~ .radio-dot { box-shadow: var(--shadow-focus); }
617
- .radio input:disabled ~ .radio-dot { opacity: 0.5; cursor: not-allowed; }
647
+ /* Disabled — explicit tokens (see .switch rationale) */
648
+ .radio:has(input:disabled) { cursor: not-allowed; }
649
+ .radio:has(input:disabled) .radio-label { color: var(--color-foreground-disabled); }
650
+ .radio input:disabled ~ .radio-dot {
651
+ background: var(--color-background-sunken);
652
+ border-color: var(--color-border-default);
653
+ }
654
+ .radio input:checked:disabled ~ .radio-dot {
655
+ border-color: color-mix(in srgb, var(--color-brand-solid) 32%, var(--color-background-sunken));
656
+ }
657
+ .radio input:checked:disabled ~ .radio-dot::after {
658
+ background: color-mix(in srgb, var(--color-brand-solid) 32%, var(--color-background-sunken));
659
+ }
618
660
 
619
661
 
620
662
  /* ----------------------------------------------------------------
@@ -697,9 +739,9 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
697
739
  stroke-width: var(--icon-stroke);
698
740
  color: var(--color-foreground-muted);
699
741
  }
700
- .file-drop .ttl { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--color-foreground-default); }
742
+ .file-drop .ttl { font-size: var(--fs-md); font-weight: var(--w-regular); color: var(--color-foreground-default); }
701
743
  .file-drop .sub { font-size: var(--fs-xs); color: var(--color-foreground-muted); }
702
- .file-drop .anchor { color: var(--color-foreground-highlight); font-weight: var(--w-semibold); }
744
+ .file-drop .anchor { color: var(--color-foreground-highlight); font-weight: var(--w-regular); }
703
745
 
704
746
  /* ----------------------------------------------------------------
705
747
  16b. FILE LIST (post-upload state)
@@ -719,6 +761,7 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
719
761
  background: var(--color-background-subtle);
720
762
  border-bottom: 1px solid var(--color-border-subtle);
721
763
  font-family: var(--font-mono);
764
+ font-size-adjust: var(--font-mono-adjust);
722
765
  font-size: var(--fs-xxs);
723
766
  color: var(--color-foreground-muted);
724
767
  text-transform: uppercase;
@@ -732,6 +775,7 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
732
775
  border: 0;
733
776
  padding: 0;
734
777
  font-family: var(--font-mono);
778
+ font-size-adjust: var(--font-mono-adjust);
735
779
  font-size: var(--fs-xxs);
736
780
  color: var(--color-foreground-highlight);
737
781
  text-transform: uppercase;
@@ -739,7 +783,7 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
739
783
  cursor: pointer;
740
784
  transition: color var(--transition-fast);
741
785
  }
742
- .file-list-action:hover { color: var(--color-brand-text); }
786
+ .file-list-action:hover { color: var(--color-foreground-brand); }
743
787
 
744
788
  .file-rows {
745
789
  list-style: none;
@@ -771,9 +815,9 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
771
815
  color: var(--color-foreground-muted);
772
816
  }
773
817
  .file-icon[data-kind="pdf"] { background: color-mix(in srgb, var(--color-danger-500) 8%, var(--color-background-surface)); color: var(--color-feedback-danger-foreground); }
774
- .file-icon[data-kind="img"] { background: color-mix(in srgb, var(--color-brand-solid) 8%, var(--color-background-surface)); color: var(--color-brand-text); }
818
+ .file-icon[data-kind="img"] { background: color-mix(in srgb, var(--color-brand-solid) 8%, var(--color-background-surface)); color: var(--color-foreground-brand); }
775
819
  .file-icon[data-kind="csv"] { background: color-mix(in srgb, var(--color-success-500) 8%, var(--color-background-surface)); color: var(--color-feedback-success-foreground); }
776
- .file-icon[data-kind="doc"] { background: color-mix(in srgb, var(--color-brand-solid) 10%, var(--color-background-surface)); color: var(--color-brand-text); }
820
+ .file-icon[data-kind="doc"] { background: color-mix(in srgb, var(--color-brand-solid) 10%, var(--color-background-surface)); color: var(--color-foreground-brand); }
777
821
 
778
822
  .file-icon-tag {
779
823
  position: absolute;
@@ -781,6 +825,7 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
781
825
  left: 50%;
782
826
  transform: translateX(-50%);
783
827
  font-family: var(--font-mono);
828
+ font-size-adjust: var(--font-mono-adjust);
784
829
  font-size: 8px;
785
830
  font-weight: var(--w-bold);
786
831
  letter-spacing: 0.04em;
@@ -800,7 +845,7 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
800
845
  .file-name {
801
846
  font-family: var(--font-sans);
802
847
  font-size: var(--fs-sm);
803
- font-weight: var(--w-semibold);
848
+ font-weight: var(--w-regular);
804
849
  color: var(--color-foreground-default);
805
850
  white-space: nowrap;
806
851
  overflow: hidden;
@@ -808,6 +853,7 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
808
853
  }
809
854
  .file-sub {
810
855
  font-family: var(--font-mono);
856
+ font-size-adjust: var(--font-mono-adjust);
811
857
  font-size: var(--fs-xxs);
812
858
  color: var(--color-foreground-muted);
813
859
  }
@@ -835,14 +881,15 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
835
881
  padding: 3px var(--space-2);
836
882
  border-radius: var(--radius-pill);
837
883
  font-family: var(--font-mono);
884
+ font-size-adjust: var(--font-mono-adjust);
838
885
  font-size: var(--fs-xxs);
839
- font-weight: var(--w-semibold);
886
+ font-weight: var(--w-regular);
840
887
  text-transform: uppercase;
841
888
  letter-spacing: var(--ls-caps);
842
889
  white-space: nowrap;
843
890
  }
844
891
  .file-status.ok { color: var(--color-feedback-success-foreground); background: var(--color-feedback-success-background); }
845
- .file-status.pending { color: var(--color-brand-text); background: color-mix(in srgb, var(--color-brand-solid) 10%, transparent); }
892
+ .file-status.pending { color: var(--color-foreground-brand); background: color-mix(in srgb, var(--color-brand-solid) 10%, transparent); }
846
893
  .file-status.err { color: var(--color-feedback-danger-foreground); background: var(--color-feedback-danger-background); cursor: pointer; }
847
894
 
848
895
  .file-remove {
@@ -912,6 +959,43 @@ textarea.input.input-lg { height: auto; min-height: 120px; padding: var(--space-
912
959
  /* ----------------------------------------------------------------
913
960
  18. ON INVERSE — dark surfaces
914
961
  ---------------------------------------------------------------- */
962
+ /* Field + selection controls on a permanently-dark surface (hero, onboarding).
963
+ Without these, every dark surface had to override colour inline. */
964
+ .field.on-inverse .field-label { color: var(--color-foreground-inverse-default); }
965
+ .field.on-inverse .field-help { color: var(--color-foreground-inverse-muted); }
966
+
967
+ .switch.on-inverse .switch-track {
968
+ background: color-mix(in srgb, var(--color-pure-white) 18%, transparent);
969
+ box-shadow: inset 0 0 0 1px var(--color-border-inverse);
970
+ }
971
+ .switch.on-inverse .switch-label { color: var(--color-foreground-inverse-default); }
972
+ .switch.on-inverse input:checked ~ .switch-track { background: var(--color-accent-solid); box-shadow: none; }
973
+ .switch.on-inverse input:focus-visible ~ .switch-track { box-shadow: var(--shadow-focus-inverse); }
974
+ .switch.on-inverse input:disabled ~ .switch-track {
975
+ background: color-mix(in srgb, var(--color-pure-white) 8%, transparent);
976
+ box-shadow: inset 0 0 0 1px var(--color-border-inverse);
977
+ }
978
+ .switch.on-inverse:has(input:disabled) .switch-label { color: var(--color-foreground-inverse-muted); }
979
+
980
+ .check.on-inverse .check-box,
981
+ .radio.on-inverse .radio-dot {
982
+ background: color-mix(in srgb, var(--color-pure-white) 8%, transparent);
983
+ border-color: var(--color-border-inverse);
984
+ }
985
+ .check.on-inverse .check-label,
986
+ .radio.on-inverse .radio-label { color: var(--color-foreground-inverse-default); }
987
+ .check.on-inverse input:checked ~ .check-box,
988
+ .check.on-inverse input:indeterminate ~ .check-box {
989
+ background: var(--color-accent-solid);
990
+ border-color: var(--color-accent-solid);
991
+ }
992
+ .radio.on-inverse input:checked ~ .radio-dot { border-color: var(--color-accent-solid); }
993
+ .radio.on-inverse input:checked ~ .radio-dot::after { background: var(--color-accent-solid); }
994
+ .check.on-inverse input:focus-visible ~ .check-box,
995
+ .radio.on-inverse input:focus-visible ~ .radio-dot { box-shadow: var(--shadow-focus-inverse); }
996
+ .check.on-inverse:has(input:disabled) .check-label,
997
+ .radio.on-inverse:has(input:disabled) .radio-label { color: var(--color-foreground-inverse-muted); }
998
+
915
999
  .input.on-inverse,
916
1000
  .dark .input,
917
1001
  .dark .group,
@@ -62,8 +62,9 @@
62
62
  border-left: 1px solid var(--color-border-subtle);
63
63
  border-right: 1px solid var(--color-border-subtle);
64
64
  font-family: var(--font-mono);
65
+ font-size-adjust: var(--font-mono-adjust);
65
66
  font-size: var(--fs-sm);
66
- font-weight: var(--w-medium);
67
+ font-weight: var(--w-regular);
67
68
  color: var(--color-foreground-default);
68
69
  text-align: center;
69
70
  -moz-appearance: textfield;
@@ -91,8 +92,9 @@
91
92
  align-items: center;
92
93
  padding: 0 var(--space-3);
93
94
  font-family: var(--font-mono);
95
+ font-size-adjust: var(--font-mono-adjust);
94
96
  font-size: var(--fs-xs);
95
- font-weight: var(--w-semibold);
97
+ font-weight: var(--w-regular);
96
98
  letter-spacing: var(--ls-caps);
97
99
  text-transform: uppercase;
98
100
  color: var(--color-foreground-muted);
@@ -105,8 +107,9 @@
105
107
  align-items: center;
106
108
  padding: 0 var(--space-3);
107
109
  font-family: var(--font-mono);
110
+ font-size-adjust: var(--font-mono-adjust);
108
111
  font-size: var(--fs-sm);
109
- font-weight: var(--w-semibold);
112
+ font-weight: var(--w-regular);
110
113
  color: var(--color-foreground-muted);
111
114
  border-right: 1px solid var(--color-border-subtle);
112
115
  background: var(--color-background-subtle);
@@ -14,6 +14,7 @@
14
14
  height: var(--av-size, 36px);
15
15
  border-radius: var(--radius-pill);
16
16
  font-family: var(--font-mono);
17
+ font-size-adjust: var(--font-mono-adjust);
17
18
  font-size: var(--av-fs, var(--fs-xs));
18
19
  font-weight: var(--w-bold);
19
20
  letter-spacing: var(--ls-caps);
@@ -32,7 +33,7 @@
32
33
 
33
34
  /* Tone — accent-on-tinted-bg uses the same background+foreground pair as feedback pills,
34
35
  so an Avatar reads as the same "object" as a status pill that references it. */
35
- .av-brand { background: var(--color-brand-subtle-solid); color: var(--color-brand-text); }
36
+ .av-brand { background: var(--color-brand-subtle-solid); color: var(--color-brand-text-on-light); }
36
37
  .av-success { background: var(--color-feedback-success-background); color: var(--color-feedback-success-foreground); }
37
38
  .av-warning { background: var(--color-feedback-warning-background); color: var(--color-feedback-warning-foreground); }
38
39
  .av-danger { background: var(--color-feedback-danger-background); color: var(--color-feedback-danger-foreground); }
@@ -79,20 +80,21 @@
79
80
  align-items: baseline;
80
81
  gap: var(--space-1);
81
82
  font-family: var(--font-mono);
83
+ font-size-adjust: var(--font-mono-adjust);
82
84
  font-variant-numeric: tabular-nums;
83
85
  font-size: var(--money-fs, var(--fs-sm));
84
- font-weight: var(--w-semibold);
86
+ font-weight: var(--w-regular);
85
87
  color: var(--color-foreground-default);
86
88
  white-space: nowrap;
87
89
  }
88
90
  .money-cur {
89
91
  font-size: 0.78em;
90
- font-weight: var(--w-semibold);
92
+ font-weight: var(--w-regular);
91
93
  letter-spacing: var(--ls-caps);
92
94
  text-transform: uppercase;
93
95
  color: var(--color-foreground-muted);
94
96
  }
95
- .money-frac { color: var(--color-foreground-secondary); font-weight: var(--w-medium); }
97
+ .money-frac { color: var(--color-foreground-secondary); font-weight: var(--w-regular); }
96
98
 
97
99
  .money-sm { --money-fs: var(--fs-xs); }
98
100
  .money-md { --money-fs: var(--fs-sm); }
@@ -102,7 +104,7 @@
102
104
 
103
105
  .money-pos { color: var(--color-feedback-success-foreground); }
104
106
  .money-neg { color: var(--color-feedback-danger-foreground); }
105
- .money-muted { color: var(--color-foreground-muted); font-weight: var(--w-medium); }
107
+ .money-muted { color: var(--color-foreground-muted); font-weight: var(--w-regular); }
106
108
 
107
109
  /* =================== METRIC (hero display number) ===================
108
110
  Big, display-weight figure for hero/KPI moments. Distinct from .money
@@ -120,7 +122,7 @@
120
122
  white-space: nowrap;
121
123
  font-size: var(--metric-fs, 38px);
122
124
  }
123
- .metric-cur { font-size: 0.58em; font-weight: var(--w-semibold); opacity: 0.55; margin-right: 0.32em; }
125
+ .metric-cur { font-size: 0.58em; font-weight: var(--w-regular); opacity: 0.55; margin-right: 0.32em; }
124
126
  .metric-frac { font-size: 0.68em; opacity: 0.55; }
125
127
  .metric-sm { --metric-fs: 30px; }
126
128
  .metric-md { --metric-fs: 38px; }
@@ -145,8 +147,9 @@
145
147
  }
146
148
  .stat-label {
147
149
  font-family: var(--font-mono);
150
+ font-size-adjust: var(--font-mono-adjust);
148
151
  font-size: var(--fs-xxs);
149
- font-weight: var(--w-semibold);
152
+ font-weight: var(--w-regular);
150
153
  letter-spacing: var(--ls-caps);
151
154
  text-transform: uppercase;
152
155
  color: var(--color-foreground-muted);
@@ -164,8 +167,9 @@
164
167
  align-items: center;
165
168
  gap: var(--space-1);
166
169
  font-family: var(--font-mono);
170
+ font-size-adjust: var(--font-mono-adjust);
167
171
  font-size: var(--fs-xs);
168
- font-weight: var(--w-semibold);
172
+ font-weight: var(--w-regular);
169
173
  }
170
174
  .stat-delta i, .stat-delta svg { width: 14px; height: 14px; stroke-width: 2.25; }
171
175
  .stat-delta-up { color: var(--color-feedback-success-foreground); }
@@ -215,8 +219,9 @@
215
219
  gap: var(--space-3);
216
220
  margin: var(--space-5) 0;
217
221
  font-family: var(--font-mono);
222
+ font-size-adjust: var(--font-mono-adjust);
218
223
  font-size: var(--fs-xxs);
219
- font-weight: var(--w-semibold);
224
+ font-weight: var(--w-regular);
220
225
  letter-spacing: var(--ls-caps);
221
226
  text-transform: uppercase;
222
227
  color: var(--color-foreground-muted);
@@ -240,7 +245,7 @@
240
245
  .eyebrow {
241
246
  display: block;
242
247
  font-size: var(--fs-xs);
243
- font-weight: var(--w-semibold);
248
+ font-weight: var(--w-regular);
244
249
  letter-spacing: var(--ls-caps);
245
250
  text-transform: uppercase;
246
251
  color: var(--color-foreground-muted);
@@ -248,12 +253,12 @@
248
253
  .eyebrow.has-icon { display: inline-flex; align-items: center; gap: var(--space-2-5); }
249
254
  .eyebrow-xs { font-size: var(--fs-xxs); font-weight: var(--w-bold); }
250
255
  .eyebrow-xs.has-icon { gap: var(--space-2); }
251
- .eyebrow-sm { font-size: var(--fs-xxs); font-weight: var(--w-semibold); }
252
- .eyebrow-md { font-size: var(--fs-xs); font-weight: var(--w-semibold); }
256
+ .eyebrow-sm { font-size: var(--fs-xxs); font-weight: var(--w-regular); }
257
+ .eyebrow-md { font-size: var(--fs-xs); font-weight: var(--w-regular); }
253
258
  .eyebrow-muted { color: var(--color-foreground-muted); }
254
259
  .eyebrow-secondary { color: var(--color-foreground-secondary); }
255
260
  .eyebrow-default { color: var(--color-foreground-default); }
256
- .eyebrow-brand { color: var(--color-brand-text); }
261
+ .eyebrow-brand { color: var(--color-foreground-brand); }
257
262
  .eyebrow-inverse { color: var(--color-foreground-inverse-muted); }
258
263
 
259
264
  /* =================== FILTER CHIP =================== */
@@ -269,7 +274,7 @@
269
274
  background: var(--color-background-surface);
270
275
  font-family: inherit;
271
276
  font-size: var(--fs-sm);
272
- font-weight: var(--w-medium);
277
+ font-weight: var(--w-regular);
273
278
  color: var(--color-foreground-secondary);
274
279
  cursor: pointer;
275
280
  white-space: nowrap;
@@ -282,7 +287,7 @@
282
287
  background: var(--color-background-selected);
283
288
  border-color: var(--color-brand-border);
284
289
  color: var(--color-foreground-brand);
285
- font-weight: var(--w-semibold);
290
+ font-weight: var(--w-regular);
286
291
  }
287
292
  .filter-chip .chip-chevron { opacity: .55; }
288
293
 
@@ -0,0 +1,212 @@
1
+ /* ============================================================
2
+ SELECTABLE CARD — components/sel-card.css
3
+ A card that IS a control: pick-one (radio) or pick-many (checkbox)
4
+ with the whole card as the hit target. Replaces the hand-rolled
5
+ `.card + .radio` composition that every onboarding/KYC flow
6
+ reinvented (each with its own padding, radius and selected state).
7
+
8
+ Structure:
9
+ .sel-card the label/button wrapper
10
+ .sel-card-index optional leading index (01, 02…)
11
+ .sel-card-body title + description
12
+ .sel-card-title
13
+ .sel-card-desc
14
+ .sel-card-mark trailing selection marker
15
+
16
+ States: :hover · .is-selected · [aria-disabled] / :has(input:disabled) · :focus-visible
17
+ Variants: .sel-card-sm (dense) · .sel-card-multi (square marker) · .on-inverse
18
+ ============================================================ */
19
+
20
+ .sel-card {
21
+ position: relative;
22
+ display: flex;
23
+ align-items: flex-start;
24
+ gap: var(--space-4);
25
+ padding: var(--space-5);
26
+ background: var(--color-background-surface);
27
+ border: 1px solid var(--color-border-default);
28
+ border-radius: var(--shape-container);
29
+ cursor: pointer;
30
+ text-align: left;
31
+ width: 100%;
32
+ box-sizing: border-box;
33
+ font-family: var(--font-sans);
34
+ transition: background var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
35
+ }
36
+ .sel-card > input {
37
+ position: absolute;
38
+ opacity: 0;
39
+ pointer-events: none;
40
+ width: 0;
41
+ height: 0;
42
+ }
43
+ .sel-card:hover {
44
+ border-color: var(--color-border-strong);
45
+ background: var(--color-background-hover);
46
+ }
47
+
48
+ /* ---------- Leading index ---------- */
49
+ .sel-card-index {
50
+ flex-shrink: 0;
51
+ font-family: var(--font-mono);
52
+ font-size-adjust: var(--font-mono-adjust);
53
+ font-size: var(--fs-xs);
54
+ font-weight: var(--w-bold);
55
+ letter-spacing: var(--ls-caps);
56
+ color: var(--color-foreground-muted);
57
+ padding-top: 2px;
58
+ font-variant-numeric: tabular-nums;
59
+ }
60
+
61
+ /* ---------- Body ---------- */
62
+ .sel-card-body {
63
+ flex: 1;
64
+ min-width: 0;
65
+ display: flex;
66
+ flex-direction: column;
67
+ gap: var(--space-1);
68
+ }
69
+ .sel-card-title {
70
+ font-size: var(--fs-md);
71
+ font-weight: var(--w-regular);
72
+ letter-spacing: var(--ls-title);
73
+ color: var(--color-foreground-default);
74
+ line-height: var(--lh-snug);
75
+ }
76
+ .sel-card-desc {
77
+ font-size: var(--fs-sm);
78
+ color: var(--color-foreground-secondary);
79
+ line-height: var(--lh-relaxed);
80
+ text-wrap: pretty;
81
+ }
82
+
83
+ /* ---------- Selection marker ---------- */
84
+ .sel-card-mark {
85
+ flex-shrink: 0;
86
+ width: 20px;
87
+ height: 20px;
88
+ border-radius: var(--radius-pill);
89
+ border: 2px solid var(--color-border-strong);
90
+ background: var(--color-background-surface);
91
+ display: inline-flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ margin-top: 1px;
95
+ transition: border-color var(--transition-fast), background var(--transition-fast);
96
+ }
97
+ .sel-card-mark::after {
98
+ content: "";
99
+ width: 10px;
100
+ height: 10px;
101
+ border-radius: var(--radius-pill);
102
+ background: var(--color-brand-solid);
103
+ transform: scale(0);
104
+ transition: transform var(--transition-fast) var(--ease-standard);
105
+ }
106
+ /* Multi = square marker with a check glyph instead of a dot */
107
+ .sel-card-multi .sel-card-mark { border-radius: var(--radius-2xs); }
108
+ .sel-card-multi .sel-card-mark::after { border-radius: 1px; }
109
+
110
+ /* ---------- Selected ---------- */
111
+ .sel-card.is-selected {
112
+ border-color: var(--color-brand-solid);
113
+ background: var(--color-background-selected);
114
+ box-shadow: inset 0 0 0 1px var(--color-brand-solid);
115
+ }
116
+ .sel-card.is-selected .sel-card-title { color: var(--color-foreground-brand); }
117
+ .sel-card.is-selected .sel-card-index { color: var(--color-foreground-brand); }
118
+ .sel-card.is-selected .sel-card-mark {
119
+ border-color: var(--color-brand-solid);
120
+ background: var(--color-background-surface);
121
+ }
122
+ .sel-card.is-selected .sel-card-mark::after { transform: scale(1); }
123
+
124
+ /* ---------- Focus ---------- */
125
+ .sel-card:focus-visible,
126
+ .sel-card:has(input:focus-visible) {
127
+ outline: none;
128
+ box-shadow: var(--shadow-focus);
129
+ }
130
+ .sel-card.is-selected:focus-visible,
131
+ .sel-card.is-selected:has(input:focus-visible) {
132
+ box-shadow: inset 0 0 0 1px var(--color-brand-solid), var(--shadow-focus);
133
+ }
134
+
135
+ /* ---------- Disabled ---------- */
136
+ .sel-card[aria-disabled="true"],
137
+ .sel-card:has(input:disabled) {
138
+ cursor: not-allowed;
139
+ background: var(--color-background-sunken);
140
+ border-color: var(--color-border-default);
141
+ box-shadow: none;
142
+ }
143
+ .sel-card[aria-disabled="true"] .sel-card-title,
144
+ .sel-card:has(input:disabled) .sel-card-title { color: var(--color-foreground-disabled); }
145
+ .sel-card[aria-disabled="true"] .sel-card-desc,
146
+ .sel-card[aria-disabled="true"] .sel-card-index,
147
+ .sel-card:has(input:disabled) .sel-card-desc,
148
+ .sel-card:has(input:disabled) .sel-card-index { color: var(--color-foreground-disabled); }
149
+ .sel-card[aria-disabled="true"] .sel-card-mark,
150
+ .sel-card:has(input:disabled) .sel-card-mark {
151
+ border-color: var(--color-border-default);
152
+ background: var(--color-background-sunken);
153
+ }
154
+ .sel-card[aria-disabled="true"] .sel-card-mark::after,
155
+ .sel-card:has(input:disabled) .sel-card-mark::after {
156
+ background: color-mix(in srgb, var(--color-brand-solid) 32%, var(--color-background-sunken));
157
+ }
158
+
159
+ /* ---------- Dense ---------- */
160
+ .sel-card-sm { padding: var(--space-4); gap: var(--space-3); }
161
+ .sel-card-sm .sel-card-title { font-size: var(--fs-sm); }
162
+ .sel-card-sm .sel-card-desc { font-size: var(--fs-xs); }
163
+ .sel-card-sm .sel-card-mark { width: 18px; height: 18px; }
164
+ .sel-card-sm .sel-card-mark::after { width: 8px; height: 8px; }
165
+
166
+ /* ---------- On inverse ---------- */
167
+ .sel-card.on-inverse {
168
+ background: color-mix(in srgb, var(--color-pure-white) 6%, transparent);
169
+ border-color: var(--color-border-inverse);
170
+ }
171
+ .sel-card.on-inverse:hover {
172
+ background: color-mix(in srgb, var(--color-pure-white) 10%, transparent);
173
+ border-color: color-mix(in srgb, var(--color-pure-white) 26%, transparent);
174
+ }
175
+ .sel-card.on-inverse .sel-card-title { color: var(--color-foreground-inverse-default); }
176
+ .sel-card.on-inverse .sel-card-desc { color: var(--color-foreground-inverse-secondary); }
177
+ .sel-card.on-inverse .sel-card-index { color: var(--color-foreground-inverse-muted); }
178
+ .sel-card.on-inverse .sel-card-mark {
179
+ border-color: color-mix(in srgb, var(--color-pure-white) 34%, transparent);
180
+ background: transparent;
181
+ }
182
+ .sel-card.on-inverse .sel-card-mark::after { background: var(--color-accent-solid); }
183
+ .sel-card.on-inverse.is-selected {
184
+ border-color: var(--color-accent-solid);
185
+ background: color-mix(in srgb, var(--color-accent-solid) 16%, transparent);
186
+ box-shadow: inset 0 0 0 1px var(--color-accent-solid);
187
+ }
188
+ .sel-card.on-inverse.is-selected .sel-card-title,
189
+ .sel-card.on-inverse.is-selected .sel-card-index { color: var(--color-foreground-inverse-default); }
190
+ .sel-card.on-inverse.is-selected .sel-card-mark { border-color: var(--color-accent-solid); background: transparent; }
191
+ .sel-card.on-inverse:focus-visible,
192
+ .sel-card.on-inverse:has(input:focus-visible) { box-shadow: var(--shadow-focus-inverse); }
193
+ .sel-card.on-inverse[aria-disabled="true"],
194
+ .sel-card.on-inverse:has(input:disabled) {
195
+ background: color-mix(in srgb, var(--color-pure-white) 3%, transparent);
196
+ box-shadow: none;
197
+ }
198
+ .sel-card.on-inverse[aria-disabled="true"] .sel-card-title,
199
+ .sel-card.on-inverse:has(input:disabled) .sel-card-title { color: var(--color-foreground-inverse-muted); }
200
+ .sel-card.on-inverse[aria-disabled="true"] .sel-card-desc,
201
+ .sel-card.on-inverse:has(input:disabled) .sel-card-desc { color: var(--color-foreground-inverse-muted); }
202
+
203
+ /* ---------- Group helper ---------- */
204
+ .sel-card-group {
205
+ display: flex;
206
+ flex-direction: column;
207
+ gap: var(--space-3);
208
+ }
209
+ .sel-card-group.is-grid {
210
+ display: grid;
211
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
212
+ }