@cdevhub/ngx-tw 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/README.md +78 -15
  2. package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
  3. package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
  4. package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
  5. package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
  6. package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
  7. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
  8. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
  9. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
  10. package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
  11. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
  12. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
  13. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
  14. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
  15. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
  16. package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
  17. package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
  18. package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
  19. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
  20. package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
  21. package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
  22. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
  23. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
  24. package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
  25. package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
  26. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
  27. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
  28. package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
  29. package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
  30. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
  31. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
  32. package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
  33. package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
  34. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
  35. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
  36. package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
  37. package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
  38. package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
  39. package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
  40. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
  41. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
  42. package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
  43. package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
  44. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
  45. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
  46. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
  47. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
  48. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +11 -2
  49. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
  50. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
  51. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
  52. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
  53. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
  54. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
  55. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
  56. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
  57. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
  58. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
  59. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
  60. package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
  61. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
  62. package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
  63. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
  64. package/fesm2022/cdevhub-ngx-tw-item.mjs +18 -3
  65. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
  66. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
  67. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
  68. package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
  69. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
  70. package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
  71. package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
  72. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
  73. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
  74. package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
  75. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
  76. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
  77. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
  78. package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
  79. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
  80. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
  81. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
  82. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
  83. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
  84. package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
  85. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
  86. package/fesm2022/{cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs → cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs} +3 -3
  87. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
  88. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
  89. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
  90. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +23 -7
  91. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
  92. package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
  93. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
  94. package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
  95. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
  96. package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
  97. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
  98. package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
  99. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
  100. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
  101. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
  102. package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
  103. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
  104. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
  105. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
  106. package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
  107. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
  108. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
  109. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
  110. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
  111. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
  112. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
  113. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
  114. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
  115. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
  116. package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
  117. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
  118. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
  119. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
  120. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
  121. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
  122. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
  123. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
  124. package/fesm2022/{cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs → cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs} +107 -19
  125. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
  126. package/fesm2022/cdevhub-ngx-tw-toast.mjs +21 -13
  127. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
  128. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
  129. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
  130. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
  131. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
  132. package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
  133. package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
  134. package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
  135. package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
  136. package/index.json +1 -1
  137. package/package.json +63 -2
  138. package/theme/_base.css +13 -0
  139. package/theme/_dark.css +110 -36
  140. package/theme/_high-contrast-dark.css +367 -0
  141. package/theme/_high-contrast.css +13 -2
  142. package/theme/_light.css +276 -0
  143. package/theme/_semantic.css +47 -12
  144. package/theme/_typography.css +17 -0
  145. package/theme/index.css +86 -7
  146. package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
  147. package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
  148. package/types/cdevhub-ngx-tw-button.d.ts +1 -0
  149. package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
  150. package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
  151. package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
  152. package/types/cdevhub-ngx-tw-card.d.ts +11 -3
  153. package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
  154. package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
  155. package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
  156. package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
  157. package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
  158. package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
  159. package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
  160. package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
  161. package/types/cdevhub-ngx-tw-core.d.ts +152 -21
  162. package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
  163. package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
  164. package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
  165. package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
  166. package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
  167. package/types/cdevhub-ngx-tw-dialog.d.ts +12 -3
  168. package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
  169. package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
  170. package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
  171. package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
  172. package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
  173. package/types/cdevhub-ngx-tw-input.d.ts +5 -8
  174. package/types/cdevhub-ngx-tw-item.d.ts +2 -0
  175. package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
  176. package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
  177. package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
  178. package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
  179. package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
  180. package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
  181. package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
  182. package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
  183. package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
  184. package/types/cdevhub-ngx-tw-select.d.ts +104 -33
  185. package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
  186. package/types/cdevhub-ngx-tw-sheet.d.ts +19 -3
  187. package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
  188. package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
  189. package/types/cdevhub-ngx-tw-split.d.ts +32 -2
  190. package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
  191. package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
  192. package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
  193. package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
  194. package/types/cdevhub-ngx-tw-table.d.ts +53 -10
  195. package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
  196. package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
  197. package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
  198. package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
  199. package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
  200. package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
  201. package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
  202. package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
  203. package/types/cdevhub-ngx-tw-toast.d.ts +20 -6
  204. package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
  205. package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
  206. package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
  207. package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
  208. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs.map +0 -1
  209. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map +0 -1
