@airframeui/tokens 0.1.4 → 0.3.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.
package/dist/tokens.css CHANGED
@@ -1,618 +1,624 @@
1
1
  /* @airframeui tokens.css (generated from CSS source files) */
2
+
3
+ /* Base tokens - shared across all themes */
4
+ /* @airframe base tokens - Foundation Primitives */
5
+
2
6
  @layer af.tokens {
7
+ :root {
8
+ /* --- Color primitives --- */
9
+ /* --light / --dark / --hc-* are stored values. The unsuffixed token is the
10
+ resolved color for the active scheme (light on :root). Dark and high-contrast
11
+ selectors reassign the unsuffixed name; they do not rely on "is the suffix
12
+ defined?" fallbacks, so brands can set every suffix at once on [data-brand]. */
13
+ --af-base-primary--light: #0876dd;
14
+ --af-base-primary: var(--af-base-primary--light);
15
+ --af-base-secondary--light: #dbe1f4;
16
+ --af-base-secondary: var(--af-base-secondary--light);
17
+ --af-base-tertiary--light: #111827;
18
+ --af-base-tertiary: var(--af-base-tertiary--light);
19
+ --af-base-success--light: #22c55e;
20
+ --af-base-success: var(--af-base-success--light);
21
+ --af-base-warning--light: #fbbf24;
22
+ --af-base-warning: var(--af-base-warning--light);
23
+ --af-base-danger--light: #dc2626;
24
+ --af-base-danger: var(--af-base-danger--light);
25
+ --af-base-info--light: #38bdf8;
26
+ --af-base-info: var(--af-base-info--light);
3
27
 
4
- /* Base tokens - shared across all themes */
5
- /* @airframe base tokens - Foundation Primitives */
6
-
7
- @layer af.tokens {
8
- :root {
9
- /* --- Color primitives --- */
10
- /* --light / --dark / --hc-* are stored values. The unsuffixed token is the
11
- resolved color for the active scheme (light on :root). Dark and high-contrast
12
- selectors reassign the unsuffixed name; they do not rely on "is the suffix
13
- defined?" fallbacks, so brands can set every suffix at once on [data-brand]. */
14
- --af-base-primary--light: #0876dd;
15
- --af-base-primary: var(--af-base-primary--light);
16
- --af-base-secondary--light: #dbe1f4;
17
- --af-base-secondary: var(--af-base-secondary--light);
18
- --af-base-tertiary--light: #111827;
19
- --af-base-tertiary: var(--af-base-tertiary--light);
20
- --af-base-success--light: #22c55e;
21
- --af-base-success: var(--af-base-success--light);
22
- --af-base-warning--light: #fbbf24;
23
- --af-base-warning: var(--af-base-warning--light);
24
- --af-base-danger--light: #dc2626;
25
- --af-base-danger: var(--af-base-danger--light);
26
- --af-base-info--light: #38bdf8;
27
- --af-base-info: var(--af-base-info--light);
28
-
29
- --af-base-white: #ffffff;
30
- --af-base-black: #000000;
31
- --af-base-neutral-50: #f8fafc;
32
- --af-base-neutral-100: #f1f5f9;
33
- --af-base-neutral-200: #e2e8f0;
34
- --af-base-neutral-300: #cbd5e1;
35
- --af-base-neutral-400: #94a3b8;
36
- --af-base-neutral-500: #64748b;
37
- --af-base-neutral-600: #475569;
38
- --af-base-neutral-700: #1d2434;
39
- --af-base-neutral-800: #121620;
40
- --af-base-neutral-900: #0d1117;
41
-
42
- /* --- Breakpoints --- */
43
- --af-bp-xs: 360px;
44
- --af-bp-sm: 640px;
45
- --af-bp-md: 768px;
46
- --af-bp-lg: 1024px;
47
- --af-bp-xl: 1280px;
48
- --af-bp-2xl: 1536px;
49
-
50
- /* --- Space scale (used by af-gap-*, af-p-*, etc.) --- */
51
- --af-space-0: 0px;
52
- --af-space-1: 4px;
53
- --af-space-2: 8px;
54
- --af-space-3: 12px;
55
- --af-space-4: 16px;
56
- --af-space-5: 24px;
57
- --af-space-6: 32px;
58
- --af-space-7: 40px;
59
- --af-space-8: 48px;
60
-
61
- /* --- Radii --- */
62
- --af-radius-0: 0px;
63
- --af-radius-sm: 6px;
64
- --af-radius-md: 10px;
65
- --af-radius-lg: 16px;
66
- --af-radius-xl: 24px;
67
- --af-radius-full: 9999px;
68
-
69
- /* --- Typography primitives --- */
70
- --af-base-font-sans:
71
- ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial,
72
- 'Apple Color Emoji', 'Segoe UI Emoji';
73
- --af-base-font-mono:
74
- ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
75
- monospace;
76
- --af-font-primary: var(--af-base-font-sans);
77
- --af-font-mono: var(--af-base-font-mono);
78
-
79
- /* Type scale — modular SaaS ramp (12 72) */
80
- --af-text-xs: 0.75rem; /* 12 badges, meta */
81
- --af-text-sm: 0.875rem; /* 14 labels, captions */
82
- --af-text-md: 1rem; /* 16 body */
83
- --af-text-lg: 1.1875rem; /* 19 — emphasized body */
84
- --af-text-xl: 1.5rem; /* 24 section titles */
85
- --af-text-2xl: 2rem; /* 32 — page titles */
86
- --af-text-3xl: 2.5rem; /* 40 — h1 */
87
- --af-text-4xl: 3.5rem; /* 56 — display */
88
- --af-text-5xl: 4.5rem; /* 72 — hero */
89
-
90
- --af-leading-tight: 1.15;
91
- --af-leading-normal: 1.55;
92
- --af-leading-loose: 1.75;
93
-
94
- --af-weight-regular: 400;
95
- --af-weight-medium: 500;
96
- --af-weight-semibold: 600;
97
- --af-weight-bold: 700;
98
- --af-weight-extrabold: 800;
99
-
100
- /* --- Shadows (keep simple, override-friendly) --- */
101
- --af-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
102
- --af-shadow-md: 0 6px 16px rgba(0, 0, 0, 0.1);
103
- --af-shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.14);
104
-
105
- /* --- Z-index scale --- */
106
- --af-z-base: 0;
107
- --af-z-dropdown: 1000;
108
- --af-z-sticky: 1100;
109
- --af-z-overlay: 1200;
110
- --af-z-modal: 1300;
111
- --af-z-toast: 1400;
112
- --af-z-loader: 1500;
113
-
114
- /* --- Motion --- */
115
- --af-duration-fast: 120ms;
116
- --af-duration-md: 200ms;
117
- --af-duration-slow: 320ms;
118
-
119
- /* Animation durations (for keyframe animations) */
120
- --af-animation-duration-fast: 200ms;
121
- --af-animation-duration-md: 400ms;
122
- --af-animation-duration-slow: 600ms;
123
- --af-animation-duration-slower: 1500ms;
124
-
125
- --af-ease-standard: cubic-bezier(0.2, 0, 0.2, 1);
126
- --af-ease-emphasized: cubic-bezier(0.2, 0, 0, 1);
127
- --af-ease-in: cubic-bezier(0.4, 0, 1, 1);
128
- --af-ease-out: cubic-bezier(0, 0, 0.2, 1);
129
- --af-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
130
- --af-ease-linear: linear;
131
-
132
- /* --- Borders --- */
133
- --af-border-width: 1px;
134
- --af-hit-size: 2.75rem;
135
-
136
- /* --- Global knobs (for color-mix derivations) --- */
137
- --af-hover-mix: 12%;
138
- --af-active-mix: 18%;
139
- --af-soft-mix: 12%;
140
- /* Hard text on soft tints: mix toward black in light, white in dark */
141
- --af-hard-mix: 45%;
142
- --af-hard-toward: black;
143
- --af-border-mix: 22%;
144
-
145
- /* --- Layout semantics --- */
146
- --af-layout-gap: var(--af-space-4);
147
- --af-sidebar-width: 16rem;
148
- --af-drawer-width: 20rem;
149
- --af-divider-spacing: var(--af-space-5);
150
- --af-container-padding-x: var(--af-space-4);
151
- --af-container-max-w: 90em; /* 1440px */
152
- --af-container-max-w-xs: 25rem; /* 400px */
153
- --af-container-max-w-sm: 40rem; /* 640px */
154
- --af-container-max-w-md: 48rem; /* 768px */
155
- --af-container-max-w-lg: 64rem; /* 1024px */
156
- --af-container-max-w-xl: 80rem; /* 1280px */
157
- --af-container-max-w-2xl: 96rem; /* 1536px */
158
-
159
- /* --- Typography semantics (roles) --- */
160
- --af-font-body: var(--af-base-font-sans);
161
- --af-font-heading: var(--af-font-primary);
162
- --af-font-code: var(--af-base-font-mono);
163
-
164
- --af-text-body-size: var(--af-text-md);
165
- --af-text-body-leading: var(--af-leading-normal);
166
- --af-text-heading-leading: var(--af-leading-tight);
167
- --af-text-heading-weight: var(--af-weight-semibold);
168
-
169
- --af-type-display-size: var(--af-text-5xl);
170
- --af-type-display-weight: var(--af-weight-bold);
171
- --af-type-display-leading: var(--af-leading-tight);
172
-
173
- --af-type-h1-size: var(--af-text-3xl);
174
- --af-type-h2-size: var(--af-text-2xl);
175
- --af-type-h3-size: var(--af-text-xl);
176
- --af-type-h4-size: var(--af-text-lg);
177
- --af-type-h5-size: var(--af-text-md);
178
- --af-type-h6-size: var(--af-text-sm);
179
- --af-type-body-size: var(--af-text-md);
180
- --af-type-caption-size: var(--af-text-sm);
181
-
182
- --af-type-h1-weight: var(--af-weight-semibold);
183
- --af-type-h2-weight: var(--af-weight-semibold);
184
- --af-type-h3-weight: var(--af-weight-semibold);
185
- --af-type-h4-weight: var(--af-weight-semibold);
186
- --af-type-h5-weight: var(--af-weight-semibold);
187
- --af-type-h6-weight: var(--af-weight-semibold);
188
- --af-type-body-weight: var(--af-weight-regular);
189
- --af-type-caption-weight: var(--af-weight-regular);
190
-
191
- --af-type-h1-leading: var(--af-leading-tight);
192
- --af-type-h2-leading: var(--af-leading-tight);
193
- --af-type-h3-leading: var(--af-leading-tight);
194
- --af-type-h4-leading: var(--af-leading-normal);
195
- --af-type-h5-leading: var(--af-leading-normal);
196
- --af-type-h6-leading: var(--af-leading-normal);
197
- --af-type-body-leading: var(--af-leading-normal);
198
- --af-type-caption-leading: var(--af-leading-normal);
199
-
200
- --af-type-h1-tracking: -0.02em;
201
- --af-type-h2-tracking: -0.01em;
202
- --af-type-h3-tracking: 0em;
203
- --af-type-h4-tracking: 0em;
204
- --af-type-h5-tracking: 0em;
205
- --af-type-h6-tracking: 0em;
206
-
207
- /* --- Component tokens (thin layer for common customizations) --- */
208
-
209
- /* Shared control tokens (for inputs, selects, etc.) */
210
- --af-control-min-height: auto;
211
- --af-control-radius: var(--af-radius-lg);
212
- --af-control-padding-y: var(--af-space-2);
213
- --af-control-padding-x: var(--af-space-3);
214
- --af-control-border-width: 1px;
215
- --af-control-border: var(--af-color-border);
216
- --af-control-border-hover: var(--af-color-border-strong);
217
-
218
- /* Choice controls (checkbox, radio, switch track) */
219
- --af-choice-size: 1.5rem;
220
- --af-switch-height: var(--af-choice-size);
221
- --af-switch-width-ratio: 0.8;
222
- --af-switch-thumb-inset: 2px;
223
-
224
- /* Link */
225
- --af-link-primary: var(--af-color-primary);
226
- --af-link-hover-primary: var(--af-color-primary-hover);
227
-
228
- /* Button */
229
- --af-btn-min-height: var(--af-control-min-height);
230
- --af-btn-radius: var(--af-radius-full);
231
- --af-btn-padding-y: var(--af-control-padding-y);
232
- --af-btn-padding-x: var(--af-space-4);
233
- --af-btn-gap: var(--af-space-2);
234
- --af-btn-icon-size: 1.25rem;
235
- --af-btn-icon-button-size: var(--af-hit-size);
236
- --af-btn-font-weight: var(--af-weight-medium);
237
- --af-btn-border-width: 1px;
238
- /* Hover darkens in light theme; dark theme flips these toward lighten */
239
- --af-btn-hover-brightness: 0.9;
240
- --af-btn-active-brightness: 0.82;
241
-
242
- --af-btn-default-bg: var(--af-color-primary);
243
- --af-btn-default-color: var(--af-color-on-primary);
244
- --af-btn-default-hover: var(--af-color-primary-hover);
245
- --af-btn-default-active: var(--af-color-primary-active);
246
-
247
- --af-btn-secondary-bg: var(--af-color-secondary);
248
- --af-btn-secondary-color: var(--af-color-on-secondary);
249
- --af-btn-secondary-hover: var(--af-color-secondary-hover);
250
- --af-btn-secondary-active: var(--af-color-secondary-active);
251
-
252
- --af-btn-outline-color: var(--af-color-primary);
253
- --af-btn-outline-border: var(--af-color-primary);
254
- --af-btn-outline-hover: var(--af-color-primary-hover);
255
- --af-btn-outline-hover-bg: var(--af-color-primary-soft);
256
- --af-btn-outline-active: color-mix(
257
- in srgb,
258
- var(--af-color-primary),
259
- var(--af-color-surface-primary) 84%
260
- );
261
-
262
- /* Input */
263
- --af-input-min-height: var(--af-hit-size);
264
- --af-input-radius: var(--af-control-radius);
265
- --af-input-padding-y: var(--af-control-padding-y);
266
- --af-input-padding-x: var(--af-control-padding-x);
267
- --af-input-border-width: var(--af-control-border-width);
268
- --af-input-border: var(--af-control-border);
269
- --af-input-border-hover: var(--af-control-border-hover);
270
- --af-input-border-focus: var(--af-color-primary);
271
- --af-input-font-size: var(--af-text-md);
272
- --af-input-leading: var(--af-leading-normal);
273
- --af-input-placeholder-color: var(--af-color-text-muted);
274
-
275
- /* Card */
276
- --af-card-radius: var(--af-radius-lg);
277
- --af-card-padding: var(--af-space-5);
278
- --af-card-border-width: 1px;
279
- --af-card-shadow: var(--af-shadow-sm);
280
- --af-card-shadow-hover: var(--af-shadow-md);
281
- --af-card-gap: var(--af-space-3);
282
-
283
- /* Focus ring */
284
- --af-color-focus: var(--af-color-primary);
285
- --af-focus-ring-color: var(--af-color-focus);
286
- --af-focus-ring-width: 2px;
287
- --af-focus-ring-offset: 2px;
288
-
289
- /* --- Intents (shared across all themes) --- */
290
- --af-color-primary: var(--af-base-primary);
291
- --af-color-secondary: var(--af-base-secondary);
292
- --af-color-tertiary: var(--af-base-tertiary);
293
- --af-color-danger: var(--af-base-danger);
294
- --af-color-success: var(--af-base-success);
295
- --af-color-warning: var(--af-base-warning);
296
- --af-color-info: var(--af-base-info);
297
-
298
- /* Default on-intent colors (scheme selectors reassign the unsuffixed token) */
299
- --af-color-on-primary--light: var(--af-base-white);
300
- --af-color-on-primary: var(--af-color-on-primary--light);
301
- --af-color-on-secondary--light: var(--af-base-neutral-900);
302
- --af-color-on-secondary: var(--af-color-on-secondary--light);
303
- --af-color-on-tertiary--light: var(--af-base-white);
304
- --af-color-on-tertiary: var(--af-color-on-tertiary--light);
305
- --af-color-on-danger--light: var(--af-base-white);
306
- --af-color-on-danger: var(--af-color-on-danger--light);
307
- --af-color-on-success--light: var(--af-base-neutral-900);
308
- --af-color-on-success: var(--af-color-on-success--light);
309
- --af-color-on-warning--light: var(--af-base-neutral-900);
310
- --af-color-on-warning: var(--af-color-on-warning--light);
311
- --af-color-on-info--light: var(--af-base-white);
312
- --af-color-on-info: var(--af-color-on-info--light);
313
-
314
- /* --- Action (semantic CTA/brand color; defaults to primary, overridable per scheme) --- */
315
- --af-color-action: var(--af-color-action--light, var(--af-color-primary));
316
- --af-color-on-action: var(--af-color-on-action--light, var(--af-color-on-primary));
317
-
318
- /* --- Derived interaction tokens (via color-mix) --- */
319
- /* These automatically use theme-specific --af-color-surface-primary */
320
- --af-color-primary-hover: color-mix(
321
- in srgb,
322
- var(--af-color-primary),
323
- black var(--af-hover-mix)
324
- );
325
- --af-color-primary-active: color-mix(
326
- in srgb,
327
- var(--af-color-primary),
328
- black var(--af-active-mix)
329
- );
330
- --af-color-primary-soft: color-mix(
331
- in srgb,
332
- var(--af-color-primary),
333
- var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
334
- );
335
- --af-color-primary-hard: color-mix(
336
- in srgb,
337
- var(--af-color-primary),
338
- var(--af-hard-toward) var(--af-hard-mix)
339
- );
340
-
341
- --af-color-action-hover: color-mix(in srgb, var(--af-color-action), black var(--af-hover-mix));
342
- --af-color-action-active: color-mix(
343
- in srgb,
344
- var(--af-color-action),
345
- black var(--af-active-mix)
346
- );
347
- --af-color-action-soft: color-mix(
348
- in srgb,
349
- var(--af-color-action),
350
- var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
351
- );
352
- --af-color-action-hard: color-mix(
353
- in srgb,
354
- var(--af-color-action),
355
- var(--af-hard-toward) var(--af-hard-mix)
356
- );
357
-
358
- --af-color-secondary-hover: color-mix(
359
- in srgb,
360
- var(--af-color-secondary),
361
- black var(--af-hover-mix)
362
- );
363
- --af-color-secondary-active: color-mix(
364
- in srgb,
365
- var(--af-color-secondary),
366
- black var(--af-active-mix)
367
- );
368
- --af-color-secondary-soft: color-mix(
369
- in srgb,
370
- var(--af-color-secondary),
371
- var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
372
- );
373
- --af-color-secondary-hard: color-mix(
374
- in srgb,
375
- var(--af-color-secondary),
376
- var(--af-hard-toward) var(--af-hard-mix)
377
- );
378
-
379
- --af-color-tertiary-hover: color-mix(
380
- in srgb,
381
- var(--af-color-tertiary),
382
- black var(--af-hover-mix)
383
- );
384
- --af-color-tertiary-active: color-mix(
385
- in srgb,
386
- var(--af-color-tertiary),
387
- black var(--af-active-mix)
388
- );
389
- --af-color-tertiary-soft: color-mix(
390
- in srgb,
391
- var(--af-color-tertiary),
392
- var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
393
- );
394
- --af-color-tertiary-hard: color-mix(
395
- in srgb,
396
- var(--af-color-tertiary),
397
- var(--af-hard-toward) var(--af-hard-mix)
398
- );
399
-
400
- --af-color-success-hover: color-mix(
401
- in srgb,
402
- var(--af-color-success),
403
- black var(--af-hover-mix)
404
- );
405
- --af-color-success-active: color-mix(
406
- in srgb,
407
- var(--af-color-success),
408
- black var(--af-active-mix)
409
- );
410
- --af-color-success-soft: color-mix(
411
- in srgb,
412
- var(--af-color-success),
413
- var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
414
- );
415
- --af-color-success-hard: color-mix(
416
- in srgb,
417
- var(--af-color-success),
418
- var(--af-hard-toward) var(--af-hard-mix)
419
- );
420
-
421
- --af-color-warning-hover: color-mix(
422
- in srgb,
423
- var(--af-color-warning),
424
- black var(--af-hover-mix)
425
- );
426
- --af-color-warning-active: color-mix(
427
- in srgb,
428
- var(--af-color-warning),
429
- black var(--af-active-mix)
430
- );
431
- --af-color-warning-soft: color-mix(
432
- in srgb,
433
- var(--af-color-warning),
434
- var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
435
- );
436
- --af-color-warning-hard: color-mix(
437
- in srgb,
438
- var(--af-color-warning),
439
- var(--af-hard-toward) var(--af-hard-mix)
440
- );
441
-
442
- --af-color-danger-hover: color-mix(in srgb, var(--af-color-danger), black var(--af-hover-mix));
443
- --af-color-danger-active: color-mix(
444
- in srgb,
445
- var(--af-color-danger),
446
- black var(--af-active-mix)
447
- );
448
- --af-color-danger-soft: color-mix(
449
- in srgb,
450
- var(--af-color-danger),
451
- var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
452
- );
453
- --af-color-danger-hard: color-mix(
454
- in srgb,
455
- var(--af-color-danger),
456
- var(--af-hard-toward) var(--af-hard-mix)
457
- );
458
-
459
- --af-color-info-hover: color-mix(in srgb, var(--af-color-info), black var(--af-hover-mix));
460
- --af-color-info-active: color-mix(in srgb, var(--af-color-info), black var(--af-active-mix));
461
- --af-color-info-soft: color-mix(
462
- in srgb,
463
- var(--af-color-info),
464
- var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
465
- );
466
- --af-color-info-hard: color-mix(
467
- in srgb,
468
- var(--af-color-info),
469
- var(--af-hard-toward) var(--af-hard-mix)
470
- );
471
- }
472
-
473
- /* Reduced motion support - override timing variables */
474
- @media (prefers-reduced-motion: reduce) {
475
- :root {
476
- --af-duration-fast: 0.01ms;
477
- --af-duration-md: 0.01ms;
478
- --af-duration-slow: 0.01ms;
479
- --af-animation-duration-fast: 0.01ms;
480
- --af-animation-duration-md: 0.01ms;
481
- --af-animation-duration-slow: 0.01ms;
482
- --af-animation-duration-slower: 0.01ms;
483
- }
484
- }
28
+ --af-base-white: #ffffff;
29
+ --af-base-black: #000000;
30
+ --af-base-neutral-50: #f8fafc;
31
+ --af-base-neutral-100: #f1f5f9;
32
+ --af-base-neutral-200: #e2e8f0;
33
+ --af-base-neutral-300: #cbd5e1;
34
+ --af-base-neutral-400: #94a3b8;
35
+ --af-base-neutral-500: #64748b;
36
+ --af-base-neutral-600: #475569;
37
+ --af-base-neutral-700: #1d2434;
38
+ --af-base-neutral-800: #121620;
39
+ --af-base-neutral-900: #0d1117;
40
+
41
+ /* --- Breakpoints --- */
42
+ --af-bp-xs: 360px;
43
+ --af-bp-sm: 640px;
44
+ --af-bp-md: 768px;
45
+ --af-bp-lg: 1024px;
46
+ --af-bp-xl: 1280px;
47
+ --af-bp-2xl: 1536px;
48
+
49
+ /* --- Space scale (used by af-gap-*, af-p-*, etc.) --- */
50
+ --af-space-0: 0px;
51
+ --af-space-1: 4px;
52
+ --af-space-2: 8px;
53
+ --af-space-3: 12px;
54
+ --af-space-4: 16px;
55
+ --af-space-5: 24px;
56
+ --af-space-6: 32px;
57
+ --af-space-7: 40px;
58
+ --af-space-8: 48px;
59
+
60
+ /* --- Radii (4px grid, same steps as space-1…4) --- */
61
+ --af-radius-0: 0px;
62
+ --af-radius-sm: 4px;
63
+ --af-radius-md: 8px;
64
+ --af-radius-lg: 12px;
65
+ --af-radius-xl: 16px;
66
+ --af-radius-full: 9999px;
67
+ /* Semantic default — cards, controls, buttons, dialogs, surfaces */
68
+ --af-radius: var(--af-radius-md);
69
+ /* Capsule / pill shape — af-pill, steps, scrollbar thumbs, opt-in buttons */
70
+ --af-pill-radius: var(--af-radius-full);
71
+
72
+ /* --- Typography primitives --- */
73
+ --af-base-font-sans:
74
+ ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial,
75
+ 'Apple Color Emoji', 'Segoe UI Emoji';
76
+ --af-base-font-mono:
77
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
78
+ monospace;
79
+ --af-font-primary: var(--af-base-font-sans);
80
+ --af-font-mono: var(--af-base-font-mono);
81
+
82
+ /* Type scale — modular SaaS ramp (12 → 72) */
83
+ --af-text-xs: 0.75rem; /* 12 — badges, meta */
84
+ --af-text-sm: 0.875rem; /* 14 — labels, captions */
85
+ --af-text-md: 1rem; /* 16 body */
86
+ --af-text-lg: 1.1875rem; /* 19 — emphasized body */
87
+ --af-text-xl: 1.5rem; /* 24 — section titles */
88
+ --af-text-2xl: 2rem; /* 32 — page titles */
89
+ --af-text-3xl: 2.5rem; /* 40 — h1 */
90
+ --af-text-4xl: 3.5rem; /* 56 — display */
91
+ --af-text-5xl: 4.5rem; /* 72 — hero */
92
+
93
+ --af-leading-tight: 1.15;
94
+ --af-leading-normal: 1.55;
95
+ --af-leading-loose: 1.75;
96
+
97
+ --af-weight-regular: 400;
98
+ --af-weight-medium: 500;
99
+ --af-weight-semibold: 600;
100
+ --af-weight-bold: 700;
101
+ --af-weight-extrabold: 800;
102
+
103
+ /* --- Shadows (keep simple, override-friendly) --- */
104
+ --af-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
105
+ --af-shadow-md: 0 6px 16px rgba(0, 0, 0, 0.1);
106
+ --af-shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.14);
107
+
108
+ /* --- Z-index scale --- */
109
+ --af-z-base: 0;
110
+ --af-z-dropdown: 1000;
111
+ --af-z-sticky: 1100;
112
+ --af-z-overlay: 1200;
113
+ --af-z-modal: 1300;
114
+ --af-z-toast: 1400;
115
+ --af-z-loader: 1500;
116
+
117
+ /* --- Motion --- */
118
+ --af-duration-fast: 120ms;
119
+ --af-duration-md: 200ms;
120
+ --af-duration-slow: 320ms;
121
+
122
+ /* Animation durations (for keyframe animations) */
123
+ --af-animation-duration-fast: 200ms;
124
+ --af-animation-duration-md: 400ms;
125
+ --af-animation-duration-slow: 600ms;
126
+ --af-animation-duration-slower: 1500ms;
127
+
128
+ --af-ease-standard: cubic-bezier(0.2, 0, 0.2, 1);
129
+ --af-ease-emphasized: cubic-bezier(0.2, 0, 0, 1);
130
+ --af-ease-in: cubic-bezier(0.4, 0, 1, 1);
131
+ --af-ease-out: cubic-bezier(0, 0, 0.2, 1);
132
+ --af-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
133
+ --af-ease-linear: linear;
134
+
135
+ /* --- Borders --- */
136
+ --af-border-width: 1px;
137
+ --af-hit-size: 2.75rem;
138
+
139
+ /* --- Global knobs (for color-mix derivations) --- */
140
+ --af-hover-mix: 12%;
141
+ --af-active-mix: 18%;
142
+ --af-soft-mix: 12%;
143
+ /* Hard text on soft tints: mix toward black in light, white in dark */
144
+ --af-hard-mix: 45%;
145
+ --af-hard-toward: black;
146
+ --af-border-mix: 22%;
147
+
148
+ /* --- Layout semantics --- */
149
+ --af-layout-gap: var(--af-space-4);
150
+ --af-sidebar-width: 16rem;
151
+ --af-drawer-width: 20rem;
152
+ --af-divider-spacing: var(--af-space-5);
153
+ --af-container-padding-x: var(--af-space-4);
154
+ --af-container-max-w: 90em; /* 1440px */
155
+ --af-container-max-w-xs: 25rem; /* 400px */
156
+ --af-container-max-w-sm: 40rem; /* 640px */
157
+ --af-container-max-w-md: 48rem; /* 768px */
158
+ --af-container-max-w-lg: 64rem; /* 1024px */
159
+ --af-container-max-w-xl: 80rem; /* 1280px */
160
+ --af-container-max-w-2xl: 96rem; /* 1536px */
161
+
162
+ /* --- Typography semantics (roles) --- */
163
+ --af-font-body: var(--af-base-font-sans);
164
+ --af-font-heading: var(--af-font-primary);
165
+ --af-font-code: var(--af-base-font-mono);
166
+
167
+ --af-text-body-size: var(--af-text-md);
168
+ --af-text-body-leading: var(--af-leading-normal);
169
+ --af-text-heading-leading: var(--af-leading-tight);
170
+ --af-text-heading-weight: var(--af-weight-semibold);
171
+
172
+ --af-type-display-size: var(--af-text-5xl);
173
+ --af-type-display-weight: var(--af-weight-bold);
174
+ --af-type-display-leading: var(--af-leading-tight);
175
+
176
+ --af-type-h1-size: var(--af-text-3xl);
177
+ --af-type-h2-size: var(--af-text-2xl);
178
+ --af-type-h3-size: var(--af-text-xl);
179
+ --af-type-h4-size: var(--af-text-lg);
180
+ --af-type-h5-size: var(--af-text-md);
181
+ --af-type-h6-size: var(--af-text-sm);
182
+ --af-type-body-size: var(--af-text-md);
183
+ --af-type-caption-size: var(--af-text-sm);
184
+
185
+ --af-type-h1-weight: var(--af-weight-semibold);
186
+ --af-type-h2-weight: var(--af-weight-semibold);
187
+ --af-type-h3-weight: var(--af-weight-semibold);
188
+ --af-type-h4-weight: var(--af-weight-semibold);
189
+ --af-type-h5-weight: var(--af-weight-semibold);
190
+ --af-type-h6-weight: var(--af-weight-semibold);
191
+ --af-type-body-weight: var(--af-weight-regular);
192
+ --af-type-caption-weight: var(--af-weight-regular);
193
+
194
+ --af-type-h1-leading: var(--af-leading-tight);
195
+ --af-type-h2-leading: var(--af-leading-tight);
196
+ --af-type-h3-leading: var(--af-leading-tight);
197
+ --af-type-h4-leading: var(--af-leading-normal);
198
+ --af-type-h5-leading: var(--af-leading-normal);
199
+ --af-type-h6-leading: var(--af-leading-normal);
200
+ --af-type-body-leading: var(--af-leading-normal);
201
+ --af-type-caption-leading: var(--af-leading-normal);
202
+
203
+ --af-type-h1-tracking: -0.02em;
204
+ --af-type-h2-tracking: -0.01em;
205
+ --af-type-h3-tracking: 0em;
206
+ --af-type-h4-tracking: 0em;
207
+ --af-type-h5-tracking: 0em;
208
+ --af-type-h6-tracking: 0em;
209
+
210
+ /* --- Component tokens (thin layer for common customizations) --- */
211
+
212
+ /* Shared control tokens (for inputs, selects, etc.) */
213
+ --af-control-min-height: var(--af-hit-size);
214
+ --af-control-radius: var(--af-radius);
215
+ --af-control-padding-y: var(--af-space-2);
216
+ --af-control-padding-x: var(--af-space-3);
217
+ --af-control-border-width: var(--af-border-width);
218
+ --af-control-border: var(--af-color-border);
219
+ --af-control-border-hover: var(--af-color-border-strong);
220
+
221
+ /* Choice controls (checkbox, radio, switch track) */
222
+ --af-choice-size: 1.5rem;
223
+ --af-switch-height: var(--af-choice-size);
224
+ --af-switch-width-ratio: 0.8;
225
+ --af-switch-thumb-inset: 2px;
226
+
227
+ /* Range slider */
228
+ --af-range-track-height: 0.625rem;
229
+ --af-range-thumb-size: 1.25rem;
230
+
231
+ /* Link */
232
+ --af-link-primary: var(--af-color-primary);
233
+ --af-link-hover-primary: var(--af-color-primary-hover);
234
+ --af-link-decoration: underline;
235
+ --af-link-hover-decoration: underline;
236
+
237
+ /* Button */
238
+ --af-btn-min-height: var(--af-control-min-height);
239
+ --af-btn-radius: var(--af-radius);
240
+ --af-btn-padding-y: var(--af-control-padding-y);
241
+ --af-btn-padding-x: var(--af-space-4);
242
+ --af-btn-gap: var(--af-space-2);
243
+ --af-btn-icon-size: 1.25rem;
244
+ --af-btn-icon-button-size: var(--af-hit-size);
245
+ --af-btn-font-weight: var(--af-weight-medium);
246
+ --af-btn-border-width: var(--af-border-width);
247
+ /* Filled borders are off. Set --af-btn-border to a color, or to
248
+ var(--af-btn-border-auto), to paint them. Ghost/link do not follow this master.
249
+ --af-btn-border-auto and variant / hover / focus tokens are initial so a scoped
250
+ alias is not frozen at :root (CSS inherits the computed value). Each .af-btn
251
+ remaps --af-btn-border-auto to its active tint. */
252
+ --af-btn-border: transparent;
253
+ --af-btn-border-hover: initial;
254
+ --af-btn-border-focus: initial;
255
+ --af-btn-border-auto: initial;
256
+ /* Hover darkens in light theme; dark theme flips these toward lighten */
257
+ --af-btn-hover-brightness: 0.9;
258
+ --af-btn-active-brightness: 0.82;
259
+
260
+ --af-btn-default-bg: var(--af-color-primary);
261
+ --af-btn-default-color: var(--af-color-on-primary);
262
+ --af-btn-default-hover: var(--af-color-primary-hover);
263
+ --af-btn-default-active: var(--af-color-primary-active);
264
+ --af-btn-default-border: initial;
265
+ --af-btn-default-border-hover: initial;
266
+ --af-btn-default-border-focus: initial;
267
+
268
+ --af-btn-secondary-bg: var(--af-color-secondary);
269
+ --af-btn-secondary-color: var(--af-color-on-secondary);
270
+ --af-btn-secondary-hover: var(--af-color-secondary-hover);
271
+ --af-btn-secondary-active: var(--af-color-secondary-active);
272
+ --af-btn-secondary-border: initial;
273
+ --af-btn-secondary-border-hover: initial;
274
+ --af-btn-secondary-border-focus: initial;
275
+
276
+ --af-btn-tertiary-border: initial;
277
+ --af-btn-tertiary-border-hover: initial;
278
+ --af-btn-tertiary-border-focus: initial;
279
+
280
+ --af-btn-success-border: initial;
281
+ --af-btn-success-border-hover: initial;
282
+ --af-btn-success-border-focus: initial;
283
+
284
+ --af-btn-warning-border: initial;
285
+ --af-btn-warning-border-hover: initial;
286
+ --af-btn-warning-border-focus: initial;
287
+
288
+ --af-btn-danger-border: initial;
289
+ --af-btn-danger-border-hover: initial;
290
+ --af-btn-danger-border-focus: initial;
291
+
292
+ --af-btn-info-border: initial;
293
+ --af-btn-info-border-hover: initial;
294
+ --af-btn-info-border-focus: initial;
295
+
296
+ --af-btn-ghost-border: transparent;
297
+
298
+ --af-btn-outline-color: var(--af-color-primary);
299
+ --af-btn-outline-border: var(--af-color-primary);
300
+ --af-btn-outline-hover: var(--af-color-primary-hover);
301
+ --af-btn-outline-hover-bg: var(--af-color-primary-soft);
302
+ --af-btn-outline-active: color-mix(
303
+ in srgb,
304
+ var(--af-color-primary),
305
+ var(--af-color-surface-primary) 84%
306
+ );
307
+
308
+ /* Input */
309
+ --af-input-min-height: var(--af-hit-size);
310
+ --af-input-radius: var(--af-control-radius);
311
+ --af-input-padding-y: var(--af-control-padding-y);
312
+ --af-input-padding-x: var(--af-control-padding-x);
313
+ --af-input-border-width: var(--af-control-border-width);
314
+ --af-input-border: var(--af-control-border);
315
+ --af-input-border-hover: var(--af-control-border-hover);
316
+ --af-input-border-focus: var(--af-color-primary);
317
+ --af-input-font-size: var(--af-text-md);
318
+ --af-input-leading: var(--af-leading-normal);
319
+ --af-input-placeholder-color: var(--af-color-text-muted);
320
+
321
+ /* Card */
322
+ --af-card-radius: var(--af-radius);
323
+ --af-card-padding: var(--af-space-5);
324
+ --af-card-border-width: 1px;
325
+ --af-card-shadow: var(--af-shadow-sm);
326
+ --af-card-shadow-hover: var(--af-shadow-md);
327
+ --af-card-gap: var(--af-space-3);
328
+
329
+ /* Focus ring */
330
+ --af-color-focus: var(--af-color-primary);
331
+ --af-focus-ring-color: var(--af-color-focus);
332
+ --af-focus-ring-width: 2px;
333
+ --af-focus-ring-offset: 2px;
334
+
335
+ /* --- Intents (shared across all themes) --- */
336
+ --af-color-primary: var(--af-base-primary);
337
+ --af-color-secondary: var(--af-base-secondary);
338
+ --af-color-tertiary: var(--af-base-tertiary);
339
+ --af-color-danger: var(--af-base-danger);
340
+ --af-color-success: var(--af-base-success);
341
+ --af-color-warning: var(--af-base-warning);
342
+ --af-color-info: var(--af-base-info);
343
+
344
+ /* Default on-intent colors (scheme selectors reassign the unsuffixed token) */
345
+ --af-color-on-primary--light: var(--af-base-white);
346
+ --af-color-on-primary: var(--af-color-on-primary--light);
347
+ --af-color-on-secondary--light: var(--af-base-neutral-900);
348
+ --af-color-on-secondary: var(--af-color-on-secondary--light);
349
+ --af-color-on-tertiary--light: var(--af-base-white);
350
+ --af-color-on-tertiary: var(--af-color-on-tertiary--light);
351
+ --af-color-on-danger--light: var(--af-base-white);
352
+ --af-color-on-danger: var(--af-color-on-danger--light);
353
+ --af-color-on-success--light: var(--af-base-neutral-900);
354
+ --af-color-on-success: var(--af-color-on-success--light);
355
+ --af-color-on-warning--light: var(--af-base-neutral-900);
356
+ --af-color-on-warning: var(--af-color-on-warning--light);
357
+ --af-color-on-info--light: var(--af-base-white);
358
+ --af-color-on-info: var(--af-color-on-info--light);
359
+
360
+ /* --- Action (semantic CTA/brand color; defaults to primary, overridable per scheme) --- */
361
+ --af-color-action: var(--af-color-action--light, var(--af-color-primary));
362
+ --af-color-on-action: var(--af-color-on-action--light, var(--af-color-on-primary));
363
+
364
+ /* --- Derived interaction tokens (via color-mix) --- */
365
+ /* These automatically use theme-specific --af-color-surface-primary */
366
+ --af-color-primary-hover: color-mix(
367
+ in srgb,
368
+ var(--af-color-primary),
369
+ black var(--af-hover-mix)
370
+ );
371
+ --af-color-primary-active: color-mix(
372
+ in srgb,
373
+ var(--af-color-primary),
374
+ black var(--af-active-mix)
375
+ );
376
+ --af-color-primary-soft: color-mix(
377
+ in srgb,
378
+ var(--af-color-primary),
379
+ var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
380
+ );
381
+ --af-color-primary-hard: color-mix(
382
+ in srgb,
383
+ var(--af-color-primary),
384
+ var(--af-hard-toward) var(--af-hard-mix)
385
+ );
386
+
387
+ --af-color-action-hover: color-mix(in srgb, var(--af-color-action), black var(--af-hover-mix));
388
+ --af-color-action-active: color-mix(
389
+ in srgb,
390
+ var(--af-color-action),
391
+ black var(--af-active-mix)
392
+ );
393
+ --af-color-action-soft: color-mix(
394
+ in srgb,
395
+ var(--af-color-action),
396
+ var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
397
+ );
398
+ --af-color-action-hard: color-mix(
399
+ in srgb,
400
+ var(--af-color-action),
401
+ var(--af-hard-toward) var(--af-hard-mix)
402
+ );
403
+
404
+ --af-color-secondary-hover: color-mix(
405
+ in srgb,
406
+ var(--af-color-secondary),
407
+ black var(--af-hover-mix)
408
+ );
409
+ --af-color-secondary-active: color-mix(
410
+ in srgb,
411
+ var(--af-color-secondary),
412
+ black var(--af-active-mix)
413
+ );
414
+ --af-color-secondary-soft: color-mix(
415
+ in srgb,
416
+ var(--af-color-secondary),
417
+ var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
418
+ );
419
+ --af-color-secondary-hard: color-mix(
420
+ in srgb,
421
+ var(--af-color-secondary),
422
+ var(--af-hard-toward) var(--af-hard-mix)
423
+ );
424
+
425
+ --af-color-tertiary-hover: color-mix(
426
+ in srgb,
427
+ var(--af-color-tertiary),
428
+ black var(--af-hover-mix)
429
+ );
430
+ --af-color-tertiary-active: color-mix(
431
+ in srgb,
432
+ var(--af-color-tertiary),
433
+ black var(--af-active-mix)
434
+ );
435
+ --af-color-tertiary-soft: color-mix(
436
+ in srgb,
437
+ var(--af-color-tertiary),
438
+ var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
439
+ );
440
+ --af-color-tertiary-hard: color-mix(
441
+ in srgb,
442
+ var(--af-color-tertiary),
443
+ var(--af-hard-toward) var(--af-hard-mix)
444
+ );
445
+
446
+ --af-color-success-hover: color-mix(
447
+ in srgb,
448
+ var(--af-color-success),
449
+ black var(--af-hover-mix)
450
+ );
451
+ --af-color-success-active: color-mix(
452
+ in srgb,
453
+ var(--af-color-success),
454
+ black var(--af-active-mix)
455
+ );
456
+ --af-color-success-soft: color-mix(
457
+ in srgb,
458
+ var(--af-color-success),
459
+ var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
460
+ );
461
+ --af-color-success-hard: color-mix(
462
+ in srgb,
463
+ var(--af-color-success),
464
+ var(--af-hard-toward) var(--af-hard-mix)
465
+ );
466
+
467
+ --af-color-warning-hover: color-mix(
468
+ in srgb,
469
+ var(--af-color-warning),
470
+ black var(--af-hover-mix)
471
+ );
472
+ --af-color-warning-active: color-mix(
473
+ in srgb,
474
+ var(--af-color-warning),
475
+ black var(--af-active-mix)
476
+ );
477
+ --af-color-warning-soft: color-mix(
478
+ in srgb,
479
+ var(--af-color-warning),
480
+ var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
481
+ );
482
+ --af-color-warning-hard: color-mix(
483
+ in srgb,
484
+ var(--af-color-warning),
485
+ var(--af-hard-toward) var(--af-hard-mix)
486
+ );
487
+
488
+ --af-color-danger-hover: color-mix(in srgb, var(--af-color-danger), black var(--af-hover-mix));
489
+ --af-color-danger-active: color-mix(
490
+ in srgb,
491
+ var(--af-color-danger),
492
+ black var(--af-active-mix)
493
+ );
494
+ --af-color-danger-soft: color-mix(
495
+ in srgb,
496
+ var(--af-color-danger),
497
+ var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
498
+ );
499
+ --af-color-danger-hard: color-mix(
500
+ in srgb,
501
+ var(--af-color-danger),
502
+ var(--af-hard-toward) var(--af-hard-mix)
503
+ );
504
+
505
+ --af-color-info-hover: color-mix(in srgb, var(--af-color-info), black var(--af-hover-mix));
506
+ --af-color-info-active: color-mix(in srgb, var(--af-color-info), black var(--af-active-mix));
507
+ --af-color-info-soft: color-mix(
508
+ in srgb,
509
+ var(--af-color-info),
510
+ var(--af-color-surface-primary) calc(100% - var(--af-soft-mix))
511
+ );
512
+ --af-color-info-hard: color-mix(
513
+ in srgb,
514
+ var(--af-color-info),
515
+ var(--af-hard-toward) var(--af-hard-mix)
516
+ );
485
517
  }
