@attrus-ds/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +27 -0
  2. package/README.md +123 -0
  3. package/dist/assets/flags/Brazil-rounded.svg +16 -0
  4. package/dist/assets/flags/Brazil-square.svg +17 -0
  5. package/dist/assets/flags/Chile-rounded.svg +11 -0
  6. package/dist/assets/flags/Chile-square.svg +11 -0
  7. package/dist/assets/flags/Colombia-rounded.svg +10 -0
  8. package/dist/assets/flags/Colombia-square.svg +10 -0
  9. package/dist/assets/flags/EUA-rounded.svg +11 -0
  10. package/dist/assets/flags/EUA-square.svg +11 -0
  11. package/dist/assets/flags/EUR-rounded.svg +9 -0
  12. package/dist/assets/flags/EUR-square.svg +9 -0
  13. package/dist/assets/flags/Mexico-rounded.svg +19 -0
  14. package/dist/assets/flags/Mexico-square.svg +19 -0
  15. package/dist/assets/icon-attrus-dark.svg +3 -0
  16. package/dist/assets/icon-attrus-light.svg +3 -0
  17. package/dist/assets/logo-attrus-dark.svg +8 -0
  18. package/dist/assets/logo-attrus-light.svg +8 -0
  19. package/dist/css/components/buttons.css +301 -0
  20. package/dist/css/components/callout.css +195 -0
  21. package/dist/css/components/cards.css +272 -0
  22. package/dist/css/components/combobox.css +303 -0
  23. package/dist/css/components/empty-states.css +61 -0
  24. package/dist/css/components/inputs.css +1027 -0
  25. package/dist/css/components/number-input.css +138 -0
  26. package/dist/css/components/overlays.css +405 -0
  27. package/dist/css/components/primitives.css +305 -0
  28. package/dist/css/components/sidebar.css +179 -0
  29. package/dist/css/components/status-pills.css +207 -0
  30. package/dist/css/components/stepper.css +309 -0
  31. package/dist/css/components/table.css +600 -0
  32. package/dist/css/components/tabs.css +319 -0
  33. package/dist/css/components/toast.css +239 -0
  34. package/dist/css/components/tooltip.css +226 -0
  35. package/dist/css/components/topbar.css +148 -0
  36. package/dist/css/fonts.css +91 -0
  37. package/dist/css/index.css +23 -0
  38. package/dist/css/tokens.css +691 -0
  39. package/dist/fonts/LICENSE-JetBrainsMono.txt +93 -0
  40. package/dist/fonts/LICENSE-Lato.txt +93 -0
  41. package/dist/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
  42. package/dist/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
  43. package/dist/fonts/jetbrains-mono-latin-600-normal.woff2 +0 -0
  44. package/dist/fonts/lato-latin-100-normal.woff2 +0 -0
  45. package/dist/fonts/lato-latin-300-italic.woff2 +0 -0
  46. package/dist/fonts/lato-latin-300-normal.woff2 +0 -0
  47. package/dist/fonts/lato-latin-400-italic.woff2 +0 -0
  48. package/dist/fonts/lato-latin-400-normal.woff2 +0 -0
  49. package/dist/fonts/lato-latin-700-italic.woff2 +0 -0
  50. package/dist/fonts/lato-latin-700-normal.woff2 +0 -0
  51. package/dist/fonts/lato-latin-900-normal.woff2 +0 -0
  52. package/dist/tokens/attrus-tokens.flat.json +1235 -0
  53. package/dist/tokens/attrus-tokens.json +1090 -0
  54. package/package.json +46 -0
