@nsaa/tokens 0.0.0-stage → 0.1.0-alpha.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/src/color.json ADDED
@@ -0,0 +1,850 @@
1
+ {
2
+ "$description": "Nsaa semantic colours. Structure from Interfere, values from Radix primitives, with Nsaa AA fixes. {name} = primitive, {@name} = semantic, {\"mix\":[a,b,amount]} = OKLab mix. highContrast applies under prefers-contrast: more (light and dark). effect = colours that only drive shadows and surfaces (Figma Color collection, EFFECT_COLOR / fill / stroke scopes); {\"alpha\":[ref, a]} = ref at opacity a.",
3
+ "color": {
4
+ "white-fill": {
5
+ "light": "#ffffff",
6
+ "dark": "#ffffff"
7
+ },
8
+ "black-fill": {
9
+ "light": "#000000",
10
+ "dark": "#000000"
11
+ },
12
+ "black-transparent": {
13
+ "light": "#00000000",
14
+ "dark": "#00000000"
15
+ },
16
+ "page": {
17
+ "light": "{@white-fill}",
18
+ "dark": "#0b0b0b"
19
+ },
20
+ "shell": {
21
+ "light": "#f6f6f6",
22
+ "dark": "{@black-fill}"
23
+ },
24
+ "container": {
25
+ "light": "{@white-fill}",
26
+ "dark": "{gray-1}"
27
+ },
28
+ "container-recessed": {
29
+ "light": "{gray-1}",
30
+ "dark": "{gray-1}"
31
+ },
32
+ "modal": {
33
+ "light": "#ffffff",
34
+ "dark": "#222222"
35
+ },
36
+ "card-subtle": {
37
+ "light": "{gray-a2}",
38
+ "dark": "{gray-a2}"
39
+ },
40
+ "sunken": {
41
+ "light": "{black-a1}",
42
+ "dark": "{black-a6}"
43
+ },
44
+ "standout": {
45
+ "light": "{gray-12}",
46
+ "dark": "{gray-3}"
47
+ },
48
+ "component": {
49
+ "light": "{gray-a3}",
50
+ "dark": "{gray-a3}"
51
+ },
52
+ "component-hover": {
53
+ "light": "{gray-a4}",
54
+ "dark": "{gray-a4}"
55
+ },
56
+ "component-active": {
57
+ "light": "{gray-a5}",
58
+ "dark": "{gray-a5}"
59
+ },
60
+ "component-on-sunken": {
61
+ "light": "{@white-fill}",
62
+ "dark": "{gray-4}"
63
+ },
64
+ "component-on-inverted": {
65
+ "light": "{white-a2}",
66
+ "dark": "{black-a2}"
67
+ },
68
+ "component-on-container-subtle": {
69
+ "light": "{@white-fill}",
70
+ "dark": "{gray-a2}"
71
+ },
72
+ "component-on-container-subtle-hover": {
73
+ "light": "{@white-fill}",
74
+ "dark": "{gray-a3}"
75
+ },
76
+ "component-on-container-strong": {
77
+ "light": "{@white-fill}",
78
+ "dark": "{gray-a3}"
79
+ },
80
+ "component-on-container-strong-hover": {
81
+ "light": "{gray-2}",
82
+ "dark": "{gray-a4}"
83
+ },
84
+ "transparent": {
85
+ "light": "{@black-transparent}",
86
+ "dark": "{@black-transparent}"
87
+ },
88
+ "transparent-hover": {
89
+ "light": "{gray-a3}",
90
+ "dark": "{gray-a4}"
91
+ },
92
+ "transparent-active": {
93
+ "light": "{gray-a3}",
94
+ "dark": "{gray-a3}"
95
+ },
96
+ "toggle-on": {
97
+ "light": "{gray-a5}",
98
+ "dark": "{gray-a5}",
99
+ "$note": "Resting fill of a neutral on toggle (decisions #65, #70): one step above transparent-hover (a4) so on never matches off + hover; paired with a 1 px border-control ring."
100
+ },
101
+ "toggle-on-hover": {
102
+ "light": "{gray-a6}",
103
+ "dark": "{gray-a6}"
104
+ },
105
+ "toggle-on-active": {
106
+ "light": "{gray-a7}",
107
+ "dark": "{gray-a7}"
108
+ },
109
+ "brand-solid": {
110
+ "light": "{gray-12}",
111
+ "dark": "{gray-12}",
112
+ "$note": "Neutral brand (#81): near-black in light, near-white in dark, like shadcn primary."
113
+ },
114
+ "brand-solid-hover": {
115
+ "light": {
116
+ "mix": [
117
+ "{gray-12}",
118
+ "#ffffff",
119
+ 0.12
120
+ ]
121
+ },
122
+ "dark": {
123
+ "mix": [
124
+ "{gray-12}",
125
+ "#000000",
126
+ 0.1
127
+ ]
128
+ }
129
+ },
130
+ "brand-solid-active": {
131
+ "light": {
132
+ "mix": [
133
+ "{gray-12}",
134
+ "#ffffff",
135
+ 0.2
136
+ ]
137
+ },
138
+ "dark": {
139
+ "mix": [
140
+ "{gray-12}",
141
+ "#000000",
142
+ 0.18
143
+ ]
144
+ }
145
+ },
146
+ "brand-solid-disabled": {
147
+ "light": "{gray-a8}",
148
+ "dark": "{gray-a8}"
149
+ },
150
+ "brand-subtle": {
151
+ "light": "{gray-a3}",
152
+ "dark": "{gray-a3}"
153
+ },
154
+ "brand-subtle-hover": {
155
+ "light": "{gray-a4}",
156
+ "dark": "{gray-a4}"
157
+ },
158
+ "brand-subtle-active": {
159
+ "light": "{gray-a5}",
160
+ "dark": "{gray-a5}"
161
+ },
162
+ "positive-solid": {
163
+ "light": "{green-11}",
164
+ "dark": "{green-9}"
165
+ },
166
+ "positive-solid-hover": {
167
+ "light": {
168
+ "mix": [
169
+ "{green-11}",
170
+ "#000000",
171
+ 0.12
172
+ ]
173
+ },
174
+ "dark": "{green-10}"
175
+ },
176
+ "positive-solid-active": {
177
+ "light": {
178
+ "mix": [
179
+ "{green-11}",
180
+ "#000000",
181
+ 0.22
182
+ ]
183
+ },
184
+ "dark": "{green-11}"
185
+ },
186
+ "positive-subtle": {
187
+ "light": "{green-a3}",
188
+ "dark": "{green-a3}"
189
+ },
190
+ "positive-subtle-hover": {
191
+ "light": "{green-a4}",
192
+ "dark": "{green-a4}"
193
+ },
194
+ "positive-subtle-active": {
195
+ "light": "{green-a5}",
196
+ "dark": "{green-a5}"
197
+ },
198
+ "warning-solid": {
199
+ "light": {
200
+ "mix": [
201
+ "{orange-11}",
202
+ "#000000",
203
+ 0.05
204
+ ]
205
+ },
206
+ "dark": "{orange-9}",
207
+ "$note": "Light: orange 11 deepened 5% in OKLab. Plain orange 11 gives white text 4.51:1 in sRGB but 4.39:1 on Display-P3 screens (decision #49)."
208
+ },
209
+ "warning-solid-hover": {
210
+ "light": {
211
+ "mix": [
212
+ "{orange-11}",
213
+ "#000000",
214
+ 0.12
215
+ ]
216
+ },
217
+ "dark": "{orange-10}"
218
+ },
219
+ "warning-solid-active": {
220
+ "light": {
221
+ "mix": [
222
+ "{orange-11}",
223
+ "#000000",
224
+ 0.22
225
+ ]
226
+ },
227
+ "dark": "{orange-11}"
228
+ },
229
+ "warning-subtle": {
230
+ "light": "{orange-a3}",
231
+ "dark": "{orange-a3}"
232
+ },
233
+ "warning-subtle-hover": {
234
+ "light": "{orange-a4}",
235
+ "dark": "{orange-a4}"
236
+ },
237
+ "warning-subtle-active": {
238
+ "light": "{orange-a5}",
239
+ "dark": "{orange-a5}"
240
+ },
241
+ "danger-solid": {
242
+ "light": "{tomato-vivid}",
243
+ "dark": "{tomato-9}",
244
+ "$note": "Light: vivid AA tomato (decision #50): punchier than step 11, white text passes 4.5:1 in sRGB and P3. Dark keeps step 9 with dark text."
245
+ },
246
+ "danger-solid-hover": {
247
+ "light": {
248
+ "mix": [
249
+ "{tomato-vivid}",
250
+ "#000000",
251
+ 0.12
252
+ ]
253
+ },
254
+ "dark": "{tomato-10}"
255
+ },
256
+ "danger-solid-active": {
257
+ "light": {
258
+ "mix": [
259
+ "{tomato-vivid}",
260
+ "#000000",
261
+ 0.22
262
+ ]
263
+ },
264
+ "dark": "{tomato-11}"
265
+ },
266
+ "danger-subtle": {
267
+ "light": "{tomato-a2}",
268
+ "dark": "{tomato-a2}"
269
+ },
270
+ "danger-subtle-hover": {
271
+ "light": "{tomato-a3}",
272
+ "dark": "{tomato-a3}"
273
+ },
274
+ "danger-subtle-active": {
275
+ "light": "{tomato-a5}",
276
+ "dark": "{tomato-a5}"
277
+ },
278
+ "destructive-hover-foreground": {
279
+ "light": "oklch(0.44 0.2 27.325)",
280
+ "dark": "oklch(0.78 0.15 22.216)",
281
+ "$note": "Destructive Button and Badge hover (#125): the tint stays at rest (light destructive/10, dark /20) and the text deepens to this colour. Emitted as shadcn-style --destructive-hover-foreground. Figma: state/destructive-hover-foreground."
282
+ },
283
+ "info-solid": {
284
+ "light": "{iris-11}",
285
+ "dark": "{iris-9}"
286
+ },
287
+ "info-solid-hover": {
288
+ "light": {
289
+ "mix": [
290
+ "{iris-11}",
291
+ "#000000",
292
+ 0.12
293
+ ]
294
+ },
295
+ "dark": {
296
+ "mix": [
297
+ "{iris-9}",
298
+ "#000000",
299
+ 0.12
300
+ ]
301
+ }
302
+ },
303
+ "info-solid-active": {
304
+ "light": {
305
+ "mix": [
306
+ "{iris-11}",
307
+ "#000000",
308
+ 0.22
309
+ ]
310
+ },
311
+ "dark": {
312
+ "mix": [
313
+ "{iris-9}",
314
+ "#000000",
315
+ 0.22
316
+ ]
317
+ }
318
+ },
319
+ "info-subtle": {
320
+ "light": "{iris-a3}",
321
+ "dark": "{iris-a3}"
322
+ },
323
+ "info-subtle-hover": {
324
+ "light": "{iris-a4}",
325
+ "dark": "{iris-a4}"
326
+ },
327
+ "info-subtle-active": {
328
+ "light": "{iris-a5}",
329
+ "dark": "{iris-a5}"
330
+ },
331
+ "inverted-solid": {
332
+ "light": "{black-a12}",
333
+ "dark": "{white-a12}"
334
+ },
335
+ "inverted-solid-hover": {
336
+ "light": "{black-a10}",
337
+ "dark": "{white-a10}"
338
+ },
339
+ "inverted-solid-active": {
340
+ "light": "{black-a9}",
341
+ "dark": "{white-a9}"
342
+ },
343
+ "disabled": {
344
+ "light": "{gray-a3}",
345
+ "dark": "{gray-a2}"
346
+ },
347
+ "foreground": {
348
+ "light": "{gray-a12}",
349
+ "dark": "{gray-a12}",
350
+ "highContrast": "{gray-a12}"
351
+ },
352
+ "paragraph-foreground": {
353
+ "light": "{gray-a12}",
354
+ "dark": "{white-a10}",
355
+ "highContrast": "{gray-a12}"
356
+ },
357
+ "muted-foreground": {
358
+ "light": "{gray-a11}",
359
+ "dark": "{gray-a11}",
360
+ "highContrast": "{gray-a12}"
361
+ },
362
+ "muted-foreground-solid": {
363
+ "light": "{gray-11}",
364
+ "dark": "{gray-11}",
365
+ "highContrast": "{gray-12}"
366
+ },
367
+ "tertiary-foreground": {
368
+ "light": "{gray-a11}",
369
+ "dark": "{gray-a11}",
370
+ "$note": "Was gray-a9 in Interfere (3.3:1). Use icon-tertiary for decorative icons.",
371
+ "highContrast": "{gray-a12}"
372
+ },
373
+ "disabled-foreground": {
374
+ "light": "{gray-a8}",
375
+ "dark": "{gray-a8}",
376
+ "highContrast": "{gray-a11}"
377
+ },
378
+ "brand-foreground": {
379
+ "light": "{gray-12}",
380
+ "dark": "{gray-12}"
381
+ },
382
+ "positive-foreground": {
383
+ "light": {
384
+ "mix": [
385
+ "{green-11}",
386
+ "#000000",
387
+ 0.18
388
+ ]
389
+ },
390
+ "dark": "{green-11}",
391
+ "$note": "Light: step 11 deepened 18% in OKLab so coloured text passes 4.5:1 on every surface (page, shell, card, component)."
392
+ },
393
+ "warning-foreground": {
394
+ "light": {
395
+ "mix": [
396
+ "{orange-11}",
397
+ "#000000",
398
+ 0.18
399
+ ]
400
+ },
401
+ "dark": "{orange-11}",
402
+ "$note": "Light: step 11 deepened 18% in OKLab so coloured text passes 4.5:1 on every surface (page, shell, card, component)."
403
+ },
404
+ "danger-foreground": {
405
+ "light": {
406
+ "mix": [
407
+ "{tomato-11}",
408
+ "#000000",
409
+ 0.18
410
+ ]
411
+ },
412
+ "dark": "{tomato-11}",
413
+ "$note": "Light: step 11 deepened 18% in OKLab so coloured text passes 4.5:1 on every surface (page, shell, card, component)."
414
+ },
415
+ "info-foreground": {
416
+ "light": {
417
+ "mix": [
418
+ "{iris-11}",
419
+ "#000000",
420
+ 0.18
421
+ ]
422
+ },
423
+ "dark": "{iris-11}",
424
+ "$note": "Info (Iris). Same rule as the other coloured text."
425
+ },
426
+ "on-inverted-foreground": {
427
+ "light": "{@white-fill}",
428
+ "dark": "{@black-fill}"
429
+ },
430
+ "on-standout-primary-foreground": {
431
+ "light": "{@white-fill}",
432
+ "dark": "{gray-a12}"
433
+ },
434
+ "on-standout-secondary-foreground": {
435
+ "light": "{white-a7}",
436
+ "dark": "{white-a7}"
437
+ },
438
+ "on-brand-solid-foreground": {
439
+ "light": "{@white-fill}",
440
+ "dark": "{gray-1}"
441
+ },
442
+ "on-brand-subtle-foreground": {
443
+ "light": "{gray-12}",
444
+ "dark": "{gray-12}"
445
+ },
446
+ "on-positive-solid-foreground": {
447
+ "light": "{@white-fill}",
448
+ "dark": "{green-1}"
449
+ },
450
+ "on-positive-subtle-foreground": {
451
+ "light": "{green-12}",
452
+ "dark": "{green-11}"
453
+ },
454
+ "on-warning-solid-foreground": {
455
+ "light": "{@white-fill}",
456
+ "dark": "{orange-1}"
457
+ },
458
+ "on-warning-subtle-foreground": {
459
+ "light": "{orange-12}",
460
+ "dark": "{orange-11}"
461
+ },
462
+ "on-danger-solid-foreground": {
463
+ "light": "{@white-fill}",
464
+ "dark": "{tomato-1}"
465
+ },
466
+ "on-danger-subtle-foreground": {
467
+ "light": "{tomato-12}",
468
+ "dark": "{tomato-11}"
469
+ },
470
+ "on-info-solid-foreground": {
471
+ "light": "{@white-fill}",
472
+ "dark": "{@white-fill}",
473
+ "$note": "Iris 9 is dark enough for white text in both modes (Radix pairs iris with white); hover and active deepen instead of lighten."
474
+ },
475
+ "on-info-subtle-foreground": {
476
+ "light": "{iris-12}",
477
+ "dark": "{iris-11}"
478
+ },
479
+ "border-default": {
480
+ "light": "{gray-a4}",
481
+ "dark": "{gray-a5}",
482
+ "highContrast": "{gray-a7}"
483
+ },
484
+ "border-subtle": {
485
+ "light": "{gray-a2}",
486
+ "dark": "{gray-a2}",
487
+ "highContrast": "{gray-a6}"
488
+ },
489
+ "border-strong": {
490
+ "light": "{gray-a6}",
491
+ "dark": "{gray-a6}",
492
+ "highContrast": "{gray-a8}"
493
+ },
494
+ "border-input": {
495
+ "light": "{@border-default}",
496
+ "dark": "{gray-a6}",
497
+ "contrastMore": "{@border-control}",
498
+ "$note": "Resting border of text inputs (decisions #62, #77): the soft border-default (same edge as an outline Button; hover steps to border-strong), which becomes border-control (3:1, WCAG 1.4.11) under prefers-contrast: more or data-contrast=\"more\" on any ancestor. Dark steps up one (shadcn: input border is a little stronger than border in dark)."
499
+ },
500
+ "border-input-hover": {
501
+ "light": "{@border-strong}",
502
+ "dark": "{gray-a7}",
503
+ "contrastMore": "{@border-control}",
504
+ "$note": "Hovered border of outline text inputs (#77): border-strong; under contrast-more it stays at border-control so hover never drops below the 3:1 resting border. Dark steps up one (shadcn: input border is a little stronger than border in dark)."
505
+ },
506
+ "border-strong-solid": {
507
+ "light": "{gray-6}",
508
+ "dark": "{gray-6}",
509
+ "highContrast": "{gray-8}"
510
+ },
511
+ "border-inverted": {
512
+ "light": "{@black-fill}",
513
+ "dark": "{@white-fill}"
514
+ },
515
+ "border-on-standout": {
516
+ "light": "{white-a2}",
517
+ "dark": "{white-a1}"
518
+ },
519
+ "brand-border-default": {
520
+ "light": "{gray-a7}",
521
+ "dark": "{gray-a7}",
522
+ "highContrast": "{gray-a11}"
523
+ },
524
+ "brand-border-subtle": {
525
+ "light": "{gray-a5}",
526
+ "dark": "{gray-a5}"
527
+ },
528
+ "brand-border-focus": {
529
+ "light": "{gray-9}",
530
+ "dark": "{gray-9}",
531
+ "highContrast": "{gray-11}",
532
+ "$note": "Neutral focus ring, 3:1 against the page (shadcn ring is lighter and fails 1.4.11; we keep the gate)."
533
+ },
534
+ "positive-border-default": {
535
+ "light": "{green-a6}",
536
+ "dark": "{green-a6}"
537
+ },
538
+ "positive-border-subtle": {
539
+ "light": "{green-a5}",
540
+ "dark": "{green-a5}"
541
+ },
542
+ "warning-border-default": {
543
+ "light": "{orange-a6}",
544
+ "dark": "{orange-a6}"
545
+ },
546
+ "warning-border-subtle": {
547
+ "light": "{orange-a5}",
548
+ "dark": "{orange-a5}"
549
+ },
550
+ "danger-border-default": {
551
+ "light": "{tomato-a6}",
552
+ "dark": "{tomato-a6}",
553
+ "contrastMore": "{@danger-foreground}",
554
+ "$note": "Invalid fields and danger outlines. Under contrast-more (#62) it becomes danger-foreground so an invalid field's boundary keeps 3:1."
555
+ },
556
+ "danger-border-subtle": {
557
+ "light": "{tomato-a4}",
558
+ "dark": "{tomato-a4}"
559
+ },
560
+ "info-border-default": {
561
+ "light": "{iris-a6}",
562
+ "dark": "{iris-a6}"
563
+ },
564
+ "info-border-subtle": {
565
+ "light": "{iris-a5}",
566
+ "dark": "{iris-a5}"
567
+ },
568
+ "brand-fill": {
569
+ "light": "{gray-12}",
570
+ "dark": "{gray-12}",
571
+ "$note": "Text-free fills only: switch tracks, progress, selection."
572
+ },
573
+ "icon-tertiary": {
574
+ "light": "{gray-a9}",
575
+ "dark": "{gray-a9}",
576
+ "$note": "Icons and non-text marks only (3:1 rule)."
577
+ },
578
+ "placeholder-foreground": {
579
+ "light": "{gray-a11}",
580
+ "dark": "{gray-a11}"
581
+ },
582
+ "border-control": {
583
+ "light": "{gray-a9}",
584
+ "dark": "{gray-a9}",
585
+ "$note": "Input, checkbox and radio outlines: meets the 3:1 non-text contrast rule (WCAG 1.4.11). border-default stays for decorative dividers."
586
+ }
587
+ },
588
+ "effect": {
589
+ "shadow/default-inset": {
590
+ "light": "#00000000",
591
+ "dark": "#ffffff12"
592
+ },
593
+ "shadow/inset-hairline": {
594
+ "light": "#0000001a",
595
+ "dark": "#ffffff14",
596
+ "$note": "The soft input's inset hairline (shadow-inset, #66)."
597
+ },
598
+ "shadow/default-ring": {
599
+ "light": "#0000000f",
600
+ "dark": "#00000000"
601
+ },
602
+ "shadow/default-1": {
603
+ "light": "#0000001a",
604
+ "dark": "#00000000"
605
+ },
606
+ "shadow/default-2": {
607
+ "light": "#0000000d",
608
+ "dark": "#00000000"
609
+ },
610
+ "shadow/large-ring": {
611
+ "light": "{gray-a3}",
612
+ "dark": "{gray-a6}"
613
+ },
614
+ "shadow/large-1": {
615
+ "light": "{gray-a3}",
616
+ "dark": "{black-a3}"
617
+ },
618
+ "shadow/large-2": {
619
+ "light": "{black-a2}",
620
+ "dark": "{black-a6}"
621
+ },
622
+ "shadow/large-3": {
623
+ "light": "{black-a1}",
624
+ "dark": "{black-a7}"
625
+ },
626
+ "shadow/xl-inset": {
627
+ "light": "#00000000",
628
+ "dark": "#ffffff12"
629
+ },
630
+ "shadow/xl-ring": {
631
+ "light": "#0000000f",
632
+ "dark": "#00000000"
633
+ },
634
+ "shadow/border": {
635
+ "light": "#00000012",
636
+ "dark": "#ffffff12"
637
+ },
638
+ "surface/glass-fill": {
639
+ "light": {
640
+ "alpha": [
641
+ "{@container}",
642
+ 0.62
643
+ ]
644
+ },
645
+ "dark": {
646
+ "alpha": [
647
+ "{gray-3}",
648
+ 0.55
649
+ ]
650
+ }
651
+ },
652
+ "surface/glass-border": {
653
+ "light": "{white-a8}",
654
+ "dark": "{white-a2}"
655
+ },
656
+ "surface/halo-glow": {
657
+ "light": "{blue-a5}",
658
+ "dark": "{blue-a4}"
659
+ },
660
+ "surface/neu-fill": {
661
+ "light": "{gray-2}",
662
+ "dark": "{gray-2}"
663
+ },
664
+ "surface/neu-border": {
665
+ "light": "{gray-a3}",
666
+ "dark": "{gray-a3}"
667
+ },
668
+ "surface/neu-shadow-dark": {
669
+ "light": "{black-a2}",
670
+ "dark": "{black-a8}"
671
+ },
672
+ "surface/neu-shadow-light": {
673
+ "light": "{white-a12}",
674
+ "dark": "{white-a1}"
675
+ }
676
+ },
677
+ "brand": {
678
+ "$description": "Brand palettes (#81). The default fills the brand-* tokens above; set data-brand on any element to switch.",
679
+ "$default": "neutral",
680
+ "neutral": {
681
+ "brand-solid": {
682
+ "light": "{gray-12}",
683
+ "dark": "{gray-12}",
684
+ "$note": "Neutral brand (#81): near-black in light, near-white in dark, like shadcn primary."
685
+ },
686
+ "brand-solid-hover": {
687
+ "light": {
688
+ "mix": [
689
+ "{gray-12}",
690
+ "#ffffff",
691
+ 0.12
692
+ ]
693
+ },
694
+ "dark": {
695
+ "mix": [
696
+ "{gray-12}",
697
+ "#000000",
698
+ 0.1
699
+ ]
700
+ }
701
+ },
702
+ "brand-solid-active": {
703
+ "light": {
704
+ "mix": [
705
+ "{gray-12}",
706
+ "#ffffff",
707
+ 0.2
708
+ ]
709
+ },
710
+ "dark": {
711
+ "mix": [
712
+ "{gray-12}",
713
+ "#000000",
714
+ 0.18
715
+ ]
716
+ }
717
+ },
718
+ "brand-solid-disabled": {
719
+ "light": "{gray-a8}",
720
+ "dark": "{gray-a8}"
721
+ },
722
+ "brand-subtle": {
723
+ "light": "{gray-a3}",
724
+ "dark": "{gray-a3}"
725
+ },
726
+ "brand-subtle-hover": {
727
+ "light": "{gray-a4}",
728
+ "dark": "{gray-a4}"
729
+ },
730
+ "brand-subtle-active": {
731
+ "light": "{gray-a5}",
732
+ "dark": "{gray-a5}"
733
+ },
734
+ "brand-foreground": {
735
+ "light": "{gray-12}",
736
+ "dark": "{gray-12}"
737
+ },
738
+ "on-brand-solid-foreground": {
739
+ "light": "{@white-fill}",
740
+ "dark": "{gray-1}"
741
+ },
742
+ "on-brand-subtle-foreground": {
743
+ "light": "{gray-12}",
744
+ "dark": "{gray-12}"
745
+ },
746
+ "brand-border-default": {
747
+ "light": "{gray-a7}",
748
+ "dark": "{gray-a7}",
749
+ "highContrast": "{gray-a11}"
750
+ },
751
+ "brand-border-subtle": {
752
+ "light": "{gray-a5}",
753
+ "dark": "{gray-a5}"
754
+ },
755
+ "brand-border-focus": {
756
+ "light": "{gray-9}",
757
+ "dark": "{gray-9}",
758
+ "highContrast": "{gray-11}",
759
+ "$note": "Neutral focus ring, 3:1 against the page (shadcn ring is lighter and fails 1.4.11; we keep the gate)."
760
+ },
761
+ "brand-fill": {
762
+ "light": "{gray-12}",
763
+ "dark": "{gray-12}",
764
+ "$note": "Text-free fills only: switch tracks, progress, selection."
765
+ }
766
+ },
767
+ "blue": {
768
+ "brand-solid": {
769
+ "light": "{blue-vivid}",
770
+ "dark": "{blue-9}",
771
+ "$note": "Light: vivid AA blue (decision #50): punchier than step 11, white text passes 4.5:1 in sRGB and P3. Dark keeps step 9 with dark text."
772
+ },
773
+ "brand-solid-hover": {
774
+ "light": {
775
+ "mix": [
776
+ "{blue-vivid}",
777
+ "#000000",
778
+ 0.12
779
+ ]
780
+ },
781
+ "dark": "{blue-10}"
782
+ },
783
+ "brand-solid-active": {
784
+ "light": {
785
+ "mix": [
786
+ "{blue-vivid}",
787
+ "#000000",
788
+ 0.22
789
+ ]
790
+ },
791
+ "dark": "{blue-11}"
792
+ },
793
+ "brand-solid-disabled": {
794
+ "light": "{blue-a8}",
795
+ "dark": "{blue-a8}"
796
+ },
797
+ "brand-subtle": {
798
+ "light": "{blue-a3}",
799
+ "dark": "{blue-a3}"
800
+ },
801
+ "brand-subtle-hover": {
802
+ "light": "{blue-a4}",
803
+ "dark": "{blue-a4}"
804
+ },
805
+ "brand-subtle-active": {
806
+ "light": "{blue-a5}",
807
+ "dark": "{blue-a5}"
808
+ },
809
+ "brand-foreground": {
810
+ "light": {
811
+ "mix": [
812
+ "{blue-11}",
813
+ "#000000",
814
+ 0.18
815
+ ]
816
+ },
817
+ "dark": "{blue-11}",
818
+ "$note": "Light: step 11 deepened 18% in OKLab so coloured text passes 4.5:1 on every surface (page, shell, card, component)."
819
+ },
820
+ "on-brand-solid-foreground": {
821
+ "light": "{@white-fill}",
822
+ "dark": "{blue-1}"
823
+ },
824
+ "on-brand-subtle-foreground": {
825
+ "light": "{blue-12}",
826
+ "dark": "{blue-11}"
827
+ },
828
+ "brand-border-default": {
829
+ "light": "{blue-a6}",
830
+ "dark": "{blue-a6}",
831
+ "highContrast": "{blue-a11}"
832
+ },
833
+ "brand-border-subtle": {
834
+ "light": "{blue-a5}",
835
+ "dark": "{blue-a5}"
836
+ },
837
+ "brand-border-focus": {
838
+ "light": "{blue-9}",
839
+ "dark": "{blue-a9}",
840
+ "highContrast": "{blue-11}",
841
+ "$note": "Focus ring must reach 3:1 against the page (was blue-a8, 2.3:1)."
842
+ },
843
+ "brand-fill": {
844
+ "light": "{blue-9}",
845
+ "dark": "{blue-9}",
846
+ "$note": "Text-free fills only: focus rings, switch tracks, progress, selection. Never put text on it."
847
+ }
848
+ }
849
+ }
850
+ }