486
-
487
518
 
488
- /* Light theme (default) */
489
- /* @airframeui light theme tokens - Semantic Tokens */
490
-
491
- @layer af.tokens {
519
+ /* Reduced motion support - override timing variables */
520
+ @media (prefers-reduced-motion: reduce) {
492
521
  :root {
493
- /* Stored light values. Brands override these (and --dark / --hc-*) on [data-brand].
494
- The unsuffixed token is the resolved color for the active scheme. */
495
- --af-color-background--light: var(--af-base-white);
496
- --af-color-surface-primary--light: var(--af-base-white);
497
- --af-color-surface-secondary--light: var(--af-base-neutral-50);
498
- --af-color-surface-tertiary--light: var(--af-base-neutral-100);
499
-
500
- --af-color-surface-inverse-primary--light: var(--af-base-neutral-900);
501
- --af-color-surface-inverse-secondary--light: var(--af-base-neutral-800);
502
- --af-color-surface-inverse-tertiary--light: var(--af-base-neutral-700);
503
-
504
- --af-color-text--light: var(--af-base-neutral-900);
505
- --af-color-text-muted--light: var(--af-base-neutral-700);
506
- --af-color-text-inverse--light: var(--af-base-white);
507
-
508
- --af-color-border--light: var(--af-base-neutral-300);
509
- --af-color-border-strong--light: var(--af-base-neutral-400);
510
-
511
- /* Resolved (light is the default scheme) */
512
- --af-color-background: var(--af-color-background--light);
513
- --af-color-surface-primary: var(--af-color-surface-primary--light);
514
- --af-color-surface-secondary: var(--af-color-surface-secondary--light);
515
- --af-color-surface-tertiary: var(--af-color-surface-tertiary--light);
516
-
517
- --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--light);
518
- --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--light);
519
- --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--light);
520
-
521
- --af-color-text: var(--af-color-text--light);
522
- --af-color-text-muted: var(--af-color-text-muted--light);
523
- --af-color-text-inverse: var(--af-color-text-inverse--light);
524
-
525
- --af-color-border: var(--af-color-border--light);
526
- --af-color-border-strong: var(--af-color-border-strong--light);
522
+ --af-duration-fast: 0.01ms;
523
+ --af-duration-md: 0.01ms;
524
+ --af-duration-slow: 0.01ms;
525
+ --af-animation-duration-fast: 0.01ms;
526
+ --af-animation-duration-md: 0.01ms;
527
+ --af-animation-duration-slow: 0.01ms;
528
+ --af-animation-duration-slower: 0.01ms;
527
529
  }
