@eifi1/ui-kit 0.32.2 → 0.33.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 (363) hide show
  1. package/README.md +16 -8
  2. package/dist/account/delete-account-setting.d.ts +10 -10
  3. package/dist/account/delete-account-setting.js +2 -1
  4. package/dist/account/delete-account-setting.js.map +1 -1
  5. package/dist/account/email-change-setting.d.ts +5 -0
  6. package/dist/account/email-change-setting.js +4 -3
  7. package/dist/account/email-change-setting.js.map +1 -1
  8. package/dist/account/sessions-setting.d.ts +4 -0
  9. package/dist/account/sessions-setting.js +3 -2
  10. package/dist/account/sessions-setting.js.map +1 -1
  11. package/dist/admin/admin-action-confirm.d.ts +10 -10
  12. package/dist/admin/admin-action-confirm.js.map +1 -1
  13. package/dist/admin/invitations-panel.d.ts +10 -10
  14. package/dist/admin/invitations-panel.js +4 -3
  15. package/dist/admin/invitations-panel.js.map +1 -1
  16. package/dist/admin/plan-change.d.ts +100 -0
  17. package/dist/admin/plan-change.js +208 -0
  18. package/dist/admin/plan-change.js.map +1 -0
  19. package/dist/admin/reviewer-scope-editor.d.ts +10 -10
  20. package/dist/admin/reviewer-scope-editor.js.map +1 -1
  21. package/dist/admin/role-select.d.ts +7 -7
  22. package/dist/admin/role-select.js.map +1 -1
  23. package/dist/admin/transfer-ownership-dialog.d.ts +10 -10
  24. package/dist/admin/user-roster.d.ts +7 -7
  25. package/dist/admin/user-roster.js +2 -2
  26. package/dist/admin/user-roster.js.map +1 -1
  27. package/dist/auth/auth-errors.d.ts +13 -2
  28. package/dist/auth/auth-errors.js +5 -1
  29. package/dist/auth/auth-errors.js.map +1 -1
  30. package/dist/auth/complete-name-dialog.d.ts +4 -1
  31. package/dist/auth/complete-name-dialog.js +2 -1
  32. package/dist/auth/complete-name-dialog.js.map +1 -1
  33. package/dist/auth/register-form.d.ts +10 -10
  34. package/dist/billing/billing-banner.d.ts +13 -11
  35. package/dist/billing/billing-banner.js.map +1 -1
  36. package/dist/billing/billing-labels.d.ts +10 -10
  37. package/dist/billing/billing-labels.js +10 -1
  38. package/dist/billing/billing-labels.js.map +1 -1
  39. package/dist/billing/billing-lock.d.ts +39 -12
  40. package/dist/billing/billing-lock.js +9 -3
  41. package/dist/billing/billing-lock.js.map +1 -1
  42. package/dist/billing/billing-overview.d.ts +154 -0
  43. package/dist/billing/billing-overview.js +2 -0
  44. package/dist/billing/billing-overview.js.map +1 -0
  45. package/dist/billing/billing-standing.d.ts +10 -10
  46. package/dist/billing/checkout-processing.d.ts +217 -0
  47. package/dist/billing/checkout-processing.js +198 -0
  48. package/dist/billing/checkout-processing.js.map +1 -0
  49. package/dist/billing/checkout-return.d.ts +51 -0
  50. package/dist/billing/checkout-return.js +43 -0
  51. package/dist/billing/checkout-return.js.map +1 -0
  52. package/dist/billing/pay-page.d.ts +210 -0
  53. package/dist/billing/pay-page.js +113 -0
  54. package/dist/billing/pay-page.js.map +1 -0
  55. package/dist/billing/plan-card.d.ts +10 -10
  56. package/dist/billing/plan-limit-notice.d.ts +10 -10
  57. package/dist/billing/plan-limit-toast.d.ts +143 -0
  58. package/dist/billing/plan-limit-toast.js +40 -0
  59. package/dist/billing/plan-limit-toast.js.map +1 -0
  60. package/dist/billing/subscription-actions.d.ts +38 -15
  61. package/dist/billing/subscription-actions.js +9 -2
  62. package/dist/billing/subscription-actions.js.map +1 -1
  63. package/dist/billing/subscription-status-chip.d.ts +9 -9
  64. package/dist/bin/eifi1-pay-page.mjs +166 -0
  65. package/dist/chart.d.ts +10 -10
  66. package/dist/components/account-chips.d.ts +6 -1
  67. package/dist/components/account-settings.d.ts +4 -1
  68. package/dist/components/account-settings.js +2 -1
  69. package/dist/components/account-settings.js.map +1 -1
  70. package/dist/components/amount-input.d.ts +10 -10
  71. package/dist/components/autocomplete.d.ts +2 -1
  72. package/dist/components/autocomplete.js +3 -1
  73. package/dist/components/autocomplete.js.map +1 -1
  74. package/dist/components/button-group.d.ts +10 -10
  75. package/dist/components/button-group.js +1 -1
  76. package/dist/components/button-group.js.map +1 -1
  77. package/dist/components/calculator.d.ts +10 -10
  78. package/dist/components/calculator.js +3 -3
  79. package/dist/components/calculator.js.map +1 -1
  80. package/dist/components/checkbox-group.d.ts +2 -1
  81. package/dist/components/checkbox-group.js.map +1 -1
  82. package/dist/components/checkbox.d.ts +2 -1
  83. package/dist/components/checkbox.js.map +1 -1
  84. package/dist/components/chip.d.ts +2 -1
  85. package/dist/components/chip.js +19 -17
  86. package/dist/components/chip.js.map +1 -1
  87. package/dist/components/choice-card.d.ts +3 -1
  88. package/dist/components/choice-card.js +1 -1
  89. package/dist/components/choice-card.js.map +1 -1
  90. package/dist/components/combobox.d.ts +4 -3
  91. package/dist/components/combobox.js.map +1 -1
  92. package/dist/components/confirm-dialog.d.ts +10 -10
  93. package/dist/components/confirm-dialog.js +6 -3
  94. package/dist/components/confirm-dialog.js.map +1 -1
  95. package/dist/components/copy-button.d.ts +11 -11
  96. package/dist/components/country-select.d.ts +2 -1
  97. package/dist/components/country-select.js.map +1 -1
  98. package/dist/components/danger-confirm.d.ts +10 -10
  99. package/dist/components/danger-confirm.js.map +1 -1
  100. package/dist/components/data-table-cells.d.ts +12 -1
  101. package/dist/components/data-table-filter-popover.d.ts +12 -1
  102. package/dist/components/data-table-filters.d.ts +12 -1
  103. package/dist/components/data-table-labels.d.ts +12 -1
  104. package/dist/components/data-table-pagination.d.ts +12 -1
  105. package/dist/components/data-table.d.ts +12 -1
  106. package/dist/components/data-table.js +3 -3
  107. package/dist/components/data-table.js.map +1 -1
  108. package/dist/components/date-picker.js +6 -4
  109. package/dist/components/date-picker.js.map +1 -1
  110. package/dist/components/entity-combobox.d.ts +3 -2
  111. package/dist/components/entity-combobox.js.map +1 -1
  112. package/dist/components/facing-pair.d.ts +10 -10
  113. package/dist/components/field-parts.d.ts +32 -4
  114. package/dist/components/field-parts.js +54 -19
  115. package/dist/components/field-parts.js.map +1 -1
  116. package/dist/components/file-button.d.ts +10 -10
  117. package/dist/components/file-button.js +3 -2
  118. package/dist/components/file-button.js.map +1 -1
  119. package/dist/components/file-dropzone.d.ts +11 -11
  120. package/dist/components/file-dropzone.js.map +1 -1
  121. package/dist/components/floating-panel.js +5 -5
  122. package/dist/components/floating-panel.js.map +1 -1
  123. package/dist/components/form-actions.d.ts +9 -9
  124. package/dist/components/form-actions.js +3 -3
  125. package/dist/components/form-actions.js.map +1 -1
  126. package/dist/components/iban-input.d.ts +10 -10
  127. package/dist/components/inline-edit-field.d.ts +2 -1
  128. package/dist/components/inline-edit-field.js +6 -6
  129. package/dist/components/inline-edit-field.js.map +1 -1
  130. package/dist/components/language-select.d.ts +10 -10
  131. package/dist/components/legal-page.d.ts +10 -10
  132. package/dist/components/legal.d.ts +10 -10
  133. package/dist/components/list.d.ts +2 -1
  134. package/dist/components/list.js +4 -5
  135. package/dist/components/list.js.map +1 -1
  136. package/dist/components/money-field.d.ts +10 -10
  137. package/dist/components/month-picker.js +54 -44
  138. package/dist/components/month-picker.js.map +1 -1
  139. package/dist/components/multi-entity-combobox.d.ts +3 -2
  140. package/dist/components/multi-entity-combobox.js.map +1 -1
  141. package/dist/components/number-field.d.ts +10 -10
  142. package/dist/components/number-input.d.ts +10 -10
  143. package/dist/components/numpad-sheet.d.ts +10 -10
  144. package/dist/components/numpad-sheet.js +2 -2
  145. package/dist/components/numpad-sheet.js.map +1 -1
  146. package/dist/components/phone-input.d.ts +10 -10
  147. package/dist/components/row-actions.d.ts +5 -5
  148. package/dist/components/row-actions.js +130 -32
  149. package/dist/components/row-actions.js.map +1 -1
  150. package/dist/components/series-chart.d.ts +10 -10
  151. package/dist/components/settings-fields.d.ts +10 -10
  152. package/dist/components/share-card.d.ts +7 -7
  153. package/dist/components/share-card.js +26 -10
  154. package/dist/components/share-card.js.map +1 -1
  155. package/dist/components/status-dot.d.ts +1 -0
  156. package/dist/components/status-dot.js +2 -2
  157. package/dist/components/status-dot.js.map +1 -1
  158. package/dist/components/swatch-picker.d.ts +2 -1
  159. package/dist/components/swatch-picker.js.map +1 -1
  160. package/dist/components/swipeable-row.d.ts +88 -17
  161. package/dist/components/swipeable-row.js +46 -9
  162. package/dist/components/swipeable-row.js.map +1 -1
  163. package/dist/components/switch.d.ts +2 -1
  164. package/dist/components/switch.js.map +1 -1
  165. package/dist/components/table.d.ts +2 -1
  166. package/dist/components/table.js +6 -0
  167. package/dist/components/table.js.map +1 -1
  168. package/dist/components/text-link.d.ts +9 -9
  169. package/dist/components/time-input.d.ts +10 -10
  170. package/dist/components/toggle-group.d.ts +2 -1
  171. package/dist/components/toggle-group.js +1 -1
  172. package/dist/components/toggle-group.js.map +1 -1
  173. package/dist/components/translation-review-editor.d.ts +4 -0
  174. package/dist/components/translation-review-editor.js +4 -3
  175. package/dist/components/translation-review-editor.js.map +1 -1
  176. package/dist/components/translation-review-parts.d.ts +1 -0
  177. package/dist/components/translation-review.d.ts +1 -0
  178. package/dist/components/translation-review.js +15 -18
  179. package/dist/components/translation-review.js.map +1 -1
  180. package/dist/components/ui.d.ts +9 -9
  181. package/dist/components/ui.js +47 -27
  182. package/dist/components/ui.js.map +1 -1
  183. package/dist/components/use-table-state.d.ts +12 -1
  184. package/dist/components/user-avatar.d.ts +1 -0
  185. package/dist/components/write-lock.d.ts +101 -13
  186. package/dist/components/write-lock.js +37 -13
  187. package/dist/components/write-lock.js.map +1 -1
  188. package/dist/{data-table-labels-kpAAVi6g.d.ts → data-table-labels-BJ5JE_X2.d.ts} +17 -0
  189. package/dist/data-table.d.ts +12 -1
  190. package/dist/{delete-account-setting-Dy4kJgUm.d.ts → delete-account-setting-DiPX4Vue.d.ts} +355 -41
  191. package/dist/feedback/feedback-attachment.d.ts +10 -10
  192. package/dist/feedback/feedback-attachment.js +7 -7
  193. package/dist/feedback/feedback-attachment.js.map +1 -1
  194. package/dist/feedback/feedback-context.d.ts +10 -10
  195. package/dist/feedback/feedback-crash.d.ts +10 -10
  196. package/dist/feedback/feedback-dialog.d.ts +10 -10
  197. package/dist/feedback/feedback-inbox.d.ts +9 -9
  198. package/dist/feedback/feedback-inbox.js +7 -3
  199. package/dist/feedback/feedback-inbox.js.map +1 -1
  200. package/dist/feedback/feedback-labels.d.ts +10 -10
  201. package/dist/feedback/feedback-menu.d.ts +3 -3
  202. package/dist/feedback/feedback-record.d.ts +10 -10
  203. package/dist/feedback/feedback-row-detail.d.ts +10 -10
  204. package/dist/feedback/feedback-row-detail.js.map +1 -1
  205. package/dist/feedback/feedback-status-undo.d.ts +10 -10
  206. package/dist/feedback/feedback-submit.d.ts +10 -10
  207. package/dist/feedback/feedback-swipe.d.ts +10 -10
  208. package/dist/feedback/feedback-swipe.js +3 -6
  209. package/dist/feedback/feedback-swipe.js.map +1 -1
  210. package/dist/feedback/feedback-table.d.ts +10 -10
  211. package/dist/feedback/feedback-table.js.map +1 -1
  212. package/dist/feedback/feedback-thread.d.ts +10 -10
  213. package/dist/feedback.d.ts +10 -10
  214. package/dist/hooks/use-file-drop.d.ts +10 -10
  215. package/dist/i18n/defaults.d.ts +10 -10
  216. package/dist/i18n/defaults.js +2 -0
  217. package/dist/i18n/defaults.js.map +1 -1
  218. package/dist/i18n/german.d.ts +10 -10
  219. package/dist/i18n/german.js +34 -1
  220. package/dist/i18n/german.js.map +1 -1
  221. package/dist/i18n/kit-labels.d.ts +4 -4
  222. package/dist/i18n/kit-labels.js.map +1 -1
  223. package/dist/i18n/languages.d.ts +10 -10
  224. package/dist/i18n/locales/de-CH.d.ts +10 -10
  225. package/dist/i18n/locales/en.d.ts +10 -10
  226. package/dist/i18n/locales/es.d.ts +10 -10
  227. package/dist/i18n/locales/es.js +34 -1
  228. package/dist/i18n/locales/es.js.map +1 -1
  229. package/dist/i18n/locales/fr.d.ts +10 -10
  230. package/dist/i18n/locales/fr.js +35 -1
  231. package/dist/i18n/locales/fr.js.map +1 -1
  232. package/dist/i18n/locales/hu.d.ts +10 -10
  233. package/dist/i18n/locales/hu.js +36 -1
  234. package/dist/i18n/locales/hu.js.map +1 -1
  235. package/dist/i18n/locales/it.d.ts +10 -10
  236. package/dist/i18n/locales/it.js +34 -1
  237. package/dist/i18n/locales/it.js.map +1 -1
  238. package/dist/i18n/locales/zh.d.ts +10 -10
  239. package/dist/i18n/locales/zh.js +34 -1
  240. package/dist/i18n/locales/zh.js.map +1 -1
  241. package/dist/i18n/review.d.ts +10 -10
  242. package/dist/i18n/review.js +8 -1
  243. package/dist/i18n/review.js.map +1 -1
  244. package/dist/index.d.ts +10 -5
  245. package/dist/index.js +40 -2
  246. package/dist/index.js.map +1 -1
  247. package/dist/landing/landing-actions.d.ts +10 -10
  248. package/dist/landing/landing-sections.d.ts +10 -10
  249. package/dist/landing/public-header.d.ts +10 -10
  250. package/dist/landing/routing.d.ts +10 -10
  251. package/dist/pay/.well-known/apple-developer-merchantid-domain-association +1 -0
  252. package/dist/pay/index.html +30 -0
  253. package/dist/pay/pay.css +126 -0
  254. package/dist/pay/pay.js +198 -0
  255. package/dist/rhf/fields.d.ts +10 -10
  256. package/dist/rhf/form.d.ts +10 -10
  257. package/dist/rhf.d.ts +10 -10
  258. package/dist/settings/settings-section.d.ts +10 -10
  259. package/dist/shell/app-shell.d.ts +9 -9
  260. package/dist/shell/top-bar-brand.d.ts +10 -10
  261. package/dist/shell/topbar-action-menu.d.ts +1 -0
  262. package/dist/shell.d.ts +10 -10
  263. package/dist/testing/css-variables.d.ts +74 -0
  264. package/dist/testing/css-variables.generated.d.ts +7 -0
  265. package/dist/testing/css-variables.generated.js +8 -0
  266. package/dist/testing/css-variables.generated.js.map +1 -0
  267. package/dist/testing/css-variables.js +93 -0
  268. package/dist/testing/css-variables.js.map +1 -0
  269. package/dist/testing/index.d.ts +1 -0
  270. package/dist/testing/index.js +12 -0
  271. package/dist/testing/index.js.map +1 -0
  272. package/dist/theme/contrast-tokens.d.ts +44 -1
  273. package/dist/theme/contrast-tokens.js +21 -0
  274. package/dist/theme/contrast-tokens.js.map +1 -1
  275. package/dist/theme/contrast.d.ts +2 -2
  276. package/dist/theme/palette-derive.js +60 -11
  277. package/dist/theme/palette-derive.js.map +1 -1
  278. package/dist/theme/palette-presets.js +45 -43
  279. package/dist/theme/palette-presets.js.map +1 -1
  280. package/dist/wizard/stepper-nav.d.ts +11 -11
  281. package/dist/wizard/stepper-nav.js.map +1 -1
  282. package/dist/wizard.d.ts +10 -10
  283. package/package.json +10 -2
  284. package/src/account/delete-account-setting.tsx +6 -1
  285. package/src/account/email-change-setting.tsx +9 -3
  286. package/src/account/sessions-setting.tsx +7 -2
  287. package/src/admin/admin-action-confirm.tsx +2 -1
  288. package/src/admin/invitations-panel.tsx +9 -3
  289. package/src/admin/plan-change.tsx +459 -0
  290. package/src/admin/reviewer-scope-editor.tsx +2 -1
  291. package/src/admin/role-select.tsx +2 -1
  292. package/src/admin/user-roster.tsx +5 -3
  293. package/src/auth/auth-errors.ts +25 -2
  294. package/src/auth/complete-name-dialog.tsx +6 -2
  295. package/src/billing/billing-banner.tsx +3 -1
  296. package/src/billing/billing-labels.ts +45 -0
  297. package/src/billing/billing-lock.ts +36 -3
  298. package/src/billing/billing-overview.ts +58 -0
  299. package/src/billing/checkout-processing.ts +391 -0
  300. package/src/billing/checkout-return.ts +90 -0
  301. package/src/billing/pay-page.ts +242 -0
  302. package/src/billing/plan-limit-toast.tsx +91 -0
  303. package/src/billing/subscription-actions.tsx +41 -8
  304. package/src/components/account-settings.tsx +6 -2
  305. package/src/components/autocomplete.tsx +5 -2
  306. package/src/components/button-group.tsx +4 -1
  307. package/src/components/calculator.tsx +10 -6
  308. package/src/components/checkbox-group.tsx +2 -2
  309. package/src/components/checkbox.tsx +2 -1
  310. package/src/components/chip.tsx +37 -32
  311. package/src/components/choice-card.tsx +4 -2
  312. package/src/components/combobox.tsx +4 -4
  313. package/src/components/confirm-dialog.tsx +13 -6
  314. package/src/components/country-select.tsx +2 -2
  315. package/src/components/danger-confirm.tsx +2 -2
  316. package/src/components/data-table.tsx +20 -9
  317. package/src/components/date-picker.tsx +10 -7
  318. package/src/components/entity-combobox.tsx +3 -3
  319. package/src/components/field-parts.tsx +61 -14
  320. package/src/components/file-button.tsx +5 -4
  321. package/src/components/file-dropzone.tsx +2 -2
  322. package/src/components/floating-panel.tsx +7 -5
  323. package/src/components/form-actions.tsx +12 -5
  324. package/src/components/inline-edit-field.tsx +13 -13
  325. package/src/components/list.tsx +10 -9
  326. package/src/components/month-picker.tsx +8 -2
  327. package/src/components/multi-entity-combobox.tsx +3 -3
  328. package/src/components/numpad-sheet.tsx +8 -4
  329. package/src/components/row-actions.tsx +208 -58
  330. package/src/components/share-card.tsx +67 -13
  331. package/src/components/status-dot.tsx +7 -7
  332. package/src/components/swatch-picker.tsx +2 -2
  333. package/src/components/swipeable-row.tsx +138 -27
  334. package/src/components/switch.tsx +2 -1
  335. package/src/components/table.tsx +8 -1
  336. package/src/components/toggle-group.tsx +5 -3
  337. package/src/components/translation-review-editor.tsx +8 -3
  338. package/src/components/translation-review.tsx +18 -22
  339. package/src/components/ui.tsx +92 -43
  340. package/src/components/write-lock.tsx +150 -24
  341. package/src/feedback/feedback-attachment.tsx +13 -9
  342. package/src/feedback/feedback-inbox.tsx +10 -6
  343. package/src/feedback/feedback-row-detail.tsx +3 -2
  344. package/src/feedback/feedback-swipe.tsx +6 -11
  345. package/src/feedback/feedback-table.tsx +2 -1
  346. package/src/i18n/defaults.ts +2 -0
  347. package/src/i18n/german.ts +38 -0
  348. package/src/i18n/kit-labels.tsx +4 -0
  349. package/src/i18n/locales/es.ts +34 -0
  350. package/src/i18n/locales/fr.ts +39 -0
  351. package/src/i18n/locales/hu.ts +37 -0
  352. package/src/i18n/locales/it.ts +35 -0
  353. package/src/i18n/locales/zh.ts +33 -0
  354. package/src/i18n/review.ts +7 -0
  355. package/src/index.ts +48 -4
  356. package/src/testing/css-variables.generated.ts +112 -0
  357. package/src/testing/css-variables.ts +191 -0
  358. package/src/testing/index.ts +13 -0
  359. package/src/theme/contrast-tokens.ts +53 -2
  360. package/src/theme/palette-derive.ts +87 -10
  361. package/src/theme/palette-presets.ts +45 -43
  362. package/src/wizard/stepper-nav.tsx +2 -1
  363. package/tokens.css +306 -46