@@ -0,0 +1,367 @@
1
+ /* ===== Dark high-contrast theme =====
2
+ The dark-based counterpart to `_high-contrast.css`, added so
3
+ `prefers-contrast: more` can COMPOSE with `prefers-color-scheme: dark`
4
+ instead of overriding it. Before it existed, `ThemeService` had to refuse to
5
+ resolve `'system'` to high contrast whenever the OS also asked for dark,
6
+ because the only high-contrast scheme was light-based and honouring the
7
+ contrast preference would have thrown a dark-mode user onto a white surface.
8
+ That compromise is gone; `detectSystemTheme()` now resolves the two
9
+ preferences independently.
10
+
11
+ ── Activation ──
12
+ `[data-theme="high-contrast-dark"]` only. There is deliberately NO
13
+ `@media (prefers-contrast: more) and (prefers-color-scheme: dark)` branch:
14
+ `_high-contrast.css` ships no `prefers-contrast` branch either, so adding
15
+ one here would make contrast auto-apply without JavaScript for one of the
16
+ two high-contrast schemes and not the other. Both schemes are reached the
17
+ same way — an explicit `data-theme`, written either by `ThemeService` or by
18
+ the consumer. (The `prefers-color-scheme` branch in `_dark.css` exists for a
19
+ different reason: plain dark mode is the one scheme that must work with no
20
+ JavaScript at all.)
21
+
22
+ ── Dependency in `_dark.css` ──
23
+ `_dark.css`'s media branch is
24
+ `:root:not([data-theme="light"]):not([data-theme="high-contrast"]):not([data-theme="high-contrast-dark"])`,
25
+ specificity 0,4,0. That third `:not()` is load-bearing for THIS file: the
26
+ block below is a bare attribute selector at 0,1,0, so on a dark-preferring
27
+ OS a `<html data-theme="high-contrast-dark">` would otherwise match the dark
28
+ media block and lose to it no matter what the import order is. Source order
29
+ cannot fix a specificity loss. If that `:not()` is ever removed, this whole
30
+ scheme silently degrades to plain dark on exactly the machines it was
31
+ written for.
32
+
33
+ ── Import order ──
34
+ Imported AFTER `_dark.css` and BEFORE `_high-contrast.css`. Only the second
35
+ half is load-bearing, and for the same reason `_light.css` has to come
36
+ first: `_high-contrast.css`'s `@media (forced-colors: active)` list names
37
+ `[data-theme="high-contrast-dark"]` at the identical 0,1,0 specificity, and
38
+ source order is the only tie-breaker — the forced-colors remap has to win.
39
+ Sitting after `_dark.css` is grouping, not cascade: this is the dark
40
+ family's contrast variant and it is read alongside the `:not()` above.
41
+
42
+ ── Derivation ──
43
+ The METHOD is mirrored from `_high-contrast.css`, not the values.
44
+
45
+ - `_high-contrast.css` shifts the light ramp one palette step DARKER
46
+ (slot 50 → `-100`, … 900 → `-950`, saturating at `-950`). Normal dark is
47
+ the plain inversion (50 → `-950` … 950 → `-50`); this file is that
48
+ inversion shifted one step LIGHTER (50 → `-900`, … 900 → `-50`,
49
+ saturating at `-50`).
50
+ - Light high contrast collapses `surface` / `-raised` / `-overlay` onto
51
+ pure white; this collapses them onto pure black.
52
+ - Foreground and border move to the opposite extreme: `fg` → white,
53
+ `border-strong` → white, with `fg-muted` / `fg-subtle` / `border` at
54
+ `gray-200` / `gray-300` / `gray-300` (the mirror of light's `gray-800` /
55
+ `gray-700` / `gray-700`).
56
+ - Slots invert the same way: `-soft` → `{c}-950`, `-soft-fg` → `{c}-50`,
57
+ `-solid` → `{c}-200` with a black foreground, `-border-strong` →
58
+ `{c}-100` so a 1px outline stays visible against `-soft`.
59
+
60
+ `surface-sunken` / `surface-muted` are mirrored EXACTLY, including the fact
61
+ that `_high-contrast.css` orders them the opposite way round from its own
62
+ base scheme (`muted` one step off the surface, `sunken` two). That looks like
63
+ an authoring slip and is not — it is a fix, and the dark ramp needs the same
64
+ one. `neutral-soft` resolves to `surface-muted` and `neutral-soft-hover` to
65
+ `surface-sunken`, so the ordering decides which way a hover moves. Measured
66
+ separation from the base surface:
67
+
68
+ muted/surface sunken/surface hover moves
69
+ light 1.10 1.04 TOWARD surface ✗
70
+ dark 1.37 1.00 TOWARD surface ✗
71
+ high-contrast 1.04 1.10 away ✓
72
+ high-contrast-dark 1.04 1.18 away ✓
73
+
74
+ Both normal schemes invert the hover — a `neutral-soft` chip slides toward
75
+ the page background when you point at it, and in `dark` it lands exactly on
76
+ it (1.00). `_high-contrast.css` is the only shipped scheme that gets this
77
+ right, and this file is the second. An earlier draft used `_dark.css`'s
78
+ ordering instead, on the reasoning that `bg-surface-muted` needs to stay
79
+ visible against a pure-black surface; that bought 1.43 muted/surface
80
+ separation and inherited the inverted hover, which is the worse trade. The
81
+ `-muted` surface being near-invisible on its own is the same property light
82
+ high contrast has (1.04) — what carries those affordances in both schemes is
83
+ `border-*`, at 14.27:1 here.
84
+
85
+ One place deviates from the pure mirror: `warning-solid` keeps the
86
+ yellow-signage convention `_high-contrast.css` uses — a light amber with
87
+ near-black amber text, not the generic `-solid` rule.
88
+
89
+ ── Measured ──
90
+ 90 foreground/background pairings (fg × every surface, border and
91
+ border-strong × surface, `primary-500` × surface for the canonical focus
92
+ ring, and per role: soft-fg/soft, soft-fg-muted/soft, soft-fg/soft-hover,
93
+ solid-fg/solid, solid-fg/solid-hover, fg/surface, icon/surface,
94
+ border/surface, border-strong/soft) were computed from the Tailwind v4
95
+ oklch palette through sRGB to WCAG relative luminance.
96
+
97
+ - 0 of 90 fall below their WCAG AA floor (4.5:1 text, 3:1 non-text).
98
+ - The weakest pairing in the whole scheme is 7.96:1
99
+ (`primary-500` on `surface`, the focus ring, floor 3:1); every one of
100
+ the other 89 is higher. The scheme therefore clears AAA (7:1)
101
+ everywhere, matching what `_high-contrast.css` targets.
102
+ - 88 of 90 also beat the same pairing measured on `_dark.css`. The two
103
+ that do not are `fg on surface-sunken` and `neutral-soft-fg on
104
+ neutral-soft-hover`, both 17.75:1 here against 19.28:1 there — and both
105
+ are an artifact of the comparison, not a regression. `_dark.css` scores
106
+ higher on those only because its `surface-sunken` IS its `surface`
107
+ (separation 1.00, an invisible well); this scheme pays 1.5 points of an
108
+ already ~4x-AAA ratio to have a recessed surface that can actually be
109
+ seen. Do not "fix" them by collapsing `sunken` back onto `surface`.
110
+
111
+ `border-muted` is not measured: `_semantic.css` documents it as the purely
112
+ decorative divider that SC 1.4.11 exempts. It is still raised to `gray-500`,
113
+ mirroring what light high contrast does with the same token.
114
+
115
+ ── forced-colors ──
116
+ No dark counterpart to `_high-contrast.css`'s `@media (forced-colors:
117
+ active)` block is needed. That block remaps tokens onto system keywords
118
+ (`Canvas`, `CanvasText`, `GrayText`, `Highlight`) whose values the OS
119
+ supplies, so it is scheme-agnostic by construction — it just needs this
120
+ scheme's selector in its list, which it has.
121
+
122
+ ── Parity ──
123
+ The 195 declarations below are exactly the key set `_light.css`, `_dark.css`
124
+ and `_high-contrast.css` declare; `theme-token-parity.spec.ts` enforces it.
125
+ The seven scheme-invariant `@theme` tokens
126
+ (`--color-overlay-control{,-hover}`, `--shadow-table-sticky{,-cell-start,
127
+ -cell-end}`, `--text-2xs{,--line-height}`) are omitted here exactly as the
128
+ other three omit them. */
129
+
130
+ [data-theme="high-contrast-dark"] {
131
+ /* ===== Surface ===== */
132
+ --color-surface: var(--color-black);
133
+ --color-surface-raised: var(--color-black);
134
+ --color-surface-overlay: var(--color-black);
135
+ --color-surface-sunken: var(--color-gray-900);
136
+ --color-surface-muted: var(--color-gray-950);
137
+
138
+ /* ===== Foreground ===== */
139
+ --color-fg: var(--color-white);
140
+ --color-fg-muted: var(--color-gray-200);
141
+ --color-fg-subtle: var(--color-gray-300);
142
+
143
+ /* ===== Border ===== */
144
+ --color-border: var(--color-gray-300);
145
+ --color-border-muted: var(--color-gray-500);
146
+ --color-border-strong: var(--color-white);
147
+
148
+ /* ===== Primary ===== */
149
+ --color-primary-50: var(--color-blue-900);
150
+ --color-primary-100: var(--color-blue-800);
151
+ --color-primary-200: var(--color-blue-700);
152
+ --color-primary-300: var(--color-blue-600);
153
+ --color-primary-400: var(--color-blue-500);
154
+ --color-primary-500: var(--color-blue-400);
155
+ --color-primary-600: var(--color-blue-300);
156
+ --color-primary-700: var(--color-blue-200);
157
+ --color-primary-800: var(--color-blue-100);
158
+ --color-primary-900: var(--color-blue-50);
159
+ --color-primary-950: var(--color-blue-50);
160
+
161
+ /* ===== Secondary ===== */
162
+ --color-secondary-50: var(--color-slate-900);
163
+ --color-secondary-100: var(--color-slate-800);
164
+ --color-secondary-200: var(--color-slate-700);
165
+ --color-secondary-300: var(--color-slate-600);
166
+ --color-secondary-400: var(--color-slate-500);
167
+ --color-secondary-500: var(--color-slate-400);
168
+ --color-secondary-600: var(--color-slate-300);
169
+ --color-secondary-700: var(--color-slate-200);
170
+ --color-secondary-800: var(--color-slate-100);
171
+ --color-secondary-900: var(--color-slate-50);
172
+ --color-secondary-950: var(--color-slate-50);
173
+
174
+ /* ===== Accent ===== */
175
+ --color-accent-50: var(--color-violet-900);
176
+ --color-accent-100: var(--color-violet-800);
177
+ --color-accent-200: var(--color-violet-700);
178
+ --color-accent-300: var(--color-violet-600);
179
+ --color-accent-400: var(--color-violet-500);
180
+ --color-accent-500: var(--color-violet-400);
181
+ --color-accent-600: var(--color-violet-300);
182
+ --color-accent-700: var(--color-violet-200);
183
+ --color-accent-800: var(--color-violet-100);
184
+ --color-accent-900: var(--color-violet-50);
185
+ --color-accent-950: var(--color-violet-50);
186
+
187
+ /* ===== Neutral ===== */
188
+ --color-neutral-50: var(--color-gray-900);
189
+ --color-neutral-100: var(--color-gray-800);
190
+ --color-neutral-200: var(--color-gray-700);
191
+ --color-neutral-300: var(--color-gray-600);
192
+ --color-neutral-400: var(--color-gray-500);
193
+ --color-neutral-500: var(--color-gray-400);
194
+ --color-neutral-600: var(--color-gray-300);
195
+ --color-neutral-700: var(--color-gray-200);
196
+ --color-neutral-800: var(--color-gray-100);
197
+ --color-neutral-900: var(--color-gray-50);
198
+ --color-neutral-950: var(--color-gray-50);
199
+
200
+ /* ===== Info ===== */
201
+ --color-info-50: var(--color-sky-900);
202
+ --color-info-100: var(--color-sky-800);
203
+ --color-info-200: var(--color-sky-700);
204
+ --color-info-300: var(--color-sky-600);
205
+ --color-info-400: var(--color-sky-500);
206
+ --color-info-500: var(--color-sky-400);
207
+ --color-info-600: var(--color-sky-300);
208
+ --color-info-700: var(--color-sky-200);
209
+ --color-info-800: var(--color-sky-100);
210
+ --color-info-900: var(--color-sky-50);
211
+ --color-info-950: var(--color-sky-50);
212
+
213
+ /* ===== Success ===== */
214
+ --color-success-50: var(--color-green-900);
215
+ --color-success-100: var(--color-green-800);
216
+ --color-success-200: var(--color-green-700);
217
+ --color-success-300: var(--color-green-600);
218
+ --color-success-400: var(--color-green-500);
219
+ --color-success-500: var(--color-green-400);
220
+ --color-success-600: var(--color-green-300);
221
+ --color-success-700: var(--color-green-200);
222
+ --color-success-800: var(--color-green-100);
223
+ --color-success-900: var(--color-green-50);
224
+ --color-success-950: var(--color-green-50);
225
+
226
+ /* ===== Warning ===== */
227
+ --color-warning-50: var(--color-amber-900);
228
+ --color-warning-100: var(--color-amber-800);
229
+ --color-warning-200: var(--color-amber-700);
230
+ --color-warning-300: var(--color-amber-600);
231
+ --color-warning-400: var(--color-amber-500);
232
+ --color-warning-500: var(--color-amber-400);
233
+ --color-warning-600: var(--color-amber-300);
234
+ --color-warning-700: var(--color-amber-200);
235
+ --color-warning-800: var(--color-amber-100);
236
+ --color-warning-900: var(--color-amber-50);
237
+ --color-warning-950: var(--color-amber-50);
238
+
239
+ /* ===== Error ===== */
240
+ --color-error-50: var(--color-red-900);
241
+ --color-error-100: var(--color-red-800);
242
+ --color-error-200: var(--color-red-700);
243
+ --color-error-300: var(--color-red-600);
244
+ --color-error-400: var(--color-red-500);
245
+ --color-error-500: var(--color-red-400);
246
+ --color-error-600: var(--color-red-300);
247
+ --color-error-700: var(--color-red-200);
248
+ --color-error-800: var(--color-red-100);
249
+ --color-error-900: var(--color-red-50);
250
+ --color-error-950: var(--color-red-50);
251
+
252
+ /* ===== Role slot tokens ===== */
253
+
254
+ /* Primary */
255
+ --color-primary-soft: var(--color-blue-950);
256
+ --color-primary-soft-hover: var(--color-blue-900);
257
+ --color-primary-soft-fg: var(--color-blue-50);
258
+ --color-primary-soft-fg-muted: var(--color-blue-100);
259
+ --color-primary-solid: var(--color-blue-200);
260
+ --color-primary-solid-hover: var(--color-blue-100);
261
+ --color-primary-solid-fg: var(--color-black);
262
+ --color-primary-border: var(--color-blue-300);
263
+ --color-primary-border-strong: var(--color-blue-100);
264
+ --color-primary-fg: var(--color-blue-100);
265
+ --color-primary-icon: var(--color-blue-200);
266
+
267
+ /* Secondary */
268
+ --color-secondary-soft: var(--color-slate-950);
269
+ --color-secondary-soft-hover: var(--color-slate-900);
270
+ --color-secondary-soft-fg: var(--color-slate-50);
271
+ --color-secondary-soft-fg-muted: var(--color-slate-100);
272
+ --color-secondary-solid: var(--color-slate-200);
273
+ --color-secondary-solid-hover: var(--color-slate-100);
274
+ --color-secondary-solid-fg: var(--color-black);
275
+ --color-secondary-border: var(--color-slate-300);
276
+ --color-secondary-border-strong: var(--color-slate-100);
277
+ --color-secondary-fg: var(--color-slate-100);
278
+ --color-secondary-icon: var(--color-slate-200);
279
+
280
+ /* Accent */
281
+ --color-accent-soft: var(--color-violet-950);
282
+ --color-accent-soft-hover: var(--color-violet-900);
283
+ --color-accent-soft-fg: var(--color-violet-50);
284
+ --color-accent-soft-fg-muted: var(--color-violet-100);
285
+ --color-accent-solid: var(--color-violet-200);
286
+ --color-accent-solid-hover: var(--color-violet-100);
287
+ --color-accent-solid-fg: var(--color-black);
288
+ --color-accent-border: var(--color-violet-300);
289
+ --color-accent-border-strong: var(--color-violet-100);
290
+ --color-accent-fg: var(--color-violet-100);
291
+ --color-accent-icon: var(--color-violet-200);
292
+
293
+ /* Neutral */
294
+ --color-neutral-soft: var(--color-surface-muted);
295
+ --color-neutral-soft-hover: var(--color-surface-sunken);
296
+ --color-neutral-soft-fg: var(--color-white);
297
+ --color-neutral-soft-fg-muted: var(--color-gray-200);
298
+ --color-neutral-solid: var(--color-white);
299
+ --color-neutral-solid-hover: var(--color-gray-200);
300
+ --color-neutral-solid-fg: var(--color-black);
301
+ --color-neutral-border: var(--color-gray-300);
302
+ --color-neutral-border-strong: var(--color-white);
303
+ --color-neutral-fg: var(--color-white);
304
+ --color-neutral-icon: var(--color-gray-200);
305
+
306
+ /* Info */
307
+ --color-info-soft: var(--color-sky-950);
308
+ --color-info-soft-hover: var(--color-sky-900);
309
+ --color-info-soft-fg: var(--color-sky-50);
310
+ --color-info-soft-fg-muted: var(--color-sky-100);
311
+ --color-info-solid: var(--color-sky-200);
312
+ --color-info-solid-hover: var(--color-sky-100);
313
+ --color-info-solid-fg: var(--color-black);
314
+ --color-info-border: var(--color-sky-300);
315
+ --color-info-border-strong: var(--color-sky-100);
316
+ --color-info-fg: var(--color-sky-100);
317
+ --color-info-icon: var(--color-sky-200);
318
+
319
+ /* Success */
320
+ --color-success-soft: var(--color-green-950);
321
+ --color-success-soft-hover: var(--color-green-900);
322
+ --color-success-soft-fg: var(--color-green-50);
323
+ --color-success-soft-fg-muted: var(--color-green-100);
324
+ --color-success-solid: var(--color-green-200);
325
+ --color-success-solid-hover: var(--color-green-100);
326
+ --color-success-solid-fg: var(--color-black);
327
+ --color-success-border: var(--color-green-300);
328
+ --color-success-border-strong: var(--color-green-100);
329
+ --color-success-fg: var(--color-green-100);
330
+ --color-success-icon: var(--color-green-200);
331
+
332
+ /* Warning */
333
+ --color-warning-soft: var(--color-amber-950);
334
+ --color-warning-soft-hover: var(--color-amber-900);
335
+ --color-warning-soft-fg: var(--color-amber-50);
336
+ --color-warning-soft-fg-muted: var(--color-amber-100);
337
+ --color-warning-solid: var(--color-amber-200);
338
+ --color-warning-solid-hover: var(--color-amber-100);
339
+ --color-warning-solid-fg: var(--color-amber-950);
340
+ --color-warning-border: var(--color-amber-300);
341
+ --color-warning-border-strong: var(--color-amber-100);
342
+ --color-warning-fg: var(--color-amber-100);
343
+ --color-warning-icon: var(--color-amber-200);
344
+
345
+ /* Error */
346
+ --color-error-soft: var(--color-red-950);
347
+ --color-error-soft-hover: var(--color-red-900);
348
+ --color-error-soft-fg: var(--color-red-50);
349
+ --color-error-soft-fg-muted: var(--color-red-100);
350
+ --color-error-solid: var(--color-red-200);
351
+ --color-error-solid-hover: var(--color-red-100);
352
+ --color-error-solid-fg: var(--color-black);
353
+ --color-error-border: var(--color-red-300);
354
+ --color-error-border-strong: var(--color-red-100);
355
+ --color-error-fg: var(--color-red-100);
356
+ --color-error-icon: var(--color-red-200);
357
+
358
+ /* ===== Legacy on-role aliases ===== */
359
+ --color-on-primary: var(--color-primary-solid-fg);
360
+ --color-on-secondary: var(--color-secondary-solid-fg);
361
+ --color-on-accent: var(--color-accent-solid-fg);
362
+ --color-on-neutral: var(--color-neutral-solid-fg);
363
+ --color-on-info: var(--color-info-solid-fg);
364
+ --color-on-success: var(--color-success-solid-fg);
365
+ --color-on-warning: var(--color-warning-solid-fg);
366
+ --color-on-error: var(--color-error-solid-fg);
367
+ }
@@ -247,12 +247,23 @@
247
247
  (`Canvas`, `CanvasText`, `Highlight`, `GrayText`, etc.). We remap the