528
530
  }
529
-
530
-
531
- /* Dark theme - automatic and manual */
532
- /* @airframeui dark theme tokens - Semantic Tokens */
533
-
534
- @layer af.tokens {
535
- /* Stored dark values always defined so [data-brand] can override them without
536
- wrapping in a media query. Light resolved tokens do not read these. */
537
- :root {
538
- --af-color-background--dark: var(--af-base-neutral-900);
539
- --af-color-surface-primary--dark: var(--af-base-neutral-800);
540
- --af-color-surface-secondary--dark: var(--af-base-neutral-700);
541
- --af-color-surface-tertiary--dark: var(--af-base-neutral-600);
542
-
543
- --af-color-surface-inverse-primary--dark: var(--af-base-white);
544
- --af-color-surface-inverse-secondary--dark: var(--af-base-neutral-50);
545
- --af-color-surface-inverse-tertiary--dark: var(--af-base-neutral-100);
546
-
547
- --af-color-text--dark: var(--af-base-neutral-50);
548
- --af-color-text-muted--dark: var(--af-base-neutral-300);
549
- --af-color-text-inverse--dark: var(--af-base-neutral-900);
550
-
551
- --af-color-border--dark: var(--af-base-neutral-600);
552
- --af-color-border-strong--dark: var(--af-base-neutral-500);
553
-
554
- --af-color-on-success--dark: var(--af-base-white);
555
- --af-base-primary--dark: #0e80eb;
556
- }
557
-
558
- /* Automatic dark mode — system preference, unless light is forced */
559
- @media (prefers-color-scheme: dark) {
560
- :root:not([data-theme='light']) {
561
- color-scheme: dark;
562
-
563
- --af-base-primary: var(--af-base-primary--dark, var(--af-base-primary--light));
564
- --af-base-secondary: var(--af-base-secondary--dark, var(--af-base-secondary--light));
565
- --af-base-tertiary: var(--af-base-tertiary--dark, var(--af-base-tertiary--light));
566
- --af-base-success: var(--af-base-success--dark, var(--af-base-success--light));
567
- --af-base-warning: var(--af-base-warning--dark, var(--af-base-warning--light));
568
- --af-base-danger: var(--af-base-danger--dark, var(--af-base-danger--light));
569
- --af-base-info: var(--af-base-info--dark, var(--af-base-info--light));
570
-
571
- --af-color-on-primary: var(--af-color-on-primary--dark, var(--af-color-on-primary--light));
572
- --af-color-on-secondary: var(
573
- --af-color-on-secondary--dark,
574
- var(--af-color-on-secondary--light)
575
- );
576
- --af-color-on-tertiary: var(--af-color-on-tertiary--dark, var(--af-color-on-tertiary--light));
577
- --af-color-on-danger: var(--af-color-on-danger--dark, var(--af-color-on-danger--light));
578
- --af-color-on-success: var(--af-color-on-success--dark, var(--af-color-on-success--light));
579
- --af-color-on-warning: var(--af-color-on-warning--dark, var(--af-color-on-warning--light));
580
- --af-color-on-info: var(--af-color-on-info--dark, var(--af-color-on-info--light));
581
-
582
- --af-color-action: var(--af-color-action--dark, var(--af-color-primary));
583
- --af-color-on-action: var(--af-color-on-action--dark, var(--af-color-on-primary));
584
-
585
- --af-color-background: var(--af-color-background--dark);
586
- --af-color-surface-primary: var(--af-color-surface-primary--dark);
587
- --af-color-surface-secondary: var(--af-color-surface-secondary--dark);
588
- --af-color-surface-tertiary: var(--af-color-surface-tertiary--dark);
589
-
590
- --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--dark);
591
- --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--dark);
592
- --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--dark);
593
-
594
- --af-color-text: var(--af-color-text--dark);
595
- --af-color-text-muted: var(--af-color-text-muted--dark);
596
- --af-color-text-inverse: var(--af-color-text-inverse--dark);
597
-
598
- --af-color-border: var(--af-color-border--dark);
599
- --af-color-border-strong: var(--af-color-border-strong--dark);
600
-
601
- --af-hard-toward: white;
602
- --af-btn-hover-brightness: 1.12;
603
- --af-btn-active-brightness: 1.2;
604
- }
605
- }
606
-
607
- /* Manual dark override (works even when system preference is light).
608
- * Duplicates the @media block because:
609
- * - @media (prefers-color-scheme: dark) only applies when the OS is dark
610
- * - [data-theme="dark"] and .dark allow a manual override regardless
611
- * Keeping both explicit aligns with Airframe's principle: organize complexity, don't hide it. */
612
- [data-theme='dark'],
613
- .dark {
531
+ }
532
+
533
+ /* Light theme (default) */
534
+ /* @airframeui light theme tokens - Semantic Tokens */
535
+
536
+ @layer af.tokens {
537
+ /* Catalog light canvas. .af-force-light re-applies this on a subtree so a
538
+ dark-first --light brand (or a dark page) cannot poison the island. */
539
+ :root,
540
+ .af-force-light {
541
+ /* Stored light values. Brands override these (and --dark / --hc-*) on [data-brand].
542
+ The unsuffixed token is the resolved color for the active scheme. */
543
+ --af-color-background--light: var(--af-base-white);
544
+ --af-color-surface-primary--light: var(--af-base-white);
545
+ --af-color-surface-secondary--light: var(--af-base-neutral-50);
546
+ --af-color-surface-tertiary--light: var(--af-base-neutral-100);
547
+
548
+ --af-color-surface-inverse-primary--light: var(--af-base-neutral-900);
549
+ --af-color-surface-inverse-secondary--light: var(--af-base-neutral-800);
550
+ --af-color-surface-inverse-tertiary--light: var(--af-base-neutral-700);
551
+
552
+ --af-color-text--light: var(--af-base-neutral-900);
553
+ --af-color-text-muted--light: var(--af-base-neutral-700);
554
+ --af-color-text-inverse--light: var(--af-base-white);
555
+
556
+ --af-color-border--light: var(--af-base-neutral-300);
557
+ --af-color-border-strong--light: var(--af-base-neutral-400);
558
+
559
+ /* Resolved (light is the default scheme) */
560
+ --af-color-background: var(--af-color-background--light);
561
+ --af-color-surface-primary: var(--af-color-surface-primary--light);
562
+ --af-color-surface-secondary: var(--af-color-surface-secondary--light);
563
+ --af-color-surface-tertiary: var(--af-color-surface-tertiary--light);
564
+
565
+ --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--light);
566
+ --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--light);
567
+ --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--light);
568
+
569
+ --af-color-text: var(--af-color-text--light);
570
+ --af-color-text-muted: var(--af-color-text-muted--light);
571
+ --af-color-text-inverse: var(--af-color-text-inverse--light);
572
+
573
+ --af-color-border: var(--af-color-border--light);
574
+ --af-color-border-strong: var(--af-color-border-strong--light);
575
+ }
576
+
577
+ .af-force-light {
578
+ color-scheme: light;
579
+ color: var(--af-color-text);
580
+ --af-hard-toward: black;
581
+ --af-btn-hover-brightness: 0.9;
582
+ --af-btn-active-brightness: 0.82;
583
+ }
584
+ }
585
+
586
+ /* Dark theme - automatic and manual */
587
+ /* @airframeui dark theme tokens - Semantic Tokens */
588
+
589
+ @layer af.tokens {
590
+ /* Stored dark canvas. .af-force-dark resets inherited brand --dark companions
591
+ on a subtree; resolved dark is applied below (not on :root — that would
592
+ paint the whole page). Intents stay on :root only. */
593
+ :root,
594
+ .af-force-dark {
595
+ --af-color-background--dark: var(--af-base-neutral-900);
596
+ --af-color-surface-primary--dark: var(--af-base-neutral-800);
597
+ --af-color-surface-secondary--dark: var(--af-base-neutral-700);
598
+ --af-color-surface-tertiary--dark: var(--af-base-neutral-600);
599
+
600
+ --af-color-surface-inverse-primary--dark: var(--af-base-white);
601
+ --af-color-surface-inverse-secondary--dark: var(--af-base-neutral-50);
602
+ --af-color-surface-inverse-tertiary--dark: var(--af-base-neutral-100);
603
+
604
+ --af-color-text--dark: var(--af-base-neutral-50);
605
+ --af-color-text-muted--dark: var(--af-base-neutral-300);
606
+ --af-color-text-inverse--dark: var(--af-base-neutral-900);
607
+
608
+ --af-color-border--dark: var(--af-base-neutral-600);
609
+ --af-color-border-strong--dark: var(--af-base-neutral-500);
610
+ }
611
+
612
+ :root {
613
+ --af-color-on-success--dark: var(--af-base-white);
614
+ --af-base-primary--dark: #1678D4;
615
+ }
616
+
617
+ /* Automatic dark mode — system preference, unless light is forced */
618
+ @media (prefers-color-scheme: dark) {
619
+ :root:not([data-theme='light']) {
614
620
  color-scheme: dark;
615
-
621
+
616
622
  --af-base-primary: var(--af-base-primary--dark, var(--af-base-primary--light));
617
623
  --af-base-secondary: var(--af-base-secondary--dark, var(--af-base-secondary--light));
618
624
  --af-base-tertiary: var(--af-base-tertiary--dark, var(--af-base-tertiary--light));
@@ -620,7 +626,7 @@
620
626
  --af-base-warning: var(--af-base-warning--dark, var(--af-base-warning--light));
621
627
  --af-base-danger: var(--af-base-danger--dark, var(--af-base-danger--light));
622
628
  --af-base-info: var(--af-base-info--dark, var(--af-base-info--light));
623
-
629
+
624
630
  --af-color-on-primary: var(--af-color-on-primary--dark, var(--af-color-on-primary--light));
625
631
  --af-color-on-secondary: var(
626
632
  --af-color-on-secondary--dark,
@@ -631,363 +637,420 @@
631
637
  --af-color-on-success: var(--af-color-on-success--dark, var(--af-color-on-success--light));
632
638
  --af-color-on-warning: var(--af-color-on-warning--dark, var(--af-color-on-warning--light));
633
639
  --af-color-on-info: var(--af-color-on-info--dark, var(--af-color-on-info--light));
634
-
640
+
635
641
  --af-color-action: var(--af-color-action--dark, var(--af-color-primary));
636
642
  --af-color-on-action: var(--af-color-on-action--dark, var(--af-color-on-primary));
637
-
643
+
638
644
  --af-color-background: var(--af-color-background--dark);
639
645
  --af-color-surface-primary: var(--af-color-surface-primary--dark);
640
646
  --af-color-surface-secondary: var(--af-color-surface-secondary--dark);
641
647
  --af-color-surface-tertiary: var(--af-color-surface-tertiary--dark);
642
-
648
+
643
649
  --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--dark);
644
650
  --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--dark);
645
651
  --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--dark);
646
-
652
+
647
653
  --af-color-text: var(--af-color-text--dark);
648
654
  --af-color-text-muted: var(--af-color-text-muted--dark);
649
655
  --af-color-text-inverse: var(--af-color-text-inverse--dark);
650
-
656
+
651
657
  --af-color-border: var(--af-color-border--dark);
652
658
  --af-color-border-strong: var(--af-color-border-strong--dark);
653
-
659
+
654
660
  --af-hard-toward: white;
655
661
  --af-btn-hover-brightness: 1.12;
656
662
  --af-btn-active-brightness: 1.2;
657
663
  }