package/tokens.css CHANGED
@@ -11,22 +11,25 @@
11
11
  * (relative to the importing CSS file — see README §2. An @source that resolves to
12
12
  * nothing is silent, and the app renders unstyled rather than erroring.)
13
13
  *
14
- * NOTE: these :root/.dark values MIRROR DEFAULT_PRESET in the palette theme module,
15
- * which is what actually paints them — the palette layer writes the active preset
16
- * tokens inline on <html> at runtime (Tailwind v4 strips a root block that holds only
17
- * custom properties, so this block is a documentation mirror, not the live source).
14
+ * NOTE: the :root/.dark values below MIRROR DEFAULT_PRESET in the palette theme module,
15
+ * and they are LIVE CSS. Tailwind 4.3.3 keeps a `:root` block that holds only custom
16
+ * properties — the built showcase CSS carries `--bg-surface-2` and `--danger`, and
17
+ * `check:tailwind` asserts such a block survives. (This note used to say Tailwind strips
18
+ * it, and the mirror was treated as documentation; that was never what 4.x did.)
19
+ * - In an app WITH a palette layer (keksdose, kastlan), `applyTokenSet` writes the
20
+ * active preset's values inline on <html>, and those beat these.
21
+ * - In an app WITHOUT one (Kurvenschmiede), these are what paints, and More contrast
22
+ * writes only its four stepped values over them (`reapplyContrastTokens`).
18
23
  *
