@mindlogic-ai/logician-ui 3.1.0-alpha.10 → 3.1.0-alpha.12

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.
@@ -33,32 +33,6 @@
33
33
  * @see https://www.w3.org/TR/WCAG21/#contrast-minimum
34
34
  * @version 3.0.0
35
35
  */
36
- /**
37
- * Semantic color tokens that map primitive colors to UI intent.
38
- *
39
- * Use these tokens in components instead of raw color values:
40
- * - `primary.*`: Buttons, links, focus states
41
- * - `secondary.*`: Accent elements, highlights
42
- * - `success.*`: Success messages, confirmations
43
- * - `warning.*`: Warning messages, caution states
44
- * - `danger.*`: Error messages, destructive actions
45
- *
46
- * Each category includes:
47
- * - `lightest`: Lightest backgrounds (ghost states, very subtle fills)
48
- * - `extralight`: Extra-light backgrounds (badges, subtle fills)
49
- * - `lighter`: Light backgrounds (toast backgrounds, subtle fills)
50
- * - `light`: Medium backgrounds (hover states, medium fills)
51
- * - `main`: Primary color (buttons, text, icons)
52
- * - `dark`: Dark variant (text on light backgrounds)
53
- * - `darker`: Darkest variant (high-contrast text)
54
- *
55
- * @example
56
- * ```tsx
57
- * <Button bgColor="primary.main" />
58
- * <Alert bgColor="danger.lighter" color="danger.dark" />
59
- * <Badge bgColor="success.lightest" color="success.dark" />
60
- * ```
61
- */
62
36
  export declare const semanticTokens: {
63
37
  readonly colors: {
64
38
  /**
@@ -117,6 +91,18 @@ export declare const semanticTokens: {
117
91
  readonly _dark: "{colors.blue.100}";
118
92
  };
119
93
  };
94
+ readonly fill: {
95
+ readonly value: {
96
+ readonly base: "{colors.blue.500}";
97
+ readonly _dark: "{colors.blue.700}";
98
+ };
99
+ };
100
+ readonly fillStrong: {
101
+ readonly value: {
102
+ readonly base: "{colors.blue.700}";
103
+ readonly _dark: "{colors.blue.800}";
104
+ };
105
+ };
120
106
  };
121
107
  /**
122
108
  * Secondary colors (Violet-based)
@@ -329,6 +315,135 @@ export declare const semanticTokens: {
329
315
  };
330
316
  };
331
317
  };
318
+ /**
319
+ * `slate.*` — the foundational **mode-aware neutral family**.
320
+ *
321
+ * A first-class neutral palette alongside the raw `gray.*` primitives, but
322
+ * mode-aware: each `slate.N` resolves to `gray.N` in light and to the
323
+ * desaturated counterpart of the *mirrored* step in dark, so a single token
324
+ * carries the same tonal level in both modes (e.g. `slate.300` is a light
325
+ * divider in light and the equivalent dark divider in dark — no `_dark={{…}}`
326
+ * at the call site). It lives under `semanticTokens` only because Chakra
327
+ * requires that for the `_dark` flip; conceptually it is a *foundation*
328
+ * (a tonal scale), not a *role*.
329
+ *
330
+ * When to use which:
331
+ * - Prefer the **role tokens** (`fg`/`bg`/`border`) when one matches the
332
+ * intent — they carry semantics and AA-tuned dark values.
333
+ * - Reach for **`slate.N`** when you need a specific neutral tonal step that
334
+ * no role names (mirroring how you'd otherwise drop to a raw `gray.N`, but
335
+ * keeping the dark flip). `slate` and the role tokens are *distinct* ramps
336
+ * (slate is a mechanical mirror; roles are hand-tuned), so they are not
337
+ * interchangeable in dark mode.
338
+ *
339
+ * `600`/`700` are lifted off the straight mirror (#8E939F/#7C818D) so the
340
+ * secondary/muted text they most often carry clears WCAG AA 4.5:1 on the
341
+ * dark canvas/surface — the straight mirrors measured ~3.0–3.9 there.
342
+ */
343
+ readonly slate: {
344
+ readonly 0: {
345
+ readonly value: {
346
+ readonly base: "{colors.gray.0}";
347
+ readonly _dark: "#0E1014";
348
+ };
349
+ };
350
+ readonly 50: {
351
+ readonly value: {
352
+ readonly base: "{colors.gray.50}";
353
+ readonly _dark: "#181A20";
354
+ };
355
+ };
356
+ readonly 100: {
357
+ readonly value: {
358
+ readonly base: "{colors.gray.100}";
359
+ readonly _dark: "#23262E";
360
+ };
361
+ };
362
+ readonly 200: {
363
+ readonly value: {
364
+ readonly base: "{colors.gray.200}";
365
+ readonly _dark: "#30343C";
366
+ };
367
+ };
368
+ readonly 300: {
369
+ readonly value: {
370
+ readonly base: "{colors.gray.300}";
371
+ readonly _dark: "#3C404B";
372
+ };
373
+ };
374
+ readonly 400: {
375
+ readonly value: {
376
+ readonly base: "{colors.gray.400}";
377
+ readonly _dark: "#4A4E5A";
378
+ };
379
+ };
380
+ readonly 500: {
381
+ readonly value: {
382
+ readonly base: "{colors.gray.500}";
383
+ readonly _dark: "#595E6B";
384
+ };
385
+ };
386
+ readonly 600: {
387
+ readonly value: {
388
+ readonly base: "{colors.gray.600}";
389
+ readonly _dark: "#898E99";
390
+ };
391
+ };
392
+ readonly 700: {
393
+ readonly value: {
394
+ readonly base: "{colors.gray.700}";
395
+ readonly _dark: "#8D919D";
396
+ };
397
+ };
398
+ readonly 800: {
399
+ readonly value: {
400
+ readonly base: "{colors.gray.800}";
401
+ readonly _dark: "#8E939F";
402
+ };
403
+ };
404
+ readonly 900: {
405
+ readonly value: {
406
+ readonly base: "{colors.gray.900}";
407
+ readonly _dark: "#A2A6B1";
408
+ };
409
+ };
410
+ readonly 1000: {
411
+ readonly value: {
412
+ readonly base: "{colors.gray.1000}";
413
+ readonly _dark: "#B6BAC3";
414
+ };
415
+ };
416
+ readonly 1100: {
417
+ readonly value: {
418
+ readonly base: "{colors.gray.1100}";
419
+ readonly _dark: "#D2D5DB";
420
+ };
421
+ };
422
+ readonly 1200: {
423
+ readonly value: {
424
+ readonly base: "{colors.gray.1200}";
425
+ readonly _dark: "#E5E8EC";
426
+ };
427
+ };
428
+ readonly 1300: {
429
+ readonly value: {
430
+ readonly base: "{colors.gray.1300}";
431
+ readonly _dark: "#F2F4F7";
432
+ };
433
+ };
434
+ readonly 1400: {
435
+ readonly value: {
436
+ readonly base: "{colors.gray.1400}";
437
+ readonly _dark: "#F8F9FB";
438
+ };
439
+ };
440
+ readonly 1500: {
441
+ readonly value: {
442
+ readonly base: "{colors.gray.1500}";
443
+ readonly _dark: "#FEFEFF";
444
+ };
445
+ };
446
+ };
332
447
  /**
333
448
  * Neutral background tokens — map onto the gray.0–1500 scale.
334
449
  * Use for: page/canvas, raised surfaces (cards, menus), subtle/muted fills,
@@ -341,46 +456,58 @@ export declare const semanticTokens: {
341
456
  * - inverse: high-contrast surface (flips to light in dark mode)
342
457
  */
343
458
  readonly bg: {
459
+ readonly DEFAULT: {
460
+ readonly value: {
461
+ readonly _light: "{colors.white}";
462
+ readonly _dark: "#0E1014";
463
+ };
464
+ };
344
465
  readonly canvas: {
345
466
  readonly value: {
346
467
  readonly base: "{colors.gray.0}";
347
- readonly _dark: "{colors.gray.1500}";
468
+ readonly _dark: "#0E1014";
348
469
  };
349
470
  };
350
471
  readonly surface: {
351
472
  readonly value: {
352
473
  readonly base: "{colors.white}";
353
- readonly _dark: "{colors.gray.1400}";
474
+ readonly _dark: "#181A20";
354
475
  };
355
476
  };
356
477
  readonly raised: {
357
478
  readonly value: {
358
479
  readonly base: "{colors.white}";
359
- readonly _dark: "{colors.gray.1100}";
480
+ readonly _dark: "#3C404B";
360
481
  };
361
482
  };
362
483
  readonly subtle: {
363
484
  readonly value: {
364
485
  readonly base: "{colors.gray.50}";
365
- readonly _dark: "{colors.gray.1300}";
486
+ readonly _dark: "#23262E";
366
487
  };
367
488
  };
368
489
  readonly muted: {
369
490
  readonly value: {
370
491
  readonly base: "{colors.gray.100}";
371
- readonly _dark: "{colors.gray.1200}";
492
+ readonly _dark: "#30343C";
372
493
  };
373
494
  };
374
495
  readonly inverse: {
375
496
  readonly value: {
376
497
  readonly base: "{colors.gray.1300}";
377
- readonly _dark: "{colors.gray.50}";
498
+ readonly _dark: "#F8F9FB";
499
+ };
500
+ };
501
+ readonly sunken: {
502
+ readonly value: {
503
+ readonly base: "{colors.gray.50}";
504
+ readonly _dark: "#0E1014";
378
505
  };
379
506
  };
380
507
  readonly panel: {
381
508
  readonly value: {
382
509
  readonly base: "{colors.white}";
383
- readonly _dark: "{colors.gray.1400}";
510
+ readonly _dark: "#181A20";
384
511
  };
385
512
  };
386
513
  /**
@@ -423,28 +550,40 @@ export declare const semanticTokens: {
423
550
  * - inverse: text on inverse surfaces (flips with mode)
424
551
  */
425
552
  readonly fg: {
426
- readonly default: {
553
+ readonly DEFAULT: {
554
+ readonly value: {
555
+ readonly _light: "{colors.black}";
556
+ readonly _dark: "#F8F9FB";
557
+ };
558
+ };
559
+ readonly emphasized: {
427
560
  readonly value: {
428
561
  readonly base: "{colors.gray.1300}";
429
- readonly _dark: "{colors.gray.200}";
562
+ readonly _dark: "#E5E8EC";
563
+ };
564
+ };
565
+ readonly default: {
566
+ readonly value: {
567
+ readonly base: "{colors.gray.1000}";
568
+ readonly _dark: "#D2D5DB";
430
569
  };
431
570
  };
432
571
  readonly muted: {
433
572
  readonly value: {
434
573
  readonly base: "{colors.gray.900}";
435
- readonly _dark: "{colors.gray.300}";
574
+ readonly _dark: "#B6BAC3";
436
575
  };
437
576
  };
438
577
  readonly subtle: {
439
578
  readonly value: {
440
579
  readonly base: "{colors.gray.700}";
441
- readonly _dark: "{colors.gray.600}";
580
+ readonly _dark: "#989DA9";
442
581
  };
443
582
  };
444
583
  readonly inverse: {
445
584
  readonly value: {
446
585
  readonly base: "{colors.gray.0}";
447
- readonly _dark: "{colors.gray.1400}";
586
+ readonly _dark: "#181A20";
448
587
  };
449
588
  };
450
589
  };
@@ -456,22 +595,28 @@ export declare const semanticTokens: {
456
595
  * - strong: high-emphasis borders, focus outlines on neutral
457
596
  */
458
597
  readonly border: {
598
+ readonly DEFAULT: {
599
+ readonly value: {
600
+ readonly _light: "{colors.gray.200}";
601
+ readonly _dark: "#6A6F7C";
602
+ };
603
+ };
459
604
  readonly default: {
460
605
  readonly value: {
461
606
  readonly base: "{colors.gray.300}";
462
- readonly _dark: "{colors.gray.1100}";
607
+ readonly _dark: "#3C404B";
463
608
  };
464
609
  };
465
610
  readonly subtle: {
466
611
  readonly value: {
467
612
  readonly base: "{colors.gray.200}";
468
- readonly _dark: "{colors.gray.1300}";
613
+ readonly _dark: "#23262E";
469
614
  };
470
615
  };
471
616
  readonly strong: {
472
617
  readonly value: {
473
618
  readonly base: "{colors.gray.500}";
474
- readonly _dark: "{colors.gray.900}";
619
+ readonly _dark: "#595E6B";
475
620
  };
476
621
  };
477
622
  };
@@ -485,11 +630,12 @@ export declare const semanticTokens: {
485
630
  * by reviewers. It is intentionally hand-maintained alongside `semanticTokens`
486
631
  * so a rename here is a visible, reviewable diff.
487
632
  *
488
- * Note: `bg.panel` is deliberately omitted it is an internal realignment of a
489
- * Chakra default (for overlay surfaces), not part of the public migration
490
- * contract. App code should use `bg.surface`/`bg.canvas`.
633
+ * Note: `bg.panel` and the bare `bg`/`fg`/`border` DEFAULT tokens are
634
+ * deliberately omitted they are internal realignments of Chakra defaults
635
+ * (overlay surfaces and html-level globals), not part of the public migration
636
+ * contract. App code should use `bg.surface`/`bg.canvas`, `fg.default`, etc.
491
637
  */
492
- export type SemanticColorToken = `bg.${'canvas' | 'surface' | 'raised' | 'subtle' | 'muted' | 'inverse' | 'selected' | 'highlighted'}` | 'bg.invalid.subtle' | `fg.${'default' | 'muted' | 'subtle' | 'inverse'}` | `border.${'default' | 'subtle' | 'strong'}` | `${'primary' | 'secondary' | 'danger' | 'success' | 'warning'}.${'lightest' | 'extralight' | 'lighter' | 'light' | 'main' | 'dark' | 'darker'}`;
638
+ export type SemanticColorToken = `bg.${'canvas' | 'surface' | 'raised' | 'subtle' | 'muted' | 'sunken' | 'inverse' | 'selected' | 'highlighted'}` | 'bg.invalid.subtle' | `fg.${'emphasized' | 'default' | 'muted' | 'subtle' | 'inverse'}` | `border.${'default' | 'subtle' | 'strong'}` | `slate.${0 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | 1100 | 1200 | 1300 | 1400 | 1500}` | `primary.${'fill' | 'fillStrong'}` | `${'primary' | 'secondary' | 'danger' | 'success' | 'warning'}.${'lightest' | 'extralight' | 'lighter' | 'light' | 'main' | 'dark' | 'darker'}`;
493
639
  /**
494
640
  * Primitive color palette following the Golden Ratio system.
495
641
  *
@@ -1 +1 @@
1
- {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/theme/colors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,cAAc;;QAEvB;;;;;;;;;;;;WAYG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyBH;;;;;;;WAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6BH;;;;;;;WAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyBH;;;;;;;WAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyBH;;;;;;;;;;WAUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyBH;;;;;;;;;;WAUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAoCD;;;;;;;;;eASG;;;;;;;;;;;;;;;;;;;;;;QAcL;;;;;;;WAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyBH;;;;;;WAMG;;;;;;;;;;;;;;;;;;;;;;CAaG,CAAC;AAEX;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,kBAAkB,GAC1B,MACI,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,SAAS,GACT,UAAU,GACV,aAAa,EAAE,GACnB,mBAAmB,GACnB,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,EAAE,GAClD,UAAU,SAAS,GAAG,QAAQ,GAAG,QAAQ,EAAE,GAC3C,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,IACzD,UAAU,GACV,YAAY,GACZ,SAAS,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,QAAQ,EAAE,CAAC;AAEnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,MAAM;IACjB;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;;;;;;;;OAUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAqBH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAaH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAaH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgBJ,CAAC"}
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/theme/colors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AA2DH,eAAO,MAAM,cAAc;;QAEvB;;;;;;;;;;;;WAYG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAqCH;;;;;;;WAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6BH;;;;;;;WAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyBH;;;;;;;WAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyBH;;;;;;;;;;WAUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyBH;;;;;;;;;;;;;;;;;;;;;;;;WAwBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+CH;;;;;;;;;;WAUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAoDD;;;;;;;;;eASG;;;;;;;;;;;;;;;;;;;;;;QAcL;;;;;;;WAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyCH;;;;;;WAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoBG,CAAC;AAEX;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,kBAAkB,GAC1B,MACI,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,SAAS,GACT,UAAU,GACV,aAAa,EAAE,GACnB,mBAAmB,GACnB,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,EAAE,GACjE,UAAU,SAAS,GAAG,QAAQ,GAAG,QAAQ,EAAE,GAI3C,SACI,CAAC,GACD,EAAE,GACF,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,EAAE,GACV,WAAW,MAAM,GAAG,YAAY,EAAE,GAClC,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,IACzD,UAAU,GACV,YAAY,GACZ,SAAS,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,QAAQ,EAAE,CAAC;AAEnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,MAAM;IACjB;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAcH;;;;;;;;;;OAUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAqBH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAaH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAaH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgBJ,CAAC"}
@@ -62,6 +62,35 @@
62
62
  * <Badge bgColor="success.lightest" color="success.dark" />
63
63
  * ```
64
64
  */
65
+ /**
66
+ * Halved-saturation counterpart of each primitive `gray.N` — same hue and
67
+ * lightness, HSL saturation cut by ~50% (e.g. `gray.1300` #1E2433 @ 26% →
68
+ * #23262E @ 13%). The blue-tinted `gray` ramp reads as the right neutral in
69
+ * light mode but turns muddy/over-chromatic as a dark surface, so every
70
+ * dark-mode neutral below (`slate.*`, and the `_dark` of `bg`/`fg`/`border`)
71
+ * resolves to this desaturated mirror instead of the raw `gray` step. Light
72
+ * mode is untouched — it keeps referencing `{colors.gray.*}` verbatim.
73
+ *
74
+ * Single source of truth: change a dark neutral here, not at each token.
75
+ */
76
+ const desaturatedGray = {
77
+ 0: '#FEFEFF',
78
+ 50: '#F8F9FB',
79
+ 100: '#F2F4F7',
80
+ 200: '#E5E8EC',
81
+ 300: '#D2D5DB',
82
+ 400: '#B6BAC3',
83
+ 500: '#A2A6B1',
84
+ 600: '#8E939F',
85
+ 800: '#6A6F7C',
86
+ 900: '#595E6B',
87
+ 1000: '#4A4E5A',
88
+ 1100: '#3C404B',
89
+ 1200: '#30343C',
90
+ 1300: '#23262E',
91
+ 1400: '#181A20',
92
+ 1500: '#0E1014',
93
+ };
65
94
  const semanticTokens = {
66
95
  colors: {
67
96
  /**
@@ -99,6 +128,18 @@ const semanticTokens = {
99
128
  darker: {
100
129
  value: { base: '{colors.blue.900}', _dark: '{colors.blue.100}' },
101
130
  }, // high-contrast text
131
+ // Solid brand-blue *fills* for surfaces with white text/icons on top
132
+ // (modal headers, hero/banner gradients, brand badges). `primary.main`/
133
+ // `primary.dark` lighten ~2 stops in dark — right for foreground, too
134
+ // light as a fill — so these stay a deep blue in dark instead. `base`
135
+ // repeats the old main/dark values, so light is unchanged. Bare accents
136
+ // (dots, progress bars) keep `primary.main`.
137
+ fill: {
138
+ value: { base: '{colors.blue.500}', _dark: '{colors.blue.700}' },
139
+ },
140
+ fillStrong: {
141
+ value: { base: '{colors.blue.700}', _dark: '{colors.blue.800}' },
142
+ },
102
143
  },
103
144
  /**
104
145
  * Secondary colors (Violet-based)
@@ -231,6 +272,76 @@ const semanticTokens = {
231
272
  value: { base: '{colors.gold.900}', _dark: '{colors.gold.100}' },
232
273
  },
233
274
  },
275
+ /**
276
+ * `slate.*` — the foundational **mode-aware neutral family**.
277
+ *
278
+ * A first-class neutral palette alongside the raw `gray.*` primitives, but
279
+ * mode-aware: each `slate.N` resolves to `gray.N` in light and to the
280
+ * desaturated counterpart of the *mirrored* step in dark, so a single token
281
+ * carries the same tonal level in both modes (e.g. `slate.300` is a light
282
+ * divider in light and the equivalent dark divider in dark — no `_dark={{…}}`
283
+ * at the call site). It lives under `semanticTokens` only because Chakra
284
+ * requires that for the `_dark` flip; conceptually it is a *foundation*
285
+ * (a tonal scale), not a *role*.
286
+ *
287
+ * When to use which:
288
+ * - Prefer the **role tokens** (`fg`/`bg`/`border`) when one matches the
289
+ * intent — they carry semantics and AA-tuned dark values.
290
+ * - Reach for **`slate.N`** when you need a specific neutral tonal step that
291
+ * no role names (mirroring how you'd otherwise drop to a raw `gray.N`, but
292
+ * keeping the dark flip). `slate` and the role tokens are *distinct* ramps
293
+ * (slate is a mechanical mirror; roles are hand-tuned), so they are not
294
+ * interchangeable in dark mode.
295
+ *
296
+ * `600`/`700` are lifted off the straight mirror (#8E939F/#7C818D) so the
297
+ * secondary/muted text they most often carry clears WCAG AA 4.5:1 on the
298
+ * dark canvas/surface — the straight mirrors measured ~3.0–3.9 there.
299
+ */
300
+ slate: {
301
+ 0: { value: { base: '{colors.gray.0}', _dark: desaturatedGray[1500] } },
302
+ 50: { value: { base: '{colors.gray.50}', _dark: desaturatedGray[1400] } },
303
+ 100: {
304
+ value: { base: '{colors.gray.100}', _dark: desaturatedGray[1300] },
305
+ },
306
+ 200: {
307
+ value: { base: '{colors.gray.200}', _dark: desaturatedGray[1200] },
308
+ },
309
+ 300: {
310
+ value: { base: '{colors.gray.300}', _dark: desaturatedGray[1100] },
311
+ },
312
+ 400: {
313
+ value: { base: '{colors.gray.400}', _dark: desaturatedGray[1000] },
314
+ },
315
+ 500: {
316
+ value: { base: '{colors.gray.500}', _dark: desaturatedGray[900] },
317
+ },
318
+ 600: { value: { base: '{colors.gray.600}', _dark: '#898E99' } },
319
+ 700: { value: { base: '{colors.gray.700}', _dark: '#8D919D' } },
320
+ 800: {
321
+ value: { base: '{colors.gray.800}', _dark: desaturatedGray[600] },
322
+ },
323
+ 900: {
324
+ value: { base: '{colors.gray.900}', _dark: desaturatedGray[500] },
325
+ },
326
+ 1000: {
327
+ value: { base: '{colors.gray.1000}', _dark: desaturatedGray[400] },
328
+ },
329
+ 1100: {
330
+ value: { base: '{colors.gray.1100}', _dark: desaturatedGray[300] },
331
+ },
332
+ 1200: {
333
+ value: { base: '{colors.gray.1200}', _dark: desaturatedGray[200] },
334
+ },
335
+ 1300: {
336
+ value: { base: '{colors.gray.1300}', _dark: desaturatedGray[100] },
337
+ },
338
+ 1400: {
339
+ value: { base: '{colors.gray.1400}', _dark: desaturatedGray[50] },
340
+ },
341
+ 1500: {
342
+ value: { base: '{colors.gray.1500}', _dark: desaturatedGray[0] },
343
+ },
344
+ },
234
345
  /**
235
346
  * Neutral background tokens — map onto the gray.0–1500 scale.
236
347
  * Use for: page/canvas, raised surfaces (cards, menus), subtle/muted fills,
@@ -243,11 +354,19 @@ const semanticTokens = {
243
354
  * - inverse: high-contrast surface (flips to light in dark mode)
244
355
  */
245
356
  bg: {
357
+ // Chakra's own global css paints `html { background: bg }` — the *plain*
358
+ // `bg` token, not `bg.canvas` — so this is the actual page background
359
+ // wherever no component paints over it. `_light` is pure white (Chakra's
360
+ // value, so light is untouched); `_dark` rejoins our neutral floor instead
361
+ // of Chakra's off-palette black.
362
+ DEFAULT: {
363
+ value: { _light: '{colors.white}', _dark: desaturatedGray[1500] },
364
+ },
246
365
  canvas: {
247
- value: { base: '{colors.gray.0}', _dark: '{colors.gray.1500}' },
366
+ value: { base: '{colors.gray.0}', _dark: desaturatedGray[1500] },
248
367
  },
249
368
  surface: {
250
- value: { base: '{colors.white}', _dark: '{colors.gray.1400}' },
369
+ value: { base: '{colors.white}', _dark: desaturatedGray[1400] },
251
370
  },
252
371
  // Strongly-raised neutral surface — one level above `surface` (e.g. the
253
372
  // selected thumb of a SegmentedControl). In dark this is the *lightest*
@@ -259,23 +378,31 @@ const semanticTokens = {
259
378
  // cannot be overridden via semanticTokens in this setup (it keeps
260
379
  // resolving to Chakra's own gray.200), whereas a fresh name is honoured.
261
380
  raised: {
262
- value: { base: '{colors.white}', _dark: '{colors.gray.1100}' },
381
+ value: { base: '{colors.white}', _dark: desaturatedGray[1100] },
263
382
  },
264
383
  subtle: {
265
- value: { base: '{colors.gray.50}', _dark: '{colors.gray.1300}' },
384
+ value: { base: '{colors.gray.50}', _dark: desaturatedGray[1300] },
266
385
  },
267
386
  muted: {
268
- value: { base: '{colors.gray.100}', _dark: '{colors.gray.1200}' },
387
+ value: { base: '{colors.gray.100}', _dark: desaturatedGray[1200] },
269
388
  },
270
389
  inverse: {
271
- value: { base: '{colors.gray.1300}', _dark: '{colors.gray.50}' },
390
+ value: { base: '{colors.gray.1300}', _dark: desaturatedGray[50] },
391
+ },
392
+ // Sunken page wash for list/overview surfaces: a gray floor in light so
393
+ // `bg.surface` cards read as raised above it. In dark the `bg.*` ramp is
394
+ // compressed (`subtle` sits *lighter* than `surface`), which would invert
395
+ // that elevation — so the dark value drops to the canvas floor instead.
396
+ // Component-level fills (hover, chips, inner blocks) keep using `bg.subtle`.
397
+ sunken: {
398
+ value: { base: '{colors.gray.50}', _dark: desaturatedGray[1500] },
272
399
  },
273
400
  // Override Chakra's default `bg.panel` (whose `_dark` resolves to Chakra's
274
401
  // own gray.950 = #111111, off our slate palette). Light value is white —
275
402
  // identical to Chakra's default — so this only realigns dark overlay
276
403
  // surfaces (Menu / Modal / Popover / Toast) onto our gray scale.
277
404
  panel: {
278
- value: { base: '{colors.white}', _dark: '{colors.gray.1400}' },
405
+ value: { base: '{colors.white}', _dark: desaturatedGray[1400] },
279
406
  },
280
407
  /**
281
408
  * Row/selection state tints. Use these for selected rows,
@@ -308,26 +435,42 @@ const semanticTokens = {
308
435
  * - inverse: text on inverse surfaces (flips with mode)
309
436
  */
310
437
  fg: {
438
+ // Plain `fg` is Chakra's html-level text color (`html { color: fg }`).
439
+ // `_light` repeats Chakra's value (black); `_dark` rejoins our desaturated
440
+ // neutral so legacy html-level text tracks `fg.default`.
441
+ DEFAULT: {
442
+ value: { _light: '{colors.black}', _dark: desaturatedGray[50] },
443
+ },
444
+ // Strongest text — headings, titles, key figures, emphasis. This is the
445
+ // near-black step that `fg.default` used to be; `default` is now re-pegged
446
+ // to a lighter body weight (see below), so reach for `emphasized` when you
447
+ // specifically want maximum contrast.
448
+ emphasized: {
449
+ value: { base: '{colors.gray.1300}', _dark: desaturatedGray[200] },
450
+ },
311
451
  default: {
312
- // _dark is gray.200 (not gray.50): near-white text on the dark canvas
313
- // ran ~18:1 brighter than the light baseline (~15:1) and close to pure
314
- // white, which causes glare/halation. gray.200 matches the light
315
- // contrast (~15.4:1) while staying AAA.
316
- value: { base: '{colors.gray.1300}', _dark: '{colors.gray.200}' },
452
+ // Primary *body* text. Re-pegged from gray.1300 gray.1000: near-black
453
+ // (gray.1300, ~14:1 on white) is unusually heavy for running copy, and
454
+ // real product usage clustered well below it. gray.1000 (~9:1) is a
455
+ // comfortable AAA body weight; the old near-black step lives on as
456
+ // `fg.emphasized`. _dark drops one step from emphasized for hierarchy.
457
+ value: { base: '{colors.gray.1000}', _dark: desaturatedGray[300] },
317
458
  },
318
459
  muted: {
319
- // _dark lifts gray.400 gray.300: secondary text read as too dim on the
320
- // dark canvas next to fg.default (gray.200). gray.300 sits one step under
321
- // default — restoring the light-mode hierarchy gap — while staying well
322
- // clear of AA (~12.8:1 on bg.canvas, ~11.7:1 on bg.surface). Light value
323
- // (gray.900) is unchanged.
324
- value: { base: '{colors.gray.900}', _dark: '{colors.gray.300}' },
460
+ // Secondary text. _dark sits one step below `default` (~9.5:1 on the dark
461
+ // canvas) to keep the default→muted hierarchy gap. Light value (gray.900)
462
+ // is unchanged.
463
+ value: { base: '{colors.gray.900}', _dark: desaturatedGray[400] },
325
464
  },
326
465
  subtle: {
327
- value: { base: '{colors.gray.700}', _dark: '{colors.gray.600}' },
466
+ // Tertiary / placeholder / icon text. _dark a11y-bumped from the straight
467
+ // mirror (desaturatedGray[600] #8E939F, ~4.06:1 on bg.muted) to #989DA9
468
+ // (~4.6:1) so it clears AA while staying below fg.muted. Light value
469
+ // (gray.700) is unchanged.
470
+ value: { base: '{colors.gray.700}', _dark: '#989DA9' },
328
471
  },
329
472
  inverse: {
330
- value: { base: '{colors.gray.0}', _dark: '{colors.gray.1400}' },
473
+ value: { base: '{colors.gray.0}', _dark: desaturatedGray[1400] },
331
474
  },
332
475
  },
333
476
  /**
@@ -338,14 +481,21 @@ const semanticTokens = {
338
481
  * - strong: high-emphasis borders, focus outlines on neutral
339
482
  */
340
483
  border: {
484
+ // Plain `border` feeds Chakra's `--global-color-border` (the implicit
485
+ // default border color). Not a text color, so its `_dark` takes the
486
+ // straight halved-saturation mirror (no a11y bump). `_light` repeats
487
+ // Chakra's value so light is untouched.
488
+ DEFAULT: {
489
+ value: { _light: '{colors.gray.200}', _dark: desaturatedGray[800] },
490
+ },
341
491
  default: {
342
- value: { base: '{colors.gray.300}', _dark: '{colors.gray.1100}' },
492
+ value: { base: '{colors.gray.300}', _dark: desaturatedGray[1100] },
343
493
  },
344
494
  subtle: {
345
- value: { base: '{colors.gray.200}', _dark: '{colors.gray.1300}' },
495
+ value: { base: '{colors.gray.200}', _dark: desaturatedGray[1300] },
346
496
  },
347
497
  strong: {
348
- value: { base: '{colors.gray.500}', _dark: '{colors.gray.900}' },
498
+ value: { base: '{colors.gray.500}', _dark: desaturatedGray[900] },
349
499
  },
350
500
  },
351
501
  },