658
-
659
- /* Forced light: keep light resolved tokens even if OS prefers dark or .dark is present.
660
- Must follow [data-theme=dark] / .dark so it wins when both are set. */
661
- [data-theme='light'] {
662
- color-scheme: light;
663
-
664
- --af-base-primary: var(--af-base-primary--light);
665
- --af-base-secondary: var(--af-base-secondary--light);
666
- --af-base-tertiary: var(--af-base-tertiary--light);
667
- --af-base-success: var(--af-base-success--light);
668
- --af-base-warning: var(--af-base-warning--light);
669
- --af-base-danger: var(--af-base-danger--light);
670
- --af-base-info: var(--af-base-info--light);
671
-
672
- --af-color-on-primary: var(--af-color-on-primary--light);
673
- --af-color-on-secondary: var(--af-color-on-secondary--light);
674
- --af-color-on-tertiary: var(--af-color-on-tertiary--light);
675
- --af-color-on-danger: var(--af-color-on-danger--light);
676
- --af-color-on-success: var(--af-color-on-success--light);
677
- --af-color-on-warning: var(--af-color-on-warning--light);
678
- --af-color-on-info: var(--af-color-on-info--light);
679
-
680
- --af-color-action: var(--af-color-action--light, var(--af-color-primary));
681
- --af-color-on-action: var(--af-color-on-action--light, var(--af-color-on-primary));
682
-
683
- --af-color-background: var(--af-color-background--light);
684
- --af-color-surface-primary: var(--af-color-surface-primary--light);
685
- --af-color-surface-secondary: var(--af-color-surface-secondary--light);
686
- --af-color-surface-tertiary: var(--af-color-surface-tertiary--light);
687
-
688
- --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--light);
689
- --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--light);
690
- --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--light);
691
-
692
- --af-color-text: var(--af-color-text--light);
693
- --af-color-text-muted: var(--af-color-text-muted--light);
694
- --af-color-text-inverse: var(--af-color-text-inverse--light);
695
-
696
- --af-color-border: var(--af-color-border--light);
697
- --af-color-border-strong: var(--af-color-border-strong--light);
698
-
699
- --af-hard-toward: black;
700
- --af-btn-hover-brightness: 0.9;
701
- --af-btn-active-brightness: 0.82;
702
- }
703
664
  }