19
- * Because it is inert, it drifts silently, and it did — twice. The surfaces and text
20
- * colour below still held the pre-#328 palette while DEFAULT_PRESET had moved to Solar
21
- * Dusk; they were resynced when --text-secondary/--text-muted were added. The money
22
- * trio and the dark brand accent were left behind that time and written off in this
23
- * note as "nothing reads them" — nine values, including the accent a consumer copies
24
- * when they want to know what the brand IS.
24
+ * Because it was taken for inert, it drifted silently, and it did — twice. The surfaces
25
+ * and text colour below still held the pre-#328 palette while DEFAULT_PRESET had moved
26
+ * to Solar Dusk; the money trio and the dark brand accent were left behind after that
27
+ * and written off as "nothing reads them" — nine values, including the accent a
28
+ * consumer copies when they want to know what the brand IS.
25
29
  *
26
- * They are resynced now, and theme/__tests__/tokens-css-mirror.test.ts compares every
27
- * one of these 46 values against DEFAULT_PRESET on each run, so the next drift fails a
28
- * test instead of earning a paragraph. The direction is one-way: the presets are the
29
- * source, this file follows. */
30
+ * theme/__tests__/tokens-css-mirror.test.ts compares every one of these 46 values against
31
+ * DEFAULT_PRESET on each run, so a drift fails a test. The direction is one-way: the
32
+ * presets are the source, this file follows. */
30
33
 