248
248
  library's structural tokens to the matching system colors so components
249
249
  keep their semantic shape, and disable `forced-color-adjust` on interactive
250
- affordances so the browser applies system colors uniformly. */
250
+ affordances so the browser applies system colors uniformly.
251
+
252
+ The block is scheme-agnostic by construction — every value below is a system
253
+ keyword the OS supplies, so there is nothing light- or dark-specific to
254
+ duplicate per scheme. What it does need is one selector per scheme: each
255
+ scheme's own `[data-theme=…]` block has the identical 0,1,0 specificity, so
256
+ a scheme missing from this list keeps its author colors under Windows High
257
+ Contrast while the others yield. Every entry is also why import order
258
+ matters — see `index.css`. `theme-token-parity.spec.ts` asserts this list
259
+ carries one entry per `TW_RESOLVED_THEMES` member, so adding a scheme
260
+ without adding it here fails the unit suite. */
251
261
  @media (forced-colors: active) {
252
262
  :root,
253
263
  [data-theme="light"],
254
264
  [data-theme="dark"],
255
- [data-theme="high-contrast"] {
265
+ [data-theme="high-contrast"],
266
+ [data-theme="high-contrast-dark"] {
256
267
  /* Surfaces collapse to the system canvas. */
257
268
  --color-surface: Canvas;
258
269
  --color-surface-raised: Canvas;
@@ -0,0 +1,276 @@
1
+ /* ===== Light theme (explicit opt-in) =====
2
+ A mechanical mirror of the light values that `_semantic.css`'s `@theme`
3
+ block already resolves on the root. It exists for one reason: Tailwind v4
4
+ emits `@theme` as `@layer theme { :root, :host { … } }`, and a
5
+ `<div data-theme="light">` matches neither `:root` nor `:host` — so before
6
+ this file a light subtree nested inside a dark or high-contrast ancestor
7
+ simply inherited the ancestor's tokens, and `[twTheme]="'light'"` was a
8
+ silent no-op. `dark` and `high-contrast` have always had element-agnostic
9
+ `[data-theme=…]` blocks; this is the missing third one.
10
+
11
+ Two invariants keep it safe:
12
+
13
+ 1. Every declaration restates the value `_semantic.css` already sets.
14
+ Nothing here is new or hand-tuned, so a light-on-light page — the common
15
+ case, where `<html data-theme="light">` matches both this block and the
16
+ `@theme` `:root` rule — computes byte-identical values and no pixel
17
+ moves. The rationale for each value (the WCAG contrast measurements, the
18
+ slot semantics, why `info-solid` is -700 and not -600) lives in
19
+ `_semantic.css` and is deliberately NOT duplicated here. Edit
20
+ `_semantic.css`, then regenerate this block from it.
21
+
22
+ 2. The 195 declarations below are exactly the key set that `_dark.css`,
23
+ `_high-contrast.css` and `_high-contrast-dark.css` define. The seven
24
+ `@theme` tokens omitted
25
+ (`--color-overlay-control{,-hover}`,
26
+ `--shadow-table-sticky{,-cell-start,-cell-end}`,
27
+ `--text-2xs{,--line-height}`) are scheme-invariant by design and are
28
+ omitted by the dark and high-contrast blocks too. The shadow tokens are
29
+ safe to omit even for subtree scoping: Tailwind inlines a named
30
+ `--shadow-*` value into the utility, so `shadow-table-sticky` compiles
31
+ to `--tw-shadow: 0 1px 0 0 var(--tw-shadow-color, var(--color-border))`
32
+ and re-resolves `--color-border` at the use site, inside the subtree.
33
+
34
+ Import order matters: this file must come BEFORE `_high-contrast.css`,
35
+ whose `@media (forced-colors: active)` block names `[data-theme="light"]`
36
+ at the same specificity and has to win — the same constraint that puts
37
+ `_high-contrast-dark.css` above `_high-contrast.css` too. `_dark.css`'s
38
+ `prefers-color-scheme` branch already excludes `[data-theme="light"]`
39
+ roots, so those two never fight. */
40
+
41
+ [data-theme="light"] {
42
+ /* ===== Surface (backgrounds) ===== */
43
+ --color-surface: var(--color-white);
44
+ --color-surface-raised: var(--color-white);
45
+ --color-surface-overlay: var(--color-white);
46
+ --color-surface-sunken: var(--color-gray-50);
47
+ --color-surface-muted: var(--color-gray-100);
48
+
49
+ /* ===== Foreground (text/icons) ===== */
50
+ --color-fg: var(--color-gray-900);
51
+ --color-fg-muted: var(--color-gray-600);
52
+ --color-fg-subtle: var(--color-gray-500);
53
+
54
+ /* ===== Border ===== */
55
+ --color-border: var(--color-gray-500);
56
+ --color-border-muted: var(--color-gray-200);
57
+ --color-border-strong: var(--color-gray-600);
58
+
59
+ /* ===== Primary ===== */
60
+ --color-primary-50: var(--color-blue-50);
61
+ --color-primary-100: var(--color-blue-100);
62
+ --color-primary-200: var(--color-blue-200);
63
+ --color-primary-300: var(--color-blue-300);
64
+ --color-primary-400: var(--color-blue-400);
65
+ --color-primary-500: var(--color-blue-500);
66
+ --color-primary-600: var(--color-blue-600);
67
+ --color-primary-700: var(--color-blue-700);
68
+ --color-primary-800: var(--color-blue-800);
69
+ --color-primary-900: var(--color-blue-900);
70
+ --color-primary-950: var(--color-blue-950);
71
+
72
+ /* ===== Secondary ===== */
73
+ --color-secondary-50: var(--color-slate-50);
74
+ --color-secondary-100: var(--color-slate-100);
75
+ --color-secondary-200: var(--color-slate-200);
76
+ --color-secondary-300: var(--color-slate-300);
77
+ --color-secondary-400: var(--color-slate-400);
78
+ --color-secondary-500: var(--color-slate-500);
79
+ --color-secondary-600: var(--color-slate-600);
80
+ --color-secondary-700: var(--color-slate-700);
81
+ --color-secondary-800: var(--color-slate-800);
82
+ --color-secondary-900: var(--color-slate-900);
83
+ --color-secondary-950: var(--color-slate-950);
84
+
85
+ /* ===== Accent ===== */
86
+ --color-accent-50: var(--color-violet-50);
87
+ --color-accent-100: var(--color-violet-100);
88
+ --color-accent-200: var(--color-violet-200);
89
+ --color-accent-300: var(--color-violet-300);
90
+ --color-accent-400: var(--color-violet-400);
91
+ --color-accent-500: var(--color-violet-500);
92
+ --color-accent-600: var(--color-violet-600);
93
+ --color-accent-700: var(--color-violet-700);
94
+ --color-accent-800: var(--color-violet-800);
95
+ --color-accent-900: var(--color-violet-900);
96
+ --color-accent-950: var(--color-violet-950);
97
+
98
+ /* ===== Neutral ===== */
99
+ --color-neutral-50: var(--color-gray-50);
100
+ --color-neutral-100: var(--color-gray-100);
101
+ --color-neutral-200: var(--color-gray-200);
102
+ --color-neutral-300: var(--color-gray-300);
103
+ --color-neutral-400: var(--color-gray-400);
104
+ --color-neutral-500: var(--color-gray-500);
105
+ --color-neutral-600: var(--color-gray-600);
106
+ --color-neutral-700: var(--color-gray-700);
107
+ --color-neutral-800: var(--color-gray-800);
108
+ --color-neutral-900: var(--color-gray-900);
109
+ --color-neutral-950: var(--color-gray-950);
110
+
111
+ /* ===== Info ===== */
112
+ --color-info-50: var(--color-sky-50);
113
+ --color-info-100: var(--color-sky-100);
114
+ --color-info-200: var(--color-sky-200);
115
+ --color-info-300: var(--color-sky-300);
116
+ --color-info-400: var(--color-sky-400);
117
+ --color-info-500: var(--color-sky-500);
118
+ --color-info-600: var(--color-sky-600);
119
+ --color-info-700: var(--color-sky-700);
120
+ --color-info-800: var(--color-sky-800);
121
+ --color-info-900: var(--color-sky-900);
122
+ --color-info-950: var(--color-sky-950);
123
+
124
+ /* ===== Success ===== */
125
+ --color-success-50: var(--color-green-50);
126
+ --color-success-100: var(--color-green-100);
127
+ --color-success-200: var(--color-green-200);
128
+ --color-success-300: var(--color-green-300);
129
+ --color-success-400: var(--color-green-400);
130
+ --color-success-500: var(--color-green-500);
131
+ --color-success-600: var(--color-green-600);
132
+ --color-success-700: var(--color-green-700);
133
+ --color-success-800: var(--color-green-800);
134
+ --color-success-900: var(--color-green-900);
135
+ --color-success-950: var(--color-green-950);
136
+
137
+ /* ===== Warning ===== */
138
+ --color-warning-50: var(--color-amber-50);
139
+ --color-warning-100: var(--color-amber-100);
140
+ --color-warning-200: var(--color-amber-200);
141
+ --color-warning-300: var(--color-amber-300);
142
+ --color-warning-400: var(--color-amber-400);
143
+ --color-warning-500: var(--color-amber-500);
144
+ --color-warning-600: var(--color-amber-600);
145
+ --color-warning-700: var(--color-amber-700);
146
+ --color-warning-800: var(--color-amber-800);
147
+ --color-warning-900: var(--color-amber-900);
148
+ --color-warning-950: var(--color-amber-950);
149
+
150
+ /* ===== Error ===== */
151
+ --color-error-50: var(--color-red-50);
152
+ --color-error-100: var(--color-red-100);
153
+ --color-error-200: var(--color-red-200);
154
+ --color-error-300: var(--color-red-300);
155
+ --color-error-400: var(--color-red-400);
156
+ --color-error-500: var(--color-red-500);
157
+ --color-error-600: var(--color-red-600);
158
+ --color-error-700: var(--color-red-700);
159
+ --color-error-800: var(--color-red-800);
160
+ --color-error-900: var(--color-red-900);
161
+ --color-error-950: var(--color-red-950);
162
+
163
+ /* ----- Primary (blue) ----- */
164
+ --color-primary-soft: var(--color-primary-50);
165
+ --color-primary-soft-hover: var(--color-primary-100);
166
+ --color-primary-soft-fg: var(--color-primary-900);
167
+ --color-primary-soft-fg-muted: var(--color-primary-800);
168
+ --color-primary-solid: var(--color-primary-600);
169
+ --color-primary-solid-hover: var(--color-primary-700);
170
+ --color-primary-solid-fg: var(--color-white);
171
+ --color-primary-border: var(--color-primary-300);
172
+ --color-primary-border-strong: var(--color-primary-500);
173
+ --color-primary-fg: var(--color-primary-700);
174
+ --color-primary-icon: var(--color-primary-600);
175
+
176
+ /* ----- Secondary (slate) ----- */
177
+ --color-secondary-soft: var(--color-secondary-50);
178
+ --color-secondary-soft-hover: var(--color-secondary-100);
179
+ --color-secondary-soft-fg: var(--color-secondary-900);
180
+ --color-secondary-soft-fg-muted: var(--color-secondary-800);
181
+ --color-secondary-solid: var(--color-secondary-700);
182
+ --color-secondary-solid-hover: var(--color-secondary-800);
183
+ --color-secondary-solid-fg: var(--color-white);
184
+ --color-secondary-border: var(--color-secondary-300);
185
+ --color-secondary-border-strong: var(--color-secondary-500);
186
+ --color-secondary-fg: var(--color-secondary-700);
187
+ --color-secondary-icon: var(--color-secondary-600);
188
+
189
+ /* ----- Accent (violet) ----- */
190
+ --color-accent-soft: var(--color-accent-50);
191
+ --color-accent-soft-hover: var(--color-accent-100);
192
+ --color-accent-soft-fg: var(--color-accent-900);
193
+ --color-accent-soft-fg-muted: var(--color-accent-800);
194
+ --color-accent-solid: var(--color-accent-600);
195
+ --color-accent-solid-hover: var(--color-accent-700);
196
+ --color-accent-solid-fg: var(--color-white);
197
+ --color-accent-border: var(--color-accent-300);
198
+ --color-accent-border-strong: var(--color-accent-500);
199
+ --color-accent-fg: var(--color-accent-700);
200
+ --color-accent-icon: var(--color-accent-600);
201
+
202
+ /* ----- Neutral ----- (uses surface/fg tokens so dark mode is automatic) */
203
+ --color-neutral-soft: var(--color-surface-muted);
204
+ --color-neutral-soft-hover: var(--color-surface-sunken);
205
+ --color-neutral-soft-fg: var(--color-fg);
206
+ --color-neutral-soft-fg-muted: var(--color-fg-muted);
207
+ --color-neutral-solid: var(--color-fg);
208
+ --color-neutral-solid-hover: var(--color-gray-700);
209
+ --color-neutral-solid-fg: var(--color-surface);
210
+ --color-neutral-border: var(--color-border);
211
+ --color-neutral-border-strong: var(--color-border-strong);
212
+ --color-neutral-fg: var(--color-fg);
213
+ --color-neutral-icon: var(--color-fg-muted);
214
+
215
+ /* ----- Info (sky) ----- */
216
+ --color-info-soft: var(--color-info-50);
217
+ --color-info-soft-hover: var(--color-info-100);
218
+ --color-info-soft-fg: var(--color-info-900);
219
+ --color-info-soft-fg-muted: var(--color-info-800);
220
+ --color-info-solid: var(--color-info-700);
221
+ --color-info-solid-hover: var(--color-info-800);
222
+ --color-info-solid-fg: var(--color-white);
223
+ --color-info-border: var(--color-info-300);
224
+ --color-info-border-strong: var(--color-info-500);
225
+ --color-info-fg: var(--color-info-700);
226
+ --color-info-icon: var(--color-info-600);
227
+
228
+ /* ----- Success (green) ----- */
229
+ --color-success-soft: var(--color-success-50);
230
+ --color-success-soft-hover: var(--color-success-100);
231
+ --color-success-soft-fg: var(--color-success-900);
232
+ --color-success-soft-fg-muted: var(--color-success-800);
233
+ --color-success-solid: var(--color-success-700);
234
+ --color-success-solid-hover: var(--color-success-800);
235
+ --color-success-solid-fg: var(--color-white);
236
+ --color-success-border: var(--color-success-300);
237
+ --color-success-border-strong: var(--color-success-500);
238
+ --color-success-fg: var(--color-success-700);
239
+ --color-success-icon: var(--color-success-600);
240
+
241
+ /* ----- Warning (amber) ----- */
242
+ --color-warning-soft: var(--color-warning-50);
243
+ --color-warning-soft-hover: var(--color-warning-100);
244
+ --color-warning-soft-fg: var(--color-warning-900);
245
+ --color-warning-soft-fg-muted: var(--color-warning-800);
246
+ --color-warning-solid: var(--color-warning-500);
247
+ --color-warning-solid-hover: var(--color-warning-600);
248
+ --color-warning-solid-fg: var(--color-warning-950);
249
+ --color-warning-border: var(--color-warning-300);
250
+ --color-warning-border-strong: var(--color-warning-500);
251
+ --color-warning-fg: var(--color-warning-800);
252
+ --color-warning-icon: var(--color-warning-600);
253
+
254
+ /* ----- Error (red) ----- */
255
+ --color-error-soft: var(--color-error-50);
256
+ --color-error-soft-hover: var(--color-error-100);
257
+ --color-error-soft-fg: var(--color-error-900);
258
+ --color-error-soft-fg-muted: var(--color-error-800);
259
+ --color-error-solid: var(--color-error-600);
260
+ --color-error-solid-hover: var(--color-error-700);
261
+ --color-error-solid-fg: var(--color-white);
262
+ --color-error-border: var(--color-error-300);
263
+ --color-error-border-strong: var(--color-error-500);
264
+ --color-error-fg: var(--color-error-700);
265
+ --color-error-icon: var(--color-error-600);
266
+
267
+ /* ===== Legacy on-role aliases — see note in `_semantic.css` ===== */
268
+ --color-on-info: var(--color-info-solid-fg);
269
+ --color-on-success: var(--color-success-solid-fg);
270
+ --color-on-warning: var(--color-warning-solid-fg);
271
+ --color-on-error: var(--color-error-solid-fg);
272
+ --color-on-primary: var(--color-primary-solid-fg);
273
+ --color-on-secondary: var(--color-secondary-solid-fg);
274
+ --color-on-accent: var(--color-accent-solid-fg);
275
+ --color-on-neutral: var(--color-neutral-solid-fg);
276
+ }