704
-
705
-
706
- /* High-contrast themes - automatic and manual */
707
- /* @airframeui high-contrast theme tokens - Semantic Tokens */
708
-
709
- @layer af.tokens {
710
- /* Stored HC values — always defined so brands can override them in :root / [data-brand]
711
- without a media query. Applied only when prefers-contrast is active. */
712
- :root {
713
- --af-color-background--hc-light: var(--af-base-white);
714
- --af-color-surface-primary--hc-light: var(--af-base-white);
715
- --af-color-surface-secondary--hc-light: #f5f5f5;
716
- --af-color-surface-tertiary--hc-light: #e6e6e6;
717
-
718
- --af-color-surface-inverse-primary--hc-light: var(--af-base-black);
719
- --af-color-surface-inverse-secondary--hc-light: #1a1a1a;
720
- --af-color-surface-inverse-tertiary--hc-light: #333333;
721
-
722
- --af-color-text--hc-light: var(--af-base-black);
723
- --af-color-text-muted--hc-light: #333333;
724
- --af-color-text-inverse--hc-light: var(--af-base-white);
725
-
726
- --af-color-border--hc-light: var(--af-base-black);
727
- --af-color-border-strong--hc-light: var(--af-base-black);
728
-
729
- --af-color-on-secondary--hc-light: var(--af-base-black);
730
- --af-color-on-warning--hc-light: var(--af-base-black);
731
-
732
- --af-color-background--hc-dark: var(--af-base-black);
733
- --af-color-surface-primary--hc-dark: #1a1a1a;
734
- --af-color-surface-secondary--hc-dark: #2a2a2a;
735
- --af-color-surface-tertiary--hc-dark: #333333;
736
-
737
- --af-color-surface-inverse-primary--hc-dark: var(--af-base-white);
738
- --af-color-surface-inverse-secondary--hc-dark: #f5f5f5;
739
- --af-color-surface-inverse-tertiary--hc-dark: #e6e6e6;
740
-
741
- --af-color-text--hc-dark: var(--af-base-white);
742
- --af-color-text-muted--hc-dark: #cccccc;
743
- --af-color-text-inverse--hc-dark: var(--af-base-black);
744
-
745
- --af-color-border--hc-dark: var(--af-base-white);
746
- --af-color-border-strong--hc-dark: var(--af-base-white);
747
-
748
- --af-color-on-primary--hc-dark: var(--af-base-black);
749
- --af-color-on-secondary--hc-dark: var(--af-base-black);
750
- --af-color-on-danger--hc-dark: var(--af-base-black);
751
- --af-color-on-success--hc-dark: var(--af-base-black);
752
- --af-color-on-warning--hc-dark: var(--af-base-black);
753
- --af-color-on-info--hc-dark: var(--af-base-black);
754
- }
755
-
756
- /* Automatic high contrast — light scheme (or forced light) */
757
- @media (prefers-contrast: more), (prefers-contrast: high) {
758
- :root:not([data-theme='dark']):not(.dark) {
759
- --af-base-primary: var(--af-base-primary--hc-light, var(--af-base-primary--light));
760
- --af-base-secondary: var(--af-base-secondary--hc-light, var(--af-base-secondary--light));
761
- --af-base-tertiary: var(--af-base-tertiary--hc-light, var(--af-base-tertiary--light));
762
- --af-base-success: var(--af-base-success--hc-light, var(--af-base-success--light));
763
- --af-base-warning: var(--af-base-warning--hc-light, var(--af-base-warning--light));
764
- --af-base-danger: var(--af-base-danger--hc-light, var(--af-base-danger--light));
765
- --af-base-info: var(--af-base-info--hc-light, var(--af-base-info--light));
766
-
767
- --af-color-on-primary: var(
768
- --af-color-on-primary--hc-light,
769
- var(--af-color-on-primary--light)
770
- );
771
- --af-color-on-secondary: var(
772
- --af-color-on-secondary--hc-light,
773
- var(--af-color-on-secondary--light)
774
- );
775
- --af-color-on-tertiary: var(
776
- --af-color-on-tertiary--hc-light,
777
- var(--af-color-on-tertiary--light)
778
- );
779
- --af-color-on-danger: var(--af-color-on-danger--hc-light, var(--af-color-on-danger--light));
780
- --af-color-on-success: var(
781
- --af-color-on-success--hc-light,
782
- var(--af-color-on-success--light)
783
- );
784
- --af-color-on-warning: var(
785
- --af-color-on-warning--hc-light,
786
- var(--af-color-on-warning--light)
787
- );
788
- --af-color-on-info: var(--af-color-on-info--hc-light, var(--af-color-on-info--light));
789
-
790
- --af-color-action: var(
791
- --af-color-action--hc-light,
792
- var(--af-color-action--light, var(--af-color-primary))
793
- );
794
- --af-color-on-action: var(
795
- --af-color-on-action--hc-light,
796
- var(--af-color-on-action--light, var(--af-color-on-primary))
797
- );
798
-
799
- --af-color-background: var(--af-color-background--hc-light);
800
- --af-color-surface-primary: var(--af-color-surface-primary--hc-light);
801
- --af-color-surface-secondary: var(--af-color-surface-secondary--hc-light);
802
- --af-color-surface-tertiary: var(--af-color-surface-tertiary--hc-light);
803
-
804
- --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--hc-light);
805
- --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--hc-light);
806
- --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--hc-light);
807
-
808
- --af-color-text: var(--af-color-text--hc-light);
809
- --af-color-text-muted: var(--af-color-text-muted--hc-light);
810
- --af-color-text-inverse: var(--af-color-text-inverse--hc-light);
811
-
812
- --af-color-border: var(--af-color-border--hc-light);
813
- --af-color-border-strong: var(--af-color-border-strong--hc-light);
814
- }
815
-
816
- [data-theme='dark'],
817
- .dark {
818
- --af-base-primary: var(
819
- --af-base-primary--hc-dark,
820
- var(--af-base-primary--dark, var(--af-base-primary--light))
821
- );
822
- --af-base-secondary: var(
823
- --af-base-secondary--hc-dark,
824
- var(--af-base-secondary--dark, var(--af-base-secondary--light))
825
- );
826
- --af-base-tertiary: var(
827
- --af-base-tertiary--hc-dark,
828
- var(--af-base-tertiary--dark, var(--af-base-tertiary--light))
829
- );
830
- --af-base-success: var(
831
- --af-base-success--hc-dark,
832
- var(--af-base-success--dark, var(--af-base-success--light))
833
- );
834
- --af-base-warning: var(
835
- --af-base-warning--hc-dark,
836
- var(--af-base-warning--dark, var(--af-base-warning--light))
837
- );
838
- --af-base-danger: var(
839
- --af-base-danger--hc-dark,
840
- var(--af-base-danger--dark, var(--af-base-danger--light))
841
- );
842
- --af-base-info: var(
843
- --af-base-info--hc-dark,
844
- var(--af-base-info--dark, var(--af-base-info--light))
845
- );
846
-
847
- --af-color-on-primary: var(
848
- --af-color-on-primary--hc-dark,
849
- var(--af-color-on-primary--dark, var(--af-color-on-primary--light))
850
- );
851
- --af-color-on-secondary: var(
852
- --af-color-on-secondary--hc-dark,
853
- var(--af-color-on-secondary--dark, var(--af-color-on-secondary--light))
854
- );
855
- --af-color-on-tertiary: var(
856
- --af-color-on-tertiary--hc-dark,
857
- var(--af-color-on-tertiary--dark, var(--af-color-on-tertiary--light))
858
- );
859
- --af-color-on-danger: var(
860
- --af-color-on-danger--hc-dark,
861
- var(--af-color-on-danger--dark, var(--af-color-on-danger--light))
862
- );
863
- --af-color-on-success: var(
864
- --af-color-on-success--hc-dark,
865
- var(--af-color-on-success--dark, var(--af-color-on-success--light))
866
- );
867
- --af-color-on-warning: var(
868
- --af-color-on-warning--hc-dark,
869
- var(--af-color-on-warning--dark, var(--af-color-on-warning--light))
870
- );
871
- --af-color-on-info: var(
872
- --af-color-on-info--hc-dark,
873
- var(--af-color-on-info--dark, var(--af-color-on-info--light))
874
- );
875
-
876
- --af-color-action: var(
877
- --af-color-action--hc-dark,
878
- var(--af-color-action--dark, var(--af-color-primary))
879
- );
880
- --af-color-on-action: var(
881
- --af-color-on-action--hc-dark,
882
- var(--af-color-on-action--dark, var(--af-color-on-primary))
883
- );
884
-
885
- --af-color-background: var(--af-color-background--hc-dark);
886
- --af-color-surface-primary: var(--af-color-surface-primary--hc-dark);
887
- --af-color-surface-secondary: var(--af-color-surface-secondary--hc-dark);
888
- --af-color-surface-tertiary: var(--af-color-surface-tertiary--hc-dark);
889
-
890
- --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--hc-dark);
891
- --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--hc-dark);
892
- --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--hc-dark);
893
-
894
- --af-color-text: var(--af-color-text--hc-dark);
895
- --af-color-text-muted: var(--af-color-text-muted--hc-dark);
896
- --af-color-text-inverse: var(--af-color-text-inverse--hc-dark);
897
-
898
- --af-color-border: var(--af-color-border--hc-dark);
899
- --af-color-border-strong: var(--af-color-border-strong--hc-dark);
900
- }
665
+
666
+ /* Manual dark override (works even when system preference is light).
667
+ * Duplicates the @media block because:
668
+ * - @media (prefers-color-scheme: dark) only applies when the OS is dark
669
+ * - [data-theme="dark"] and .dark allow a manual override regardless
670
+ * Keeping both explicit aligns with Airframe's principle: organize complexity, don't hide it. */
671
+ [data-theme='dark'],
672
+ .dark,
673
+ .af-force-dark {
674
+ color-scheme: dark;
675
+
676
+ --af-color-background: var(--af-color-background--dark);
677
+ --af-color-surface-primary: var(--af-color-surface-primary--dark);
678
+ --af-color-surface-secondary: var(--af-color-surface-secondary--dark);
679
+ --af-color-surface-tertiary: var(--af-color-surface-tertiary--dark);
680
+
681
+ --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--dark);
682
+ --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--dark);
683
+ --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--dark);
684
+
685
+ --af-color-text: var(--af-color-text--dark);
686
+ --af-color-text-muted: var(--af-color-text-muted--dark);
687
+ --af-color-text-inverse: var(--af-color-text-inverse--dark);
688
+
689
+ --af-color-border: var(--af-color-border--dark);
690
+ --af-color-border-strong: var(--af-color-border-strong--dark);
691
+
692
+ --af-hard-toward: white;
693
+ --af-btn-hover-brightness: 1.12;
694
+ --af-btn-active-brightness: 1.2;
695
+ }
696
+
697
+ [data-theme='dark'],
698
+ .dark {
699
+ --af-base-primary: var(--af-base-primary--dark, var(--af-base-primary--light));
700
+ --af-base-secondary: var(--af-base-secondary--dark, var(--af-base-secondary--light));
701
+ --af-base-tertiary: var(--af-base-tertiary--dark, var(--af-base-tertiary--light));
702
+ --af-base-success: var(--af-base-success--dark, var(--af-base-success--light));
703
+ --af-base-warning: var(--af-base-warning--dark, var(--af-base-warning--light));
704
+ --af-base-danger: var(--af-base-danger--dark, var(--af-base-danger--light));
705
+ --af-base-info: var(--af-base-info--dark, var(--af-base-info--light));
706
+
707
+ --af-color-on-primary: var(--af-color-on-primary--dark, var(--af-color-on-primary--light));
708
+ --af-color-on-secondary: var(
709
+ --af-color-on-secondary--dark,
710
+ var(--af-color-on-secondary--light)
711
+ );
712
+ --af-color-on-tertiary: var(--af-color-on-tertiary--dark, var(--af-color-on-tertiary--light));
713
+ --af-color-on-danger: var(--af-color-on-danger--dark, var(--af-color-on-danger--light));
714
+ --af-color-on-success: var(--af-color-on-success--dark, var(--af-color-on-success--light));
715
+ --af-color-on-warning: var(--af-color-on-warning--dark, var(--af-color-on-warning--light));
716
+ --af-color-on-info: var(--af-color-on-info--dark, var(--af-color-on-info--light));
717
+
718
+ --af-color-action: var(--af-color-action--dark, var(--af-color-primary));
719
+ --af-color-on-action: var(--af-color-on-action--dark, var(--af-color-on-primary));
720
+ }
721
+
722
+ .af-force-dark {
723
+ color: var(--af-color-text);
724
+ }
725
+
726
+ /* Forced light: keep light resolved tokens even if OS prefers dark or .dark is present.
727
+ Must follow [data-theme=dark] / .dark so it wins when both are set. */
728
+ [data-theme='light'] {
729
+ color-scheme: light;
730
+
731
+ --af-base-primary: var(--af-base-primary--light);
732
+ --af-base-secondary: var(--af-base-secondary--light);
733
+ --af-base-tertiary: var(--af-base-tertiary--light);
734
+ --af-base-success: var(--af-base-success--light);
735
+ --af-base-warning: var(--af-base-warning--light);
736
+ --af-base-danger: var(--af-base-danger--light);
737
+ --af-base-info: var(--af-base-info--light);
738
+
739
+ --af-color-on-primary: var(--af-color-on-primary--light);
740
+ --af-color-on-secondary: var(--af-color-on-secondary--light);
741
+ --af-color-on-tertiary: var(--af-color-on-tertiary--light);
742
+ --af-color-on-danger: var(--af-color-on-danger--light);
743
+ --af-color-on-success: var(--af-color-on-success--light);
744
+ --af-color-on-warning: var(--af-color-on-warning--light);
745
+ --af-color-on-info: var(--af-color-on-info--light);
746
+
747
+ --af-color-action: var(--af-color-action--light, var(--af-color-primary));
748
+ --af-color-on-action: var(--af-color-on-action--light, var(--af-color-on-primary));
749
+
750
+ --af-color-background: var(--af-color-background--light);
751
+ --af-color-surface-primary: var(--af-color-surface-primary--light);
752
+ --af-color-surface-secondary: var(--af-color-surface-secondary--light);
753
+ --af-color-surface-tertiary: var(--af-color-surface-tertiary--light);
754
+
755
+ --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--light);
756
+ --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--light);
757
+ --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--light);
758
+
759
+ --af-color-text: var(--af-color-text--light);
760
+ --af-color-text-muted: var(--af-color-text-muted--light);
761
+ --af-color-text-inverse: var(--af-color-text-inverse--light);
762
+
763
+ --af-color-border: var(--af-color-border--light);
764
+ --af-color-border-strong: var(--af-color-border-strong--light);
765
+
766
+ --af-hard-toward: black;
767
+ --af-btn-hover-brightness: 0.9;
768
+ --af-btn-active-brightness: 0.82;
769
+ }
770
+ }
771
+
772
+ /* High-contrast themes - automatic and manual */
773
+ /* @airframeui high-contrast theme tokens - Semantic Tokens */
774
+
775
+ @layer af.tokens {
776
+ /* Stored HC values — always defined so brands can override them in :root / [data-brand]
777
+ without a media query. Applied only when prefers-contrast is active. */
778
+ :root {
779
+ --af-color-background--hc-light: var(--af-base-white);
780
+ --af-color-surface-primary--hc-light: var(--af-base-white);
781
+ --af-color-surface-secondary--hc-light: #f5f5f5;
782
+ --af-color-surface-tertiary--hc-light: #e6e6e6;
783
+
784
+ --af-color-surface-inverse-primary--hc-light: var(--af-base-black);
785
+ --af-color-surface-inverse-secondary--hc-light: #1a1a1a;
786
+ --af-color-surface-inverse-tertiary--hc-light: #333333;
787
+
788
+ --af-color-text--hc-light: var(--af-base-black);
789
+ --af-color-text-muted--hc-light: #333333;
790
+ --af-color-text-inverse--hc-light: var(--af-base-white);
791
+
792
+ --af-color-border--hc-light: var(--af-base-black);
793
+ --af-color-border-strong--hc-light: var(--af-base-black);
794
+
795
+ --af-color-on-secondary--hc-light: var(--af-base-black);
796
+ --af-color-on-warning--hc-light: var(--af-base-black);
797
+
798
+ --af-color-background--hc-dark: var(--af-base-black);
799
+ --af-color-surface-primary--hc-dark: #1a1a1a;
800
+ --af-color-surface-secondary--hc-dark: #2a2a2a;
801
+ --af-color-surface-tertiary--hc-dark: #333333;
802
+
803
+ --af-color-surface-inverse-primary--hc-dark: var(--af-base-white);
804
+ --af-color-surface-inverse-secondary--hc-dark: #f5f5f5;
805
+ --af-color-surface-inverse-tertiary--hc-dark: #e6e6e6;
806
+
807
+ --af-color-text--hc-dark: var(--af-base-white);
808
+ --af-color-text-muted--hc-dark: #cccccc;
809
+ --af-color-text-inverse--hc-dark: var(--af-base-black);
810
+
811
+ --af-color-border--hc-dark: var(--af-base-white);
812
+ --af-color-border-strong--hc-dark: var(--af-base-white);
813
+
814
+ --af-color-on-primary--hc-dark: var(--af-base-black);
815
+ --af-color-on-secondary--hc-dark: var(--af-base-black);
816
+ --af-color-on-danger--hc-dark: var(--af-base-black);
817
+ --af-color-on-success--hc-dark: var(--af-base-black);
818
+ --af-color-on-warning--hc-dark: var(--af-base-black);
819
+ --af-color-on-info--hc-dark: var(--af-base-black);
820
+ }
821
+
822
+ /* Automatic high contrast — light scheme (or forced light) */
823
+ @media (prefers-contrast: more), (prefers-contrast: high) {
824
+ :root:not([data-theme='dark']):not(.dark) {
825
+ --af-base-primary: var(--af-base-primary--hc-light, var(--af-base-primary--light));
826
+ --af-base-secondary: var(--af-base-secondary--hc-light, var(--af-base-secondary--light));
827
+ --af-base-tertiary: var(--af-base-tertiary--hc-light, var(--af-base-tertiary--light));
828
+ --af-base-success: var(--af-base-success--hc-light, var(--af-base-success--light));
829
+ --af-base-warning: var(--af-base-warning--hc-light, var(--af-base-warning--light));
830
+ --af-base-danger: var(--af-base-danger--hc-light, var(--af-base-danger--light));
831
+ --af-base-info: var(--af-base-info--hc-light, var(--af-base-info--light));
832
+
833
+ --af-color-on-primary: var(
834
+ --af-color-on-primary--hc-light,
835
+ var(--af-color-on-primary--light)
836
+ );
837
+ --af-color-on-secondary: var(
838
+ --af-color-on-secondary--hc-light,
839
+ var(--af-color-on-secondary--light)
840
+ );
841
+ --af-color-on-tertiary: var(
842
+ --af-color-on-tertiary--hc-light,
843
+ var(--af-color-on-tertiary--light)
844
+ );
845
+ --af-color-on-danger: var(--af-color-on-danger--hc-light, var(--af-color-on-danger--light));
846
+ --af-color-on-success: var(
847
+ --af-color-on-success--hc-light,
848
+ var(--af-color-on-success--light)
849
+ );
850
+ --af-color-on-warning: var(
851
+ --af-color-on-warning--hc-light,
852
+ var(--af-color-on-warning--light)
853
+ );
854
+ --af-color-on-info: var(--af-color-on-info--hc-light, var(--af-color-on-info--light));
855
+
856
+ --af-color-action: var(
857
+ --af-color-action--hc-light,
858
+ var(--af-color-action--light, var(--af-color-primary))
859
+ );
860
+ --af-color-on-action: var(
861
+ --af-color-on-action--hc-light,
862
+ var(--af-color-on-action--light, var(--af-color-on-primary))
863
+ );
864
+
865
+ --af-color-background: var(--af-color-background--hc-light);
866
+ --af-color-surface-primary: var(--af-color-surface-primary--hc-light);
867
+ --af-color-surface-secondary: var(--af-color-surface-secondary--hc-light);
868
+ --af-color-surface-tertiary: var(--af-color-surface-tertiary--hc-light);
869
+
870
+ --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--hc-light);
871
+ --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--hc-light);
872
+ --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--hc-light);
873
+
874
+ --af-color-text: var(--af-color-text--hc-light);
875
+ --af-color-text-muted: var(--af-color-text-muted--hc-light);
876
+ --af-color-text-inverse: var(--af-color-text-inverse--hc-light);
877
+
878
+ --af-color-border: var(--af-color-border--hc-light);
879
+ --af-color-border-strong: var(--af-color-border-strong--hc-light);
901
880
  }