@@ -0,0 +1,272 @@
1
+ /* ================================================================
2
+ CARDS — components/cards.css
3
+ The container component. Defines surface, elevation, radius, padding.
4
+ 100% token-driven; consumed by cards.html and any product UI.
5
+ ================================================================ */
6
+
7
+ /* ----------------------------------------------------------------
8
+ Base — .card
9
+ Default = surface + xs shadow + md radius + hairline border.
10
+ ---------------------------------------------------------------- */
11
+ .card {
12
+ display: block;
13
+ background: var(--color-background-surface);
14
+ border: 1px solid var(--color-border-default);
15
+ border-radius: var(--radius-md);
16
+ box-shadow: var(--shadow-xs);
17
+ color: var(--color-foreground-default);
18
+ font-family: var(--font-sans);
19
+ /* base padding kicks in only when the card holds direct content
20
+ (no .card-header / .card-body subdivision) */
21
+ padding: var(--space-5) var(--space-6);
22
+ transition:
23
+ box-shadow var(--transition-base),
24
+ border-color var(--transition-base),
25
+ transform var(--transition-base),
26
+ background var(--transition-base);
27
+ }
28
+
29
+ /* If the card uses structured slots, drop the base padding —
30
+ each slot brings its own. */
31
+ .card:has(> .card-header),
32
+ .card:has(> .card-body),
33
+ .card:has(> .card-footer),
34
+ .card:has(> .card-canvas),
35
+ .card:has(> .card-divider) {
36
+ padding: 0;
37
+ }
38
+
39
+
40
+ /* ----------------------------------------------------------------
41
+ Surface variants — pick by "what role does this container play"
42
+ ---------------------------------------------------------------- */
43
+
44
+ /* Flat — no shadow. Use inside another card, or for table rows. */
45
+ .card.flat { box-shadow: none; }
46
+
47
+ /* Subtle / inset — neutral fill, no shadow. Use for nested groups. */
48
+ .card.subtle { background: var(--color-background-subtle); box-shadow: none; }
49
+
50
+ /* Sunken — like an input well; nested receipt/totals. */
51
+ .card.sunken { background: var(--color-background-sunken); box-shadow: none; border-color: var(--color-border-subtle); }
52
+
53
+ /* Raised — md shadow. Floating panels, popovers, dropdowns. */
54
+ .card.raised { box-shadow: var(--shadow-md); }
55
+
56
+ /* Floating — lg shadow. Modals, command palettes. */
57
+ .card.floating { box-shadow: var(--shadow-lg); border: 0; }
58
+
59
+ /* Hero — brand gradient. For dashboard summary tiles only. */
60
+ .card.hero {
61
+ background: var(--grad-hero);
62
+ color: var(--color-foreground-on-solid);
63
+ border: 0;
64
+ position: relative;
65
+ overflow: hidden;
66
+ }
67
+ .card.hero::before {
68
+ content: "";
69
+ position: absolute;
70
+ inset: 0;
71
+ background: var(--grad-radial-glow);
72
+ pointer-events: none;
73
+ }
74
+ .card.hero > * { position: relative; z-index: 1; }
75
+
76
+ /* Inverse — for cards on dark surfaces */
77
+ .card.inverse {
78
+ background: var(--color-background-inverse);
79
+ color: var(--color-foreground-inverse-default);
80
+ border-color: var(--color-border-inverse);
81
+ box-shadow: none;
82
+ }
83
+
84
+
85
+ /* ----------------------------------------------------------------
86
+ Semantic accents — banner-style cards with semantic shadow
87
+ ---------------------------------------------------------------- */
88
+ .card.accent-success {
89
+ background: var(--color-feedback-success-background);
90
+ border-color: var(--color-feedback-success-border);
91
+ box-shadow: var(--shadow-success-sm);
92
+ color: var(--color-foreground-default);
93
+ }
94
+ .card.accent-warning {
95
+ background: var(--color-feedback-warning-background);
96
+ border-color: var(--color-feedback-warning-border);
97
+ box-shadow: var(--shadow-warning-sm);
98
+ color: var(--color-foreground-default);
99
+ }
100
+ .card.accent-danger {
101
+ background: var(--color-feedback-danger-background);
102
+ border-color: var(--color-feedback-danger-border);
103
+ box-shadow: var(--shadow-danger-sm);
104
+ color: var(--color-foreground-default);
105
+ }
106
+ .card.accent-info {
107
+ background: var(--color-feedback-info-background);
108
+ border-color: var(--color-feedback-info-border);
109
+ box-shadow: var(--shadow-info-sm);
110
+ color: var(--color-foreground-default);
111
+ }
112
+
113
+
114
+ /* ----------------------------------------------------------------
115
+ Density modifiers — affect both .card and slot padding
116
+ ---------------------------------------------------------------- */
117
+ .card.compact > .card-header,
118
+ .card.compact > .card-body,
119
+ .card.compact > .card-footer { padding: var(--space-3) var(--space-4); }
120
+ .card.compact:not(:has(> .card-header)):not(:has(> .card-body)):not(:has(> .card-footer)):not(:has(> .card-canvas)):not(:has(> .card-divider)) {
121
+ padding: var(--space-3) var(--space-4);
122
+ }
123
+
124
+ .card.spacious > .card-header,
125
+ .card.spacious > .card-body,
126
+ .card.spacious > .card-footer { padding: var(--space-7) var(--space-8); }
127
+ .card.spacious:not(:has(> .card-header)):not(:has(> .card-body)):not(:has(> .card-footer)):not(:has(> .card-canvas)):not(:has(> .card-divider)) {
128
+ padding: var(--space-7) var(--space-8);
129
+ }
130
+
131
+
132
+ /* ----------------------------------------------------------------
133
+ Slots — header / body / footer / canvas / divider
134
+ ---------------------------------------------------------------- */
135
+ .card-header {
136
+ padding: var(--space-5) var(--space-6);
137
+ display: flex;
138
+ align-items: flex-start;
139
+ justify-content: space-between;
140
+ gap: var(--space-4);
141
+ border-bottom: 1px solid var(--color-border-subtle);
142
+ }
143
+ .card-header h3,
144
+ .card-header h4 {
145
+ margin: 0;
146
+ font-size: var(--fs-md);
147
+ font-weight: var(--w-semibold);
148
+ letter-spacing: var(--ls-title);
149
+ color: var(--color-foreground-default);
150
+ }
151
+ .card-header p {
152
+ margin: var(--space-1) 0 0;
153
+ font-size: var(--fs-sm);
154
+ color: var(--color-foreground-secondary);
155
+ line-height: var(--lh-relaxed);
156
+ }
157
+ .card-header .actions {
158
+ display: flex;
159
+ gap: var(--space-2);
160
+ flex-shrink: 0;
161
+ }
162
+
163
+ .card-body {
164
+ padding: var(--space-5) var(--space-6);
165
+ }
166
+
167
+ .card-footer {
168
+ padding: var(--space-4) var(--space-6);
169
+ border-top: 1px solid var(--color-border-subtle);
170
+ background: var(--color-background-subtle);
171
+ border-bottom-left-radius: inherit;
172
+ border-bottom-right-radius: inherit;
173
+ display: flex;
174
+ align-items: center;
175
+ justify-content: space-between;
176
+ gap: var(--space-4);
177
+ }
178
+
179
+ /* Canvas slot — full-bleed image / chart area */
180
+ .card-canvas {
181
+ background: var(--color-background-canvas);
182
+ border-bottom: 1px solid var(--color-border-subtle);
183
+ overflow: hidden;
184
+ border-top-left-radius: inherit;
185
+ border-top-right-radius: inherit;
186
+ }
187
+
188
+ /* Divider — thin separator inside body sections */
189
+ .card-divider {
190
+ height: 1px;
191
+ background: var(--color-border-subtle);
192
+ margin: 0;
193
+ border: 0;
194
+ }
195
+
196
+
197
+ /* ----------------------------------------------------------------
198
+ Card layouts (helpers — common compositions)
199
+ ---------------------------------------------------------------- */
200
+
201
+ /* KPI / stat card */
202
+ .card-stat {
203
+ display: flex;
204
+ flex-direction: column;
205
+ gap: var(--space-2);
206
+ }
207
+ .card-stat .stat-label {
208
+ font-family: var(--font-mono);
209
+ font-size: var(--fs-xxs);
210
+ font-weight: var(--w-semibold);
211
+ color: var(--color-foreground-muted);
212
+ text-transform: uppercase;
213
+ letter-spacing: var(--ls-caps);
214
+ }
215
+ .card-stat .stat-value {
216
+ font-family: var(--font-sans);
217
+ font-weight: var(--w-bold);
218
+ font-size: var(--fs-3xl);
219
+ letter-spacing: var(--ls-display);
220
+ font-variant-numeric: tabular-nums;
221
+ color: var(--color-foreground-default);
222
+ line-height: 1.1;
223
+ }
224
+ .card-stat .stat-delta {
225
+ display: inline-flex;
226
+ align-items: center;
227
+ gap: var(--space-1);
228
+ font-size: var(--fs-xs);
229
+ font-weight: var(--w-semibold);
230
+ font-variant-numeric: tabular-nums;
231
+ }
232
+ .card-stat .stat-delta.up { color: var(--color-feedback-success-foreground); }
233
+ .card-stat .stat-delta.down { color: var(--color-feedback-danger-foreground); }
234
+ .card-stat .stat-delta.flat { color: var(--color-foreground-muted); }
235
+ .card-stat .stat-delta i, .card-stat .stat-delta svg,
236
+ .card-stat .stat-delta svg { width: 12px; height: 12px; stroke-width: var(--icon-stroke); }
237
+
238
+ /* Hero stat — for .card.hero */
239
+ .card.hero .card-stat .stat-label { color: color-mix(in srgb, var(--color-pure-white) 70%, transparent); }
240
+ .card.hero .card-stat .stat-value { color: var(--color-foreground-on-solid); font-size: var(--fs-5xl); }
241
+
242
+
243
+ /* ----------------------------------------------------------------
244
+ Interactive — link / button cards
245
+ Apply .card.interactive to make the whole card clickable.
246
+ The card itself should be wrapped in <a> or <button>.
247
+ ---------------------------------------------------------------- */
248
+ .card.interactive {
249
+ cursor: pointer;
250
+ text-decoration: none;
251
+ color: inherit;
252
+ }
253
+ .card.interactive:hover {
254
+ border-color: var(--color-border-strong);
255
+ box-shadow: var(--shadow-sm);
256
+ transform: translateY(-1px);
257
+ }
258
+ .card.interactive:active {
259
+ transform: translateY(0);
260
+ box-shadow: var(--shadow-xs);
261
+ }
262
+ .card.interactive:focus-visible {
263
+ outline: none;
264
+ box-shadow: var(--shadow-focus);
265
+ border-color: var(--color-border-focus);
266
+ }
267
+
268
+ /* On inverse interactive */
269
+ .card.inverse.interactive:hover {
270
+ background: var(--color-background-inverse-hover);
271
+ border-color: var(--color-border-inverse-strong);
272
+ }
@@ -0,0 +1,303 @@
1
+ /* ============================================================
2
+ COMBOBOX — searchable single-select dropdown
3
+ Trigger + popover listbox with filterable options.
4
+ All values from tokens.
5
+ ============================================================ */
6
+
7
+ .combobox {
8
+ position: relative;
9
+ display: inline-block;
10
+ width: 100%;
11
+ font-family: var(--font-sans);
12
+ }
13
+
14
+ /* Trigger — looks like an input with a chevron */
15
+ .combobox-trigger {
16
+ display: flex;
17
+ align-items: center;
18
+ gap: var(--space-3);
19
+ width: 100%;
20
+ height: 40px;
21
+ padding: 0 var(--space-3) 0 var(--space-4);
22
+ background: var(--color-background-surface);
23
+ border: 1px solid var(--color-border-default);
24
+ border-radius: var(--radius-sm);
25
+ font-family: var(--font-sans);
26
+ font-size: var(--fs-sm);
27
+ font-weight: var(--w-medium);
28
+ color: var(--color-foreground-default);
29
+ cursor: pointer;
30
+ text-align: left;
31
+ transition: var(--transition-fast);
32
+ }
33
+ .combobox-trigger:hover {
34
+ background: var(--color-background-hover);
35
+ border-color: var(--color-border-strong);
36
+ }
37
+ .combobox-trigger:focus-visible,
38
+ .combobox.is-open .combobox-trigger {
39
+ outline: none;
40
+ border-color: var(--color-foreground-accent);
41
+ box-shadow: var(--shadow-focus);
42
+ }
43
+
44
+ .combobox-value {
45
+ flex: 1;
46
+ min-width: 0;
47
+ white-space: nowrap;
48
+ overflow: hidden;
49
+ text-overflow: ellipsis;
50
+ }
51
+ .combobox-placeholder {
52
+ color: var(--color-foreground-muted);
53
+ font-weight: var(--w-regular);
54
+ }
55
+ .combobox-chevron {
56
+ width: 16px; height: 16px;
57
+ stroke-width: var(--icon-stroke);
58
+ color: var(--color-foreground-muted);
59
+ flex-shrink: 0;
60
+ transition: transform var(--duration-fast) var(--ease-standard);
61
+ }
62
+ .combobox.is-open .combobox-chevron { transform: rotate(180deg); }
63
+
64
+ /* Leading icon variant */
65
+ .combobox-trigger-icon {
66
+ width: 16px; height: 16px;
67
+ stroke-width: var(--icon-stroke);
68
+ color: var(--color-foreground-secondary);
69
+ flex-shrink: 0;
70
+ }
71
+
72
+ /* Avatar inside trigger (counterparty selector pattern) */
73
+ .combobox-avatar {
74
+ width: 24px; height: 24px;
75
+ border-radius: var(--radius-pill);
76
+ background: var(--color-brand-secondary-100);
77
+ color: var(--color-brand-secondary-700);
78
+ display: inline-flex; align-items: center; justify-content: center;
79
+ font-size: var(--fs-xxs);
80
+ font-weight: var(--w-semibold);
81
+ flex-shrink: 0;
82
+ margin-left: calc(var(--space-1) * -1);
83
+ }
84
+
85
+ /* Listbox popover */
86
+ .combobox-popover {
87
+ position: absolute;
88
+ top: calc(100% + var(--space-2));
89
+ left: 0;
90
+ right: 0;
91
+ z-index: 7000;
92
+ background: var(--color-background-surface);
93
+ border: 1px solid var(--color-border-default);
94
+ border-radius: var(--radius-md);
95
+ box-shadow: var(--shadow-xl);
96
+ display: none;
97
+ flex-direction: column;
98
+ max-height: 320px;
99
+ }
100
+ .combobox.is-open .combobox-popover { display: flex; }
101
+
102
+ /* Search header */
103
+ .combobox-search {
104
+ position: relative;
105
+ padding: var(--space-3);
106
+ border-bottom: 1px solid var(--color-border-subtle);
107
+ flex-shrink: 0;
108
+ }
109
+ .combobox-search input {
110
+ width: 100%;
111
+ box-sizing: border-box;
112
+ height: 32px;
113
+ padding: 0 var(--space-3) 0 var(--space-7);
114
+ background: var(--color-background-canvas);
115
+ border: 1px solid var(--color-border-default);
116
+ border-radius: var(--radius-xs);
117
+ font-family: var(--font-sans);
118
+ font-size: var(--fs-sm);
119
+ color: var(--color-foreground-default);
120
+ }
121
+ .combobox-search input::placeholder { color: var(--color-foreground-muted); }
122
+ .combobox-search input:focus {
123
+ outline: none;
124
+ border-color: var(--color-foreground-accent);
125
+ box-shadow: var(--shadow-focus);
126
+ }
127
+ .combobox-search-icon {
128
+ position: absolute;
129
+ left: calc(var(--space-3) + var(--space-2));
130
+ top: 50%;
131
+ transform: translateY(-50%);
132
+ width: 14px; height: 14px;
133
+ stroke-width: var(--icon-stroke);
134
+ color: var(--color-foreground-muted);
135
+ pointer-events: none;
136
+ }
137
+
138
+ /* Listbox region */
139
+ .combobox-list {
140
+ list-style: none;
141
+ margin: 0;
142
+ padding: var(--space-1);
143
+ overflow-y: auto;
144
+ flex: 1;
145
+ }
146
+
147
+ /* Group headers */
148
+ .combobox-group-label {
149
+ padding: var(--space-2) var(--space-3) var(--space-1);
150
+ font-family: var(--font-mono);
151
+ font-size: var(--fs-xxs);
152
+ font-weight: var(--w-semibold);
153
+ letter-spacing: var(--ls-caps);
154
+ text-transform: uppercase;
155
+ color: var(--color-foreground-muted);
156
+ }
157
+
158
+ .combobox-option {
159
+ display: flex;
160
+ align-items: center;
161
+ gap: var(--space-3);
162
+ padding: var(--space-2) var(--space-3);
163
+ border-radius: var(--radius-xs);
164
+ cursor: pointer;
165
+ font-size: var(--fs-sm);
166
+ color: var(--color-foreground-default);
167
+ transition: background var(--duration-fast) var(--ease-standard);
168
+ }
169
+ .combobox-option:hover,
170
+ .combobox-option.is-active {
171
+ background: var(--color-background-hover);
172
+ }
173
+ .combobox-option.is-selected {
174
+ background: var(--color-brand-secondary-50);
175
+ color: var(--color-foreground-accent);
176
+ font-weight: var(--w-semibold);
177
+ }
178
+ .combobox-option.is-disabled {
179
+ opacity: 0.5;
180
+ cursor: not-allowed;
181
+ }
182
+
183
+ .combobox-option-content {
184
+ flex: 1;
185
+ min-width: 0;
186
+ }
187
+ .combobox-option-label {
188
+ display: block;
189
+ white-space: nowrap;
190
+ overflow: hidden;
191
+ text-overflow: ellipsis;
192
+ }
193
+ .combobox-option-meta {
194
+ display: block;
195
+ font-size: var(--fs-xs);
196
+ color: var(--color-foreground-secondary);
197
+ font-weight: var(--w-regular);
198
+ margin-top: 1px;
199
+ }
200
+ .combobox-option.is-selected .combobox-option-meta {
201
+ color: var(--color-brand-secondary-600);
202
+ }
203
+
204
+ .combobox-option-check {
205
+ width: 16px; height: 16px;
206
+ stroke-width: 2.4;
207
+ color: var(--color-foreground-accent);
208
+ flex-shrink: 0;
209
+ opacity: 0;
210
+ }
211
+ .combobox-option.is-selected .combobox-option-check { opacity: 1; }
212
+
213
+ .combobox-option-trailing {
214
+ font-family: var(--font-mono);
215
+ font-size: var(--fs-xxs);
216
+ color: var(--color-foreground-muted);
217
+ flex-shrink: 0;
218
+ }
219
+
220
+ /* Empty state */
221
+ .combobox-empty {
222
+ padding: var(--space-8) var(--space-4);
223
+ text-align: center;
224
+ color: var(--color-foreground-muted);
225
+ font-size: var(--fs-sm);
226
+ }
227
+ .combobox-empty strong {
228
+ display: block;
229
+ color: var(--color-foreground-default);
230
+ font-weight: var(--w-semibold);
231
+ margin-bottom: var(--space-1);
232
+ }
233
+
234
+ /* Footer (e.g. "Create new …") */
235
+ .combobox-footer {
236
+ padding: var(--space-2);
237
+ border-top: 1px solid var(--color-border-subtle);
238
+ flex-shrink: 0;
239
+ }
240
+ .combobox-footer-action {
241
+ display: flex;
242
+ align-items: center;
243
+ justify-content: center;
244
+ gap: var(--space-2);
245
+ padding: var(--space-3) var(--space-4);
246
+ margin: var(--space-2);
247
+ margin-top: 0;
248
+ width: calc(100% - var(--space-4));
249
+ background: var(--color-background-surface);
250
+ border: 1px solid var(--color-border-default);
251
+ border-radius: var(--radius-sm);
252
+ font-family: var(--font-sans);
253
+ font-size: var(--fs-sm);
254
+ font-weight: var(--w-semibold);
255
+ color: var(--color-foreground-default);
256
+ cursor: pointer;
257
+ text-align: center;
258
+ box-shadow: var(--shadow-xs);
259
+ transition: var(--transition-fast);
260
+ }
261
+ .combobox-footer-action:hover {
262
+ background: var(--color-background-hover);
263
+ border-color: var(--color-border-strong);
264
+ }
265
+ .combobox-footer-action:active {
266
+ background: var(--color-background-press);
267
+ }
268
+ .combobox-footer-action:focus-visible {
269
+ outline: none;
270
+ box-shadow: var(--shadow-focus);
271
+ }
272
+ .combobox-footer-action svg,
273
+ .combobox-footer-action i {
274
+ width: 14px;
275
+ height: 14px;
276
+ stroke-width: var(--icon-stroke);
277
+ color: var(--color-foreground-secondary);
278
+ }
279
+ .combobox-footer-action i, .combobox-footer-action svg {
280
+ width: 16px; height: 16px;
281
+ stroke-width: var(--icon-stroke);
282
+ }
283
+
284
+ /* States */
285
+ .combobox-trigger[aria-disabled="true"],
286
+ .combobox.is-disabled .combobox-trigger {
287
+ background: var(--color-background-subtle);
288
+ color: var(--color-foreground-muted);
289
+ cursor: not-allowed;
290
+ border-color: var(--color-border-subtle);
291
+ }
292
+ .combobox.is-invalid .combobox-trigger {
293
+ border-color: var(--color-feedback-danger-border);
294
+ }
295
+ .combobox.is-invalid .combobox-trigger:focus-visible {
296
+ box-shadow: 0 0 0 3px var(--color-feedback-danger-background);
297
+ }
298
+
299
+ /* Reduced motion */
300
+ @media (prefers-reduced-motion: reduce) {
301
+ .combobox-chevron { transition: none; }
302
+ .combobox-option { transition: none; }
303
+ }
@@ -0,0 +1,61 @@
1
+ /* ============================================================
2
+ EMPTY STATES — production component CSS
3
+ Used by empty-states.html and any product surface that needs
4
+ a zero-data placeholder. All values resolve to design tokens.
5
+ ============================================================ */
6
+
7
+ .empty {
8
+ display: flex;
9
+ flex-direction: column;
10
+ align-items: center;
11
+ text-align: center;
12
+ gap: 14px;
13
+ padding: 56px 24px;
14
+ border-radius: var(--radius-md);
15
+ background: transparent;
16
+ border: 0;
17
+ }
18
+ .empty.empty-default { padding: 56px 24px; gap: 14px; }
19
+ .empty.empty-compact { padding: 28px 20px; gap: 10px; }
20
+
21
+ .empty-illo {
22
+ display: inline-flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ }
26
+ .empty-illo svg { display: block; }
27
+
28
+ .empty h4 {
29
+ font-family: var(--font-sans);
30
+ font-size: var(--fs-lg);
31
+ font-weight: var(--w-bold);
32
+ letter-spacing: -.01em;
33
+ color: var(--color-foreground-default);
34
+ margin: 0;
35
+ max-width: 360px;
36
+ }
37
+ .empty.empty-compact h4 { font-size: var(--fs-md); }
38
+
39
+ .empty p {
40
+ font-family: var(--font-sans);
41
+ font-size: var(--fs-sm);
42
+ color: var(--color-foreground-secondary);
43
+ line-height: var(--lh-relaxed);
44
+ margin: 0;
45
+ max-width: 360px;
46
+ text-wrap: pretty;
47
+ }
48
+
49
+ .empty-actions {
50
+ display: flex;
51
+ gap: var(--space-2);
52
+ margin-top: var(--space-1);
53
+ flex-wrap: wrap;
54
+ justify-content: center;
55
+ }
56
+
57
+ /* ---- tone: warning ---- */
58
+ .empty.empty-warning {
59
+ background: var(--color-feedback-warning-background);
60
+ border: 1px solid var(--color-feedback-warning-border);
61
+ }