@ceebee/ui 0.2.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,2498 @@
1
+ /* tokens/structure.css */
2
+ /* Structure tokens: stable across brands. A Skin never overrides these (CONTEXT.md: Token). */
3
+ :root {
4
+ --cb-space-0: 0;
5
+ --cb-space-1: 0.25rem;
6
+ --cb-space-2: 0.5rem;
7
+ --cb-space-3: 0.75rem;
8
+ --cb-space-4: 1rem;
9
+ --cb-space-5: 1.5rem;
10
+ --cb-space-6: 2rem;
11
+ --cb-space-7: 3rem;
12
+ --cb-space-8: 4rem;
13
+
14
+ --cb-radius-sm: 0.5rem;
15
+ --cb-radius-md: 0.875rem;
16
+ --cb-radius-lg: 1.25rem;
17
+ --cb-radius-xl: 1.75rem;
18
+ --cb-radius-full: 999px;
19
+
20
+ --cb-text-xs: 0.75rem;
21
+ --cb-text-sm: 0.875rem;
22
+ --cb-text-md: 1rem;
23
+ --cb-text-lg: 1.125rem;
24
+ --cb-text-xl: 1.5rem;
25
+ --cb-text-2xl: 2rem;
26
+ --cb-text-3xl: 2.75rem;
27
+
28
+ --cb-leading-tight: 1.2;
29
+ --cb-leading-normal: 1.55;
30
+
31
+ --cb-weight-regular: 400;
32
+ --cb-weight-medium: 500;
33
+ --cb-weight-semibold: 600;
34
+
35
+ --cb-control-height-sm: 2rem;
36
+ --cb-control-height-md: 2.5rem;
37
+ --cb-control-height-lg: 3rem;
38
+
39
+ --cb-border-width: 1px;
40
+ --cb-focus-width: 2px;
41
+ /* Outside a control's own edge. */
42
+ --cb-focus-offset: 2px;
43
+ /* Inset, for a control that sits flush inside a bordered container — a stepper button, a
44
+ sidebar row, a tab — where an outside ring would be clipped or would overlap its neighbour. */
45
+ --cb-focus-offset-inset: -2px;
46
+
47
+ --cb-z-base: 0;
48
+ --cb-z-sticky: 100;
49
+ --cb-z-overlay: 200;
50
+ --cb-z-popover: 300;
51
+ --cb-z-toast: 400;
52
+ --cb-z-coachmark: 500;
53
+ }
54
+
55
+ /* tokens/skin.css */
56
+ /* Skin tokens: the default Ceebee skin. A Skin file rewrites only these (ADR 0002).
57
+ Light is defined on bare :root so no colour has its only definition inside a media query. */
58
+ :root {
59
+ --cb-hue-brand: 274;
60
+ --cb-hue-info: 214;
61
+ --cb-hue-success: 152;
62
+ --cb-hue-warning: 38;
63
+ --cb-hue-danger: 4;
64
+
65
+ --cb-brand-50: oklch(0.97 0.02 var(--cb-hue-brand));
66
+ --cb-brand-100: oklch(0.94 0.05 var(--cb-hue-brand));
67
+ --cb-brand-200: oklch(0.88 0.09 var(--cb-hue-brand));
68
+ --cb-brand-300: oklch(0.8 0.13 var(--cb-hue-brand));
69
+ --cb-brand-400: oklch(0.71 0.17 var(--cb-hue-brand));
70
+ --cb-brand-500: oklch(0.62 0.2 var(--cb-hue-brand));
71
+ --cb-brand-600: oklch(0.54 0.19 var(--cb-hue-brand));
72
+ --cb-brand-700: oklch(0.45 0.16 var(--cb-hue-brand));
73
+
74
+ --cb-bg: oklch(0.985 0.004 280);
75
+ --cb-bg-subtle: oklch(0.945 0.01 280);
76
+ --cb-surface: oklch(1 0 0);
77
+ --cb-surface-raised: oklch(1 0 0);
78
+ --cb-border: oklch(0.84 0.012 280);
79
+ --cb-border-strong: oklch(0.64 0.018 280);
80
+
81
+ --cb-fg: oklch(0.22 0.02 280);
82
+ --cb-fg-muted: oklch(0.45 0.02 280);
83
+ --cb-fg-subtle: oklch(0.53 0.018 280);
84
+ --cb-fg-on-brand: oklch(0.99 0 0);
85
+ /* A boundary has to be visible to be a boundary: border-strong carries the 3:1 WCAG asks of a
86
+ control's edge, and border the quieter separation between panels. */
87
+
88
+ --cb-tone-neutral: var(--cb-fg-muted);
89
+ --cb-tone-brand: var(--cb-brand-500);
90
+ --cb-tone-info: oklch(0.62 0.16 var(--cb-hue-info));
91
+ --cb-tone-success: oklch(0.62 0.15 var(--cb-hue-success));
92
+ --cb-tone-warning: oklch(0.75 0.15 var(--cb-hue-warning));
93
+ --cb-tone-danger: oklch(0.6 0.19 var(--cb-hue-danger));
94
+
95
+ /* Decorative hues: the pastel card set the board leans on. */
96
+ --cb-decor-violet: oklch(0.68 0.17 292);
97
+ --cb-decor-blue: oklch(0.68 0.15 240);
98
+ --cb-decor-teal: oklch(0.72 0.12 190);
99
+ --cb-decor-green: oklch(0.74 0.14 150);
100
+ --cb-decor-amber: oklch(0.8 0.14 75);
101
+ --cb-decor-rose: oklch(0.7 0.16 15);
102
+
103
+ /* The wash behind an overlay, and the dark field a coachmark cuts its hole out of. */
104
+ --cb-scrim: oklch(0.15 0.02 280 / 0.45);
105
+ --cb-scrim-strong: oklch(0.15 0.02 280 / 0.55);
106
+ /* Text that sits on the warning ramp, which is too light to carry white. */
107
+ --cb-on-warning: oklch(0.24 0.05 75);
108
+
109
+ --cb-shadow-none: 0 0 transparent;
110
+ --cb-shadow-sm: 0 1px 2px oklch(0.3 0.03 280 / 0.06);
111
+ --cb-shadow-md: 0 4px 16px oklch(0.3 0.03 280 / 0.08);
112
+ --cb-shadow-lg: 0 18px 48px oklch(0.3 0.03 280 / 0.12);
113
+
114
+ --cb-glass-bg: oklch(1 0 0 / 0.62);
115
+ --cb-glass-bg-opaque: oklch(0.985 0.004 280);
116
+ --cb-glass-border: oklch(1 0 0 / 0.55);
117
+ --cb-glass-border-strong: oklch(0.64 0.018 280);
118
+ --cb-glass-blur: 18px;
119
+ --cb-glass-saturation: 1.4;
120
+ --cb-glass-specular: linear-gradient(145deg, oklch(1 0 0 / 0.34), transparent 42%);
121
+ --cb-glass-inset: inset 0 1px 0 oklch(1 0 0 / 0.62), inset 0 -1px 0 oklch(0.3 0.03 280 / 0.1);
122
+
123
+ --cb-tint-strength: 0.09;
124
+ --cb-gradient-angle: 145deg;
125
+
126
+ --cb-font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
127
+ --cb-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
128
+ }
129
+
130
+ /* System dark, unless the document explicitly asked for light. */
131
+ @media (prefers-color-scheme: dark) {
132
+ :root:not([data-theme="light"]) {
133
+ --cb-bg: oklch(0.16 0.02 280);
134
+ --cb-bg-subtle: oklch(0.225 0.024 280);
135
+ --cb-surface: oklch(0.25 0.024 280);
136
+ --cb-surface-raised: oklch(0.31 0.026 280);
137
+ --cb-border: oklch(0.45 0.024 280);
138
+ --cb-border-strong: oklch(0.56 0.028 280);
139
+
140
+ --cb-fg: oklch(0.96 0.006 280);
141
+ --cb-fg-muted: oklch(0.78 0.015 280);
142
+ --cb-fg-subtle: oklch(0.66 0.018 280);
143
+
144
+ --cb-brand-500: oklch(0.72 0.19 var(--cb-hue-brand));
145
+ --cb-brand-600: oklch(0.64 0.2 var(--cb-hue-brand));
146
+
147
+ --cb-shadow-sm: 0 1px 2px oklch(0 0 0 / 0.4);
148
+ --cb-shadow-md: 0 6px 20px oklch(0 0 0 / 0.45);
149
+ --cb-shadow-lg: 0 22px 56px oklch(0 0 0 / 0.55);
150
+
151
+ --cb-glass-bg: oklch(0.3 0.03 280 / 0.55);
152
+ --cb-glass-bg-opaque: oklch(0.25 0.024 280);
153
+ --cb-glass-border: oklch(0.8 0.02 280 / 0.16);
154
+ --cb-glass-border-strong: oklch(0.72 0.03 280);
155
+ --cb-glass-blur: 20px;
156
+ --cb-glass-saturation: 1.25;
157
+ --cb-glass-specular: linear-gradient(145deg, oklch(1 0 0 / 0.18), transparent 42%);
158
+ --cb-glass-inset: inset 0 1px 0 oklch(1 0 0 / 0.26), inset 0 -1px 0 oklch(0 0 0 / 0.34);
159
+
160
+ --cb-scrim: oklch(0.08 0.01 280 / 0.6);
161
+ --cb-scrim-strong: oklch(0.08 0.01 280 / 0.7);
162
+
163
+ --cb-tint-strength: 0.16;
164
+ }
165
+ }
166
+
167
+ /* Explicit choice wins in both directions. */
168
+ :root[data-theme="dark"] {
169
+ --cb-bg: oklch(0.16 0.02 280);
170
+ --cb-bg-subtle: oklch(0.225 0.024 280);
171
+ --cb-surface: oklch(0.25 0.024 280);
172
+ --cb-surface-raised: oklch(0.31 0.026 280);
173
+ --cb-border: oklch(0.45 0.024 280);
174
+ --cb-border-strong: oklch(0.56 0.028 280);
175
+
176
+ --cb-fg: oklch(0.96 0.006 280);
177
+ --cb-fg-muted: oklch(0.78 0.015 280);
178
+ --cb-fg-subtle: oklch(0.66 0.018 280);
179
+
180
+ --cb-brand-500: oklch(0.72 0.19 var(--cb-hue-brand));
181
+ --cb-brand-600: oklch(0.64 0.2 var(--cb-hue-brand));
182
+
183
+ --cb-shadow-sm: 0 1px 2px oklch(0 0 0 / 0.4);
184
+ --cb-shadow-md: 0 6px 20px oklch(0 0 0 / 0.45);
185
+ --cb-shadow-lg: 0 22px 56px oklch(0 0 0 / 0.55);
186
+
187
+ --cb-glass-bg: oklch(0.3 0.03 280 / 0.55);
188
+ --cb-glass-bg-opaque: oklch(0.25 0.024 280);
189
+ --cb-glass-border: oklch(0.8 0.02 280 / 0.16);
190
+ --cb-glass-border-strong: oklch(0.72 0.03 280);
191
+ --cb-glass-blur: 20px;
192
+ --cb-glass-saturation: 1.25;
193
+ --cb-glass-specular: linear-gradient(145deg, oklch(1 0 0 / 0.18), transparent 42%);
194
+ --cb-glass-inset: inset 0 1px 0 oklch(1 0 0 / 0.26), inset 0 -1px 0 oklch(0 0 0 / 0.34);
195
+
196
+ --cb-scrim: oklch(0.08 0.01 280 / 0.6);
197
+ --cb-scrim-strong: oklch(0.08 0.01 280 / 0.7);
198
+
199
+ --cb-tint-strength: 0.16;
200
+ }
201
+
202
+ html, body { background: var(--cb-bg); color: var(--cb-fg); }
203
+
204
+ /* Someone who asked their system for more contrast gets stronger edges and darker secondary
205
+ text, without the palette changing hue underneath them. */
206
+ @media (prefers-contrast: more) {
207
+ :root {
208
+ --cb-border: oklch(0.7 0.014 280);
209
+ --cb-border-strong: oklch(0.45 0.02 280);
210
+ --cb-fg-muted: oklch(0.35 0.02 280);
211
+ --cb-fg-subtle: oklch(0.4 0.018 280);
212
+ --cb-tint-strength: 0.16;
213
+ --cb-glass-border-strong: oklch(0.45 0.02 280);
214
+ }
215
+
216
+ :root[data-theme="dark"],
217
+ :root:not([data-theme="light"]) {
218
+ --cb-border: oklch(0.58 0.026 280);
219
+ --cb-border-strong: oklch(0.72 0.03 280);
220
+ --cb-fg-muted: oklch(0.88 0.012 280);
221
+ --cb-fg-subtle: oklch(0.78 0.016 280);
222
+ --cb-glass-border-strong: oklch(0.72 0.03 280);
223
+ }
224
+ }
225
+
226
+ /* tokens/motion.css */
227
+ /* Motion tokens. A component reads these; it never writes a duration (ADR 0004). */
228
+ :root {
229
+ --cb-duration-instant: 80ms;
230
+ --cb-duration-fast: 140ms;
231
+ --cb-duration-base: 220ms;
232
+ --cb-duration-slow: 380ms;
233
+ --cb-duration-deliberate: 620ms;
234
+
235
+ --cb-ease-standard: cubic-bezier(0.2, 0, 0, 1);
236
+ --cb-ease-entrance: cubic-bezier(0.05, 0.7, 0.1, 1);
237
+ --cb-ease-exit: cubic-bezier(0.3, 0, 0.8, 0.15);
238
+ --cb-ease-emphasis: cubic-bezier(0.34, 1.56, 0.64, 1);
239
+
240
+ /* Scale hook: MotionProvider writes this, CSS animation reads it. 0 disables. */
241
+ --cb-motion-scale: 1;
242
+ }
243
+
244
+ @media (prefers-reduced-motion: reduce) {
245
+ :root { --cb-motion-scale: 0; }
246
+ }
247
+
248
+ /* foundation/layout.css */
249
+ .cb-stack { display: flex; gap: var(--cb-stack-gap); }
250
+ .cb-stack--column { flex-direction: column; }
251
+ .cb-stack--row { flex-direction: row; }
252
+ .cb-stack--wrap { flex-wrap: wrap; }
253
+ .cb-stack[data-align="start"] { align-items: flex-start; }
254
+ .cb-stack[data-align="center"] { align-items: center; }
255
+ .cb-stack[data-align="end"] { align-items: flex-end; }
256
+ .cb-stack[data-align="stretch"] { align-items: stretch; }
257
+ .cb-stack[data-align="baseline"] { align-items: baseline; }
258
+ .cb-stack[data-justify="start"] { justify-content: flex-start; }
259
+ .cb-stack[data-justify="center"] { justify-content: center; }
260
+ .cb-stack[data-justify="end"] { justify-content: flex-end; }
261
+ .cb-stack[data-justify="between"] { justify-content: space-between; }
262
+
263
+ .cb-grid {
264
+ display: grid;
265
+ gap: var(--cb-grid-gap);
266
+ grid-template-columns: repeat(var(--cb-grid-columns), minmax(0, 1fr));
267
+ }
268
+ .cb-grid--auto {
269
+ grid-template-columns: repeat(auto-fit, minmax(min(var(--cb-grid-min), 100%), 1fr));
270
+ }
271
+ @media (max-width: 900px) {
272
+ .cb-grid:not(.cb-grid--auto) { grid-template-columns: repeat(min(var(--cb-grid-columns), 2), minmax(0, 1fr)); }
273
+ }
274
+ @media (max-width: 560px) {
275
+ .cb-grid:not(.cb-grid--auto) { grid-template-columns: minmax(0, 1fr); }
276
+ }
277
+
278
+ .cb-container { width: 100%; margin-inline: auto; padding-inline: var(--cb-space-4); }
279
+ .cb-container--sm { max-width: 40rem; }
280
+ .cb-container--md { max-width: 56rem; }
281
+ .cb-container--lg { max-width: 76rem; }
282
+ .cb-container--full { max-width: none; }
283
+
284
+ /* foundation/surface.css */
285
+ .cb-surface {
286
+ --cb-surface-accent: var(--cb-tone-neutral);
287
+ --cb-surface-material-shadow: var(--cb-shadow-none);
288
+ background: var(--cb-surface);
289
+ color: var(--cb-fg);
290
+ box-sizing: border-box;
291
+ }
292
+ .cb-surface--bordered { border: var(--cb-border-width) solid var(--cb-border); }
293
+
294
+ .cb-surface[data-tone="brand"] { --cb-surface-accent: var(--cb-tone-brand); }
295
+ .cb-surface[data-tone="info"] { --cb-surface-accent: var(--cb-tone-info); }
296
+ .cb-surface[data-tone="success"] { --cb-surface-accent: var(--cb-tone-success); }
297
+ .cb-surface[data-tone="warning"] { --cb-surface-accent: var(--cb-tone-warning); }
298
+ .cb-surface[data-tone="danger"] { --cb-surface-accent: var(--cb-tone-danger); }
299
+
300
+ .cb-surface[data-hue="violet"] { --cb-surface-accent: var(--cb-decor-violet); }
301
+ .cb-surface[data-hue="blue"] { --cb-surface-accent: var(--cb-decor-blue); }
302
+ .cb-surface[data-hue="teal"] { --cb-surface-accent: var(--cb-decor-teal); }
303
+ .cb-surface[data-hue="green"] { --cb-surface-accent: var(--cb-decor-green); }
304
+ .cb-surface[data-hue="amber"] { --cb-surface-accent: var(--cb-decor-amber); }
305
+ .cb-surface[data-hue="rose"] { --cb-surface-accent: var(--cb-decor-rose); }
306
+
307
+ /* Tint mixes the accent into the surface so one strength token retunes every tinted card. */
308
+ .cb-surface--tinted {
309
+ background: color-mix(in oklch, var(--cb-surface-accent) calc(var(--cb-tint-strength) * 100%), var(--cb-surface));
310
+ border-color: color-mix(in oklch, var(--cb-surface-accent) 22%, transparent);
311
+ }
312
+
313
+ .cb-surface--glass {
314
+ background: var(--cb-glass-specular), var(--cb-glass-bg);
315
+ border-color: var(--cb-glass-border);
316
+ backdrop-filter: blur(var(--cb-glass-blur)) saturate(var(--cb-glass-saturation));
317
+ -webkit-backdrop-filter: blur(var(--cb-glass-blur)) saturate(var(--cb-glass-saturation));
318
+ --cb-surface-material-shadow: var(--cb-glass-inset);
319
+ }
320
+
321
+ .cb-surface--gradient {
322
+ background: linear-gradient(
323
+ var(--cb-gradient-angle),
324
+ color-mix(in oklch, var(--cb-surface-accent) 26%, var(--cb-surface)),
325
+ color-mix(in oklch, var(--cb-surface-accent) 6%, var(--cb-surface))
326
+ );
327
+ border-color: color-mix(in oklch, var(--cb-surface-accent) 24%, transparent);
328
+ }
329
+
330
+ .cb-elevation--none { box-shadow: var(--cb-surface-material-shadow); }
331
+ .cb-elevation--sm { box-shadow: var(--cb-surface-material-shadow), var(--cb-shadow-sm); }
332
+ .cb-elevation--md { box-shadow: var(--cb-surface-material-shadow), var(--cb-shadow-md); }
333
+ .cb-elevation--lg { box-shadow: var(--cb-surface-material-shadow), var(--cb-shadow-lg); }
334
+
335
+ @supports not ((backdrop-filter: blur(var(--cb-glass-blur))) or (-webkit-backdrop-filter: blur(var(--cb-glass-blur)))) {
336
+ .cb-surface--glass { background: var(--cb-glass-bg-opaque); }
337
+ }
338
+
339
+ @media (prefers-reduced-transparency: reduce) {
340
+ .cb-surface--glass {
341
+ background: var(--cb-glass-bg-opaque);
342
+ backdrop-filter: none;
343
+ -webkit-backdrop-filter: none;
344
+ }
345
+ }
346
+
347
+ @media (prefers-contrast: more) {
348
+ .cb-surface--glass {
349
+ background: var(--cb-glass-bg-opaque);
350
+ border-color: var(--cb-glass-border-strong);
351
+ backdrop-filter: none;
352
+ -webkit-backdrop-filter: none;
353
+ }
354
+ }
355
+
356
+ @media (forced-colors: active) {
357
+ .cb-surface--glass {
358
+ background: Canvas;
359
+ border-color: CanvasText;
360
+ color: CanvasText;
361
+ box-shadow: none;
362
+ backdrop-filter: none;
363
+ -webkit-backdrop-filter: none;
364
+ }
365
+ }
366
+
367
+ .cb-radius--sm { border-radius: var(--cb-radius-sm); }
368
+ .cb-radius--md { border-radius: var(--cb-radius-md); }
369
+ .cb-radius--lg { border-radius: var(--cb-radius-lg); }
370
+ .cb-radius--xl { border-radius: var(--cb-radius-xl); }
371
+
372
+ .cb-pad--none { padding: 0; }
373
+ .cb-pad--sm { padding: var(--cb-space-3); }
374
+ .cb-pad--md { padding: var(--cb-space-5); }
375
+ .cb-pad--lg { padding: var(--cb-space-6); }
376
+
377
+ /* foundation/text.css */
378
+ .cb-text, .cb-heading { margin: 0; font-family: var(--cb-font-sans); color: var(--cb-fg); }
379
+ .cb-text { line-height: var(--cb-leading-normal); }
380
+ .cb-heading { line-height: var(--cb-leading-tight); font-weight: var(--cb-weight-semibold); letter-spacing: -0.015em; }
381
+
382
+ .cb-text--xs { font-size: var(--cb-text-xs); }
383
+ .cb-text--sm { font-size: var(--cb-text-sm); }
384
+ .cb-text--md { font-size: var(--cb-text-md); }
385
+ .cb-text--lg { font-size: var(--cb-text-lg); }
386
+ .cb-text--xl { font-size: var(--cb-text-xl); }
387
+ .cb-text--2xl { font-size: var(--cb-text-2xl); }
388
+ .cb-text--3xl { font-size: var(--cb-text-3xl); }
389
+
390
+ .cb-weight--regular { font-weight: var(--cb-weight-regular); }
391
+ .cb-weight--medium { font-weight: var(--cb-weight-medium); }
392
+ .cb-weight--semibold { font-weight: var(--cb-weight-semibold); }
393
+
394
+ .cb-numeric { font-variant-numeric: tabular-nums; }
395
+
396
+ .cb-text[data-tone="muted"] { color: var(--cb-fg-muted); }
397
+ .cb-text[data-tone="subtle"] { color: var(--cb-fg-subtle); }
398
+ .cb-text[data-tone="brand"] { color: var(--cb-tone-brand); }
399
+ .cb-text[data-tone="info"] { color: var(--cb-tone-info); }
400
+ .cb-text[data-tone="success"] { color: var(--cb-tone-success); }
401
+ .cb-text[data-tone="warning"] { color: var(--cb-tone-warning); }
402
+ .cb-text[data-tone="danger"] { color: var(--cb-tone-danger); }
403
+
404
+ /* form/button.css */
405
+ .cb-button {
406
+ --cb-button-accent: var(--cb-tone-brand);
407
+ --cb-button-fg: var(--cb-fg-on-brand);
408
+ display: inline-flex;
409
+ align-items: center;
410
+ justify-content: center;
411
+ gap: var(--cb-space-2);
412
+ border: var(--cb-border-width) solid transparent;
413
+ border-radius: var(--cb-radius-md);
414
+ font-family: var(--cb-font-sans);
415
+ font-weight: var(--cb-weight-medium);
416
+ cursor: pointer;
417
+ white-space: nowrap;
418
+ transition: background-color var(--cb-duration-fast) var(--cb-ease-standard),
419
+ color var(--cb-duration-fast) var(--cb-ease-standard),
420
+ border-color var(--cb-duration-fast) var(--cb-ease-standard);
421
+ }
422
+ .cb-button:disabled { opacity: 0.55; cursor: not-allowed; }
423
+ .cb-button:focus-visible {
424
+ outline: var(--cb-focus-width) solid var(--cb-button-accent);
425
+ outline-offset: var(--cb-focus-offset);
426
+ }
427
+
428
+ .cb-button[data-tone="neutral"] { --cb-button-accent: var(--cb-fg); --cb-button-fg: var(--cb-bg); }
429
+ .cb-button[data-tone="info"] { --cb-button-accent: var(--cb-tone-info); }
430
+ .cb-button[data-tone="success"] { --cb-button-accent: var(--cb-tone-success); }
431
+ .cb-button[data-tone="warning"] { --cb-button-accent: var(--cb-tone-warning); --cb-button-fg: var(--cb-on-warning); }
432
+ .cb-button[data-tone="danger"] { --cb-button-accent: var(--cb-tone-danger); }
433
+
434
+ .cb-button--sm { height: var(--cb-control-height-sm); padding-inline: var(--cb-space-3); font-size: var(--cb-text-sm); }
435
+ .cb-button--md { height: var(--cb-control-height-md); padding-inline: var(--cb-space-4); font-size: var(--cb-text-sm); }
436
+ .cb-button--lg { height: var(--cb-control-height-lg); padding-inline: var(--cb-space-5); font-size: var(--cb-text-md); }
437
+
438
+ .cb-button--solid { background: var(--cb-button-accent); color: var(--cb-button-fg); }
439
+ .cb-button--solid:hover:not(:disabled) { background: color-mix(in oklch, var(--cb-button-accent) 88%, black); }
440
+
441
+ .cb-button--soft {
442
+ background: color-mix(in oklch, var(--cb-button-accent) 14%, transparent);
443
+ color: var(--cb-button-accent);
444
+ }
445
+ .cb-button--soft:hover:not(:disabled) { background: color-mix(in oklch, var(--cb-button-accent) 22%, transparent); }
446
+
447
+ .cb-button--outline { border-color: var(--cb-border-strong); color: var(--cb-fg); background: transparent; }
448
+ .cb-button--outline:hover:not(:disabled) { border-color: var(--cb-button-accent); color: var(--cb-button-accent); }
449
+
450
+ .cb-button--ghost { background: transparent; color: var(--cb-fg-muted); }
451
+ .cb-button--ghost:hover:not(:disabled) { background: var(--cb-bg-subtle); color: var(--cb-fg); }
452
+
453
+ /* Square, no text padding, no gap: the glyph sits on the centre of the control. */
454
+ .cb-button--icon { padding-inline: 0; gap: 0; }
455
+ .cb-button--icon.cb-button--sm { width: var(--cb-control-height-sm); }
456
+ .cb-button--icon.cb-button--md { width: var(--cb-control-height-md); }
457
+ .cb-button--icon.cb-button--lg { width: var(--cb-control-height-lg); }
458
+
459
+ .cb-button__spinner {
460
+ width: 1em;
461
+ height: 1em;
462
+ border-radius: var(--cb-radius-full);
463
+ border: 2px solid currentColor;
464
+ border-top-color: transparent;
465
+ animation: cb-spin calc(var(--cb-duration-deliberate) * 1.5) linear infinite;
466
+ }
467
+ @keyframes cb-spin { to { transform: rotate(360deg); } }
468
+ /* Reduced motion: the spinner stops turning but the busy state stays visible and announced. */
469
+ @media (prefers-reduced-motion: reduce) {
470
+ /* Square, no text padding, no gap: the glyph sits on the centre of the control. */
471
+ .cb-button--icon { padding-inline: 0; gap: 0; }
472
+ .cb-button--icon.cb-button--sm { width: var(--cb-control-height-sm); }
473
+ .cb-button--icon.cb-button--md { width: var(--cb-control-height-md); }
474
+ .cb-button--icon.cb-button--lg { width: var(--cb-control-height-lg); }
475
+
476
+ .cb-button__spinner { animation: none; opacity: 0.6; }
477
+ }
478
+
479
+ /* form/choice.css */
480
+ .cb-choice { display: flex; align-items: flex-start; gap: var(--cb-space-3); }
481
+ /* A row whose text is a single line centres on the control instead of hanging from its top. */
482
+ .cb-choice:not(:has(.cb-choice__description)) { align-items: center; }
483
+ .cb-choice--justified { align-items: center; justify-content: space-between; width: 100%; }
484
+ .cb-choice__text { display: flex; flex-direction: column; gap: var(--cb-space-1); }
485
+ .cb-choice__label {
486
+ font-family: var(--cb-font-sans);
487
+ font-size: var(--cb-text-sm);
488
+ color: var(--cb-fg);
489
+ cursor: pointer;
490
+ line-height: 1.35;
491
+ }
492
+ .cb-choice__description { margin: 0; font-family: var(--cb-font-sans); font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
493
+
494
+ .cb-checkbox,
495
+ .cb-radio {
496
+ position: relative;
497
+ flex: none;
498
+ display: inline-flex;
499
+ align-items: center;
500
+ justify-content: center;
501
+ width: 1.125rem;
502
+ height: 1.125rem;
503
+ margin-top: 0.0625rem;
504
+ padding: 0;
505
+ background: var(--cb-surface);
506
+ border: var(--cb-border-width) solid var(--cb-border-strong);
507
+ color: var(--cb-fg-on-brand);
508
+ cursor: pointer;
509
+ transition: background-color var(--cb-duration-fast) var(--cb-ease-standard),
510
+ border-color var(--cb-duration-fast) var(--cb-ease-standard);
511
+ }
512
+ .cb-checkbox { border-radius: 0.3125rem; }
513
+
514
+ /* The pointer target is 24px even though the box reads as 18px. The switch is excluded: it is
515
+ already 40x24, and without a positioned ancestor its pseudo-element grew to the width of a
516
+ distant container and swallowed every click on the page. */
517
+ .cb-checkbox::before,
518
+ .cb-radio::before {
519
+ content: "";
520
+ position: absolute;
521
+ inset: 50% auto auto 50%;
522
+ width: max(100%, 1.5rem);
523
+ height: max(100%, 1.5rem);
524
+ translate: -50% -50%;
525
+ }
526
+ .cb-radio { border-radius: var(--cb-radius-full); }
527
+
528
+ .cb-checkbox[data-checked],
529
+ .cb-checkbox[data-indeterminate] {
530
+ background: var(--cb-tone-brand);
531
+ border-color: var(--cb-tone-brand);
532
+ }
533
+ .cb-radio[data-checked] { border-color: var(--cb-tone-brand); border-width: 2px; }
534
+
535
+ .cb-checkbox:focus-visible,
536
+ .cb-radio:focus-visible,
537
+ .cb-switch:focus-visible {
538
+ outline: var(--cb-focus-width) solid var(--cb-tone-brand);
539
+ outline-offset: var(--cb-focus-offset);
540
+ }
541
+ /* Disabled has to be legible as a state, not merely dimmer: the control loses its fill, drops
542
+ to a dashed edge, and takes the muted foreground with it. */
543
+ .cb-checkbox[data-disabled],
544
+ .cb-radio[data-disabled],
545
+ .cb-switch[data-disabled] {
546
+ cursor: not-allowed;
547
+ opacity: 1;
548
+ background: var(--cb-bg-subtle);
549
+ border-style: dashed;
550
+ border-color: var(--cb-border-strong);
551
+ color: var(--cb-fg-subtle);
552
+ }
553
+ .cb-switch[data-disabled] { border-style: solid; background: color-mix(in oklch, var(--cb-fg) 12%, transparent); }
554
+ .cb-switch[data-disabled] .cb-switch__thumb { background: var(--cb-bg-subtle); box-shadow: none; }
555
+ .cb-radio[data-disabled] .cb-radio__indicator,
556
+ .cb-checkbox[data-disabled] .cb-checkbox__indicator { color: var(--cb-fg-subtle); background: var(--cb-fg-subtle); }
557
+ .cb-choice:has([data-disabled]) .cb-choice__label,
558
+ .cb-choice:has([data-disabled]) .cb-choice__description { color: var(--cb-fg-subtle); cursor: not-allowed; }
559
+
560
+ .cb-checkbox__indicator { display: inline-flex; }
561
+ .cb-radio__indicator {
562
+ width: 0.5rem;
563
+ height: 0.5rem;
564
+ border-radius: var(--cb-radius-full);
565
+ background: var(--cb-tone-brand);
566
+ transition: scale var(--cb-duration-fast) var(--cb-ease-emphasis);
567
+ }
568
+ .cb-radio__indicator[data-starting-style] { scale: 0; }
569
+ @media (prefers-reduced-motion: reduce) {
570
+ .cb-radio__indicator { transition: none; }
571
+ }
572
+
573
+ .cb-radio-group { display: flex; gap: var(--cb-space-3); }
574
+ .cb-radio-group--column { flex-direction: column; }
575
+ .cb-radio-group--row { flex-direction: row; flex-wrap: wrap; gap: var(--cb-space-5); }
576
+
577
+ .cb-switch {
578
+ /* Geometry is derived, not hand-tuned: the thumb size and its travel both come from the
579
+ track's own dimensions, so changing one number keeps the whole control symmetrical. */
580
+ --cb-switch-width: 2.5rem;
581
+ --cb-switch-height: 1.5rem;
582
+ --cb-switch-inset: 0.1875rem;
583
+ --cb-switch-thumb: calc(var(--cb-switch-height) - var(--cb-switch-inset) * 2);
584
+ flex: none;
585
+ display: inline-flex;
586
+ align-items: center;
587
+ width: var(--cb-switch-width);
588
+ height: var(--cb-switch-height);
589
+ padding: var(--cb-switch-inset);
590
+ box-sizing: border-box;
591
+ border: none;
592
+ border-radius: var(--cb-radius-full);
593
+ background: color-mix(in oklch, var(--cb-fg) 25%, transparent);
594
+ cursor: pointer;
595
+ transition: background-color var(--cb-duration-base) var(--cb-ease-standard);
596
+ }
597
+ .cb-switch[data-checked] { background: var(--cb-tone-brand); }
598
+ .cb-switch__thumb {
599
+ display: block;
600
+ width: var(--cb-switch-thumb);
601
+ height: var(--cb-switch-thumb);
602
+ border-radius: var(--cb-radius-full);
603
+ background: var(--cb-surface-raised);
604
+ box-shadow: var(--cb-shadow-sm);
605
+ transition: translate var(--cb-duration-base) var(--cb-ease-emphasis);
606
+ }
607
+ .cb-switch[data-checked] .cb-switch__thumb {
608
+ translate: calc(var(--cb-switch-width) - var(--cb-switch-height)) 0;
609
+ }
610
+ /* Reduced motion: the thumb still moves — that is the state — it just stops easing. */
611
+ @media (prefers-reduced-motion: reduce) {
612
+ .cb-switch__thumb { transition: none; }
613
+ }
614
+
615
+ /* form/combobox.css */
616
+ .cb-combobox {
617
+ display: flex;
618
+ align-items: center;
619
+ gap: var(--cb-space-1);
620
+ width: 100%;
621
+ box-sizing: border-box;
622
+ background: var(--cb-surface);
623
+ border: var(--cb-border-width) solid var(--cb-border-strong);
624
+ border-radius: var(--cb-radius-md);
625
+ padding-inline: var(--cb-space-3) var(--cb-space-1);
626
+ transition: border-color var(--cb-duration-fast) var(--cb-ease-standard),
627
+ box-shadow var(--cb-duration-fast) var(--cb-ease-standard);
628
+ }
629
+ .cb-combobox--sm { height: var(--cb-control-height-sm); }
630
+ .cb-combobox--md { height: var(--cb-control-height-md); }
631
+ .cb-combobox--lg { height: var(--cb-control-height-lg); }
632
+ .cb-combobox:focus-within {
633
+ border-color: var(--cb-tone-brand);
634
+ box-shadow: 0 0 0 var(--cb-focus-width) color-mix(in oklch, var(--cb-tone-brand) 30%, transparent);
635
+ }
636
+ .cb-combobox[data-disabled] { opacity: 0.55; }
637
+ .cb-combobox:has(.cb-combobox__input[aria-invalid="true"]) { border-color: var(--cb-tone-danger); }
638
+
639
+ .cb-combobox__input {
640
+ flex: 1;
641
+ min-width: 0;
642
+ border: none;
643
+ background: transparent;
644
+ color: var(--cb-fg);
645
+ font-family: var(--cb-font-sans);
646
+ font-size: var(--cb-text-sm);
647
+ outline: none;
648
+ }
649
+ .cb-combobox__input::placeholder { color: var(--cb-fg-subtle); }
650
+
651
+ .cb-combobox__clear,
652
+ .cb-combobox__trigger {
653
+ flex: none;
654
+ display: inline-flex;
655
+ align-items: center;
656
+ justify-content: center;
657
+ width: 1.75rem;
658
+ height: 1.75rem;
659
+ border: none;
660
+ border-radius: var(--cb-radius-sm);
661
+ background: transparent;
662
+ color: var(--cb-fg-subtle);
663
+ cursor: pointer;
664
+ }
665
+ .cb-combobox__clear:hover,
666
+ .cb-combobox__trigger:hover { color: var(--cb-fg); background: var(--cb-bg-subtle); }
667
+ .cb-combobox__clear:focus-visible,
668
+ .cb-combobox__trigger:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset-inset); }
669
+
670
+ .cb-combobox__popup {
671
+ box-sizing: border-box;
672
+ min-width: var(--anchor-width, 12rem);
673
+ max-height: 18rem;
674
+ overflow-y: auto;
675
+ padding: var(--cb-space-1);
676
+ background: var(--cb-surface-raised);
677
+ border: var(--cb-border-width) solid var(--cb-border);
678
+ border-radius: var(--cb-radius-md);
679
+ box-shadow: var(--cb-shadow-md);
680
+ z-index: var(--cb-z-popover);
681
+ font-family: var(--cb-font-sans);
682
+ transition: opacity var(--cb-duration-fast) var(--cb-ease-entrance);
683
+ }
684
+ .cb-combobox__popup[data-starting-style],
685
+ .cb-combobox__popup[data-ending-style] { opacity: 0; }
686
+
687
+ .cb-combobox__item {
688
+ display: grid;
689
+ grid-template-columns: 1.25rem 1fr;
690
+ align-items: start;
691
+ gap: var(--cb-space-2);
692
+ padding: var(--cb-space-2) var(--cb-space-3);
693
+ min-height: 2.25rem;
694
+ border-radius: var(--cb-radius-sm);
695
+ font-size: var(--cb-text-sm);
696
+ color: var(--cb-fg);
697
+ cursor: pointer;
698
+ outline: none;
699
+ }
700
+ .cb-combobox__item[data-highlighted] { background: color-mix(in oklch, var(--cb-tone-brand) 12%, transparent); }
701
+ .cb-combobox__check { display: inline-flex; justify-content: center; align-items: center; min-height: 1.25rem; color: var(--cb-tone-brand); }
702
+ .cb-combobox__text { display: flex; flex-direction: column; gap: 0.0625rem; min-width: 0; line-height: 1.25rem; }
703
+ .cb-combobox__description { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
704
+ .cb-combobox__empty { padding: var(--cb-space-3); font-size: var(--cb-text-sm); color: var(--cb-fg-subtle); text-align: center; }
705
+
706
+ /* form/date-input.css */
707
+ .cb-date {
708
+ display: flex;
709
+ align-items: center;
710
+ width: 100%;
711
+ box-sizing: border-box;
712
+ background: var(--cb-surface);
713
+ border: var(--cb-border-width) solid var(--cb-border-strong);
714
+ border-radius: var(--cb-radius-md);
715
+ padding-inline: var(--cb-space-3) var(--cb-space-1);
716
+ transition: border-color var(--cb-duration-fast) var(--cb-ease-standard),
717
+ box-shadow var(--cb-duration-fast) var(--cb-ease-standard);
718
+ }
719
+ .cb-date--sm { height: var(--cb-control-height-sm); }
720
+ .cb-date--md { height: var(--cb-control-height-md); }
721
+ .cb-date--lg { height: var(--cb-control-height-lg); }
722
+ .cb-date:focus-within {
723
+ border-color: var(--cb-tone-brand);
724
+ box-shadow: 0 0 0 var(--cb-focus-width) color-mix(in oklch, var(--cb-tone-brand) 30%, transparent);
725
+ }
726
+ .cb-date[data-disabled] { opacity: 0.55; }
727
+ .cb-date:has(.cb-date__input[aria-invalid="true"]) { border-color: var(--cb-tone-danger); }
728
+
729
+ .cb-date__input {
730
+ flex: 1;
731
+ min-width: 0;
732
+ border: none;
733
+ background: transparent;
734
+ color: var(--cb-fg);
735
+ font-family: var(--cb-font-sans);
736
+ font-size: var(--cb-text-sm);
737
+ font-variant-numeric: tabular-nums;
738
+ outline: none;
739
+ }
740
+ .cb-date__input::placeholder { color: var(--cb-fg-subtle); }
741
+ .cb-date__trigger {
742
+ flex: none;
743
+ display: inline-flex;
744
+ align-items: center;
745
+ justify-content: center;
746
+ width: 1.75rem;
747
+ height: 1.75rem;
748
+ border: none;
749
+ border-radius: var(--cb-radius-sm);
750
+ background: transparent;
751
+ color: var(--cb-fg-subtle);
752
+ cursor: pointer;
753
+ }
754
+ .cb-date__trigger:hover { color: var(--cb-fg); background: var(--cb-bg-subtle); }
755
+ .cb-date__trigger:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset-inset); }
756
+
757
+ .cb-calendar {
758
+ padding: var(--cb-space-3);
759
+ background: var(--cb-surface-raised);
760
+ border: var(--cb-border-width) solid var(--cb-border);
761
+ border-radius: var(--cb-radius-md);
762
+ box-shadow: var(--cb-shadow-md);
763
+ font-family: var(--cb-font-sans);
764
+ z-index: var(--cb-z-popover);
765
+ transition: opacity var(--cb-duration-fast) var(--cb-ease-entrance);
766
+ }
767
+ .cb-calendar[data-starting-style],
768
+ .cb-calendar[data-ending-style] { opacity: 0; }
769
+
770
+ .cb-calendar__head { display: flex; align-items: center; justify-content: space-between; gap: var(--cb-space-2); margin-bottom: var(--cb-space-2); }
771
+ .cb-calendar__month { margin: 0; font-size: var(--cb-text-sm); font-weight: var(--cb-weight-medium); color: var(--cb-fg); }
772
+ .cb-calendar__nav {
773
+ display: inline-flex;
774
+ align-items: center;
775
+ justify-content: center;
776
+ width: 1.75rem;
777
+ height: 1.75rem;
778
+ border: none;
779
+ border-radius: var(--cb-radius-sm);
780
+ background: transparent;
781
+ color: var(--cb-fg-muted);
782
+ cursor: pointer;
783
+ }
784
+ .cb-calendar__nav:hover { background: var(--cb-bg-subtle); color: var(--cb-fg); }
785
+ .cb-calendar__nav:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset); }
786
+
787
+ .cb-calendar__grid { border-collapse: collapse; }
788
+ .cb-calendar__grid th {
789
+ font-size: 0.6875rem;
790
+ font-weight: var(--cb-weight-medium);
791
+ color: var(--cb-fg-subtle);
792
+ padding-bottom: var(--cb-space-1);
793
+ }
794
+ .cb-calendar__day {
795
+ width: 2rem;
796
+ height: 2rem;
797
+ border: none;
798
+ border-radius: var(--cb-radius-sm);
799
+ background: transparent;
800
+ color: var(--cb-fg);
801
+ font-family: inherit;
802
+ font-size: var(--cb-text-sm);
803
+ font-variant-numeric: tabular-nums;
804
+ cursor: pointer;
805
+ }
806
+ .cb-calendar__day:hover:not(:disabled) { background: var(--cb-bg-subtle); }
807
+ .cb-calendar__day[data-outside] { color: var(--cb-fg-subtle); }
808
+ .cb-calendar__day[data-today] { box-shadow: inset 0 0 0 1px var(--cb-border-strong); }
809
+ .cb-calendar__day[data-selected] { background: var(--cb-tone-brand); color: var(--cb-fg-on-brand); font-weight: var(--cb-weight-medium); }
810
+ .cb-calendar__day:disabled { opacity: 0.3; cursor: not-allowed; }
811
+ .cb-calendar__day:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset-inset); }
812
+
813
+ .cb-times {
814
+ max-height: 15rem;
815
+ overflow-y: auto;
816
+ padding: var(--cb-space-1);
817
+ background: var(--cb-surface-raised);
818
+ border: var(--cb-border-width) solid var(--cb-border);
819
+ border-radius: var(--cb-radius-md);
820
+ box-shadow: var(--cb-shadow-md);
821
+ z-index: var(--cb-z-popover);
822
+ font-family: var(--cb-font-sans);
823
+ }
824
+ .cb-times__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.125rem; min-width: 7rem; }
825
+ .cb-times__option {
826
+ width: 100%;
827
+ padding: var(--cb-space-2) var(--cb-space-3);
828
+ border: none;
829
+ border-radius: var(--cb-radius-sm);
830
+ background: transparent;
831
+ color: var(--cb-fg);
832
+ font-family: inherit;
833
+ font-size: var(--cb-text-sm);
834
+ font-variant-numeric: tabular-nums;
835
+ text-align: start;
836
+ cursor: pointer;
837
+ }
838
+ .cb-times__option:hover { background: var(--cb-bg-subtle); }
839
+ .cb-times__option[data-selected] { background: color-mix(in oklch, var(--cb-tone-brand) 16%, transparent); color: var(--cb-tone-brand); font-weight: var(--cb-weight-medium); }
840
+ .cb-times__option:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset-inset); }
841
+
842
+ /* form/field.css */
843
+ .cb-field { display: flex; flex-direction: column; gap: var(--cb-space-2); }
844
+ .cb-field__label {
845
+ font-family: var(--cb-font-sans);
846
+ font-size: var(--cb-text-sm);
847
+ font-weight: var(--cb-weight-medium);
848
+ color: var(--cb-fg);
849
+ }
850
+ .cb-field__required { color: var(--cb-tone-danger); margin-inline-start: var(--cb-space-1); }
851
+ .cb-field__hint { margin: 0; font-family: var(--cb-font-sans); font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
852
+ .cb-field__error { margin: 0; font-family: var(--cb-font-sans); font-size: var(--cb-text-xs); color: var(--cb-tone-danger); }
853
+
854
+ .cb-visually-hidden {
855
+ position: absolute;
856
+ width: 1px;
857
+ height: 1px;
858
+ margin: -1px;
859
+ padding: 0;
860
+ overflow: hidden;
861
+ clip-path: inset(50%);
862
+ white-space: nowrap;
863
+ }
864
+
865
+ .cb-input {
866
+ width: 100%;
867
+ box-sizing: border-box;
868
+ background: var(--cb-surface);
869
+ color: var(--cb-fg);
870
+ border: var(--cb-border-width) solid var(--cb-border-strong);
871
+ border-radius: var(--cb-radius-md);
872
+ font-family: var(--cb-font-sans);
873
+ font-size: var(--cb-text-sm);
874
+ padding-inline: var(--cb-space-3);
875
+ transition: border-color var(--cb-duration-fast) var(--cb-ease-standard),
876
+ box-shadow var(--cb-duration-fast) var(--cb-ease-standard);
877
+ }
878
+ .cb-input--sm { height: var(--cb-control-height-sm); }
879
+ .cb-input--md { height: var(--cb-control-height-md); }
880
+ .cb-input--lg { height: var(--cb-control-height-lg); }
881
+ .cb-input--textarea { height: auto; padding-block: var(--cb-space-3); min-height: 6rem; resize: vertical; }
882
+ .cb-input::placeholder { color: var(--cb-fg-subtle); }
883
+ .cb-input:focus-visible {
884
+ outline: none;
885
+ border-color: var(--cb-tone-brand);
886
+ box-shadow: 0 0 0 var(--cb-focus-width) color-mix(in oklch, var(--cb-tone-brand) 30%, transparent);
887
+ }
888
+ .cb-input[aria-invalid="true"] { border-color: var(--cb-tone-danger); }
889
+ .cb-input[aria-invalid="true"]:focus-visible {
890
+ box-shadow: 0 0 0 var(--cb-focus-width) color-mix(in oklch, var(--cb-tone-danger) 30%, transparent);
891
+ }
892
+
893
+ /* form/file-drop.css */
894
+ .cb-filedrop { display: flex; flex-direction: column; gap: var(--cb-space-3); font-family: var(--cb-font-sans); }
895
+ .cb-filedrop__zone {
896
+ cursor: pointer;
897
+ display: flex;
898
+ flex-direction: column;
899
+ align-items: center;
900
+ gap: var(--cb-space-2);
901
+ padding: var(--cb-space-6) var(--cb-space-4);
902
+ border: 1px dashed var(--cb-border-strong);
903
+ border-radius: var(--cb-radius-lg);
904
+ background: var(--cb-surface);
905
+ text-align: center;
906
+ transition: border-color var(--cb-duration-fast) var(--cb-ease-standard),
907
+ background-color var(--cb-duration-fast) var(--cb-ease-standard);
908
+ }
909
+ .cb-filedrop__zone[data-over] {
910
+ border-color: var(--cb-tone-brand);
911
+ background: color-mix(in oklch, var(--cb-tone-brand) 8%, var(--cb-surface));
912
+ }
913
+ .cb-filedrop__zone[data-disabled] { opacity: 0.55; }
914
+ .cb-filedrop__icon { color: var(--cb-fg-subtle); }
915
+ .cb-filedrop__button {
916
+ color: var(--cb-tone-brand);
917
+ font-size: var(--cb-text-sm);
918
+ font-weight: var(--cb-weight-medium);
919
+ border-radius: var(--cb-radius-sm);
920
+ padding: var(--cb-space-1) var(--cb-space-2);
921
+ }
922
+ .cb-filedrop__zone:hover .cb-filedrop__button { background: color-mix(in oklch, var(--cb-tone-brand) 12%, transparent); }
923
+ /* The input is what receives focus, so the ring is drawn on the zone around it. */
924
+ .cb-filedrop__zone:has(input:focus-visible) {
925
+ outline: var(--cb-focus-width) solid var(--cb-tone-brand);
926
+ outline-offset: var(--cb-focus-offset);
927
+ }
928
+ .cb-filedrop__zone[data-disabled] { cursor: not-allowed; }
929
+ .cb-filedrop__hint { margin: 0; font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
930
+
931
+ .cb-filedrop__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--cb-space-2); }
932
+ .cb-filedrop__file {
933
+ margin: 0;
934
+ display: flex;
935
+ align-items: center;
936
+ gap: var(--cb-space-3);
937
+ padding: var(--cb-space-2) var(--cb-space-3);
938
+ border: var(--cb-border-width) solid var(--cb-border);
939
+ border-radius: var(--cb-radius-md);
940
+ background: var(--cb-surface);
941
+ font-size: var(--cb-text-sm);
942
+ }
943
+ .cb-filedrop__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--cb-fg); }
944
+ .cb-filedrop__size { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); font-variant-numeric: tabular-nums; }
945
+ .cb-filedrop__remove {
946
+ border: none;
947
+ background: transparent;
948
+ color: var(--cb-fg-subtle);
949
+ cursor: pointer;
950
+ display: inline-flex;
951
+ padding: var(--cb-space-1);
952
+ border-radius: var(--cb-radius-sm);
953
+ }
954
+ .cb-filedrop__remove:hover { color: var(--cb-tone-danger); background: color-mix(in oklch, var(--cb-tone-danger) 10%, transparent); }
955
+ .cb-filedrop__remove:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-danger); outline-offset: var(--cb-focus-offset); }
956
+
957
+ /* form/number-input.css */
958
+ .cb-number {
959
+ display: inline-flex;
960
+ align-items: center;
961
+ gap: var(--cb-space-1);
962
+ width: 100%;
963
+ box-sizing: border-box;
964
+ background: var(--cb-surface);
965
+ border: var(--cb-border-width) solid var(--cb-border-strong);
966
+ border-radius: var(--cb-radius-md);
967
+ padding-inline: var(--cb-space-3) var(--cb-space-1);
968
+ transition: border-color var(--cb-duration-fast) var(--cb-ease-standard),
969
+ box-shadow var(--cb-duration-fast) var(--cb-ease-standard);
970
+ }
971
+ .cb-number--sm { height: var(--cb-control-height-sm); }
972
+ .cb-number--md { height: var(--cb-control-height-md); }
973
+ .cb-number--lg { height: var(--cb-control-height-lg); }
974
+ .cb-number:focus-within {
975
+ border-color: var(--cb-tone-brand);
976
+ box-shadow: 0 0 0 var(--cb-focus-width) color-mix(in oklch, var(--cb-tone-brand) 30%, transparent);
977
+ }
978
+ .cb-number[data-disabled] { opacity: 0.55; }
979
+ .cb-number:has(.cb-number__input[aria-invalid="true"]) { border-color: var(--cb-tone-danger); }
980
+
981
+ .cb-number__input {
982
+ flex: 1;
983
+ min-width: 0;
984
+ border: none;
985
+ background: transparent;
986
+ color: var(--cb-fg);
987
+ font-family: var(--cb-font-sans);
988
+ font-size: var(--cb-text-sm);
989
+ font-variant-numeric: tabular-nums;
990
+ outline: none;
991
+ }
992
+ .cb-number__suffix { font-family: var(--cb-font-sans); font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
993
+
994
+ .cb-number__steppers { display: inline-flex; flex: none; gap: 0.125rem; }
995
+
996
+ .cb-number__step {
997
+ flex: none;
998
+ display: inline-flex;
999
+ align-items: center;
1000
+ justify-content: center;
1001
+ width: 1.75rem;
1002
+ height: 1.75rem;
1003
+ border: none;
1004
+ border-radius: var(--cb-radius-sm);
1005
+ background: transparent;
1006
+ color: var(--cb-fg-muted);
1007
+ cursor: pointer;
1008
+ transition: background-color var(--cb-duration-fast) var(--cb-ease-standard);
1009
+ }
1010
+ .cb-number__step:hover:not(:disabled) { background: var(--cb-bg-subtle); color: var(--cb-fg); }
1011
+ .cb-number__step:disabled { opacity: 0.35; cursor: not-allowed; }
1012
+ .cb-number__step:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset-inset); }
1013
+
1014
+ /* form/select.css */
1015
+ .cb-select {
1016
+ display: inline-flex;
1017
+ align-items: center;
1018
+ justify-content: space-between;
1019
+ gap: var(--cb-space-2);
1020
+ width: 100%;
1021
+ box-sizing: border-box;
1022
+ background: var(--cb-surface);
1023
+ color: var(--cb-fg);
1024
+ border: var(--cb-border-width) solid var(--cb-border-strong);
1025
+ border-radius: var(--cb-radius-md);
1026
+ font-family: var(--cb-font-sans);
1027
+ font-size: var(--cb-text-sm);
1028
+ padding-inline: var(--cb-space-3);
1029
+ cursor: pointer;
1030
+ text-align: start;
1031
+ transition: border-color var(--cb-duration-fast) var(--cb-ease-standard),
1032
+ box-shadow var(--cb-duration-fast) var(--cb-ease-standard);
1033
+ }
1034
+ .cb-select--sm { height: var(--cb-control-height-sm); }
1035
+ .cb-select--md { height: var(--cb-control-height-md); }
1036
+ .cb-select--lg { height: var(--cb-control-height-lg); }
1037
+ .cb-select:hover:not(:disabled) { border-color: var(--cb-fg-subtle); }
1038
+ .cb-select:focus-visible {
1039
+ outline: none;
1040
+ border-color: var(--cb-tone-brand);
1041
+ box-shadow: 0 0 0 var(--cb-focus-width) color-mix(in oklch, var(--cb-tone-brand) 30%, transparent);
1042
+ }
1043
+ .cb-select[aria-invalid="true"] { border-color: var(--cb-tone-danger); }
1044
+ .cb-select[data-disabled] { opacity: 0.55; cursor: not-allowed; }
1045
+ .cb-select__icon { display: inline-flex; color: var(--cb-fg-subtle); }
1046
+
1047
+ .cb-select__popup {
1048
+ box-sizing: border-box;
1049
+ min-width: var(--anchor-width, 10rem);
1050
+ max-height: 18rem;
1051
+ overflow-y: auto;
1052
+ background: var(--cb-surface-raised);
1053
+ border: var(--cb-border-width) solid var(--cb-border);
1054
+ border-radius: var(--cb-radius-md);
1055
+ box-shadow: var(--cb-shadow-md);
1056
+ padding: var(--cb-space-1);
1057
+ z-index: var(--cb-z-popover);
1058
+ font-family: var(--cb-font-sans);
1059
+ font-size: var(--cb-text-sm);
1060
+ transition: opacity var(--cb-duration-fast) var(--cb-ease-entrance),
1061
+ transform var(--cb-duration-fast) var(--cb-ease-entrance);
1062
+ }
1063
+ .cb-select__popup[data-starting-style],
1064
+ .cb-select__popup[data-ending-style] { opacity: 0; transform: scale(0.98); }
1065
+ @media (prefers-reduced-motion: reduce) {
1066
+ .cb-select__popup { transition: opacity var(--cb-duration-fast) linear; }
1067
+ .cb-select__popup[data-starting-style],
1068
+ .cb-select__popup[data-ending-style] { transform: none; }
1069
+ }
1070
+
1071
+ .cb-select__item {
1072
+ display: grid;
1073
+ grid-template-columns: 1.25rem 1fr;
1074
+ align-items: center;
1075
+ gap: var(--cb-space-2);
1076
+ padding: var(--cb-space-2) var(--cb-space-2);
1077
+ border-radius: var(--cb-radius-sm);
1078
+ cursor: pointer;
1079
+ outline: none;
1080
+ color: var(--cb-fg);
1081
+ }
1082
+ .cb-select__item[data-highlighted] { background: color-mix(in oklch, var(--cb-tone-brand) 12%, transparent); }
1083
+ .cb-select__item[data-selected] { font-weight: var(--cb-weight-medium); }
1084
+ .cb-select__item[data-disabled] { color: var(--cb-fg-subtle); text-decoration: line-through; cursor: not-allowed; }
1085
+ .cb-select__check { display: inline-flex; justify-content: center; color: var(--cb-tone-brand); }
1086
+
1087
+ /* feedback/badge.css */
1088
+ .cb-badge {
1089
+ --cb-badge-accent: var(--cb-fg-muted);
1090
+ display: inline-flex;
1091
+ align-items: center;
1092
+ gap: var(--cb-space-1);
1093
+ border-radius: var(--cb-radius-full);
1094
+ font-family: var(--cb-font-sans);
1095
+ font-weight: var(--cb-weight-medium);
1096
+ white-space: nowrap;
1097
+ border: var(--cb-border-width) solid transparent;
1098
+ }
1099
+ .cb-badge--sm { font-size: 0.6875rem; padding: 0.0625rem var(--cb-space-2); }
1100
+ .cb-badge--md { font-size: var(--cb-text-xs); padding: var(--cb-space-1) var(--cb-space-3); }
1101
+
1102
+ .cb-badge[data-tone="brand"] { --cb-badge-accent: var(--cb-tone-brand); }
1103
+ .cb-badge[data-tone="info"] { --cb-badge-accent: var(--cb-tone-info); }
1104
+ .cb-badge[data-tone="success"] { --cb-badge-accent: var(--cb-tone-success); }
1105
+ .cb-badge[data-tone="warning"] { --cb-badge-accent: var(--cb-tone-warning); }
1106
+ .cb-badge[data-tone="danger"] { --cb-badge-accent: var(--cb-tone-danger); }
1107
+
1108
+ .cb-badge--soft { background: color-mix(in oklch, var(--cb-badge-accent) 14%, transparent); color: var(--cb-badge-accent); }
1109
+ .cb-badge--solid { background: var(--cb-badge-accent); color: var(--cb-fg-on-brand); }
1110
+ .cb-badge--outline { border-color: color-mix(in oklch, var(--cb-badge-accent) 45%, transparent); color: var(--cb-badge-accent); }
1111
+ .cb-badge__dot { width: 0.375rem; height: 0.375rem; border-radius: var(--cb-radius-full); background: currentColor; }
1112
+
1113
+ .cb-alert {
1114
+ --cb-alert-accent: var(--cb-tone-info);
1115
+ display: flex;
1116
+ gap: var(--cb-space-3);
1117
+ padding: var(--cb-space-4);
1118
+ border-radius: var(--cb-radius-md);
1119
+ border: var(--cb-border-width) solid color-mix(in oklch, var(--cb-alert-accent) 30%, transparent);
1120
+ background: color-mix(in oklch, var(--cb-alert-accent) 9%, var(--cb-surface));
1121
+ font-family: var(--cb-font-sans);
1122
+ }
1123
+ .cb-alert[data-tone="neutral"] { --cb-alert-accent: var(--cb-fg-muted); }
1124
+ .cb-alert[data-tone="brand"] { --cb-alert-accent: var(--cb-tone-brand); }
1125
+ .cb-alert[data-tone="success"] { --cb-alert-accent: var(--cb-tone-success); }
1126
+ .cb-alert[data-tone="warning"] { --cb-alert-accent: var(--cb-tone-warning); }
1127
+ .cb-alert[data-tone="danger"] { --cb-alert-accent: var(--cb-tone-danger); }
1128
+
1129
+ .cb-alert__icon { flex: none; color: var(--cb-alert-accent); display: inline-flex; margin-top: 0.0625rem; }
1130
+ .cb-alert__body { flex: 1; display: flex; flex-direction: column; gap: var(--cb-space-1); min-width: 0; }
1131
+ .cb-alert__title { margin: 0; font-size: var(--cb-text-sm); font-weight: var(--cb-weight-semibold); color: var(--cb-fg); }
1132
+ .cb-alert__text { font-size: var(--cb-text-sm); color: var(--cb-fg-muted); line-height: var(--cb-leading-normal); }
1133
+ .cb-alert__actions { display: flex; gap: var(--cb-space-2); margin-top: var(--cb-space-2); }
1134
+ .cb-alert__close {
1135
+ flex: none; border: none; background: transparent; color: var(--cb-fg-subtle);
1136
+ cursor: pointer; border-radius: var(--cb-radius-sm); padding: var(--cb-space-1); height: fit-content;
1137
+ }
1138
+ .cb-alert__close:hover { color: var(--cb-fg); background: color-mix(in oklch, var(--cb-fg) 8%, transparent); }
1139
+ .cb-alert__close:focus-visible { outline: var(--cb-focus-width) solid var(--cb-alert-accent); outline-offset: var(--cb-focus-offset); }
1140
+
1141
+ .cb-empty {
1142
+ display: flex;
1143
+ flex-direction: column;
1144
+ align-items: center;
1145
+ text-align: center;
1146
+ gap: var(--cb-space-2);
1147
+ padding: var(--cb-space-7) var(--cb-space-5);
1148
+ font-family: var(--cb-font-sans);
1149
+ }
1150
+ .cb-empty__icon {
1151
+ display: inline-flex;
1152
+ align-items: center;
1153
+ justify-content: center;
1154
+ width: 3rem;
1155
+ height: 3rem;
1156
+ border-radius: var(--cb-radius-full);
1157
+ background: var(--cb-bg-subtle);
1158
+ color: var(--cb-fg-subtle);
1159
+ margin-bottom: var(--cb-space-2);
1160
+ }
1161
+ .cb-empty[data-variant="error"] .cb-empty__icon {
1162
+ background: color-mix(in oklch, var(--cb-tone-danger) 12%, transparent);
1163
+ color: var(--cb-tone-danger);
1164
+ }
1165
+ .cb-empty__title { margin: 0; font-size: var(--cb-text-md); font-weight: var(--cb-weight-semibold); color: var(--cb-fg); }
1166
+ .cb-empty__description { margin: 0; font-size: var(--cb-text-sm); color: var(--cb-fg-muted); max-width: 32rem; }
1167
+ .cb-empty__actions { display: flex; gap: var(--cb-space-2); margin-top: var(--cb-space-3); }
1168
+
1169
+ /* feedback/progress.css */
1170
+ .cb-spinner {
1171
+ --cb-spinner-accent: var(--cb-tone-brand);
1172
+ display: inline-block;
1173
+ border-radius: var(--cb-radius-full);
1174
+ border: 2px solid color-mix(in oklch, var(--cb-spinner-accent) 25%, transparent);
1175
+ border-top-color: var(--cb-spinner-accent);
1176
+ animation: cb-spin calc(var(--cb-duration-deliberate) * 1.4) linear infinite;
1177
+ }
1178
+ .cb-spinner[data-tone="neutral"] { --cb-spinner-accent: var(--cb-fg-muted); }
1179
+ .cb-spinner[data-tone="info"] { --cb-spinner-accent: var(--cb-tone-info); }
1180
+ .cb-spinner[data-tone="success"] { --cb-spinner-accent: var(--cb-tone-success); }
1181
+ .cb-spinner[data-tone="warning"] { --cb-spinner-accent: var(--cb-tone-warning); }
1182
+ .cb-spinner[data-tone="danger"] { --cb-spinner-accent: var(--cb-tone-danger); }
1183
+ .cb-spinner--sm { width: 0.875rem; height: 0.875rem; }
1184
+ .cb-spinner--md { width: 1.25rem; height: 1.25rem; border-width: 2px; }
1185
+ .cb-spinner--lg { width: 2rem; height: 2rem; border-width: 3px; }
1186
+ /* Reduced motion: it stops turning and reads as a ring — the surrounding text says "loading". */
1187
+ @media (prefers-reduced-motion: reduce) {
1188
+ .cb-spinner { animation: none; opacity: 0.6; }
1189
+ }
1190
+
1191
+ .cb-progress {
1192
+ --cb-progress-accent: var(--cb-tone-brand);
1193
+ display: flex;
1194
+ align-items: center;
1195
+ gap: var(--cb-space-3);
1196
+ width: 100%;
1197
+ font-family: var(--cb-font-sans);
1198
+ }
1199
+ .cb-progress[data-tone="neutral"] { --cb-progress-accent: var(--cb-fg-muted); }
1200
+ .cb-progress[data-tone="info"] { --cb-progress-accent: var(--cb-tone-info); }
1201
+ .cb-progress[data-tone="success"] { --cb-progress-accent: var(--cb-tone-success); }
1202
+ .cb-progress[data-tone="warning"] { --cb-progress-accent: var(--cb-tone-warning); }
1203
+ .cb-progress[data-tone="danger"] { --cb-progress-accent: var(--cb-tone-danger); }
1204
+
1205
+ .cb-progress__track {
1206
+ flex: 1;
1207
+ overflow: hidden;
1208
+ border-radius: var(--cb-radius-full);
1209
+ background: color-mix(in oklch, var(--cb-fg) 10%, transparent);
1210
+ }
1211
+ .cb-progress[data-size="sm"] .cb-progress__track { height: 0.25rem; }
1212
+ .cb-progress[data-size="md"] .cb-progress__track { height: 0.5rem; }
1213
+
1214
+ .cb-progress__fill {
1215
+ height: 100%;
1216
+ border-radius: inherit;
1217
+ background: var(--cb-progress-accent);
1218
+ transition: width var(--cb-duration-base) var(--cb-ease-standard);
1219
+ }
1220
+ .cb-progress__fill[data-indeterminate] {
1221
+ width: 40%;
1222
+ animation: cb-progress-slide calc(var(--cb-duration-deliberate) * 2) var(--cb-ease-standard) infinite;
1223
+ }
1224
+ @keyframes cb-progress-slide {
1225
+ 0% { transform: translateX(-100%); }
1226
+ 100% { transform: translateX(250%); }
1227
+ }
1228
+ /* Reduced motion: an indeterminate bar sits still at partial width rather than sliding forever. */
1229
+ @media (prefers-reduced-motion: reduce) {
1230
+ .cb-progress__fill { transition: none; }
1231
+ .cb-progress__fill[data-indeterminate] { animation: none; width: 100%; opacity: 0.4; }
1232
+ }
1233
+
1234
+ .cb-progress__value {
1235
+ font-size: var(--cb-text-xs);
1236
+ color: var(--cb-fg-muted);
1237
+ font-variant-numeric: tabular-nums;
1238
+ min-width: 2.5rem;
1239
+ text-align: end;
1240
+ }
1241
+
1242
+ /* feedback/skeleton.css */
1243
+ .cb-skeleton {
1244
+ display: block;
1245
+ width: var(--cb-skeleton-w);
1246
+ height: var(--cb-skeleton-h);
1247
+ position: relative;
1248
+ overflow: hidden;
1249
+ background: color-mix(in oklch, var(--cb-fg) 8%, var(--cb-surface));
1250
+ }
1251
+ .cb-skeleton::after {
1252
+ content: "";
1253
+ position: absolute;
1254
+ inset: 0;
1255
+ transform: translateX(-100%);
1256
+ background: linear-gradient(
1257
+ 90deg,
1258
+ transparent,
1259
+ color-mix(in oklch, var(--cb-fg) 6%, transparent),
1260
+ transparent
1261
+ );
1262
+ animation: cb-skeleton-sweep calc(var(--cb-duration-deliberate) * 2) var(--cb-ease-standard) infinite;
1263
+ }
1264
+ @keyframes cb-skeleton-sweep {
1265
+ 100% { transform: translateX(100%); }
1266
+ }
1267
+
1268
+ /* Reduced motion keeps the shape and drops the sweep — the placeholder still reads as loading. */
1269
+ @media (prefers-reduced-motion: reduce) {
1270
+ .cb-skeleton::after { animation: none; }
1271
+ }
1272
+
1273
+ .cb-skeleton-text { display: flex; flex-direction: column; gap: var(--cb-space-2); }
1274
+
1275
+ /* feedback/toast.css */
1276
+ .cb-toast__viewport {
1277
+ position: fixed;
1278
+ z-index: var(--cb-z-toast);
1279
+ display: flex;
1280
+ flex-direction: column;
1281
+ gap: var(--cb-space-2);
1282
+ width: min(22rem, calc(100vw - var(--cb-space-6)));
1283
+ }
1284
+ .cb-toast__viewport[data-position^="bottom"] { inset-block-end: var(--cb-space-4); }
1285
+ .cb-toast__viewport[data-position^="top"] { inset-block-start: var(--cb-space-4); }
1286
+ .cb-toast__viewport[data-position$="end"] { inset-inline-end: var(--cb-space-4); }
1287
+ .cb-toast__viewport[data-position$="start"] { inset-inline-start: var(--cb-space-4); }
1288
+ .cb-toast__viewport[data-position$="center"] { inset-inline-start: 50%; translate: -50% 0; }
1289
+ /* A stack at the top should enter from above, not slide up from below. */
1290
+ .cb-toast__viewport[data-position^="top"] .cb-toast[data-starting-style],
1291
+ .cb-toast__viewport[data-position^="top"] .cb-toast[data-ending-style] { transform: translateY(-8px); }
1292
+
1293
+ .cb-toast {
1294
+ --cb-toast-accent: var(--cb-tone-info);
1295
+ display: grid;
1296
+ grid-template-columns: auto minmax(0, 1fr) auto;
1297
+ grid-template-areas:
1298
+ "icon content close"
1299
+ ". action .";
1300
+ align-items: start;
1301
+ column-gap: var(--cb-space-3);
1302
+ row-gap: var(--cb-space-2);
1303
+ box-sizing: border-box;
1304
+ width: 100%;
1305
+ padding: var(--cb-space-3) var(--cb-space-4);
1306
+ border-radius: var(--cb-radius-md);
1307
+ border: var(--cb-border-width) solid var(--cb-border);
1308
+ background: var(--cb-surface-raised);
1309
+ box-shadow: var(--cb-shadow-md);
1310
+ font-family: var(--cb-font-sans);
1311
+ transition: opacity var(--cb-duration-base) var(--cb-ease-entrance),
1312
+ transform var(--cb-duration-base) var(--cb-ease-entrance);
1313
+ }
1314
+ .cb-toast[data-tone="success"] { --cb-toast-accent: var(--cb-tone-success); }
1315
+ .cb-toast[data-tone="warning"] { --cb-toast-accent: var(--cb-tone-warning); }
1316
+ .cb-toast[data-tone="danger"] { --cb-toast-accent: var(--cb-tone-danger); }
1317
+ .cb-toast[data-starting-style],
1318
+ .cb-toast[data-ending-style] { opacity: 0; transform: translateY(8px); }
1319
+ @media (prefers-reduced-motion: reduce) {
1320
+ .cb-toast { transition: opacity var(--cb-duration-fast) linear; }
1321
+ .cb-toast[data-starting-style],
1322
+ .cb-toast[data-ending-style] { transform: none; }
1323
+ }
1324
+
1325
+ .cb-toast__icon { grid-area: icon; color: var(--cb-toast-accent); display: inline-flex; margin-top: 0.125rem; }
1326
+ .cb-toast__content { grid-area: content; display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
1327
+ /* Base UI renders these as <h2> and <p>, which inherit the host app's heading and paragraph
1328
+ margins — without this reset a two-line toast is twice as tall in one app as in another. */
1329
+ .cb-toast__title { margin: 0; font-size: var(--cb-text-sm); font-weight: var(--cb-weight-semibold); color: var(--cb-fg); }
1330
+ .cb-toast__description { margin: 0; font-size: var(--cb-text-sm); color: var(--cb-fg-muted); }
1331
+ /* A bare text action reads as misaligned until it is hovered: its padding pushes the label off
1332
+ the line the title sits on, and nothing explains the gap. Carrying the soft Button treatment
1333
+ at rest makes the padding part of a control instead of stray space. */
1334
+ .cb-toast__action {
1335
+ grid-area: action;
1336
+ justify-self: start;
1337
+ display: inline-flex;
1338
+ align-items: center;
1339
+ height: var(--cb-control-height-sm);
1340
+ padding-inline: var(--cb-space-3);
1341
+ border: none;
1342
+ border-radius: var(--cb-radius-md);
1343
+ background: color-mix(in oklch, var(--cb-toast-accent) 16%, transparent);
1344
+ color: var(--cb-toast-accent);
1345
+ font-family: var(--cb-font-sans);
1346
+ font-size: var(--cb-text-sm);
1347
+ font-weight: var(--cb-weight-medium);
1348
+ cursor: pointer;
1349
+ transition: background-color var(--cb-duration-fast) var(--cb-ease-standard);
1350
+ }
1351
+ .cb-toast__action:hover { background: color-mix(in oklch, var(--cb-toast-accent) 26%, transparent); }
1352
+ /* An action-less toast must not reserve the row it would have sat in. */
1353
+ .cb-toast:not(:has(.cb-toast__action)) { grid-template-areas: "icon content close"; }
1354
+ .cb-toast__close {
1355
+ grid-area: close;
1356
+ border: none;
1357
+ background: transparent;
1358
+ color: var(--cb-fg-subtle);
1359
+ cursor: pointer;
1360
+ padding: var(--cb-space-1);
1361
+ border-radius: var(--cb-radius-sm);
1362
+ }
1363
+ .cb-toast__close:hover { color: var(--cb-fg); }
1364
+ .cb-toast__close:focus-visible,
1365
+ .cb-toast__action:focus-visible { outline: var(--cb-focus-width) solid var(--cb-toast-accent); outline-offset: var(--cb-focus-offset); }
1366
+
1367
+ /* overlay/command-palette.css */
1368
+ .cb-palette {
1369
+ position: fixed;
1370
+ top: 12vh;
1371
+ left: 50%;
1372
+ translate: -50% 0;
1373
+ z-index: calc(var(--cb-z-overlay) + 1);
1374
+ display: flex;
1375
+ flex-direction: column;
1376
+ width: min(34rem, calc(100vw - var(--cb-space-6)));
1377
+ max-height: 60vh;
1378
+ box-sizing: border-box;
1379
+ background: var(--cb-surface-raised);
1380
+ border: var(--cb-border-width) solid var(--cb-border);
1381
+ border-radius: var(--cb-radius-lg);
1382
+ box-shadow: var(--cb-shadow-lg);
1383
+ overflow: hidden;
1384
+ font-family: var(--cb-font-sans);
1385
+ transition: opacity var(--cb-duration-base) var(--cb-ease-entrance),
1386
+ translate var(--cb-duration-base) var(--cb-ease-entrance);
1387
+ }
1388
+ .cb-palette[data-starting-style],
1389
+ .cb-palette[data-ending-style] { opacity: 0; translate: -50% -0.5rem; }
1390
+ @media (prefers-reduced-motion: reduce) {
1391
+ .cb-palette { transition: opacity var(--cb-duration-fast) linear; }
1392
+ .cb-palette[data-starting-style],
1393
+ .cb-palette[data-ending-style] { translate: -50% 0; }
1394
+ }
1395
+
1396
+ .cb-palette__search {
1397
+ display: flex;
1398
+ align-items: center;
1399
+ gap: var(--cb-space-3);
1400
+ padding: var(--cb-space-4);
1401
+ border-bottom: var(--cb-border-width) solid var(--cb-border);
1402
+ }
1403
+ .cb-palette__search-icon { color: var(--cb-fg-subtle); flex: none; }
1404
+ .cb-palette__input {
1405
+ flex: 1;
1406
+ border: none;
1407
+ background: transparent;
1408
+ color: var(--cb-fg);
1409
+ font-family: inherit;
1410
+ font-size: var(--cb-text-md);
1411
+ outline: none;
1412
+ }
1413
+ .cb-palette__input::placeholder { color: var(--cb-fg-subtle); }
1414
+
1415
+ .cb-palette__list { overflow-y: auto; padding: var(--cb-space-2); }
1416
+ .cb-palette__group + .cb-palette__group { margin-top: var(--cb-space-2); }
1417
+ .cb-palette__group-label {
1418
+ margin: 0 0 var(--cb-space-1);
1419
+ padding-inline: var(--cb-space-2);
1420
+ font-size: 0.6875rem;
1421
+ text-transform: uppercase;
1422
+ letter-spacing: 0.08em;
1423
+ color: var(--cb-fg-subtle);
1424
+ }
1425
+ .cb-palette__item {
1426
+ display: flex;
1427
+ align-items: center;
1428
+ gap: var(--cb-space-3);
1429
+ padding: var(--cb-space-2) var(--cb-space-3);
1430
+ border-radius: var(--cb-radius-sm);
1431
+ font-size: var(--cb-text-sm);
1432
+ color: var(--cb-fg);
1433
+ cursor: pointer;
1434
+ }
1435
+ .cb-palette__item[data-active] { background: color-mix(in oklch, var(--cb-tone-brand) 12%, transparent); }
1436
+ .cb-palette__icon { display: inline-flex; color: var(--cb-fg-subtle); width: 1.25rem; justify-content: center; }
1437
+ .cb-palette__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1438
+ .cb-palette__shortcut { margin: 0; padding: 0; border: none; background: none; font-family: var(--cb-font-mono); font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
1439
+ .cb-palette__empty { margin: 0; padding: var(--cb-space-5); text-align: center; font-size: var(--cb-text-sm); color: var(--cb-fg-subtle); }
1440
+
1441
+ /* overlay/dialog.css */
1442
+ .cb-dialog__backdrop {
1443
+ position: fixed;
1444
+ inset: 0;
1445
+ z-index: var(--cb-z-overlay);
1446
+ background: var(--cb-scrim);
1447
+ backdrop-filter: blur(2px);
1448
+ transition: opacity var(--cb-duration-base) var(--cb-ease-standard);
1449
+ }
1450
+ .cb-dialog__backdrop[data-starting-style],
1451
+ .cb-dialog__backdrop[data-ending-style] { opacity: 0; }
1452
+
1453
+ .cb-dialog {
1454
+ position: fixed;
1455
+ z-index: calc(var(--cb-z-overlay) + 1);
1456
+ display: flex;
1457
+ flex-direction: column;
1458
+ gap: var(--cb-space-3);
1459
+ box-sizing: border-box;
1460
+ background: var(--cb-surface-raised);
1461
+ color: var(--cb-fg);
1462
+ border: var(--cb-border-width) solid var(--cb-border);
1463
+ border-radius: var(--cb-radius-lg);
1464
+ box-shadow: var(--cb-shadow-lg);
1465
+ padding: var(--cb-space-5);
1466
+ width: calc(100vw - var(--cb-space-6));
1467
+ transition: opacity var(--cb-duration-base) var(--cb-ease-entrance),
1468
+ transform var(--cb-duration-base) var(--cb-ease-entrance);
1469
+ }
1470
+ .cb-dialog--sm { max-width: 24rem; }
1471
+ .cb-dialog--md { max-width: 32rem; }
1472
+ .cb-dialog--lg { max-width: 46rem; }
1473
+
1474
+ .cb-dialog--center { top: 50%; left: 50%; transform: translate(-50%, -50%) scale(1); }
1475
+ .cb-dialog--center[data-starting-style],
1476
+ .cb-dialog--center[data-ending-style] { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
1477
+
1478
+ .cb-dialog--end { inset-inline-end: var(--cb-space-4); inset-block-end: var(--cb-space-4); transform: translateY(0); }
1479
+ .cb-dialog--end[data-starting-style],
1480
+ .cb-dialog--end[data-ending-style] { opacity: 0; transform: translateY(12px); }
1481
+
1482
+ /* Reduced motion: the dialog still fades so its arrival is not invisible, but it stops moving. */
1483
+ @media (prefers-reduced-motion: reduce) {
1484
+ .cb-dialog { transition: opacity var(--cb-duration-fast) linear; }
1485
+ .cb-dialog--center[data-starting-style],
1486
+ .cb-dialog--center[data-ending-style] { transform: translate(-50%, -50%) scale(1); }
1487
+ .cb-dialog--end[data-starting-style],
1488
+ .cb-dialog--end[data-ending-style] { transform: translateY(0); }
1489
+ }
1490
+
1491
+ .cb-dialog__title { margin: 0; font-family: var(--cb-font-sans); font-size: var(--cb-text-lg); font-weight: var(--cb-weight-semibold); }
1492
+ .cb-dialog__description { margin: 0; font-family: var(--cb-font-sans); font-size: var(--cb-text-sm); color: var(--cb-fg-muted); }
1493
+ .cb-dialog__body { font-family: var(--cb-font-sans); font-size: var(--cb-text-sm); }
1494
+ .cb-dialog__footer { display: flex; justify-content: flex-end; gap: var(--cb-space-2); margin-top: var(--cb-space-2); }
1495
+
1496
+ /* overlay/popover.css */
1497
+ .cb-popover {
1498
+ box-sizing: border-box;
1499
+ max-width: 22rem;
1500
+ background: var(--cb-surface-raised);
1501
+ color: var(--cb-fg);
1502
+ border: var(--cb-border-width) solid var(--cb-border);
1503
+ border-radius: var(--cb-radius-md);
1504
+ box-shadow: var(--cb-shadow-md);
1505
+ padding: var(--cb-space-4);
1506
+ font-family: var(--cb-font-sans);
1507
+ font-size: var(--cb-text-sm);
1508
+ z-index: var(--cb-z-popover);
1509
+ transition: opacity var(--cb-duration-fast) var(--cb-ease-entrance),
1510
+ transform var(--cb-duration-fast) var(--cb-ease-entrance);
1511
+ }
1512
+ .cb-popover[data-starting-style],
1513
+ .cb-popover[data-ending-style] { opacity: 0; transform: scale(0.96); }
1514
+ @media (prefers-reduced-motion: reduce) {
1515
+ .cb-popover { transition: opacity var(--cb-duration-fast) linear; }
1516
+ .cb-popover[data-starting-style],
1517
+ .cb-popover[data-ending-style] { transform: none; }
1518
+ }
1519
+
1520
+ /* The tail is a square straddling the popup's edge, rotated 45deg, with a border on only the
1521
+ two edges that end up facing outward. Its own fill covers the popup's border underneath, so
1522
+ the outline runs from bubble into tail without a line across the join — which is what the
1523
+ clip-a-diamond-in-half version could never do: the popup border still crossed its base. */
1524
+ .cb-popover__arrow {
1525
+ position: absolute;
1526
+ width: 18px;
1527
+ height: 9px;
1528
+ pointer-events: none;
1529
+ }
1530
+ .cb-popover__arrow[data-side="bottom"] { top: 0; }
1531
+ .cb-popover__arrow[data-side="top"] { bottom: 0; rotate: 180deg; }
1532
+ .cb-popover__arrow[data-side="left"] { right: 0; rotate: 90deg; }
1533
+ .cb-popover__arrow[data-side="right"] { left: 0; rotate: -90deg; }
1534
+
1535
+ .cb-arrow {
1536
+ position: absolute;
1537
+ left: 50%;
1538
+ top: 0;
1539
+ width: 12px;
1540
+ height: 12px;
1541
+ translate: -50% -50%;
1542
+ rotate: 45deg;
1543
+ background: var(--cb-surface-raised);
1544
+ border-top: var(--cb-border-width) solid var(--cb-border);
1545
+ border-left: var(--cb-border-width) solid var(--cb-border);
1546
+ border-start-start-radius: 3px;
1547
+ }
1548
+
1549
+ .cb-tooltip {
1550
+ background: var(--cb-fg);
1551
+ color: var(--cb-bg);
1552
+ font-family: var(--cb-font-sans);
1553
+ font-size: var(--cb-text-xs);
1554
+ padding: var(--cb-space-1) var(--cb-space-2);
1555
+ border-radius: var(--cb-radius-sm);
1556
+ z-index: var(--cb-z-popover);
1557
+ transition: opacity var(--cb-duration-fast) var(--cb-ease-standard);
1558
+ }
1559
+ .cb-tooltip[data-starting-style],
1560
+ .cb-tooltip[data-ending-style] { opacity: 0; }
1561
+
1562
+ /* data/donut.css */
1563
+ .cb-donut { position: relative; display: inline-grid; place-items: center; }
1564
+ .cb-donut svg { position: absolute; inset: 0; }
1565
+ .cb-donut__track { stroke: color-mix(in oklch, var(--cb-fg) 8%, transparent); }
1566
+ .cb-donut__arc { transition: stroke-dasharray var(--cb-duration-deliberate) var(--cb-ease-entrance); }
1567
+ /* Reduced motion: the arcs are drawn at their final length rather than growing into place. */
1568
+ @media (prefers-reduced-motion: reduce) {
1569
+ .cb-donut__arc { transition: none; }
1570
+ }
1571
+ .cb-donut__arc[data-hue="violet"] { stroke: var(--cb-decor-violet); }
1572
+ .cb-donut__arc[data-hue="blue"] { stroke: var(--cb-decor-blue); }
1573
+ .cb-donut__arc[data-hue="teal"] { stroke: var(--cb-decor-teal); }
1574
+ .cb-donut__arc[data-hue="green"] { stroke: var(--cb-decor-green); }
1575
+ .cb-donut__arc[data-hue="amber"] { stroke: var(--cb-decor-amber); }
1576
+ .cb-donut__arc[data-hue="rose"] { stroke: var(--cb-decor-rose); }
1577
+ .cb-donut__center {
1578
+ font-family: var(--cb-font-sans);
1579
+ font-variant-numeric: tabular-nums;
1580
+ text-align: center;
1581
+ color: var(--cb-fg);
1582
+ z-index: 1;
1583
+ }
1584
+
1585
+ .cb-sparkline { --cb-spark-accent: var(--cb-tone-brand); display: inline-flex; }
1586
+ .cb-sparkline[data-tone="neutral"] { --cb-spark-accent: var(--cb-fg-muted); }
1587
+ .cb-sparkline[data-tone="info"] { --cb-spark-accent: var(--cb-tone-info); }
1588
+ .cb-sparkline[data-tone="success"] { --cb-spark-accent: var(--cb-tone-success); }
1589
+ .cb-sparkline[data-tone="warning"] { --cb-spark-accent: var(--cb-tone-warning); }
1590
+ .cb-sparkline[data-tone="danger"] { --cb-spark-accent: var(--cb-tone-danger); }
1591
+ .cb-sparkline[data-hue="violet"] { --cb-spark-accent: var(--cb-decor-violet); }
1592
+ .cb-sparkline[data-hue="blue"] { --cb-spark-accent: var(--cb-decor-blue); }
1593
+ .cb-sparkline[data-hue="teal"] { --cb-spark-accent: var(--cb-decor-teal); }
1594
+ .cb-sparkline[data-hue="green"] { --cb-spark-accent: var(--cb-decor-green); }
1595
+ .cb-sparkline[data-hue="amber"] { --cb-spark-accent: var(--cb-decor-amber); }
1596
+ .cb-sparkline[data-hue="rose"] { --cb-spark-accent: var(--cb-decor-rose); }
1597
+
1598
+ .cb-sparkline__line { stroke: var(--cb-spark-accent); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
1599
+ .cb-sparkline__area { fill: color-mix(in oklch, var(--cb-spark-accent) 16%, transparent); }
1600
+ .cb-sparkline__last { fill: var(--cb-spark-accent); }
1601
+ .cb-sparkline__bar { fill: color-mix(in oklch, var(--cb-spark-accent) 70%, transparent); }
1602
+
1603
+ /* data/leaderboard.css */
1604
+ .cb-leaderboard { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--cb-space-1); font-family: var(--cb-font-sans); }
1605
+ .cb-leaderboard__row {
1606
+ margin: 0;
1607
+ --cb-rank-accent: transparent;
1608
+ display: flex;
1609
+ align-items: center;
1610
+ gap: var(--cb-space-3);
1611
+ padding: var(--cb-space-2) var(--cb-space-3);
1612
+ border-radius: var(--cb-radius-md);
1613
+ border: var(--cb-border-width) solid transparent;
1614
+ }
1615
+ .cb-leaderboard__row[data-rank="1"] { --cb-rank-accent: var(--cb-decor-amber); }
1616
+ .cb-leaderboard__row[data-rank="2"] { --cb-rank-accent: var(--cb-fg-subtle); }
1617
+ .cb-leaderboard__row[data-rank="3"] { --cb-rank-accent: var(--cb-decor-rose); }
1618
+ .cb-leaderboard__row[data-rank] {
1619
+ background: color-mix(in oklch, var(--cb-rank-accent) 12%, transparent);
1620
+ }
1621
+ .cb-leaderboard__row[data-you] {
1622
+ border-color: color-mix(in oklch, var(--cb-tone-brand) 45%, transparent);
1623
+ background: color-mix(in oklch, var(--cb-tone-brand) 10%, transparent);
1624
+ }
1625
+
1626
+ .cb-leaderboard__rank {
1627
+ flex: none;
1628
+ width: 1.5rem;
1629
+ text-align: center;
1630
+ font-size: var(--cb-text-sm);
1631
+ font-weight: var(--cb-weight-semibold);
1632
+ font-variant-numeric: tabular-nums;
1633
+ color: var(--cb-fg-subtle);
1634
+ }
1635
+ .cb-leaderboard__row[data-rank] .cb-leaderboard__rank { color: color-mix(in oklch, var(--cb-rank-accent) 70%, var(--cb-fg)); }
1636
+
1637
+ .cb-leaderboard__text { flex: 1; display: flex; flex-direction: column; gap: 0.0625rem; min-width: 0; }
1638
+ .cb-leaderboard__name { display: flex; align-items: center; gap: var(--cb-space-2); font-size: var(--cb-text-sm); color: var(--cb-fg); }
1639
+ .cb-leaderboard__you {
1640
+ font-size: 0.625rem;
1641
+ text-transform: uppercase;
1642
+ letter-spacing: 0.06em;
1643
+ color: var(--cb-tone-brand);
1644
+ background: color-mix(in oklch, var(--cb-tone-brand) 14%, transparent);
1645
+ border-radius: var(--cb-radius-full);
1646
+ padding: 0 var(--cb-space-2);
1647
+ }
1648
+ .cb-leaderboard__detail { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
1649
+ .cb-leaderboard__delta { font-size: var(--cb-text-xs); font-variant-numeric: tabular-nums; }
1650
+ .cb-leaderboard__delta[data-direction="up"] { color: var(--cb-tone-success); }
1651
+ .cb-leaderboard__delta[data-direction="down"] { color: var(--cb-tone-danger); }
1652
+ .cb-leaderboard__delta[data-direction="flat"] { color: var(--cb-fg-subtle); }
1653
+ .cb-leaderboard__score { font-size: var(--cb-text-sm); font-weight: var(--cb-weight-semibold); font-variant-numeric: tabular-nums; color: var(--cb-fg); }
1654
+
1655
+ /* data/progress-ring.css */
1656
+ .cb-ring {
1657
+ --cb-ring-accent: var(--cb-tone-brand);
1658
+ position: relative;
1659
+ width: var(--cb-ring-size);
1660
+ height: var(--cb-ring-size);
1661
+ display: inline-grid;
1662
+ place-items: center;
1663
+ }
1664
+ .cb-ring[data-tone="neutral"] { --cb-ring-accent: var(--cb-tone-neutral); }
1665
+ .cb-ring[data-tone="info"] { --cb-ring-accent: var(--cb-tone-info); }
1666
+ .cb-ring[data-tone="success"] { --cb-ring-accent: var(--cb-tone-success); }
1667
+ .cb-ring[data-tone="warning"] { --cb-ring-accent: var(--cb-tone-warning); }
1668
+ .cb-ring[data-tone="danger"] { --cb-ring-accent: var(--cb-tone-danger); }
1669
+ .cb-ring[data-hue="violet"] { --cb-ring-accent: var(--cb-decor-violet); }
1670
+ .cb-ring[data-hue="blue"] { --cb-ring-accent: var(--cb-decor-blue); }
1671
+ .cb-ring[data-hue="teal"] { --cb-ring-accent: var(--cb-decor-teal); }
1672
+ .cb-ring[data-hue="green"] { --cb-ring-accent: var(--cb-decor-green); }
1673
+ .cb-ring[data-hue="amber"] { --cb-ring-accent: var(--cb-decor-amber); }
1674
+ .cb-ring[data-hue="rose"] { --cb-ring-accent: var(--cb-decor-rose); }
1675
+
1676
+ .cb-ring svg { position: absolute; inset: 0; }
1677
+ .cb-ring__track { stroke: color-mix(in oklch, var(--cb-ring-accent) 16%, transparent); }
1678
+ .cb-ring__value {
1679
+ stroke: var(--cb-ring-accent);
1680
+ animation: cb-ring-fill var(--cb-duration-deliberate) var(--cb-ease-entrance) both;
1681
+ }
1682
+ @keyframes cb-ring-fill {
1683
+ from { stroke-dashoffset: var(--cb-ring-circumference); }
1684
+ to { stroke-dashoffset: var(--cb-ring-offset); }
1685
+ }
1686
+ /* Reduced motion: the arc is drawn at its final length rather than swept into place. */
1687
+ @media (prefers-reduced-motion: reduce) {
1688
+ .cb-ring__value { animation: none; }
1689
+ }
1690
+
1691
+ .cb-ring__center {
1692
+ font-family: var(--cb-font-sans);
1693
+ font-variant-numeric: tabular-nums;
1694
+ font-weight: var(--cb-weight-semibold);
1695
+ font-size: var(--cb-text-lg);
1696
+ color: var(--cb-fg);
1697
+ }
1698
+
1699
+ /* data/stat-card.css */
1700
+ .cb-stat { display: flex; flex-direction: column; gap: var(--cb-space-3); }
1701
+ .cb-stat__head { display: flex; align-items: center; justify-content: space-between; gap: var(--cb-space-2); }
1702
+ .cb-stat__icon { display: inline-flex; color: var(--cb-surface-accent); }
1703
+ .cb-stat__body { display: flex; align-items: center; justify-content: space-between; gap: var(--cb-space-4); }
1704
+ .cb-stat__skeleton-col { display: flex; flex-direction: column; gap: var(--cb-space-2); }
1705
+
1706
+ .cb-stat__value {
1707
+ margin: 0;
1708
+ font-family: var(--cb-font-sans);
1709
+ font-size: var(--cb-text-2xl);
1710
+ font-weight: var(--cb-weight-semibold);
1711
+ line-height: var(--cb-leading-tight);
1712
+ color: var(--cb-fg);
1713
+ }
1714
+
1715
+ .cb-stat__delta {
1716
+ display: inline-block;
1717
+ margin-top: var(--cb-space-1);
1718
+ font-family: var(--cb-font-sans);
1719
+ font-size: var(--cb-text-xs);
1720
+ font-weight: var(--cb-weight-medium);
1721
+ font-variant-numeric: tabular-nums;
1722
+ padding: var(--cb-space-1) var(--cb-space-2);
1723
+ border-radius: var(--cb-radius-full);
1724
+ }
1725
+ .cb-stat__delta[data-direction="up"] {
1726
+ color: var(--cb-tone-success);
1727
+ background: color-mix(in oklch, var(--cb-tone-success) 14%, transparent);
1728
+ }
1729
+ .cb-stat__delta[data-direction="down"] {
1730
+ color: var(--cb-tone-danger);
1731
+ background: color-mix(in oklch, var(--cb-tone-danger) 14%, transparent);
1732
+ }
1733
+ .cb-stat__delta[data-direction="flat"] {
1734
+ color: var(--cb-fg-muted);
1735
+ background: color-mix(in oklch, var(--cb-fg-muted) 12%, transparent);
1736
+ }
1737
+ .cb-stat__caption { margin-top: var(--cb-space-2); }
1738
+
1739
+ /* data/table.css */
1740
+ .cb-table__scroll {
1741
+ width: 100%;
1742
+ overflow-x: auto;
1743
+ border: var(--cb-border-width) solid var(--cb-border);
1744
+ border-radius: var(--cb-radius-lg);
1745
+ background: var(--cb-surface);
1746
+ }
1747
+ .cb-table { width: 100%; border-collapse: collapse; font-family: var(--cb-font-sans); font-size: var(--cb-text-sm); }
1748
+
1749
+ .cb-table th {
1750
+ text-align: start;
1751
+ font-size: var(--cb-text-xs);
1752
+ font-weight: var(--cb-weight-medium);
1753
+ color: var(--cb-fg-subtle);
1754
+ text-transform: uppercase;
1755
+ letter-spacing: 0.05em;
1756
+ padding: var(--cb-space-2) var(--cb-space-3);
1757
+ border-bottom: var(--cb-border-width) solid var(--cb-border);
1758
+ white-space: nowrap;
1759
+ background: var(--cb-bg-subtle);
1760
+ }
1761
+ .cb-table td {
1762
+ padding: var(--cb-space-2) var(--cb-space-3);
1763
+ height: 3rem;
1764
+ border-bottom: var(--cb-border-width) solid var(--cb-border);
1765
+ color: var(--cb-fg);
1766
+ vertical-align: middle;
1767
+ }
1768
+ .cb-table tbody tr:last-child td { border-bottom: none; }
1769
+ .cb-table [data-align="end"] { text-align: end; }
1770
+ /* Truncation needs a bound to truncate against, which a table cell only gets from max-width. */
1771
+ .cb-table td[data-truncate] {
1772
+ max-width: 1px;
1773
+ overflow: hidden;
1774
+ text-overflow: ellipsis;
1775
+ white-space: nowrap;
1776
+ }
1777
+
1778
+ /* First and last cells keep the table's own gutter, so content lines up with the panel edge
1779
+ rather than floating a second inset inside it. */
1780
+ .cb-table th:first-child,
1781
+ .cb-table td:first-child { padding-inline-start: var(--cb-space-4); }
1782
+ .cb-table th:last-child,
1783
+ .cb-table td:last-child { padding-inline-end: var(--cb-space-2); }
1784
+
1785
+ /* A cell holding only a control does not need text padding around it. */
1786
+ .cb-table td:has(> .cb-button--icon),
1787
+ .cb-table td:has(> .cb-menu-anchor) { padding-block: 0; }
1788
+
1789
+ .cb-table tbody tr[data-clickable] { cursor: pointer; }
1790
+ .cb-table tbody tr[data-clickable]:hover td { background: var(--cb-bg-subtle); }
1791
+
1792
+ .cb-table__sort {
1793
+ display: inline-flex;
1794
+ align-items: center;
1795
+ min-height: 1.5rem;
1796
+ margin-block: calc(var(--cb-space-1) * -1);
1797
+ padding-block: var(--cb-space-1);
1798
+ gap: var(--cb-space-1);
1799
+ border: none;
1800
+ background: transparent;
1801
+ color: inherit;
1802
+ font: inherit;
1803
+ letter-spacing: inherit;
1804
+ text-transform: inherit;
1805
+ cursor: pointer;
1806
+ padding: 0;
1807
+ border-radius: var(--cb-radius-sm);
1808
+ }
1809
+ .cb-table__sort:hover { color: var(--cb-fg); }
1810
+ .cb-table__sort:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset); }
1811
+ .cb-table__sort-idle { opacity: 0.4; }
1812
+
1813
+ .cb-table__empty {
1814
+ border: var(--cb-border-width) solid var(--cb-border);
1815
+ border-radius: var(--cb-radius-lg);
1816
+ background: var(--cb-surface);
1817
+ }
1818
+
1819
+ @media (max-width: 720px) {
1820
+ .cb-table [data-secondary] { display: none; }
1821
+ }
1822
+
1823
+ .cb-pagination {
1824
+ display: flex;
1825
+ align-items: center;
1826
+ justify-content: space-between;
1827
+ gap: var(--cb-space-4);
1828
+ flex-wrap: wrap;
1829
+ font-family: var(--cb-font-sans);
1830
+ }
1831
+ .cb-pagination__summary { margin: 0; font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); font-variant-numeric: tabular-nums; }
1832
+ .cb-pagination__controls { display: flex; align-items: center; gap: var(--cb-space-1); }
1833
+
1834
+ .cb-pagination__page,
1835
+ .cb-pagination__step {
1836
+ display: inline-flex;
1837
+ align-items: center;
1838
+ justify-content: center;
1839
+ min-width: 2rem;
1840
+ height: 2rem;
1841
+ padding-inline: var(--cb-space-2);
1842
+ border: var(--cb-border-width) solid transparent;
1843
+ border-radius: var(--cb-radius-sm);
1844
+ background: transparent;
1845
+ color: var(--cb-fg-muted);
1846
+ font-family: inherit;
1847
+ font-size: var(--cb-text-sm);
1848
+ font-variant-numeric: tabular-nums;
1849
+ cursor: pointer;
1850
+ transition: background-color var(--cb-duration-fast) var(--cb-ease-standard),
1851
+ color var(--cb-duration-fast) var(--cb-ease-standard);
1852
+ }
1853
+ .cb-pagination__page:hover:not([data-active]),
1854
+ .cb-pagination__step:hover:not(:disabled) { background: var(--cb-bg-subtle); color: var(--cb-fg); }
1855
+ .cb-pagination__page[data-active] {
1856
+ background: color-mix(in oklch, var(--cb-tone-brand) 14%, transparent);
1857
+ border-color: color-mix(in oklch, var(--cb-tone-brand) 35%, transparent);
1858
+ color: var(--cb-tone-brand);
1859
+ font-weight: var(--cb-weight-medium);
1860
+ }
1861
+ .cb-pagination__step:disabled { opacity: 0.35; cursor: not-allowed; }
1862
+ .cb-pagination__page:focus-visible,
1863
+ .cb-pagination__step:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset); }
1864
+ .cb-pagination__gap { color: var(--cb-fg-subtle); padding-inline: var(--cb-space-1); }
1865
+
1866
+ /* data/timeline.css */
1867
+ .cb-timeline { list-style: none; margin: 0; padding: 0; font-family: var(--cb-font-sans); }
1868
+ .cb-timeline__entry { margin: 0; --cb-timeline-accent: var(--cb-fg-subtle); display: flex; gap: var(--cb-space-3); }
1869
+ .cb-timeline__entry[data-tone="brand"] { --cb-timeline-accent: var(--cb-tone-brand); }
1870
+ .cb-timeline__entry[data-tone="info"] { --cb-timeline-accent: var(--cb-tone-info); }
1871
+ .cb-timeline__entry[data-tone="success"] { --cb-timeline-accent: var(--cb-tone-success); }
1872
+ .cb-timeline__entry[data-tone="warning"] { --cb-timeline-accent: var(--cb-tone-warning); }
1873
+ .cb-timeline__entry[data-tone="danger"] { --cb-timeline-accent: var(--cb-tone-danger); }
1874
+
1875
+ .cb-timeline__rail { position: relative; display: flex; justify-content: center; width: 1.5rem; flex: none; }
1876
+ /* The connecting line is drawn on every entry but the last, so the rail ends with the last event. */
1877
+ .cb-timeline__entry:not(:last-child) .cb-timeline__rail::after {
1878
+ content: "";
1879
+ position: absolute;
1880
+ top: 1.5rem;
1881
+ bottom: -0.25rem;
1882
+ width: 1px;
1883
+ background: var(--cb-border);
1884
+ }
1885
+ .cb-timeline__marker {
1886
+ display: inline-flex;
1887
+ align-items: center;
1888
+ justify-content: center;
1889
+ width: 1.5rem;
1890
+ height: 1.5rem;
1891
+ border-radius: var(--cb-radius-full);
1892
+ background: color-mix(in oklch, var(--cb-timeline-accent) 16%, var(--cb-surface));
1893
+ color: var(--cb-timeline-accent);
1894
+ border: var(--cb-border-width) solid color-mix(in oklch, var(--cb-timeline-accent) 35%, transparent);
1895
+ }
1896
+
1897
+ .cb-timeline__body { flex: 1; padding-bottom: var(--cb-space-5); min-width: 0; }
1898
+ .cb-timeline__entry:last-child .cb-timeline__body { padding-bottom: 0; }
1899
+ .cb-timeline__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--cb-space-3); }
1900
+ .cb-timeline__title { margin: 0; font-size: var(--cb-text-sm); font-weight: var(--cb-weight-medium); color: var(--cb-fg); }
1901
+ .cb-timeline__time { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); white-space: nowrap; font-variant-numeric: tabular-nums; }
1902
+ .cb-timeline__description { margin: var(--cb-space-1) 0 0; font-size: var(--cb-text-sm); color: var(--cb-fg-muted); line-height: var(--cb-leading-normal); }
1903
+
1904
+ /* media/avatar.css */
1905
+ .cb-avatar {
1906
+ --cb-avatar-accent: var(--cb-decor-violet);
1907
+ position: relative;
1908
+ display: inline-flex;
1909
+ align-items: center;
1910
+ justify-content: center;
1911
+ flex: none;
1912
+ border-radius: var(--cb-radius-full);
1913
+ background: color-mix(in oklch, var(--cb-avatar-accent) 22%, var(--cb-surface));
1914
+ color: color-mix(in oklch, var(--cb-avatar-accent) 70%, var(--cb-fg));
1915
+ font-family: var(--cb-font-sans);
1916
+ font-weight: var(--cb-weight-semibold);
1917
+ overflow: visible;
1918
+ }
1919
+ .cb-avatar[data-hue="violet"] { --cb-avatar-accent: var(--cb-decor-violet); }
1920
+ .cb-avatar[data-hue="blue"] { --cb-avatar-accent: var(--cb-decor-blue); }
1921
+ .cb-avatar[data-hue="teal"] { --cb-avatar-accent: var(--cb-decor-teal); }
1922
+ .cb-avatar[data-hue="green"] { --cb-avatar-accent: var(--cb-decor-green); }
1923
+ .cb-avatar[data-hue="amber"] { --cb-avatar-accent: var(--cb-decor-amber); }
1924
+ .cb-avatar[data-hue="rose"] { --cb-avatar-accent: var(--cb-decor-rose); }
1925
+
1926
+ .cb-avatar--sm { width: 1.75rem; height: 1.75rem; font-size: 0.625rem; }
1927
+ .cb-avatar--md { width: 2.25rem; height: 2.25rem; font-size: var(--cb-text-xs); }
1928
+ .cb-avatar--lg { width: 3rem; height: 3rem; font-size: var(--cb-text-sm); }
1929
+ .cb-avatar--xl { width: 4rem; height: 4rem; font-size: var(--cb-text-lg); }
1930
+
1931
+ .cb-avatar__image {
1932
+ position: absolute;
1933
+ inset: 0;
1934
+ width: 100%;
1935
+ height: 100%;
1936
+ object-fit: cover;
1937
+ border-radius: inherit;
1938
+ }
1939
+ .cb-avatar__initials { line-height: 1; }
1940
+ .cb-avatar--overflow {
1941
+ background: var(--cb-bg-subtle);
1942
+ color: var(--cb-fg-muted);
1943
+ }
1944
+
1945
+ .cb-avatar__status {
1946
+ position: absolute;
1947
+ right: -1px;
1948
+ bottom: -1px;
1949
+ width: 0.6em;
1950
+ height: 0.6em;
1951
+ min-width: 0.5rem;
1952
+ min-height: 0.5rem;
1953
+ border-radius: var(--cb-radius-full);
1954
+ border: 2px solid var(--cb-surface);
1955
+ }
1956
+ .cb-avatar__status[data-status="online"] { background: var(--cb-tone-success); }
1957
+ .cb-avatar__status[data-status="busy"] { background: var(--cb-tone-danger); }
1958
+ .cb-avatar__status[data-status="away"] { background: var(--cb-tone-warning); }
1959
+ .cb-avatar__status[data-status="offline"] { background: var(--cb-fg-subtle); }
1960
+
1961
+ .cb-avatar-group { display: inline-flex; }
1962
+ .cb-avatar-group > .cb-avatar { box-shadow: 0 0 0 2px var(--cb-surface); }
1963
+ .cb-avatar-group > .cb-avatar + .cb-avatar { margin-inline-start: -0.5rem; }
1964
+
1965
+ /* media/carousel.css */
1966
+ .cb-carousel { position: relative; }
1967
+ .cb-carousel:focus-visible {
1968
+ outline: var(--cb-focus-width) solid var(--cb-tone-brand);
1969
+ outline-offset: var(--cb-focus-offset);
1970
+ border-radius: var(--cb-radius-lg);
1971
+ }
1972
+ .cb-carousel__viewport { overflow: hidden; }
1973
+ .cb-carousel__track { display: flex; gap: var(--cb-carousel-gap); }
1974
+ .cb-carousel__slide {
1975
+ flex: 0 0 var(--cb-carousel-slide);
1976
+ min-width: 0;
1977
+ }
1978
+
1979
+ .cb-carousel__arrows {
1980
+ position: absolute;
1981
+ inset-block-start: 50%;
1982
+ inset-inline: calc(var(--cb-space-3) * -1);
1983
+ translate: 0 -50%;
1984
+ display: flex;
1985
+ justify-content: space-between;
1986
+ pointer-events: none;
1987
+ }
1988
+ .cb-carousel__arrow {
1989
+ pointer-events: auto;
1990
+ display: inline-flex;
1991
+ align-items: center;
1992
+ justify-content: center;
1993
+ width: 2.25rem;
1994
+ height: 2.25rem;
1995
+ border-radius: var(--cb-radius-full);
1996
+ border: var(--cb-border-width) solid var(--cb-border);
1997
+ background: var(--cb-surface-raised);
1998
+ color: var(--cb-fg);
1999
+ box-shadow: var(--cb-shadow-sm);
2000
+ cursor: pointer;
2001
+ transition: background-color var(--cb-duration-fast) var(--cb-ease-standard),
2002
+ opacity var(--cb-duration-fast) var(--cb-ease-standard);
2003
+ }
2004
+ .cb-carousel__arrow:hover:not(:disabled) { background: var(--cb-bg-subtle); }
2005
+ .cb-carousel__arrow:disabled { opacity: 0.35; cursor: not-allowed; }
2006
+ .cb-carousel__arrow:focus-visible {
2007
+ outline: var(--cb-focus-width) solid var(--cb-tone-brand);
2008
+ outline-offset: var(--cb-focus-offset);
2009
+ }
2010
+
2011
+ .cb-carousel__dots { display: flex; gap: var(--cb-space-2); justify-content: center; margin-top: var(--cb-space-4); }
2012
+ .cb-carousel__dot {
2013
+ width: 0.5rem;
2014
+ height: 0.5rem;
2015
+ padding: 0;
2016
+ border: none;
2017
+ border-radius: var(--cb-radius-full);
2018
+ background: color-mix(in oklch, var(--cb-fg) 22%, transparent);
2019
+ cursor: pointer;
2020
+ transition: width var(--cb-duration-base) var(--cb-ease-emphasis),
2021
+ background-color var(--cb-duration-base) var(--cb-ease-standard);
2022
+ }
2023
+ .cb-carousel__dot[data-active] { width: 1.5rem; background: var(--cb-tone-brand); }
2024
+ .cb-carousel__dot:focus-visible {
2025
+ outline: var(--cb-focus-width) solid var(--cb-tone-brand);
2026
+ outline-offset: var(--cb-focus-offset);
2027
+ }
2028
+ /* Reduced motion: the active dot still changes colour, it just stops stretching. */
2029
+ @media (prefers-reduced-motion: reduce) {
2030
+ .cb-carousel__dot { transition: background-color var(--cb-duration-fast) linear; }
2031
+ }
2032
+
2033
+ /* media/image.css */
2034
+ .cb-image {
2035
+ position: relative;
2036
+ display: block;
2037
+ overflow: hidden;
2038
+ background-color: var(--cb-bg-subtle);
2039
+ background-size: cover;
2040
+ background-position: center;
2041
+ }
2042
+ /* The placeholder is blurred hard and scaled up, so its edges never show through. */
2043
+ .cb-image[data-blurred]::before {
2044
+ content: "";
2045
+ position: absolute;
2046
+ inset: -5%;
2047
+ background: inherit;
2048
+ background-size: cover;
2049
+ background-position: center;
2050
+ filter: blur(16px);
2051
+ transform: scale(1.05);
2052
+ transition: opacity var(--cb-duration-slow) var(--cb-ease-standard);
2053
+ }
2054
+ .cb-image[data-loaded][data-blurred]::before { opacity: 0; }
2055
+
2056
+ .cb-image__img {
2057
+ position: relative;
2058
+ display: block;
2059
+ width: 100%;
2060
+ height: 100%;
2061
+ opacity: 0;
2062
+ transition: opacity var(--cb-duration-slow) var(--cb-ease-entrance);
2063
+ }
2064
+ .cb-image[data-loaded] .cb-image__img { opacity: 1; }
2065
+
2066
+ /* Reduced motion: the image appears rather than fading, and the placeholder still holds the space. */
2067
+ @media (prefers-reduced-motion: reduce) {
2068
+ .cb-image__img,
2069
+ .cb-image[data-blurred]::before { transition: none; }
2070
+ }
2071
+
2072
+ /* nav/nav.css */
2073
+ .cb-menu {
2074
+ box-sizing: border-box;
2075
+ min-width: 12rem;
2076
+ padding: var(--cb-space-1);
2077
+ background: var(--cb-surface-raised);
2078
+ border: var(--cb-border-width) solid var(--cb-border);
2079
+ border-radius: var(--cb-radius-md);
2080
+ box-shadow: var(--cb-shadow-md);
2081
+ font-family: var(--cb-font-sans);
2082
+ font-size: var(--cb-text-sm);
2083
+ z-index: var(--cb-z-popover);
2084
+ transition: opacity var(--cb-duration-fast) var(--cb-ease-entrance),
2085
+ transform var(--cb-duration-fast) var(--cb-ease-entrance);
2086
+ }
2087
+ .cb-menu[data-starting-style],
2088
+ .cb-menu[data-ending-style] { opacity: 0; transform: scale(0.97); }
2089
+ @media (prefers-reduced-motion: reduce) {
2090
+ .cb-menu { transition: opacity var(--cb-duration-fast) linear; }
2091
+ .cb-menu[data-starting-style],
2092
+ .cb-menu[data-ending-style] { transform: none; }
2093
+ }
2094
+
2095
+ .cb-menu__item {
2096
+ display: grid;
2097
+ grid-template-columns: 1.25rem 1fr auto;
2098
+ align-items: center;
2099
+ gap: var(--cb-space-2);
2100
+ padding: var(--cb-space-2);
2101
+ border-radius: var(--cb-radius-sm);
2102
+ color: var(--cb-fg);
2103
+ cursor: pointer;
2104
+ outline: none;
2105
+ }
2106
+ .cb-menu__item[data-highlighted] { background: color-mix(in oklch, var(--cb-tone-brand) 12%, transparent); }
2107
+ .cb-menu__item[data-tone="danger"] { color: var(--cb-tone-danger); }
2108
+ .cb-menu__item[data-tone="danger"][data-highlighted] { background: color-mix(in oklch, var(--cb-tone-danger) 12%, transparent); }
2109
+ .cb-menu__item[data-disabled] { color: var(--cb-fg-subtle); text-decoration: line-through; cursor: not-allowed; }
2110
+ .cb-menu__icon { display: inline-flex; justify-content: center; color: var(--cb-fg-subtle); }
2111
+ .cb-menu__item[data-tone="danger"] .cb-menu__icon { color: inherit; }
2112
+ .cb-menu__shortcut {
2113
+ margin: 0;
2114
+ padding: 0;
2115
+ border: none;
2116
+ background: none;
2117
+ font-family: var(--cb-font-mono);
2118
+ font-size: var(--cb-text-xs);
2119
+ color: var(--cb-fg-subtle);
2120
+ }
2121
+ .cb-menu__separator { height: 1px; background: var(--cb-border); margin: var(--cb-space-1) 0; }
2122
+
2123
+ .cb-crumbs__list {
2124
+ display: flex;
2125
+ flex-wrap: wrap;
2126
+ align-items: center;
2127
+ gap: var(--cb-space-1);
2128
+ list-style: none;
2129
+ margin: 0;
2130
+ padding: 0;
2131
+ font-family: var(--cb-font-sans);
2132
+ font-size: var(--cb-text-sm);
2133
+ }
2134
+ .cb-crumbs__item { margin: 0; display: inline-flex; align-items: center; gap: var(--cb-space-1); }
2135
+ .cb-crumbs__link { color: var(--cb-fg-muted); text-decoration: none; border-radius: var(--cb-radius-sm); }
2136
+ .cb-crumbs__link:hover { color: var(--cb-fg); text-decoration: underline; }
2137
+ .cb-crumbs__link:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset); }
2138
+ .cb-crumbs__text { color: var(--cb-fg-subtle); }
2139
+ .cb-crumbs__current { color: var(--cb-fg); font-weight: var(--cb-weight-medium); }
2140
+ .cb-crumbs__separator { color: var(--cb-fg-subtle); flex: none; }
2141
+
2142
+ .cb-stepper { list-style: none; margin: 0; padding: 0; font-family: var(--cb-font-sans); display: flex; }
2143
+ .cb-stepper--horizontal { flex-direction: row; gap: var(--cb-space-5); flex-wrap: wrap; }
2144
+ .cb-stepper--vertical { flex-direction: column; gap: var(--cb-space-4); }
2145
+ .cb-stepper__step { margin: 0; display: flex; align-items: flex-start; gap: var(--cb-space-3); }
2146
+ .cb-stepper__marker {
2147
+ flex: none;
2148
+ display: inline-flex;
2149
+ align-items: center;
2150
+ justify-content: center;
2151
+ width: 1.5rem;
2152
+ height: 1.5rem;
2153
+ border-radius: var(--cb-radius-full);
2154
+ border: var(--cb-border-width) solid var(--cb-border-strong);
2155
+ font-size: var(--cb-text-xs);
2156
+ font-variant-numeric: tabular-nums;
2157
+ color: var(--cb-fg-subtle);
2158
+ background: var(--cb-surface);
2159
+ }
2160
+ .cb-stepper__step[data-state="done"] .cb-stepper__marker {
2161
+ background: var(--cb-tone-success);
2162
+ border-color: var(--cb-tone-success);
2163
+ color: var(--cb-fg-on-brand);
2164
+ }
2165
+ .cb-stepper__step[data-state="current"] .cb-stepper__marker {
2166
+ border-color: var(--cb-tone-brand);
2167
+ color: var(--cb-tone-brand);
2168
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--cb-tone-brand) 16%, transparent);
2169
+ }
2170
+ .cb-stepper__text { display: flex; flex-direction: column; gap: 0.125rem; }
2171
+ .cb-stepper__label { font-size: var(--cb-text-sm); font-weight: var(--cb-weight-medium); color: var(--cb-fg-muted); }
2172
+ .cb-stepper__step[data-state="current"] .cb-stepper__label { color: var(--cb-fg); }
2173
+ .cb-stepper__description { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
2174
+
2175
+ .cb-sidebar {
2176
+ display: flex;
2177
+ flex-direction: column;
2178
+ gap: var(--cb-space-4);
2179
+ width: 15rem;
2180
+ padding: var(--cb-space-4);
2181
+ box-sizing: border-box;
2182
+ background: var(--cb-bg-subtle);
2183
+ border-right: var(--cb-border-width) solid var(--cb-border);
2184
+ font-family: var(--cb-font-sans);
2185
+ transition: width var(--cb-duration-base) var(--cb-ease-standard);
2186
+ }
2187
+ .cb-sidebar--collapsed { width: 4.25rem; align-items: center; }
2188
+ @media (prefers-reduced-motion: reduce) {
2189
+ .cb-sidebar { transition: none; }
2190
+ }
2191
+
2192
+ .cb-sidebar__body { flex: 1; display: flex; flex-direction: column; gap: var(--cb-space-4); width: 100%; }
2193
+ .cb-sidebar__section { display: flex; flex-direction: column; gap: 0.125rem; }
2194
+ .cb-sidebar__title {
2195
+ margin: 0 0 var(--cb-space-1);
2196
+ font-size: var(--cb-text-xs);
2197
+ text-transform: uppercase;
2198
+ letter-spacing: 0.08em;
2199
+ color: var(--cb-fg-subtle);
2200
+ }
2201
+ .cb-sidebar__item {
2202
+ display: flex;
2203
+ align-items: center;
2204
+ gap: var(--cb-space-3);
2205
+ width: 100%;
2206
+ padding: var(--cb-space-2) var(--cb-space-3);
2207
+ border: none;
2208
+ border-radius: var(--cb-radius-sm);
2209
+ background: transparent;
2210
+ color: var(--cb-fg-muted);
2211
+ font: inherit;
2212
+ font-size: var(--cb-text-sm);
2213
+ text-align: start;
2214
+ text-decoration: none;
2215
+ cursor: pointer;
2216
+ }
2217
+ .cb-sidebar__item:hover { background: var(--cb-surface); color: var(--cb-fg); }
2218
+ .cb-sidebar__item[data-active] { background: var(--cb-surface); color: var(--cb-fg); font-weight: var(--cb-weight-medium); }
2219
+ .cb-sidebar__item:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset-inset); }
2220
+ .cb-sidebar__icon { display: inline-flex; flex: none; }
2221
+ .cb-sidebar__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2222
+ .cb-sidebar--collapsed .cb-sidebar__item { justify-content: center; padding-inline: var(--cb-space-2); }
2223
+ /* Collapsed hides the label visually but keeps it for assistive technology. */
2224
+ .cb-sidebar--collapsed .cb-sidebar__label {
2225
+ position: absolute;
2226
+ width: 1px;
2227
+ height: 1px;
2228
+ overflow: hidden;
2229
+ clip-path: inset(50%);
2230
+ white-space: nowrap;
2231
+ }
2232
+ .cb-sidebar__adornment { flex: none; }
2233
+ .cb-sidebar__toggle {
2234
+ align-self: flex-start;
2235
+ display: inline-flex;
2236
+ padding: var(--cb-space-2);
2237
+ border: none;
2238
+ border-radius: var(--cb-radius-sm);
2239
+ background: transparent;
2240
+ color: var(--cb-fg-subtle);
2241
+ cursor: pointer;
2242
+ }
2243
+ .cb-sidebar__toggle:hover { background: var(--cb-surface); color: var(--cb-fg); }
2244
+ .cb-sidebar__toggle:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset); }
2245
+
2246
+ .cb-topbar {
2247
+ display: flex;
2248
+ align-items: center;
2249
+ gap: var(--cb-space-4);
2250
+ padding: var(--cb-space-3) var(--cb-space-5);
2251
+ background: var(--cb-surface);
2252
+ border-bottom: var(--cb-border-width) solid var(--cb-border);
2253
+ font-family: var(--cb-font-sans);
2254
+ }
2255
+ .cb-topbar--sticky { position: sticky; top: 0; z-index: var(--cb-z-sticky); }
2256
+ .cb-topbar__lead { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
2257
+ .cb-topbar__title { font-size: var(--cb-text-lg); font-weight: var(--cb-weight-semibold); color: var(--cb-fg); }
2258
+ .cb-topbar__subtitle { margin: 0; font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
2259
+ .cb-topbar__center { flex: 1; display: flex; justify-content: center; min-width: 0; }
2260
+ .cb-topbar__actions { display: flex; align-items: center; gap: var(--cb-space-2); margin-inline-start: auto; }
2261
+
2262
+ /* Submenus. A parent is a disclosure, and its children indent under a rail that ties them to it. */
2263
+ .cb-sidebar__chevron {
2264
+ flex: none;
2265
+ color: var(--cb-fg-subtle);
2266
+ transition: rotate var(--cb-duration-fast) var(--cb-ease-standard);
2267
+ }
2268
+ .cb-sidebar__chevron[data-open] { rotate: 90deg; }
2269
+ @media (prefers-reduced-motion: reduce) {
2270
+ .cb-sidebar__chevron { transition: none; }
2271
+ }
2272
+
2273
+ .cb-sidebar__children {
2274
+ display: flex;
2275
+ flex-direction: column;
2276
+ gap: 0.125rem;
2277
+ margin-inline-start: calc(var(--cb-space-3) + 0.5rem);
2278
+ padding-inline-start: var(--cb-space-3);
2279
+ border-inline-start: var(--cb-border-width) solid var(--cb-border);
2280
+ }
2281
+ .cb-sidebar__item--nested { font-size: var(--cb-text-sm); }
2282
+
2283
+ .cb-sidebar__flyout-trigger { display: block; width: 100%; }
2284
+ .cb-sidebar__flyout-positioner { z-index: var(--cb-z-popover); }
2285
+
2286
+ /* Collapsed, this is where the labels live. */
2287
+ .cb-sidebar__flyout {
2288
+ min-width: 11rem;
2289
+ padding: var(--cb-space-2);
2290
+ background: var(--cb-surface-raised);
2291
+ border: var(--cb-border-width) solid var(--cb-border);
2292
+ border-radius: var(--cb-radius-md);
2293
+ box-shadow: var(--cb-shadow-md);
2294
+ font-family: var(--cb-font-sans);
2295
+ transition: opacity var(--cb-duration-fast) var(--cb-ease-entrance);
2296
+ }
2297
+ .cb-sidebar__flyout[data-starting-style],
2298
+ .cb-sidebar__flyout[data-ending-style] { opacity: 0; }
2299
+ .cb-sidebar__flyout-title {
2300
+ margin: 0;
2301
+ padding: var(--cb-space-1) var(--cb-space-2);
2302
+ font-size: var(--cb-text-sm);
2303
+ font-weight: var(--cb-weight-semibold);
2304
+ color: var(--cb-fg);
2305
+ }
2306
+ .cb-sidebar__flyout-items {
2307
+ display: flex;
2308
+ flex-direction: column;
2309
+ gap: 0.125rem;
2310
+ margin-top: var(--cb-space-1);
2311
+ padding-top: var(--cb-space-1);
2312
+ border-top: var(--cb-border-width) solid var(--cb-border);
2313
+ }
2314
+
2315
+ /* nav/tabs.css */
2316
+ .cb-tabs { display: flex; flex-direction: column; gap: var(--cb-space-4); }
2317
+ .cb-tabs__list { position: relative; display: flex; gap: var(--cb-space-1); }
2318
+ .cb-tabs--underline .cb-tabs__list { border-bottom: var(--cb-border-width) solid var(--cb-border); }
2319
+
2320
+ .cb-tabs__tab {
2321
+ display: inline-flex;
2322
+ align-items: center;
2323
+ gap: var(--cb-space-2);
2324
+ border: none;
2325
+ background: transparent;
2326
+ color: var(--cb-fg-muted);
2327
+ font-family: var(--cb-font-sans);
2328
+ font-size: var(--cb-text-sm);
2329
+ font-weight: var(--cb-weight-medium);
2330
+ padding: var(--cb-space-2) var(--cb-space-3);
2331
+ cursor: pointer;
2332
+ border-radius: var(--cb-radius-sm);
2333
+ transition: color var(--cb-duration-fast) var(--cb-ease-standard),
2334
+ background-color var(--cb-duration-fast) var(--cb-ease-standard);
2335
+ }
2336
+ .cb-tabs__tab:hover:not([data-disabled]) { color: var(--cb-fg); }
2337
+ .cb-tabs__tab[data-selected] { color: var(--cb-fg); }
2338
+ .cb-tabs__tab[data-disabled] { opacity: 0.45; cursor: not-allowed; }
2339
+ .cb-tabs__tab:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset-inset); }
2340
+ .cb-tabs__adornment { display: inline-flex; }
2341
+
2342
+ .cb-tabs--pill .cb-tabs__list { background: var(--cb-bg-subtle); padding: var(--cb-space-1); border-radius: var(--cb-radius-md); }
2343
+ .cb-tabs--pill .cb-tabs__tab[data-selected] { color: var(--cb-fg); }
2344
+
2345
+ /* The indicator is positioned by Base UI's own custom properties; we only style it. */
2346
+ .cb-tabs__indicator {
2347
+ position: absolute;
2348
+ transition: translate var(--cb-duration-base) var(--cb-ease-emphasis),
2349
+ width var(--cb-duration-base) var(--cb-ease-emphasis);
2350
+ translate: var(--active-tab-left) 0;
2351
+ width: var(--active-tab-width);
2352
+ }
2353
+ .cb-tabs--underline .cb-tabs__indicator {
2354
+ bottom: -1px;
2355
+ height: 2px;
2356
+ background: var(--cb-tone-brand);
2357
+ border-radius: var(--cb-radius-full);
2358
+ }
2359
+ .cb-tabs--pill .cb-tabs__indicator {
2360
+ top: var(--cb-space-1);
2361
+ height: calc(100% - var(--cb-space-2));
2362
+ background: var(--cb-surface-raised);
2363
+ border-radius: var(--cb-radius-sm);
2364
+ box-shadow: var(--cb-shadow-sm);
2365
+ z-index: 0;
2366
+ }
2367
+ .cb-tabs--pill .cb-tabs__tab { position: relative; z-index: 1; }
2368
+ @media (prefers-reduced-motion: reduce) {
2369
+ .cb-tabs__indicator { transition: none; }
2370
+ }
2371
+
2372
+ .cb-tabs__panel:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset); }
2373
+
2374
+ /* onboarding/checklist.css */
2375
+ .cb-checklist {
2376
+ display: flex;
2377
+ flex-direction: column;
2378
+ gap: var(--cb-space-3);
2379
+ padding: var(--cb-space-4);
2380
+ border: var(--cb-border-width) solid var(--cb-border);
2381
+ border-radius: var(--cb-radius-lg);
2382
+ background: var(--cb-surface);
2383
+ font-family: var(--cb-font-sans);
2384
+ }
2385
+ .cb-checklist__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--cb-space-3); }
2386
+ .cb-checklist__title { margin: 0; font-size: var(--cb-text-sm); font-weight: var(--cb-weight-semibold); color: var(--cb-fg); }
2387
+ .cb-checklist__count { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); font-variant-numeric: tabular-nums; }
2388
+
2389
+ .cb-checklist__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.125rem; }
2390
+ .cb-checklist__task {
2391
+ display: flex;
2392
+ align-items: flex-start;
2393
+ gap: var(--cb-space-3);
2394
+ width: 100%;
2395
+ padding: var(--cb-space-2);
2396
+ border: none;
2397
+ border-radius: var(--cb-radius-sm);
2398
+ background: transparent;
2399
+ color: var(--cb-fg);
2400
+ font: inherit;
2401
+ text-align: start;
2402
+ cursor: pointer;
2403
+ }
2404
+ .cb-checklist__task:disabled { cursor: default; }
2405
+ .cb-checklist__task:hover:not(:disabled) { background: var(--cb-bg-subtle); }
2406
+ .cb-checklist__task:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset-inset); }
2407
+
2408
+ .cb-checklist__marker {
2409
+ flex: none;
2410
+ display: inline-flex;
2411
+ align-items: center;
2412
+ justify-content: center;
2413
+ width: 1.125rem;
2414
+ height: 1.125rem;
2415
+ margin-top: 0.0625rem;
2416
+ border-radius: var(--cb-radius-full);
2417
+ border: var(--cb-border-width) solid var(--cb-border-strong);
2418
+ color: var(--cb-fg-on-brand);
2419
+ }
2420
+ .cb-checklist__task[data-done] .cb-checklist__marker { background: var(--cb-tone-success); border-color: var(--cb-tone-success); }
2421
+
2422
+ .cb-checklist__text { flex: 1; display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
2423
+ .cb-checklist__label { font-size: var(--cb-text-sm); }
2424
+ .cb-checklist__task[data-done] .cb-checklist__label { color: var(--cb-fg-muted); text-decoration: line-through; }
2425
+ .cb-checklist__description { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
2426
+ .cb-checklist__chevron { flex: none; color: var(--cb-fg-subtle); align-self: center; }
2427
+ .cb-checklist__complete { padding: var(--cb-space-2) 0; }
2428
+
2429
+ /* onboarding/coachmark.css */
2430
+ /* The hole is a box-shadow spread rather than an SVG mask: it stays crisp at any size and
2431
+ costs no extra element, and the shadow colour is the same token the dialog backdrop uses. */
2432
+ .cb-spotlight {
2433
+ position: fixed;
2434
+ z-index: var(--cb-z-coachmark);
2435
+ left: var(--cb-spotlight-x);
2436
+ top: var(--cb-spotlight-y);
2437
+ width: var(--cb-spotlight-w);
2438
+ height: var(--cb-spotlight-h);
2439
+ border-radius: var(--cb-radius-md);
2440
+ box-shadow: 0 0 0 9999px var(--cb-scrim-strong);
2441
+ pointer-events: auto;
2442
+ transition: left var(--cb-duration-base) var(--cb-ease-standard),
2443
+ top var(--cb-duration-base) var(--cb-ease-standard),
2444
+ width var(--cb-duration-base) var(--cb-ease-standard),
2445
+ height var(--cb-duration-base) var(--cb-ease-standard);
2446
+ }
2447
+ /* Reduced motion: the hole jumps to the next target instead of gliding to it. */
2448
+ @media (prefers-reduced-motion: reduce) {
2449
+ .cb-spotlight { transition: none; }
2450
+ }
2451
+
2452
+ /* The positioner is what the portal places, so the stacking order has to live here; a z-index
2453
+ on the popup alone loses to the spotlight's own layer. */
2454
+ .cb-coachmark__positioner { z-index: calc(var(--cb-z-coachmark) + 1); }
2455
+
2456
+ .cb-coachmark {
2457
+ box-sizing: border-box;
2458
+ width: 20rem;
2459
+ max-width: calc(100vw - var(--cb-space-6));
2460
+ background: var(--cb-surface-raised);
2461
+ color: var(--cb-fg);
2462
+ border: var(--cb-border-width) solid var(--cb-border);
2463
+ border-radius: var(--cb-radius-lg);
2464
+ box-shadow: var(--cb-shadow-lg);
2465
+ padding: var(--cb-space-4);
2466
+ font-family: var(--cb-font-sans);
2467
+ display: flex;
2468
+ flex-direction: column;
2469
+ gap: var(--cb-space-3);
2470
+ transition: opacity var(--cb-duration-base) var(--cb-ease-entrance),
2471
+ transform var(--cb-duration-base) var(--cb-ease-entrance);
2472
+ }
2473
+ .cb-coachmark[data-starting-style],
2474
+ .cb-coachmark[data-ending-style] { opacity: 0; transform: scale(0.96); }
2475
+ @media (prefers-reduced-motion: reduce) {
2476
+ .cb-coachmark { transition: opacity var(--cb-duration-fast) linear; }
2477
+ .cb-coachmark[data-starting-style],
2478
+ .cb-coachmark[data-ending-style] { transform: none; }
2479
+ }
2480
+
2481
+ .cb-coachmark__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--cb-space-2); }
2482
+ .cb-coachmark__title { margin: 0; font-size: var(--cb-text-md); font-weight: var(--cb-weight-semibold); }
2483
+ .cb-coachmark__close {
2484
+ border: none;
2485
+ background: transparent;
2486
+ color: var(--cb-fg-subtle);
2487
+ cursor: pointer;
2488
+ padding: var(--cb-space-1);
2489
+ border-radius: var(--cb-radius-sm);
2490
+ display: inline-flex;
2491
+ }
2492
+ .cb-coachmark__close:hover { color: var(--cb-fg); background: var(--cb-bg-subtle); }
2493
+ .cb-coachmark__close:focus-visible { outline: var(--cb-focus-width) solid var(--cb-tone-brand); outline-offset: var(--cb-focus-offset); }
2494
+
2495
+ .cb-coachmark__body { font-size: var(--cb-text-sm); color: var(--cb-fg-muted); line-height: var(--cb-leading-normal); }
2496
+ .cb-coachmark__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--cb-space-3); }
2497
+ .cb-coachmark__progress { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); font-variant-numeric: tabular-nums; }
2498
+ .cb-coachmark__actions { display: flex; gap: var(--cb-space-2); }