902
-
903
- @media (prefers-contrast: more) and (prefers-color-scheme: dark),
904
- (prefers-contrast: high) and (prefers-color-scheme: dark) {
905
- :root:not([data-theme='light']) {
906
- --af-base-primary: var(
907
- --af-base-primary--hc-dark,
908
- var(--af-base-primary--dark, var(--af-base-primary--light))
909
- );
910
- --af-base-secondary: var(
911
- --af-base-secondary--hc-dark,
912
- var(--af-base-secondary--dark, var(--af-base-secondary--light))
913
- );
914
- --af-base-tertiary: var(
915
- --af-base-tertiary--hc-dark,
916
- var(--af-base-tertiary--dark, var(--af-base-tertiary--light))
917
- );
918
- --af-base-success: var(
919
- --af-base-success--hc-dark,
920
- var(--af-base-success--dark, var(--af-base-success--light))
921
- );
922
- --af-base-warning: var(
923
- --af-base-warning--hc-dark,
924
- var(--af-base-warning--dark, var(--af-base-warning--light))
925
- );
926
- --af-base-danger: var(
927
- --af-base-danger--hc-dark,
928
- var(--af-base-danger--dark, var(--af-base-danger--light))
929
- );
930
- --af-base-info: var(
931
- --af-base-info--hc-dark,
932
- var(--af-base-info--dark, var(--af-base-info--light))
933
- );
934
-
935
- --af-color-on-primary: var(
936
- --af-color-on-primary--hc-dark,
937
- var(--af-color-on-primary--dark, var(--af-color-on-primary--light))
938
- );
939
- --af-color-on-secondary: var(
940
- --af-color-on-secondary--hc-dark,
941
- var(--af-color-on-secondary--dark, var(--af-color-on-secondary--light))
942
- );
943
- --af-color-on-tertiary: var(
944
- --af-color-on-tertiary--hc-dark,
945
- var(--af-color-on-tertiary--dark, var(--af-color-on-tertiary--light))
946
- );
947
- --af-color-on-danger: var(
948
- --af-color-on-danger--hc-dark,
949
- var(--af-color-on-danger--dark, var(--af-color-on-danger--light))
950
- );
951
- --af-color-on-success: var(
952
- --af-color-on-success--hc-dark,
953
- var(--af-color-on-success--dark, var(--af-color-on-success--light))
954
- );
955
- --af-color-on-warning: var(
956
- --af-color-on-warning--hc-dark,
957
- var(--af-color-on-warning--dark, var(--af-color-on-warning--light))
958
- );
959
- --af-color-on-info: var(
960
- --af-color-on-info--hc-dark,
961
- var(--af-color-on-info--dark, var(--af-color-on-info--light))
962
- );
963
-
964
- --af-color-action: var(
965
- --af-color-action--hc-dark,
966
- var(--af-color-action--dark, var(--af-color-primary))
967
- );
968
- --af-color-on-action: var(
969
- --af-color-on-action--hc-dark,
970
- var(--af-color-on-action--dark, var(--af-color-on-primary))
971
- );
972
-
973
- --af-color-background: var(--af-color-background--hc-dark);
974
- --af-color-surface-primary: var(--af-color-surface-primary--hc-dark);
975
- --af-color-surface-secondary: var(--af-color-surface-secondary--hc-dark);
976
- --af-color-surface-tertiary: var(--af-color-surface-tertiary--hc-dark);
977
-
978
- --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--hc-dark);
979
- --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--hc-dark);
980
- --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--hc-dark);
981
-
982
- --af-color-text: var(--af-color-text--hc-dark);
983
- --af-color-text-muted: var(--af-color-text-muted--hc-dark);
984
- --af-color-text-inverse: var(--af-color-text-inverse--hc-dark);
985
-
986
- --af-color-border: var(--af-color-border--hc-dark);
987
- --af-color-border-strong: var(--af-color-border-strong--hc-dark);
988
- }
881
+
882
+ [data-theme='dark'],
883
+ .dark {
884
+ --af-base-primary: var(
885
+ --af-base-primary--hc-dark,
886
+ var(--af-base-primary--dark, var(--af-base-primary--light))
887
+ );
888
+ --af-base-secondary: var(
889
+ --af-base-secondary--hc-dark,
890
+ var(--af-base-secondary--dark, var(--af-base-secondary--light))
891
+ );
892
+ --af-base-tertiary: var(
893
+ --af-base-tertiary--hc-dark,
894
+ var(--af-base-tertiary--dark, var(--af-base-tertiary--light))
895
+ );
896
+ --af-base-success: var(
897
+ --af-base-success--hc-dark,
898
+ var(--af-base-success--dark, var(--af-base-success--light))
899
+ );
900
+ --af-base-warning: var(
901
+ --af-base-warning--hc-dark,
902
+ var(--af-base-warning--dark, var(--af-base-warning--light))
903
+ );
904
+ --af-base-danger: var(
905
+ --af-base-danger--hc-dark,
906
+ var(--af-base-danger--dark, var(--af-base-danger--light))
907
+ );
908
+ --af-base-info: var(
909
+ --af-base-info--hc-dark,
910
+ var(--af-base-info--dark, var(--af-base-info--light))
911
+ );
912
+
913
+ --af-color-on-primary: var(
914
+ --af-color-on-primary--hc-dark,
915
+ var(--af-color-on-primary--dark, var(--af-color-on-primary--light))
916
+ );
917
+ --af-color-on-secondary: var(
918
+ --af-color-on-secondary--hc-dark,
919
+ var(--af-color-on-secondary--dark, var(--af-color-on-secondary--light))
920
+ );
921
+ --af-color-on-tertiary: var(
922
+ --af-color-on-tertiary--hc-dark,
923
+ var(--af-color-on-tertiary--dark, var(--af-color-on-tertiary--light))
924
+ );
925
+ --af-color-on-danger: var(
926
+ --af-color-on-danger--hc-dark,
927
+ var(--af-color-on-danger--dark, var(--af-color-on-danger--light))
928
+ );
929
+ --af-color-on-success: var(
930
+ --af-color-on-success--hc-dark,
931
+ var(--af-color-on-success--dark, var(--af-color-on-success--light))
932
+ );
933
+ --af-color-on-warning: var(
934
+ --af-color-on-warning--hc-dark,
935
+ var(--af-color-on-warning--dark, var(--af-color-on-warning--light))
936
+ );
937
+ --af-color-on-info: var(
938
+ --af-color-on-info--hc-dark,
939
+ var(--af-color-on-info--dark, var(--af-color-on-info--light))
940
+ );
941
+
942
+ --af-color-action: var(
943
+ --af-color-action--hc-dark,
944
+ var(--af-color-action--dark, var(--af-color-primary))
945
+ );
946
+ --af-color-on-action: var(
947
+ --af-color-on-action--hc-dark,
948
+ var(--af-color-on-action--dark, var(--af-color-on-primary))
949
+ );
950
+
951
+ --af-color-background: var(--af-color-background--hc-dark);
952
+ --af-color-surface-primary: var(--af-color-surface-primary--hc-dark);
953
+ --af-color-surface-secondary: var(--af-color-surface-secondary--hc-dark);
954
+ --af-color-surface-tertiary: var(--af-color-surface-tertiary--hc-dark);
955
+
956
+ --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--hc-dark);
957
+ --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--hc-dark);
958
+ --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--hc-dark);
959
+
960
+ --af-color-text: var(--af-color-text--hc-dark);
961
+ --af-color-text-muted: var(--af-color-text-muted--hc-dark);
962
+ --af-color-text-inverse: var(--af-color-text-inverse--hc-dark);
963
+
964
+ --af-color-border: var(--af-color-border--hc-dark);
965
+ --af-color-border-strong: var(--af-color-border-strong--hc-dark);
989
966
  }