31
34
  @custom-variant dark (&:where(.dark, .dark *));
32
35
 
@@ -172,10 +175,27 @@ html[data-text-size="xlarge"] {
172
175
  @custom-variant xlarge (&:where([data-text-size=xlarge], [data-text-size=xlarge] *));
173
176
  @custom-variant contrast (&:where([data-contrast=more], [data-contrast=more] *));
174
177
 
178
+ /* "Truncate at Normal, wrap at Large" under one name (0.33, docs/text-size-harmonization.md
179
+ §10.17): `truncate` — one line and an ellipsis — and from Large up, the text wraps
180
+ instead, breaking a word only where nothing else fits (`overflow-wrap: anywhere`, as
181
+ List's copy had it). At Large and Extra large nothing may cut its text: the size sweep
182
+ reports a one-line ellipsis that does. Normal keeps its ellipses. It replaces the
183
+ hand-written `large:whitespace-normal large:…` copies, and an app's own JS switches
184
+ (`!large && "truncate"`) can take it too: it follows the attribute in CSS. */
185
+ @utility truncate-until-large {
186
+ overflow: hidden;
187
+ text-overflow: ellipsis;
188
+ white-space: nowrap;
189
+ @variant large {
190
+ white-space: normal;
191
+ overflow-wrap: anywhere;
192
+ }
193
+ }
194
+
175
195
  :root {
176
196
  --bg-page: #ede3cf; /* warm dim sand — low-glare light page */
177
197
  --bg-surface: #f6ecd9; /* warm off-white card/panel (not pure white) */
178
- --bg-surface-2: #f3ead6; /* inset/well surface */
198
+ --bg-surface-2: #ede3cf; /* inset/well surface: the page itself in light (0.33) */
179
199
  --border: #e2d6bd; /* warm hairline border */
180
200
  --text-primary: #463f33; /* warm dark grey — not pure black */
181
201
  /* The two quieter text roles. Contrast against the WORST of the three surfaces
@@ -204,9 +224,12 @@ html[data-text-size="xlarge"] {
204
224
 
205
225
  They mark a field's FRAME and an ICON at its end — non-text graphics, for which
206
226
  WCAG 1.4.11 asks 3:1 against the surface — and all four clear it on the worst of
207
- the three light surfaces. `--status-edited` is amber rather than the orange-800 it
227
+ the three light surfaces, in every shipped preset (theme/__tests__/
228
+ tokens-css-audit.test.ts measures it; until 0.33 this note only claimed it, and
229
+ amber-600 sat at 2.45:1). `--status-edited` is amber rather than the orange-800 it
208
230
  was: beside red-700 that orange read as a second error colour, and "unsaved" has
209
- to look like a caution, not an alarm. Amber is below 4.5:1, so it is not a TEXT
231
+ to look like a caution, not an alarm. Light, it is amber-600's hue and chroma at a
232
+ SOLVED lightness (3.1:1 on the worst surface). Below 4.5:1, so it is not a TEXT
210
233
  colour: `FieldSyncIndicator` prints its words in `--text-secondary` beside it.
211
234
 
212
235
  GREEN AND RED ARE THE CLASSIC CVD-UNSAFE PAIR, and the rest of this file goes out
@@ -216,7 +239,7 @@ html[data-text-size="xlarge"] {
216
239
  the only signal. Do not drop the icons. */
217
240
  --status-synced: #166534; /* green-800 — persisted */
218
241
  --status-pending: #1d4ed8; /* blue-700 — in flight */
219
- --status-edited: #d97706; /* amber-600 — dirty, not yet saved */
242
+ --status-edited: #bf6800; /* solved — dirty, not yet saved */
220
243
  --status-error: #b91c1c; /* red-700 — the save failed */
221
244
  --chart-1: #332288;
222
245
  --chart-2: #88ccee;
@@ -288,10 +311,23 @@ html[data-text-size="xlarge"] {
288
311
  value. Mixing TOWARD the surface fades it in light and in dark alike. */
289
312
  --text-placeholder: color-mix(in oklab, var(--text-muted) 65%, var(--bg-surface));
290
313
 
291
- /* The wash under a hovered row, menu item or icon button. Mixing the TEXT colour
292
- into the surface darkens it on a light theme and lightens it on a dark one,
293
- which is the behaviour a fixed `slate-100`/`slate-800` pair was faking. */
294
- --bg-hover: color-mix(in oklab, var(--text-primary) 7%, var(--bg-surface));
314
+ /* The wash under a hovered row, menu item or icon button ON A CARD. Mixing the TEXT
315
+ colour into the surface darkens it on a light theme and lightens it on a dark one,
316
+ which is the behaviour a fixed `slate-100`/`slate-800` pair was faking.
317
+
318
+ 5.5 %, not the 7 % it was (0.33, colour-roles §12.10): text sits on a hovered row,
319
+ and at 7 % the status, money and muted colours fell to 4.25–4.49:1 on it. Text wins
320
+ over the hover's step, which is still 1.09–1.13:1 from the card. `HOVER_INK` in
321
+ theme/contrast-tokens.ts is this number for the deriver; the token audit holds them
322
+ equal.
323
+
324
+ Two hovers it is NOT for (§12.2, §12.10): a row that rests on `--bg-surface-2`
325
+ hovers to `--bg-surface` (in light the well is the page, and this wash sits only
326
+ 1.04:1 from it); and a control that can sit on the page, the card or the well
327
+ (Button secondary/ghost, IconButton muted) hovers with a translucent ink,
328
+ `color-mix(in srgb, var(--text-primary) 7%, transparent)`, 1.11:1 or more on all
329
+ three. */
330
+ --bg-hover: color-mix(in oklab, var(--text-primary) 5.5%, var(--bg-surface));
295
331
  --bg-active: color-mix(in oklab, var(--text-primary) 12%, var(--bg-surface));
296
332
 
297
333
  /* A chip that inverts against the page — a selected day, a keyboard hint. These
@@ -313,8 +349,49 @@ html[data-text-size="xlarge"] {
313
349
  --brand-bg: color-mix(in oklab, var(--brand) 14%, var(--bg-surface));
314
350
  --brand-bg-hover: color-mix(in oklab, var(--brand) 24%, var(--bg-surface));
315
351
  /* Brand text ON `--brand-bg` — pulled away from the surface so it keeps contrast
316
- against its own tint in both themes. */
317
- --brand-muted: color-mix(in oklab, var(--brand) 70%, var(--text-primary));
352
+ against its own tint in both themes, and against `--brand-bg-hover` under it.
353
+ 62 %, not the 70 % it was (0.33, colour-roles §12.11): on the hovered chip 70 %
354
+ read 4.08–4.42:1 (Default and Moss light; Ink, Moss, Plum and Contrast dark);
355
+ 62 % clears 4.5:1 in every preset and mode.
356
+ `BRAND_MUTED_SHARE` in theme/contrast-tokens.ts is this number for the deriver; the
357
+ token audit holds them equal. */
358
+ --brand-muted: color-mix(in oklab, var(--brand) 62%, var(--text-primary));
359
+ }
360
+
361
+ /* ── A foreground for every fill (0.33, docs/colour-roles-harmonization.md §5.1) ──
362
+ A fill names the ink that goes on it, `<fill>-contrast`, so a pill, a badge or an
363
+ armed swipe never has to guess. Guessing is what went wrong: white on a money fill
364
+ (k22) and white on every status fill in dark mode, where the fills are pastels and
365
+ white sits at 1.4–3.6:1 (k23). The status and hue pairs are with their families
366
+ below; these are the money and neutral ones.
367
+
368
+ Money is white in light and the PAGE in dark — `--brand-contrast`'s precedent. Both
369
+ hold for any token set, not only the shipped ones: the preset audit solves income,
370
+ expense, net and neutral to 4.5:1 against the page, which is the darkest surface in
371
+ dark, and white is lighter than any light page. Four names for one value, one per
372
+ fill, so a preset whose money colours differ in lightness has room to differ. */
373
+ :root {
374
+ --money-income-contrast: #ffffff;
375
+ --money-expense-contrast: #ffffff;
376
+ --money-net-contrast: #ffffff;
377
+ --money-neutral-contrast: #ffffff;
378
+ }
379
+ .dark {
380
+ --money-income-contrast: var(--bg-page);
381
+ --money-expense-contrast: var(--bg-page);
382
+ --money-net-contrast: var(--bg-page);
383
+ --money-neutral-contrast: var(--bg-page);
384
+ }
385
+
386
+ /* "Neutral" as a fill — a step back, a state with no tone: the muted ink under the
387
+ surface colour, 5.1:1 and up in every preset. Not a new grey: it is the pair the
388
+ translation review's reset swipe improvised, made official, and it follows More
389
+ contrast through `--text-muted` (7.6:1 and up there). Chip `solid neutral` is a
390
+ different, louder thing — the inverse pair, a count pill — and keeps it. */
391
+ :root,
392
+ .dark {
393
+ --neutral: var(--text-muted);
394
+ --neutral-contrast: var(--text-inverse);
318
395
  }
319
396
 
320
397
  /* ── Semantic status ────────────────────────────────────────────────────────
@@ -327,20 +404,43 @@ html[data-text-size="xlarge"] {
327
404
  Distinct from the `--status-*` family above: those describe a FIELD's journey
328
405
  to the database, these describe an ACTION's consequence. A row can be
329
406
  `--status-error` (its last save failed) inside a form whose delete button is
330
- `--danger` (it will destroy something), and they should not look identical. */
407
+ `--danger` (it will destroy something), and they should not look identical.
408
+
409
+ Each tone is a family: the colour (text on any surface, and a fill), `-contrast`
410
+ (text ON the fill), `-border` (a soft frame), `-bg` (a wash, text in the tone's
411
+ colour on it) and, for danger and warning, `-border-strong` (a line that has to be
412
+ seen: an invalid field, a loud frame, a focus ring). In dark the fills are pastels,
413
+ so their `-contrast` is the tone's 950, never white.
414
+
415
+ THE LIGHT VALUES ARE SOLVED, not Tailwind steps, where a 700 failed (0.33,
416
+ docs/colour-roles-harmonization.md §5.5): the cream and tinted grounds are darker
417
+ than the white those steps were made for. Each keeps its 700's OKLCH hue and chroma
418
+ at the lightness that clears 4.5:1 as text on the page, the card, the well, its own
419
+ wash and a hovered row, in every shipped preset — amber-700 managed 3.86:1, emerald
420
+ 4.22. `--money-expense` went the same way earlier. tokens-css-audit.test.ts holds
421
+ every pair here to its ratio. */
331
422
  :root {
332
423
  --danger: #be123c; /* rose-700 */
333
424
  --danger-hover: #9f1239; /* rose-800 */
334
425
  --danger-contrast: #ffffff;
335
426
  --danger-border: #fb7185; /* rose-400 */
336
427
  /* The error LINE: an invalid field, a failed upload, a danger banner's frame, a focus
337
- ring on a destructive control. Equal to the border in light mode; in dark the tone
338
- border is soft like its siblings and this one stays loud (WCAG 1.4.11's 3:1). */
339
- --danger-border-strong: #fb7185; /* rose-400 */
428
+ ring on a destructive control — loud, WCAG 1.4.11's 3:1 against every surface.
429
+ Rose-600 in both modes since 0.33: light was rose-400, the soft border's value,
430
+ which reached only 2.07:1 while this note claimed 3:1. */
431
+ --danger-border-strong: #e11d48; /* rose-600 */
340
432
  --danger-bg: #fff1f2; /* rose-50 */
341
433
 
342
- --warning: #b45309; /* amber-700 */
434
+ --warning: #a34800; /* amber-700's hue, solved (was #b45309, 3.86:1) */
435
+ /* Text on a `--warning` fill (0.33, k24): a solid warning chip, a badge, an armed
436
+ swipe. White here, amber-950 on the dark theme's pastel. */
437
+ --warning-contrast: #ffffff;
343
438
  --warning-border: #fcd34d; /* amber-300 */
439
+ /* Warning's loud line (0.33, k27), as `--danger-border-strong` is danger's: Card
440
+ `toneStrength="strong"`, IconButton's warning focus ring. In light the warning
441
+ colour itself — amber-600 would be only 2.5:1 on the cream page; in dark amber-600,
442
+ the step danger's line takes, 4.8:1 and up without shouting. */
443
+ --warning-border-strong: var(--warning);
344
444
  --warning-bg: #fffbeb; /* amber-50 */
345
445
 
346
446
  /* Informational, and deliberately NOT the brand: a count of active filters is
@@ -357,7 +457,7 @@ html[data-text-size="xlarge"] {
357
457
  `--danger` is distinct from `--status-error`: that family describes a FIELD's
358
458
  journey to the database, this one an ACTION's outcome. Emerald rather than the
359
459
  money teal, so a "resolved" chip cannot be misread as an inflow. */
360
- --success: #047857; /* emerald-700 */
460
+ --success: #007152; /* emerald-700's hue, solved (was #047857, 4.22:1) */
361
461
  /* Text on a `--success` fill (0.26: a swipe's approve panel) — white here, the
362
462
  darkest emerald in dark mode, where the fill is a pastel and white text failed. */
363
463
  --success-contrast: #ffffff;
@@ -377,7 +477,9 @@ html[data-text-size="xlarge"] {
377
477
  --danger-bg: rgba(136, 19, 55, 0.2);
378
478
 
379
479
  --warning: #fcd34d; /* amber-300 */
480
+ --warning-contrast: #451a03; /* amber-950 */
380
481
  --warning-border: rgba(180, 83, 9, 0.6);
482
+ --warning-border-strong: #d97706; /* amber-600 */
381
483
  --warning-bg: rgba(120, 53, 15, 0.2);
382
484
 
383
485
  --info: #7dd3fc; /* sky-300 */
@@ -434,15 +536,16 @@ html[data-text-size="xlarge"] {
434
536
  .kit-toaster [data-sonner-toast][data-styled="true"]:not([data-type="success"], [data-type="info"], [data-type="warning"], [data-type="error"]) [data-description] {
435
537
  color: var(--text-secondary);
436
538
  }
437
- /* The action button in the tone's own colour rather than sonner's black pill. */
539
+ /* The action button in the tone's own colour rather than sonner's black pill, under
540
+ that fill's own foreground (0.33): the surface colour on light warning was 4.3:1. */
438
541
  .kit-toaster [data-sonner-toast][data-styled="true"] [data-button]:not([data-cancel]) {
439
542
  background: var(--toast-action-bg, var(--text-primary));
440
- color: var(--bg-surface);
543
+ color: var(--toast-action-fg, var(--bg-surface));
441
544
  }
442
- .kit-toaster [data-sonner-toast][data-type="success"] { --toast-action-bg: var(--success); }
443
- .kit-toaster [data-sonner-toast][data-type="info"] { --toast-action-bg: var(--info); }
444
- .kit-toaster [data-sonner-toast][data-type="warning"] { --toast-action-bg: var(--warning); }
445
- .kit-toaster [data-sonner-toast][data-type="error"] { --toast-action-bg: var(--danger); }
545
+ .kit-toaster [data-sonner-toast][data-type="success"] { --toast-action-bg: var(--success); --toast-action-fg: var(--success-contrast); }
546
+ .kit-toaster [data-sonner-toast][data-type="info"] { --toast-action-bg: var(--info); --toast-action-fg: var(--info-contrast); }
547
+ .kit-toaster [data-sonner-toast][data-type="warning"] { --toast-action-bg: var(--warning); --toast-action-fg: var(--warning-contrast); }
548
+ .kit-toaster [data-sonner-toast][data-type="error"] { --toast-action-bg: var(--danger); --toast-action-fg: var(--danger-contrast); }
446
549
  /* The kit's focus ring on the toast's buttons — sonner's is a black shadow that
447
550
  vanishes on the dark theme. */
448
551
  .kit-toaster [data-sonner-toast][data-styled="true"] :is([data-button], [data-close-button]):focus-visible {
@@ -459,64 +562,221 @@ html[data-text-size="xlarge"] {
459
562
  orange (terminated / high urgency), teal (invoiced) and indigo (a meeting
460
563
  stage). The smallest set that covers every enum; deliberately not a ramp.
461
564
 
462
- Same triple and same shades as the status family (700 text / 300 border /
565
+ Same family and same shades as the status family (700 text / 300 border /
463
566
  100 surface in light, 300 text / translucent 700 border / 900 wash in dark),
464
567
  so a categorical chip sits beside a semantic one at the same weight. Not in
465
568
  `TokenSet`: like `--danger`, a hue is a specific colour, not a tint of the
466
- palette preset, so it lives here and nowhere else. */
569
+ palette preset, so it lives here and nowhere else.
570
+
571
+ `-contrast` (0.33) is the text on the hue as a fill — a solid chip: white in light,
572
+ the hue's 950 on the dark pastel. Teal and orange are SOLVED in light, as warning
573
+ and success are (§5.5): their 700s reached 4.21 and 3.98:1 on the cream page. */
467
574
  :root {
468
575
  --hue-blue: #1d4ed8; /* blue-700 */
576
+ --hue-blue-contrast: #ffffff;
469
577
  --hue-blue-border: #93c5fd; /* blue-300 */
470
578
  --hue-blue-bg: #dbeafe; /* blue-100 */
471
579
  --hue-indigo: #4338ca; /* indigo-700 */
580
+ --hue-indigo-contrast: #ffffff;
472
581
  --hue-indigo-border: #a5b4fc; /* indigo-300 */
473
582
  --hue-indigo-bg: #e0e7ff; /* indigo-100 */
474
583
  --hue-purple: #7e22ce; /* purple-700 */
584
+ --hue-purple-contrast: #ffffff;
475
585
  --hue-purple-border: #d8b4fe; /* purple-300 */
476
586
  --hue-purple-bg: #f3e8ff; /* purple-100 */
477
- --hue-teal: #0f766e; /* teal-700 */
587
+ --hue-teal: #006f68; /* teal-700's hue, solved */
588
+ --hue-teal-contrast: #ffffff;
478
589
  --hue-teal-border: #5eead4; /* teal-300 */
479
590
  --hue-teal-bg: #ccfbf1; /* teal-100 */
480
- --hue-orange: #c2410c; /* orange-700 */
591
+ --hue-orange: #b43800; /* orange-700's hue, solved */
592
+ --hue-orange-contrast: #ffffff;
481
593
  --hue-orange-border: #fdba74; /* orange-300 */
482
594
  --hue-orange-bg: #ffedd5; /* orange-100 */
483
595
  }
484
596
 
485
597
  .dark {
486
598
  --hue-blue: #93c5fd; /* blue-300 */
599
+ --hue-blue-contrast: #172554; /* blue-950 */
487
600
  --hue-blue-border: rgba(29, 78, 216, 0.6);
488
601
  --hue-blue-bg: rgba(30, 58, 138, 0.25);
489
602
  --hue-indigo: #a5b4fc; /* indigo-300 */
603
+ --hue-indigo-contrast: #1e1b4b; /* indigo-950 */
490
604
  --hue-indigo-border: rgba(67, 56, 202, 0.6);
491
605
  --hue-indigo-bg: rgba(49, 46, 129, 0.25);
492
606
  --hue-purple: #d8b4fe; /* purple-300 */
607
+ --hue-purple-contrast: #3b0764; /* purple-950 */
493
608
  --hue-purple-border: rgba(126, 34, 206, 0.6);
494
609
  --hue-purple-bg: rgba(88, 28, 135, 0.25);
495
610
  --hue-teal: #5eead4; /* teal-300 */
611
+ --hue-teal-contrast: #042f2e; /* teal-950 */
496
612
  --hue-teal-border: rgba(15, 118, 110, 0.6);
497
613
  --hue-teal-bg: rgba(19, 78, 74, 0.25);
498
614
  --hue-orange: #fdba74; /* orange-300 */
615
+ --hue-orange-contrast: #431407; /* orange-950 */
499
616
  --hue-orange-border: rgba(194, 65, 12, 0.6);
500
617
  --hue-orange-bg: rgba(124, 45, 18, 0.25);
501
618
  }
502
619
 
503
- /* Semantic colour utilities backed by the tokens above. Unlayered so they win
504
- over Tailwind's layered colour utilities, and theme-aware for free (the var
505
- flips under .dark) — no dark: variant needed at the call site. */
620
+ /* ── Role utilities (0.33, docs/colour-roles-harmonization.md §7, k25) ─────────────
621
+ *
622
+ * `text-muted`, `bg-surface-2`, `border-subtle`, `ring-brand`, `fill-surface` … instead of
623
+ * `text-[var(--text-muted)]`. Each name is the token's name with the property's own
624
+ * prefix dropped (`--bg-surface` → `bg-surface`, `--danger-border` → `border-danger`); a
625
+ * tone's wash is `-soft` (Chip's word for it), and `--border` is `subtle`.
626
+ *
627
+ * PROPERTY-SCOPED, on purpose. `--text-color-*` makes a `text-*` utility and nothing
628
+ * else, `--background-color-*` only `bg-*`, `--border-color-*` only `border-*` (and
629
+ * `divide-*`, which falls back to it). So `bg-muted` and `text-surface` do not exist,
630
+ * and a name cannot be put on the wrong property by accident. Shadcn-style `--color-*`
631
+ * names would make every name on every property — and fight an app's own
632
+ * `--color-muted` / `--color-primary` (kastlan's), where these win for their property
633
+ * only. No `text-*` for the border roles: an SVG drawn in `currentColor` takes
634
+ * `stroke-subtle` / `stroke-strong` instead.
635
+ *
636
+ * `inline`: each utility reads the role variable AT THE ELEMENT (`color: var(--text-muted)`),
637
+ * so a local override still works, and no `--text-color-muted` is emitted on `:root` —
638
+ * which is why `@eifi1/ui-kit/testing` does not count these names as declared:
639
+ * `var(--text-color-muted)` would paint nothing. A name costs nothing until a scanned
640
+ * file uses it, and variants and opacity work on all of them (`hover:bg-hover`,
641
+ * `md:text-secondary`, `text-muted/60`).
642
+ *
643
+ * The kit's own ~1,750 `[var(--…)]` classes stay where they are (a rewrite would change
644
+ * hundreds of class assertions here and in the apps); `scripts/check-token-discipline.mjs`
645
+ * counts them wherever one of these exists and lets the number only fall. New and
646
+ * touched code uses these. `check:tailwind` asserts one per namespace survives a build.
647
+ *
648
+ * `text-brand`, `bg-brand` and `border-brand` were plain classes until 0.33, which
649
+ * Tailwind gives no variants (`hover:bg-brand` generated nothing); they are theme names
650
+ * now. The money classes below stay plain: `-muted` is an opacity, not a colour. */
651
+ @theme inline {
652
+ /* text-* — the text roles, the tone colours as text, and every fill's foreground */
653
+ --text-color-primary: var(--text-primary);
654
+ --text-color-secondary: var(--text-secondary);
655
+ --text-color-muted: var(--text-muted);
656
+ --text-color-placeholder: var(--text-placeholder);
657
+ --text-color-inverse: var(--text-inverse);
658
+ --text-color-brand: var(--brand);
659
+ --text-color-brand-muted: var(--brand-muted);
660
+ --text-color-danger: var(--danger);
661
+ --text-color-warning: var(--warning);
662
+ --text-color-success: var(--success);
663
+ --text-color-info: var(--info);
664
+ --text-color-hue-blue: var(--hue-blue);
665
+ --text-color-hue-indigo: var(--hue-indigo);
666
+ --text-color-hue-purple: var(--hue-purple);
667
+ --text-color-hue-teal: var(--hue-teal);
668
+ --text-color-hue-orange: var(--hue-orange);
669
+ --text-color-brand-contrast: var(--brand-contrast);
670
+ --text-color-danger-contrast: var(--danger-contrast);
671
+ --text-color-warning-contrast: var(--warning-contrast);
672
+ --text-color-success-contrast: var(--success-contrast);
673
+ --text-color-info-contrast: var(--info-contrast);
674
+ --text-color-neutral-contrast: var(--neutral-contrast);
675
+ --text-color-money-income-contrast: var(--money-income-contrast);
676
+ --text-color-money-expense-contrast: var(--money-expense-contrast);
677
+ --text-color-money-net-contrast: var(--money-net-contrast);
678
+ --text-color-money-neutral-contrast: var(--money-neutral-contrast);
679
+ --text-color-hue-blue-contrast: var(--hue-blue-contrast);
680
+ --text-color-hue-indigo-contrast: var(--hue-indigo-contrast);
681
+ --text-color-hue-purple-contrast: var(--hue-purple-contrast);
682
+ --text-color-hue-teal-contrast: var(--hue-teal-contrast);
683
+ --text-color-hue-orange-contrast: var(--hue-orange-contrast);
684
+ --text-color-media-ink: var(--media-ink);
685
+
686
+ /* bg-* — the surfaces, the fills, and each tone's wash as `-soft` (Chip's word) */
687
+ --background-color-page: var(--bg-page);
688
+ --background-color-surface: var(--bg-surface);
689
+ --background-color-surface-2: var(--bg-surface-2);
690
+ --background-color-hover: var(--bg-hover);
691
+ --background-color-active: var(--bg-active);
692
+ --background-color-inverse: var(--bg-inverse);
693
+ --background-color-brand: var(--brand);
694
+ --background-color-brand-hover: var(--brand-hover);
695
+ --background-color-brand-soft: var(--brand-bg);
696
+ --background-color-brand-soft-hover: var(--brand-bg-hover);
697
+ --background-color-danger: var(--danger);
698
+ --background-color-danger-hover: var(--danger-hover);
699
+ --background-color-warning: var(--warning);
700
+ --background-color-success: var(--success);
701
+ --background-color-info: var(--info);
702
+ --background-color-neutral: var(--neutral);
703
+ --background-color-danger-soft: var(--danger-bg);
704
+ --background-color-warning-soft: var(--warning-bg);
705
+ --background-color-success-soft: var(--success-bg);
706
+ --background-color-info-soft: var(--info-bg);
707
+ --background-color-hue-blue: var(--hue-blue);
708
+ --background-color-hue-indigo: var(--hue-indigo);
709
+ --background-color-hue-purple: var(--hue-purple);
710
+ --background-color-hue-teal: var(--hue-teal);
711
+ --background-color-hue-orange: var(--hue-orange);
712
+ --background-color-hue-blue-soft: var(--hue-blue-bg);
713
+ --background-color-hue-indigo-soft: var(--hue-indigo-bg);
714
+ --background-color-hue-purple-soft: var(--hue-purple-bg);
715
+ --background-color-hue-teal-soft: var(--hue-teal-bg);
716
+ --background-color-hue-orange-soft: var(--hue-orange-bg);
717
+ --background-color-media-scrim: var(--media-scrim);
718
+ --background-color-media-scrim-hover: var(--media-scrim-hover);
719
+
720
+ /* border-* (and divide-*, which falls back to these) — `subtle` is `--border` */
721
+ --border-color-subtle: var(--border);
722
+ --border-color-strong: var(--border-strong);
723
+ --border-color-brand: var(--brand);
724
+ --border-color-danger: var(--danger-border);
725
+ --border-color-warning: var(--warning-border);
726
+ --border-color-success: var(--success-border);
727
+ --border-color-info: var(--info-border);
728
+ --border-color-danger-strong: var(--danger-border-strong);
729
+ --border-color-warning-strong: var(--warning-border-strong);
730
+ --border-color-hue-blue: var(--hue-blue-border);
731
+ --border-color-hue-indigo: var(--hue-indigo-border);
732
+ --border-color-hue-purple: var(--hue-purple-border);
733
+ --border-color-hue-teal: var(--hue-teal-border);
734
+ --border-color-hue-orange: var(--hue-orange-border);
735
+ --border-color-media-ink: var(--media-ink);
736
+
737
+ /* ring-* and outline-* — a focus ring, a selection frame, an inside line */
738
+ --ring-color-subtle: var(--border);
739
+ --ring-color-strong: var(--border-strong);
740
+ --ring-color-brand: var(--brand);
741
+ --ring-color-danger-strong: var(--danger-border-strong);
742
+ --ring-color-warning-strong: var(--warning-border-strong);
743
+ --outline-color-subtle: var(--border);
744
+ --outline-color-strong: var(--border-strong);
745
+ --outline-color-brand: var(--brand);
746
+ --outline-color-danger-strong: var(--danger-border-strong);
747
+ --outline-color-warning-strong: var(--warning-border-strong);
748
+ --ring-color-media-ink: var(--media-ink);
749
+
750
+ /* fill-* and stroke-* — for SVG: the text roles, the card, and the two lines */
751
+ --fill-primary: var(--text-primary);
752
+ --fill-secondary: var(--text-secondary);
753
+ --fill-muted: var(--text-muted);
754
+ --fill-surface: var(--bg-surface);
755
+ --fill-subtle: var(--border);
756
+ --fill-strong: var(--border-strong);
757
+ --stroke-primary: var(--text-primary);
758
+ --stroke-secondary: var(--text-secondary);
759
+ --stroke-muted: var(--text-muted);
760
+ --stroke-surface: var(--bg-surface);
761
+ --stroke-subtle: var(--border);
762
+ --stroke-strong: var(--border-strong);
763
+ }
764
+
765
+ /* Money utilities backed by the tokens above. Unlayered so they win over Tailwind's
766
+ layered colour utilities, and theme-aware for free (the var flips under .dark) — no
767
+ dark: variant needed at the call site. Plain classes, so no variants: a site that
768
+ needs one keeps `[var(--money-…)]` (no money theme names this round, §12.4). */
506
769
  .text-money-pos { color: var(--money-income); }
507
770
  .text-money-neg { color: var(--money-expense); }
508
771
  .text-money-net { color: var(--money-net); }
509
772
  .text-money-pos-muted { color: var(--money-income); opacity: 0.72; }
510
773
  .text-money-neg-muted { color: var(--money-expense); opacity: 0.72; }
511
- .text-brand { color: var(--brand); }
512
- .bg-brand { background-color: var(--brand); }
513
774
  .bg-money-pos { background-color: var(--money-income); }
514
775
  .bg-money-neg { background-color: var(--money-expense); }
515
776
  /* "No money has moved" — the fill for markers on rows that are not real yet
516
777
  (scheduled / future-dated). Deliberately NOT brand and NOT money-pos: those
517
778
  two mean settled, and a future row wearing one of them reads as done. */
518
779
  .bg-money-neutral { background-color: var(--money-neutral); }
519
- .border-brand { border-color: var(--brand); }
520
780
 
521
781
  /* Visually hidden, like Tailwind's `sr-only`, but POSITION: FIXED rather than absolute.
522
782
  *