990
967
  }
991
-
992
968
 
969
+ @media (prefers-contrast: more) and (prefers-color-scheme: dark),
970
+ (prefers-contrast: high) and (prefers-color-scheme: dark) {
971
+ :root:not([data-theme='light']) {
972
+ --af-base-primary: var(
973
+ --af-base-primary--hc-dark,
974
+ var(--af-base-primary--dark, var(--af-base-primary--light))
975
+ );
976
+ --af-base-secondary: var(
977
+ --af-base-secondary--hc-dark,
978
+ var(--af-base-secondary--dark, var(--af-base-secondary--light))
979
+ );
980
+ --af-base-tertiary: var(
981
+ --af-base-tertiary--hc-dark,
982
+ var(--af-base-tertiary--dark, var(--af-base-tertiary--light))
983
+ );
984
+ --af-base-success: var(
985
+ --af-base-success--hc-dark,
986
+ var(--af-base-success--dark, var(--af-base-success--light))
987
+ );
988
+ --af-base-warning: var(
989
+ --af-base-warning--hc-dark,
990
+ var(--af-base-warning--dark, var(--af-base-warning--light))
991
+ );
992
+ --af-base-danger: var(
993
+ --af-base-danger--hc-dark,
994
+ var(--af-base-danger--dark, var(--af-base-danger--light))
995
+ );
996
+ --af-base-info: var(
997
+ --af-base-info--hc-dark,
998
+ var(--af-base-info--dark, var(--af-base-info--light))
999
+ );
1000
+
1001
+ --af-color-on-primary: var(
1002
+ --af-color-on-primary--hc-dark,
1003
+ var(--af-color-on-primary--dark, var(--af-color-on-primary--light))
1004
+ );
1005
+ --af-color-on-secondary: var(
1006
+ --af-color-on-secondary--hc-dark,
1007
+ var(--af-color-on-secondary--dark, var(--af-color-on-secondary--light))
1008
+ );
1009
+ --af-color-on-tertiary: var(
1010
+ --af-color-on-tertiary--hc-dark,
1011
+ var(--af-color-on-tertiary--dark, var(--af-color-on-tertiary--light))
1012
+ );
1013
+ --af-color-on-danger: var(
1014
+ --af-color-on-danger--hc-dark,
1015
+ var(--af-color-on-danger--dark, var(--af-color-on-danger--light))
1016
+ );
1017
+ --af-color-on-success: var(
1018
+ --af-color-on-success--hc-dark,
1019
+ var(--af-color-on-success--dark, var(--af-color-on-success--light))
1020
+ );
1021
+ --af-color-on-warning: var(
1022
+ --af-color-on-warning--hc-dark,
1023
+ var(--af-color-on-warning--dark, var(--af-color-on-warning--light))
1024
+ );
1025
+ --af-color-on-info: var(
1026
+ --af-color-on-info--hc-dark,
1027
+ var(--af-color-on-info--dark, var(--af-color-on-info--light))
1028
+ );
1029
+
1030
+ --af-color-action: var(
1031
+ --af-color-action--hc-dark,
1032
+ var(--af-color-action--dark, var(--af-color-primary))
1033
+ );
1034
+ --af-color-on-action: var(
1035
+ --af-color-on-action--hc-dark,
1036
+ var(--af-color-on-action--dark, var(--af-color-on-primary))
1037
+ );
1038
+
1039
+ --af-color-background: var(--af-color-background--hc-dark);
1040
+ --af-color-surface-primary: var(--af-color-surface-primary--hc-dark);
1041
+ --af-color-surface-secondary: var(--af-color-surface-secondary--hc-dark);
1042
+ --af-color-surface-tertiary: var(--af-color-surface-tertiary--hc-dark);
1043
+
1044
+ --af-color-surface-inverse-primary: var(--af-color-surface-inverse-primary--hc-dark);
1045
+ --af-color-surface-inverse-secondary: var(--af-color-surface-inverse-secondary--hc-dark);
1046
+ --af-color-surface-inverse-tertiary: var(--af-color-surface-inverse-tertiary--hc-dark);
1047
+
1048
+ --af-color-text: var(--af-color-text--hc-dark);
1049
+ --af-color-text-muted: var(--af-color-text-muted--hc-dark);
1050
+ --af-color-text-inverse: var(--af-color-text-inverse--hc-dark);
1051
+
1052
+ --af-color-border: var(--af-color-border--hc-dark);
1053
+ --af-color-border-strong: var(--af-color-border-strong--hc-dark);
1054
+ }
1055
+ }
993
1056
  }