@eifi1/ui-kit 0.48.1 → 0.49.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 (318) hide show
  1. package/README.md +28 -13
  2. package/dist/admin/admin-action-confirm.js +1 -1
  3. package/dist/admin/admin-action-confirm.js.map +1 -1
  4. package/dist/admin/invitations-panel.js +5 -1
  5. package/dist/admin/invitations-panel.js.map +1 -1
  6. package/dist/admin/user-roster.d.ts +11 -5
  7. package/dist/admin/user-roster.js +15 -4
  8. package/dist/admin/user-roster.js.map +1 -1
  9. package/dist/auth/accept-invitation.js +2 -2
  10. package/dist/auth/accept-invitation.js.map +1 -1
  11. package/dist/auth/not-found-page.js +1 -1
  12. package/dist/auth/not-found-page.js.map +1 -1
  13. package/dist/auth/reset-password-form.js +2 -2
  14. package/dist/auth/reset-password-form.js.map +1 -1
  15. package/dist/auth/verify-email.js +2 -2
  16. package/dist/auth/verify-email.js.map +1 -1
  17. package/dist/billing/plan-card.js +2 -2
  18. package/dist/billing/plan-card.js.map +1 -1
  19. package/dist/components/breadcrumbs.d.ts +19 -1
  20. package/dist/components/breadcrumbs.js +11 -4
  21. package/dist/components/breadcrumbs.js.map +1 -1
  22. package/dist/components/button-look.d.ts +37 -7
  23. package/dist/components/button-look.js +33 -6
  24. package/dist/components/button-look.js.map +1 -1
  25. package/dist/components/button.d.ts +4 -1
  26. package/dist/components/button.js +2 -2
  27. package/dist/components/button.js.map +1 -1
  28. package/dist/components/calendar-heatmap.js +2 -1
  29. package/dist/components/calendar-heatmap.js.map +1 -1
  30. package/dist/components/chart-edge.d.ts +10 -0
  31. package/dist/components/chart-edge.js +57 -0
  32. package/dist/components/chart-edge.js.map +1 -0
  33. package/dist/components/chart.js +2 -1
  34. package/dist/components/chart.js.map +1 -1
  35. package/dist/components/chip.d.ts +8 -1
  36. package/dist/components/chip.js +4 -1
  37. package/dist/components/chip.js.map +1 -1
  38. package/dist/components/confirm-context.d.ts +5 -0
  39. package/dist/components/confirm-context.js +7 -0
  40. package/dist/components/confirm-context.js.map +1 -0
  41. package/dist/components/confirm-dialog.js +3 -3
  42. package/dist/components/confirm-dialog.js.map +1 -1
  43. package/dist/components/danger-confirm.d.ts +2 -2
  44. package/dist/components/danger-confirm.js +1 -1
  45. package/dist/components/danger-confirm.js.map +1 -1
  46. package/dist/components/data-table-fit.d.ts +8 -1
  47. package/dist/components/data-table-fit.js +28 -4
  48. package/dist/components/data-table-fit.js.map +1 -1
  49. package/dist/components/data-table-groups.d.ts +3 -1
  50. package/dist/components/data-table-groups.js +11 -5
  51. package/dist/components/data-table-groups.js.map +1 -1
  52. package/dist/components/data-table-head.d.ts +8 -1
  53. package/dist/components/data-table-head.js +11 -3
  54. package/dist/components/data-table-head.js.map +1 -1
  55. package/dist/components/data-table-leading-row.d.ts +3 -1
  56. package/dist/components/data-table-leading-row.js +2 -1
  57. package/dist/components/data-table-leading-row.js.map +1 -1
  58. package/dist/components/data-table-mobile.d.ts +48 -2
  59. package/dist/components/data-table-mobile.js +87 -10
  60. package/dist/components/data-table-mobile.js.map +1 -1
  61. package/dist/components/data-table-row-actions.d.ts +2 -1
  62. package/dist/components/data-table-row-actions.js +9 -2
  63. package/dist/components/data-table-row-actions.js.map +1 -1
  64. package/dist/components/data-table-row.d.ts +84 -0
  65. package/dist/components/data-table-row.js +261 -0
  66. package/dist/components/data-table-row.js.map +1 -0
  67. package/dist/components/data-table-selection.d.ts +3 -0
  68. package/dist/components/data-table-selection.js +12 -1
  69. package/dist/components/data-table-selection.js.map +1 -1
  70. package/dist/components/data-table-virtual.d.ts +98 -0
  71. package/dist/components/data-table-virtual.js +369 -0
  72. package/dist/components/data-table-virtual.js.map +1 -0
  73. package/dist/components/data-table.d.ts +74 -2
  74. package/dist/components/data-table.js +241 -221
  75. package/dist/components/data-table.js.map +1 -1
  76. package/dist/components/error-boundary.js +2 -2
  77. package/dist/components/error-boundary.js.map +1 -1
  78. package/dist/components/floating-panel.d.ts +36 -13
  79. package/dist/components/floating-panel.js +27 -7
  80. package/dist/components/floating-panel.js.map +1 -1
  81. package/dist/components/form-actions.d.ts +1 -1
  82. package/dist/components/form-actions.js +1 -1
  83. package/dist/components/form-actions.js.map +1 -1
  84. package/dist/components/icon-button.d.ts +11 -0
  85. package/dist/components/icon-button.js +7 -5
  86. package/dist/components/icon-button.js.map +1 -1
  87. package/dist/components/nav-pills.d.ts +8 -1
  88. package/dist/components/nav-pills.js +61 -38
  89. package/dist/components/nav-pills.js.map +1 -1
  90. package/dist/components/page-header-context.d.ts +8 -0
  91. package/dist/components/page-header-context.js +7 -0
  92. package/dist/components/page-header-context.js.map +1 -0
  93. package/dist/components/page-header.d.ts +14 -2
  94. package/dist/components/page-header.js +10 -1
  95. package/dist/components/page-header.js.map +1 -1
  96. package/dist/components/pie-chart.js +2 -1
  97. package/dist/components/pie-chart.js.map +1 -1
  98. package/dist/components/progress-bar.js +5 -4
  99. package/dist/components/progress-bar.js.map +1 -1
  100. package/dist/components/reauth-dialog.js +1 -1
  101. package/dist/components/reauth-dialog.js.map +1 -1
  102. package/dist/components/row-actions-labels.js +3 -1
  103. package/dist/components/row-actions-labels.js.map +1 -1
  104. package/dist/components/row-actions.d.ts +43 -9
  105. package/dist/components/row-actions.js +78 -15
  106. package/dist/components/row-actions.js.map +1 -1
  107. package/dist/components/section-nav.d.ts +37 -0
  108. package/dist/components/section-nav.js +33 -0
  109. package/dist/components/section-nav.js.map +1 -0
  110. package/dist/components/series-chart.js +8 -3
  111. package/dist/components/series-chart.js.map +1 -1
  112. package/dist/components/share-card.js +1 -1
  113. package/dist/components/share-card.js.map +1 -1
  114. package/dist/components/signature-pad.js +1 -1
  115. package/dist/components/signature-pad.js.map +1 -1
  116. package/dist/components/sparkline.js +2 -1
  117. package/dist/components/sparkline.js.map +1 -1
  118. package/dist/components/stat-tile.js +14 -7
  119. package/dist/components/stat-tile.js.map +1 -1
  120. package/dist/components/status-dot.d.ts +5 -1
  121. package/dist/components/status-dot.js +4 -1
  122. package/dist/components/status-dot.js.map +1 -1
  123. package/dist/components/tooltip.js +1 -1
  124. package/dist/components/tooltip.js.map +1 -1
  125. package/dist/components/translation-review-editor.js +2 -2
  126. package/dist/components/translation-review-editor.js.map +1 -1
  127. package/dist/components/translation-review.js +2 -2
  128. package/dist/components/translation-review.js.map +1 -1
  129. package/dist/components/treemap.d.ts +5 -2
  130. package/dist/components/treemap.js +26 -6
  131. package/dist/components/treemap.js.map +1 -1
  132. package/dist/components/use-table-state.js +37 -6
  133. package/dist/components/use-table-state.js.map +1 -1
  134. package/dist/data-table.d.ts +1 -0
  135. package/dist/data-table.js.map +1 -1
  136. package/dist/demo/demo-banner.js +1 -1
  137. package/dist/demo/demo-banner.js.map +1 -1
  138. package/dist/demo/demo-ended.js +1 -1
  139. package/dist/demo/demo-ended.js.map +1 -1
  140. package/dist/demo/demo-start.js +1 -1
  141. package/dist/demo/demo-start.js.map +1 -1
  142. package/dist/eslint/index.js +1 -1
  143. package/dist/feedback/feedback-inbox.js +1 -1
  144. package/dist/feedback/feedback-inbox.js.map +1 -1
  145. package/dist/hooks/use-anchored-panel.js +2 -1
  146. package/dist/hooks/use-anchored-panel.js.map +1 -1
  147. package/dist/hooks/use-dismiss.d.ts +9 -1
  148. package/dist/hooks/use-dismiss.js +25 -5
  149. package/dist/hooks/use-dismiss.js.map +1 -1
  150. package/dist/hooks/use-document-title.d.ts +14 -0
  151. package/dist/hooks/use-document-title.js +22 -0
  152. package/dist/hooks/use-document-title.js.map +1 -0
  153. package/dist/i18n/german.js +6 -2
  154. package/dist/i18n/german.js.map +1 -1
  155. package/dist/i18n/kit-labels.d.ts +31 -1
  156. package/dist/i18n/kit-labels.js +43 -2
  157. package/dist/i18n/kit-labels.js.map +1 -1
  158. package/dist/i18n/locales/en.js +6 -2
  159. package/dist/i18n/locales/en.js.map +2 -2
  160. package/dist/i18n/locales/es.js +6 -2
  161. package/dist/i18n/locales/es.js.map +1 -1
  162. package/dist/i18n/locales/fr.js +6 -2
  163. package/dist/i18n/locales/fr.js.map +1 -1
  164. package/dist/i18n/locales/hu.js +6 -2
  165. package/dist/i18n/locales/hu.js.map +1 -1
  166. package/dist/i18n/locales/it.js +6 -2
  167. package/dist/i18n/locales/it.js.map +1 -1
  168. package/dist/i18n/locales/zh.js +6 -2
  169. package/dist/i18n/locales/zh.js.map +1 -1
  170. package/dist/i18n/review.js +2 -0
  171. package/dist/i18n/review.js.map +1 -1
  172. package/dist/i18n/shared-labels.js +1 -0
  173. package/dist/i18n/shared-labels.js.map +1 -1
  174. package/dist/index.d.ts +8 -1
  175. package/dist/index.js +11 -0
  176. package/dist/index.js.map +1 -1
  177. package/dist/landing/landing-actions.js +2 -2
  178. package/dist/landing/landing-actions.js.map +1 -1
  179. package/dist/landing/public-header.js +2 -2
  180. package/dist/landing/public-header.js.map +1 -1
  181. package/dist/lib/clipboard-minus.d.ts +27 -0
  182. package/dist/lib/clipboard-minus.js +63 -0
  183. package/dist/lib/clipboard-minus.js.map +1 -0
  184. package/dist/lib/document-title.d.ts +17 -0
  185. package/dist/lib/document-title.js +29 -0
  186. package/dist/lib/document-title.js.map +1 -0
  187. package/dist/lib/float-clearance.js +8 -2
  188. package/dist/lib/float-clearance.js.map +1 -1
  189. package/dist/lib/format.d.ts +35 -10
  190. package/dist/lib/format.js +55 -11
  191. package/dist/lib/format.js.map +1 -1
  192. package/dist/lib/minus.d.ts +22 -0
  193. package/dist/lib/minus.js +14 -0
  194. package/dist/lib/minus.js.map +1 -0
  195. package/dist/lib/status-tone.d.ts +30 -0
  196. package/dist/lib/status-tone.js +17 -0
  197. package/dist/lib/status-tone.js.map +1 -0
  198. package/dist/settings/settings-layout.js +3 -2
  199. package/dist/settings/settings-layout.js.map +1 -1
  200. package/dist/shell/account-menu-language.d.ts +1 -1
  201. package/dist/shell/account-menu-language.js +9 -1
  202. package/dist/shell/account-menu-language.js.map +1 -1
  203. package/dist/shell/app-shell-labels.js +2 -1
  204. package/dist/shell/app-shell-labels.js.map +1 -1
  205. package/dist/shell/app-shell.d.ts +58 -16
  206. package/dist/shell/app-shell.js +158 -44
  207. package/dist/shell/app-shell.js.map +1 -1
  208. package/dist/shell/language-code.d.ts +3 -0
  209. package/dist/shell/language-code.js +8 -0
  210. package/dist/shell/language-code.js.map +1 -0
  211. package/dist/shell/topbar-controls.d.ts +14 -6
  212. package/dist/shell/topbar-controls.js +14 -17
  213. package/dist/shell/topbar-controls.js.map +1 -1
  214. package/dist/testing/css-variables.generated.d.ts +1 -1
  215. package/dist/testing/css-variables.generated.js +1 -1
  216. package/dist/testing/css-variables.generated.js.map +1 -1
  217. package/dist/theme/chart-palette.d.ts +82 -15
  218. package/dist/theme/chart-palette.js +51 -24
  219. package/dist/theme/chart-palette.js.map +1 -1
  220. package/dist/theme/palette-presets.d.ts +9 -0
  221. package/dist/theme/palette-presets.js +77 -62
  222. package/dist/theme/palette-presets.js.map +1 -1
  223. package/dist/tour/tour.js +1 -1
  224. package/dist/tour/tour.js.map +1 -1
  225. package/dist/wizard/stepper-nav.d.ts +1 -1
  226. package/dist/wizard/stepper-nav.js +3 -3
  227. package/dist/wizard/stepper-nav.js.map +1 -1
  228. package/package.json +1 -1
  229. package/src/admin/admin-action-confirm.tsx +1 -1
  230. package/src/admin/invitations-panel.tsx +7 -3
  231. package/src/admin/user-roster.tsx +23 -6
  232. package/src/auth/accept-invitation.tsx +3 -3
  233. package/src/auth/not-found-page.tsx +1 -1
  234. package/src/auth/reset-password-form.tsx +3 -3
  235. package/src/auth/verify-email.tsx +3 -3
  236. package/src/billing/plan-card.tsx +2 -2
  237. package/src/components/breadcrumbs.tsx +32 -4
  238. package/src/components/button-look.ts +86 -15
  239. package/src/components/button.tsx +6 -3
  240. package/src/components/calendar-heatmap.tsx +2 -1
  241. package/src/components/chart-edge.ts +73 -0
  242. package/src/components/chart.tsx +3 -1
  243. package/src/components/chip.tsx +10 -1
  244. package/src/components/confirm-context.ts +7 -0
  245. package/src/components/confirm-dialog.tsx +3 -3
  246. package/src/components/danger-confirm.tsx +3 -3
  247. package/src/components/data-table-fit.ts +58 -8
  248. package/src/components/data-table-groups.tsx +15 -4
  249. package/src/components/data-table-head.tsx +25 -2
  250. package/src/components/data-table-leading-row.tsx +4 -1
  251. package/src/components/data-table-mobile.tsx +162 -11
  252. package/src/components/data-table-row-actions.tsx +12 -3
  253. package/src/components/data-table-row.tsx +485 -0
  254. package/src/components/data-table-selection.ts +17 -1
  255. package/src/components/data-table-virtual.ts +547 -0
  256. package/src/components/data-table.tsx +367 -326
  257. package/src/components/error-boundary.tsx +2 -2
  258. package/src/components/floating-panel.tsx +67 -16
  259. package/src/components/form-actions.tsx +2 -2
  260. package/src/components/icon-button.tsx +21 -8
  261. package/src/components/nav-pills.tsx +29 -2
  262. package/src/components/page-header-context.ts +8 -0
  263. package/src/components/page-header.tsx +34 -2
  264. package/src/components/pie-chart.tsx +2 -1
  265. package/src/components/progress-bar.tsx +6 -3
  266. package/src/components/reauth-dialog.tsx +1 -1
  267. package/src/components/row-actions-labels.ts +2 -0
  268. package/src/components/row-actions.tsx +154 -33
  269. package/src/components/section-nav.tsx +65 -0
  270. package/src/components/series-chart.tsx +12 -3
  271. package/src/components/share-card.tsx +1 -1
  272. package/src/components/signature-pad.tsx +1 -1
  273. package/src/components/sparkline.tsx +2 -1
  274. package/src/components/stat-tile.tsx +19 -7
  275. package/src/components/status-dot.tsx +7 -1
  276. package/src/components/tooltip.tsx +3 -1
  277. package/src/components/translation-review-editor.tsx +2 -2
  278. package/src/components/translation-review.tsx +2 -2
  279. package/src/components/treemap.tsx +34 -8
  280. package/src/components/use-table-state.ts +63 -8
  281. package/src/data-table.ts +5 -3
  282. package/src/demo/demo-banner.tsx +1 -1
  283. package/src/demo/demo-ended.tsx +1 -1
  284. package/src/demo/demo-start.tsx +1 -1
  285. package/src/feedback/feedback-inbox.tsx +1 -1
  286. package/src/hooks/use-anchored-panel.ts +9 -1
  287. package/src/hooks/use-dismiss.ts +43 -4
  288. package/src/hooks/use-document-title.ts +31 -0
  289. package/src/i18n/german.ts +4 -0
  290. package/src/i18n/kit-labels.tsx +76 -1
  291. package/src/i18n/locales/es.ts +4 -0
  292. package/src/i18n/locales/fr.ts +4 -0
  293. package/src/i18n/locales/hu.ts +4 -0
  294. package/src/i18n/locales/it.ts +4 -0
  295. package/src/i18n/locales/zh.ts +4 -0
  296. package/src/i18n/review.ts +2 -0
  297. package/src/i18n/shared-labels.ts +1 -0
  298. package/src/index.ts +13 -0
  299. package/src/landing/landing-actions.tsx +2 -2
  300. package/src/landing/public-header.tsx +2 -2
  301. package/src/lib/clipboard-minus.ts +94 -0
  302. package/src/lib/document-title.ts +41 -0
  303. package/src/lib/float-clearance.ts +19 -3
  304. package/src/lib/format.ts +115 -30
  305. package/src/lib/minus.ts +40 -0
  306. package/src/lib/status-tone.ts +43 -0
  307. package/src/settings/settings-layout.tsx +3 -2
  308. package/src/shell/account-menu-language.tsx +14 -2
  309. package/src/shell/app-shell-labels.ts +1 -0
  310. package/src/shell/app-shell.tsx +298 -69
  311. package/src/shell/language-code.ts +5 -0
  312. package/src/shell/topbar-controls.tsx +35 -15
  313. package/src/testing/css-variables.generated.ts +6 -6
  314. package/src/theme/chart-palette.ts +102 -20
  315. package/src/theme/palette-presets.ts +121 -84
  316. package/src/tour/tour.tsx +1 -1
  317. package/src/wizard/stepper-nav.tsx +4 -4
  318. package/tokens.css +28 -18
@@ -1,9 +1,45 @@
1
1
  "use client";
2
2
  import { contrastStep, rememberTokenSet } from "./contrast-tokens.js";
3
+ const IMPRINT_HUES = [
4
+ "#009e73",
5
+ // brand green — first series, always
6
+ "#c475fd",
7
+ // lavender — creative
8
+ "#4467a3",
9
+ // blue — cool / info
10
+ "#bd8233",
11
+ // ochre — earth / commodity
12
+ "#ae3030",
13
+ // matte red — bad / loss / error
14
+ "#2abccd",
15
+ // cyan — sky / tech-cool
16
+ "#954477",
17
+ // rose — wellness / health
18
+ "#99b314"
19
+ // lime — growth / nature
20
+ ];
21
+ const ANYPLOT_HEAT = {
22
+ light: {
23
+ neutral: "#faf8f1",
24
+ under: "#4467a3",
25
+ over: "#ae3030",
26
+ seqLow: "#009e73",
27
+ seqHigh: "#4467a3",
28
+ empty: "rgba(148,163,184,0.14)"
29
+ },
30
+ dark: {
31
+ neutral: "#1a1a17",
32
+ under: "#4467a3",
33
+ over: "#ae3030",
34
+ seqLow: "#009e73",
35
+ seqHigh: "#4467a3",
36
+ empty: "rgba(148,163,184,0.10)"
37
+ }
38
+ };
3
39
  const DEFAULT_PRESET = {
4
40
  id: "default",
5
- name: "Default",
6
- blurb: "Solar-dusk light \xB7 indigo-noir dark",
41
+ name: "Imprint",
42
+ blurb: "anyplot.ai chart hues \xB7 solar-dusk light \xB7 indigo-noir dark",
7
43
  light: {
8
44
  // Solar Dusk (light) surfaces, with the brand unified to indigo (see above).
9
45
  bgPage: "#ede3cf",
@@ -22,15 +58,8 @@ const DEFAULT_PRESET = {
22
58
  moneyExpense: "#905902",
23
59
  moneyNet: "#7a4fa3",
24
60
  moneyNeutral: "#6b6453",
25
- chart: ["#332288", "#88ccee", "#44aa99", "#117733", "#999933", "#ddcc77", "#cc6677", "#882255", "#aa4499"],
26
- heat: {
27
- neutral: "#f1e7d2",
28
- under: "#0b6650",
29
- over: "#9c6418",
30
- seqLow: "#f6ecd0",
31
- seqHigh: "#9c6418",
32
- empty: "rgba(148,163,184,0.14)"
33
- }
61
+ chart: IMPRINT_HUES,
62
+ heat: ANYPLOT_HEAT.light
34
63
  },
35
64
  dark: {
36
65
  // Indigo Noir (dark)
@@ -53,6 +82,28 @@ const DEFAULT_PRESET = {
53
82
  moneyExpense: "#e4b035",
54
83
  moneyNet: "#b39aef",
55
84
  moneyNeutral: "#9aa1bd",
85
+ chart: IMPRINT_HUES,
86
+ heat: ANYPLOT_HEAT.dark
87
+ }
88
+ };
89
+ const PAUL_TOL_PRESET = {
90
+ id: "paul-tol",
91
+ name: "Paul Tol muted",
92
+ blurb: "Paul Tol's CVD-safe chart hues \xB7 solar-dusk light \xB7 indigo-noir dark",
93
+ light: {
94
+ ...DEFAULT_PRESET.light,
95
+ chart: ["#332288", "#88ccee", "#44aa99", "#117733", "#999933", "#ddcc77", "#cc6677", "#882255", "#aa4499"],
96
+ heat: {
97
+ neutral: "#f1e7d2",
98
+ under: "#0b6650",
99
+ over: "#9c6418",
100
+ seqLow: "#f6ecd0",
101
+ seqHigh: "#9c6418",
102
+ empty: "rgba(148,163,184,0.14)"
103
+ }
104
+ },
105
+ dark: {
106
+ ...DEFAULT_PRESET.dark,
56
107
  chart: ["#7e72d6", "#9fd8f2", "#5fc4b0", "#3fa45f", "#bfbf5e", "#e8dda0", "#e08c9a", "#c25a78", "#cc78be"],
57
108
  heat: {
58
109
  neutral: "#363a5a",
@@ -64,47 +115,8 @@ const DEFAULT_PRESET = {
64
115
  }
65
116
  }
66
117
  };
67
- const IMPRINT_HUES_LIGHT = [
68
- "#009E73",
69
- // brand green — first series
70
- "#C475FD",
71
- // lavender — creative
72
- "#4467A3",
73
- // blue — cool / info
74
- "#BD8233",
75
- // ochre — earth / commodity
76
- "#AE3030",
77
- // matte red — bad / loss / error
78
- "#2ABCCD",
79
- // cyan — sky / tech-cool
80
- "#954477",
81
- // rose — wellness / health
82
- "#99B314",
83
- // lime — growth / nature
84
- "#DDCC77"
85
- // amber — anyplot's semantic anchor, used here as slot 9
86
- ];
87
- const IMPRINT_HUES_DARK = [
88
- "#009E73",
89
- "#C475FD",
90
- "#4467A3",
91
- "#BD8233",
92
- "#BF413E",
93
- // matte red, L-lifted for our dark surface
94
- "#2ABCCD",
95
- "#A25083",
96
- // rose, L-lifted for our dark surface
97
- "#99B314",
98
- "#DDCC77"
99
- ];
100
- const IMPRINT_PRESET = {
101
- id: "imprint",
102
- name: "Imprint",
103
- blurb: "Colourblind-safe chart hues by anyplot.ai",
104
- light: { ...DEFAULT_PRESET.light, chart: IMPRINT_HUES_LIGHT },
105
- dark: { ...DEFAULT_PRESET.dark, chart: IMPRINT_HUES_DARK }
106
- };
107
- const PAUL_TOL = {
118
+ const IMPRINT_PRESET = DEFAULT_PRESET;
119
+ const KIT_RAMP = {
108
120
  light: DEFAULT_PRESET.light.chart,
109
121
  dark: DEFAULT_PRESET.dark.chart
110
122
  };
@@ -128,7 +140,7 @@ const DERIVED_PRESETS = [
128
140
  moneyExpense: "#8e5900",
129
141
  moneyNet: "#7356a2",
130
142
  moneyNeutral: "#61646c",
131
- chart: PAUL_TOL.light,
143
+ chart: KIT_RAMP.light,
132
144
  heat: {
133
145
  neutral: "#dce2ef",
134
146
  under: "#00725f",
@@ -153,7 +165,7 @@ const DERIVED_PRESETS = [
153
165
  moneyExpense: "#b77b29",
154
166
  moneyNet: "#9679c9",
155
167
  moneyNeutral: "#a1a5ac",
156
- chart: PAUL_TOL.dark,
168
+ chart: KIT_RAMP.dark,
157
169
  heat: {
158
170
  neutral: "#1d212b",
159
171
  under: "#009a80",
@@ -183,7 +195,7 @@ const DERIVED_PRESETS = [
183
195
  moneyExpense: "#8e5900",
184
196
  moneyNet: "#7356a2",
185
197
  moneyNeutral: "#5f6662",
186
- chart: PAUL_TOL.light,
198
+ chart: KIT_RAMP.light,
187
199
  heat: {
188
200
  neutral: "#d8e6dd",
189
201
  under: "#00725f",
@@ -208,7 +220,7 @@ const DERIVED_PRESETS = [
208
220
  moneyExpense: "#b87c2a",
209
221
  moneyNet: "#977ac9",
210
222
  moneyNeutral: "#9fa7a2",
211
- chart: PAUL_TOL.dark,
223
+ chart: KIT_RAMP.dark,
212
224
  heat: {
213
225
  neutral: "#1a241e",
214
226
  under: "#009a80",
@@ -238,7 +250,7 @@ const DERIVED_PRESETS = [
238
250
  moneyExpense: "#8d5800",
239
251
  moneyNet: "#7355a2",
240
252
  moneyNeutral: "#676269",
241
- chart: PAUL_TOL.light,
253
+ chart: KIT_RAMP.light,
242
254
  heat: {
243
255
  neutral: "#e7dfea",
244
256
  under: "#00715e",
@@ -263,7 +275,7 @@ const DERIVED_PRESETS = [
263
275
  moneyExpense: "#b77b29",
264
276
  moneyNet: "#9679c9",
265
277
  moneyNeutral: "#a8a2aa",
266
- chart: PAUL_TOL.dark,
278
+ chart: KIT_RAMP.dark,
267
279
  heat: {
268
280
  neutral: "#251f27",
269
281
  under: "#009980",
@@ -293,7 +305,7 @@ const DERIVED_PRESETS = [
293
305
  moneyExpense: "#8d5800",
294
306
  moneyNet: "#7255a1",
295
307
  moneyNeutral: "#616467",
296
- chart: PAUL_TOL.light,
308
+ chart: KIT_RAMP.light,
297
309
  heat: {
298
310
  neutral: "#e1e2e3",
299
311
  under: "#00715e",
@@ -318,7 +330,7 @@ const DERIVED_PRESETS = [
318
330
  moneyExpense: "#b77b29",
319
331
  moneyNet: "#9679c9",
320
332
  moneyNeutral: "#a2a5a8",
321
- chart: PAUL_TOL.dark,
333
+ chart: KIT_RAMP.dark,
322
334
  heat: {
323
335
  neutral: "#212122",
324
336
  under: "#009a80",
@@ -330,7 +342,7 @@ const DERIVED_PRESETS = [
330
342
  }
331
343
  }
332
344
  ];
333
- const PALETTES = [DEFAULT_PRESET, IMPRINT_PRESET, ...DERIVED_PRESETS];
345
+ const PALETTES = [DEFAULT_PRESET, PAUL_TOL_PRESET, ...DERIVED_PRESETS];
334
346
  function presetById(id) {
335
347
  return PALETTES.find((p) => p.id === id) ?? DEFAULT_PRESET;
336
348
  }
@@ -353,13 +365,16 @@ function applyTokenSet(el, t, contrast = el.getAttribute("data-contrast") === "m
353
365
  el.style.setProperty("--money-expense", step?.well?.moneyExpense ?? t.moneyExpense);
354
366
  el.style.setProperty("--money-net", step?.well?.moneyNet ?? t.moneyNet);
355
367
  el.style.setProperty("--money-neutral", step?.well?.moneyNeutral ?? t.moneyNeutral);
356
- t.chart.forEach((c, i) => el.style.setProperty(`--chart-${i + 1}`, c));
368
+ if (t.chart.length > 0) {
369
+ for (let i = 0; i < 9; i++) el.style.setProperty(`--chart-${i + 1}`, t.chart[i % t.chart.length]);
370
+ }
357
371
  }
358
372
  export {
359
373
  DEFAULT_PRESET,
360
374
  DERIVED_PRESETS,
361
375
  IMPRINT_PRESET,
362
376
  PALETTES,
377
+ PAUL_TOL_PRESET,
363
378
  applyTokenSet,
364
379
  presetById
365
380
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/theme/palette-presets.ts"],"sourcesContent":["// Appearance presets — the single source of truth for the \"palette switcher\"\n// (feedback #307). Each preset is a full set of design-token values for BOTH\n// light and dark, covering the page/surface backgrounds, the brand accent, the\n// semantic money trio and the 9-colour categorical chart palette, plus the\n// heatmap stops. A preset is applied at runtime by writing these as CSS custom\n// properties onto <html> (see palette-store.ts), which instantly re-skins every\n// token-driven surface and chart. The two heatmaps and the treemap interpolate\n// concrete hex in JS, so they read the same values from here via the hooks in\n// palette-store.\n//\n// The default preset here mirrors the :root/.dark blocks in tokens.css exactly. The\n// five hand-picked alternatives of #307 (`ALTERNATIVE_PRESETS`, a reference bank that\n// `presetById` never resolved) were removed in 0.35 (refactor audit 2026-10, API-6c;\n// deprecated in 0.34): `PALETTES` is what an app offers, and `derivePalette` makes a\n// palette of its own.\n\nimport type { HeatStops } from \"./chart-palette\";\nimport { contrastStep, rememberTokenSet } from \"./contrast-tokens\";\n\nexport interface TokenSet {\n // Backgrounds & chrome\n bgPage: string;\n bgSurface: string;\n bgSurface2: string;\n border: string;\n textPrimary: string;\n // The two quieter text roles. Derived per preset by blending `textPrimary` toward\n // that preset's own surfaces until the contrast against the WORST of bgPage /\n // bgSurface / bgSurface2 hits 7:1 and 4.8:1 — so both clear WCAG AA for normal text\n // (4.5:1) on every surface they can land on, and both inherit the preset's warmth\n // instead of importing a cool grey from Tailwind's palette.\n textSecondary: string;\n textMuted: string;\n // Interactive brand accent\n brand: string;\n brandHover: string;\n brandContrast: string;\n // Semantic money (never red/green — CVD-safe, paired with +/- cues elsewhere)\n moneyIncome: string;\n moneyExpense: string;\n moneyNet: string;\n moneyNeutral: string;\n // Categorical chart series (Paul Tol \"Muted\" by default — CVD-safe), exactly 9\n chart: string[];\n // Heatmap interpolation stops (variance diverging + spending sequential)\n heat: HeatStops;\n}\n\nexport interface PalettePreset {\n id: string;\n name: string;\n blurb: string;\n light: TokenSet;\n dark: TokenSet;\n}\n\n// The shipped default (feedback #328): SOLAR-DUSK warm light + INDIGO-NOIR deep\n// dark surfaces — the two curated presets the user picked per mode — but with a\n// SINGLE unified brand accent (indigo) across both modes rather than each\n// preset's own accent (the user asked for the brand accent to stay the same).\n// So the light block is Solar Dusk with its teal brand overridden to indigo, and\n// the dark block is Indigo Noir (already indigo). The money trio\n// (income/expense/net) drives the chart bars and stays palette-driven so those\n// semantic colours adapt to each mode's contrast (best practice — feedback #328).\nexport const DEFAULT_PRESET: PalettePreset = {\n id: \"default\",\n name: \"Default\",\n blurb: \"Solar-dusk light · indigo-noir dark\",\n light: {\n // Solar Dusk (light) surfaces, with the brand unified to indigo (see above).\n bgPage: \"#ede3cf\",\n bgSurface: \"#f6ecd9\",\n // The well is the page in light (0.33, k26): #f3ead6 stood 1.02:1 from the card it\n // is inset in. Every light preset does the same; see SURFACE_L in palette-derive.ts.\n bgSurface2: \"#ede3cf\",\n border: \"#e2d6bd\",\n textPrimary: \"#463f33\",\n textSecondary: \"#50493c\",\n textMuted: \"#696153\",\n brand: \"#4f46e5\",\n brandHover: \"#4338ca\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#0b6650\",\n moneyExpense: \"#905902\",\n moneyNet: \"#7a4fa3\",\n moneyNeutral: \"#6b6453\",\n chart: [\"#332288\", \"#88ccee\", \"#44aa99\", \"#117733\", \"#999933\", \"#ddcc77\", \"#cc6677\", \"#882255\", \"#aa4499\"],\n heat: {\n neutral: \"#f1e7d2\",\n under: \"#0b6650\",\n over: \"#9c6418\",\n seqLow: \"#f6ecd0\",\n seqHigh: \"#9c6418\",\n empty: \"rgba(148,163,184,0.14)\",\n },\n },\n dark: {\n // Indigo Noir (dark)\n bgPage: \"#0e0f1c\",\n bgSurface: \"#181a2c\",\n bgSurface2: \"#21243a\",\n border: \"#2e3252\",\n textPrimary: \"#e6e8f4\",\n textSecondary: \"#adafbe\",\n textMuted: \"#8d90a0\",\n brand: \"#8b93f8\",\n brandHover: \"#aab1fb\",\n brandContrast: \"#16182b\",\n moneyIncome: \"#22c3b6\",\n // Amber-400 (#fbbf24) sat at OKLab L 0.84 while every other dark token lives\n // at 0.68–0.74, so outflows outshouted the inflows they are paired with. Same\n // hue and chroma, pulled to L 0.785 (dev#434). The heat stops below keep the\n // brighter amber on purpose: a gradient endpoint is meant to be the loudest\n // thing in its scale, and it is a fill, not a figure.\n moneyExpense: \"#e4b035\",\n moneyNet: \"#b39aef\",\n moneyNeutral: \"#9aa1bd\",\n chart: [\"#7e72d6\", \"#9fd8f2\", \"#5fc4b0\", \"#3fa45f\", \"#bfbf5e\", \"#e8dda0\", \"#e08c9a\", \"#c25a78\", \"#cc78be\"],\n heat: {\n neutral: \"#363a5a\",\n under: \"#22c3b6\",\n over: \"#fbbf24\",\n seqLow: \"#3a2c14\",\n seqHigh: \"#fbbf24\",\n empty: \"rgba(148,163,184,0.10)\",\n },\n },\n};\n\n// ── \"Imprint\" chart hues (feedback #119) ──────────────────────────────────────\n// anyplot's categorical palette (https://anyplot.ai/palette), by a colleague of\n// Marcel's. 8 hues + an amber semantic anchor, derived from Wong 2011 by a\n// Petroff-style max-min ΔE search in CAM02-UCS with Machado 2009 CVD simulation —\n// the same lineage as our default Paul Tol \"Muted\", one generation on, and tuned\n// for exactly the warm cream paper our light theme uses.\n//\n// This preset is DEFAULT_PRESET with ONLY the 9 categorical chart hues swapped;\n// surfaces, brand and the semantic money trio stay put, because those were their\n// own deliberate decisions (#307/#328) and are not what the palette is for. The\n// heatmap stops likewise stay teal/amber: they encode under/over, and imprint's\n// own diverging ramp is red↔blue, which would fight the money semantics.\n//\n// Measured on our surfaces (CIEDE2000, Machado severity-100, 8 like-for-like\n// slots on the cream light surface #f6ecd9) — neither palette dominates:\n// Paul Tol Muted min-contrast 1.38 · worst-CVD ΔE00 11.8 · normal ΔE00 16.1\n// imprint min-contrast 1.95 · worst-CVD ΔE00 7.2 · normal ΔE00 22.2\n// i.e. imprint is punchier and has no near-invisible pale slot (Tol's #88ccee\n// sits at 1.5:1 on cream), while Tol separates better under colour-vision\n// deficiency. So this ships as a CHOICE, not as a new default.\n//\n// The dark set keeps imprint's hues verbatim except matte-red and rose, whose\n// lightness is lifted (oklch L 0.50→0.55) because verbatim they land at 2.67:1\n// and 2.76:1 on our deep-indigo dark surface — under WCAG 2.1 SC 1.4.11's 3:1\n// non-text minimum. Lifted they clear it at 3.30:1 / 3.28:1. anyplot documents\n// the same shortfall on their own dark ground and answers it with a stroke halo;\n// lifting keeps the fix in the token layer instead of every chart component.\nconst IMPRINT_HUES_LIGHT = [\n \"#009E73\", // brand green — first series\n \"#C475FD\", // lavender — creative\n \"#4467A3\", // blue — cool / info\n \"#BD8233\", // ochre — earth / commodity\n \"#AE3030\", // matte red — bad / loss / error\n \"#2ABCCD\", // cyan — sky / tech-cool\n \"#954477\", // rose — wellness / health\n \"#99B314\", // lime — growth / nature\n \"#DDCC77\", // amber — anyplot's semantic anchor, used here as slot 9\n];\nconst IMPRINT_HUES_DARK = [\n \"#009E73\",\n \"#C475FD\",\n \"#4467A3\",\n \"#BD8233\",\n \"#BF413E\", // matte red, L-lifted for our dark surface\n \"#2ABCCD\",\n \"#A25083\", // rose, L-lifted for our dark surface\n \"#99B314\",\n \"#DDCC77\",\n];\n\nexport const IMPRINT_PRESET: PalettePreset = {\n id: \"imprint\",\n name: \"Imprint\",\n blurb: \"Colourblind-safe chart hues by anyplot.ai\",\n light: { ...DEFAULT_PRESET.light, chart: IMPRINT_HUES_LIGHT },\n dark: { ...DEFAULT_PRESET.dark, chart: IMPRINT_HUES_DARK },\n};\n\n// The full-theme switcher from #307 stayed retired (feedback #328) — the default\n// is still the single source of truth for surfaces, brand and money (its five\n// alternatives are gone, see the header). What IS selectable is\n// the categorical chart ramp (feedback #119), so these two presets are the live\n// set; presetById falls back to the default for any stale persisted id.\n/**\n * The categorical chart ramp, shared by every derived preset below.\n *\n * Paul Tol's \"Muted\" set, unchanged, and deliberately NOT re-derived per preset. A\n * categorical ramp solves a different problem from a UI palette — separability among\n * nine unknown siblings, rather than contrast against one known surface — and a set\n * optimised against real dichromat confusion lines beats one spaced evenly by formula.\n * `auditChartRamp` in palette-derive.ts measures it: 0.059 minimum separation in the\n * light variant, which is the number MIN_SEPARATION was calibrated under.\n *\n * It pays for that in contrast: four of the nine light hues sit below the 3:1 WCAG\n * 1.4.11 asks of a filled shape. That is not fixable by darkening them — see\n * SINGLE_LIGHTNESS_MAX_SERIES — so a chart with more than four series must carry a\n * second channel (a direct label, a pattern, a legend adjacent to the mark).\n */\nconst PAUL_TOL = {\n light: DEFAULT_PRESET.light.chart,\n dark: DEFAULT_PRESET.dark.chart,\n} as const;\n\n/**\n * Presets DERIVED rather than picked, by `derivePalette` from one brand colour each.\n *\n * Every text role here was solved to a contrast target against the worst of the three\n * surfaces it can land on, every semantic colour against both the page and its own badge\n * tint, and the whole set is re-checked by `__tests__/palette-audit.test.ts` (\"derived\n * presets\") — which re-runs the deriver and fails if these committed values drift from\n * what it now produces.\n *\n * They are committed rather than derived at import because deriving eight token sets\n * costs ~34ms, and charging every consumer that at startup for palettes most of them\n * will never select is the wrong trade. The test is what keeps the two in agreement.\n *\n * Regenerated in 0.34 (round 0.34 BUG-8): the solve now measures the hex it ships rather\n * than the float before rounding, and the audit no longer lets a hex pair pass 0.05 under\n * its threshold. 52 values moved one step (66 counting the heat stops that repeat them);\n * Contrast's neutrals lost half their slate tint, its brand having half the chroma at\n * which the neutrals carry a hue in full.\n */\nexport const DERIVED_PRESETS: PalettePreset[] = [\n {\n id: \"ink\",\n name: \"Ink\",\n blurb: \"Cool blue-grey ground · solved for AAA body text\",\n light: {\n bgPage: \"#dce2ef\",\n bgSurface: \"#e6edfa\",\n bgSurface2: \"#dce2ef\",\n border: \"#b0bace\",\n textPrimary: \"#2e3139\",\n textSecondary: \"#454850\",\n textMuted: \"#5f636c\",\n brand: \"#2f5fd0\",\n brandHover: \"#1f4cbc\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#00725f\",\n moneyExpense: \"#8e5900\",\n moneyNet: \"#7356a2\",\n moneyNeutral: \"#61646c\",\n chart: PAUL_TOL.light,\n heat: {\n neutral: \"#dce2ef\",\n under: \"#00725f\",\n over: \"#8e5900\",\n seqLow: \"#fee3c5\",\n seqHigh: \"#8e5900\",\n empty: \"rgba(120,110,95,0.14)\",\n },\n },\n dark: {\n bgPage: \"#090d15\",\n bgSurface: \"#131720\",\n bgSurface2: \"#1d212b\",\n border: \"#363e4f\",\n textPrimary: \"#c8ccd6\",\n textSecondary: \"#a7abb5\",\n textMuted: \"#858a92\",\n brand: \"#3466d7\",\n brandHover: \"#2353c3\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#009a80\",\n moneyExpense: \"#b77b29\",\n moneyNet: \"#9679c9\",\n moneyNeutral: \"#a1a5ac\",\n chart: PAUL_TOL.dark,\n heat: {\n neutral: \"#1d212b\",\n under: \"#009a80\",\n over: \"#b77b29\",\n seqLow: \"#331f05\",\n seqHigh: \"#b77b29\",\n empty: \"rgba(160,170,190,0.10)\",\n },\n },\n },\n {\n id: \"moss\",\n name: \"Moss\",\n blurb: \"Green ground · solved for AAA body text\",\n light: {\n bgPage: \"#d8e6dd\",\n bgSurface: \"#e3f1e8\",\n bgSurface2: \"#d8e6dd\",\n border: \"#abbfb2\",\n textPrimary: \"#2c332e\",\n textSecondary: \"#424b45\",\n textMuted: \"#5d6660\",\n brand: \"#2f7a52\",\n brandHover: \"#196842\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#00725f\",\n moneyExpense: \"#8e5900\",\n moneyNet: \"#7356a2\",\n moneyNeutral: \"#5f6662\",\n chart: PAUL_TOL.light,\n heat: {\n neutral: \"#d8e6dd\",\n under: \"#00725f\",\n over: \"#8e5900\",\n seqLow: \"#fee3c5\",\n seqHigh: \"#8e5900\",\n empty: \"rgba(120,110,95,0.14)\",\n },\n },\n dark: {\n bgPage: \"#060f0a\",\n bgSurface: \"#101a14\",\n bgSurface2: \"#1a241e\",\n border: \"#314337\",\n textPrimary: \"#c6cfc9\",\n textSecondary: \"#a5aea8\",\n textMuted: \"#838c86\",\n brand: \"#317b53\",\n brandHover: \"#1c6943\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#009a80\",\n moneyExpense: \"#b87c2a\",\n moneyNet: \"#977ac9\",\n moneyNeutral: \"#9fa7a2\",\n chart: PAUL_TOL.dark,\n heat: {\n neutral: \"#1a241e\",\n under: \"#009a80\",\n over: \"#b87c2a\",\n seqLow: \"#331f05\",\n seqHigh: \"#b87c2a\",\n empty: \"rgba(160,170,190,0.10)\",\n },\n },\n },\n {\n id: \"plum\",\n name: \"Plum\",\n blurb: \"Violet ground · solved for AAA body text\",\n light: {\n bgPage: \"#e7dfea\",\n bgSurface: \"#f2e9f5\",\n bgSurface2: \"#e7dfea\",\n border: \"#c2b5c6\",\n textPrimary: \"#352f36\",\n textSecondary: \"#4c464e\",\n textMuted: \"#676169\",\n brand: \"#7b3f8f\",\n brandHover: \"#692d7d\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#00715e\",\n moneyExpense: \"#8d5800\",\n moneyNet: \"#7355a2\",\n moneyNeutral: \"#676269\",\n chart: PAUL_TOL.light,\n heat: {\n neutral: \"#e7dfea\",\n under: \"#00715e\",\n over: \"#8d5800\",\n seqLow: \"#fee3c5\",\n seqHigh: \"#8d5800\",\n empty: \"rgba(120,110,95,0.14)\",\n },\n },\n dark: {\n bgPage: \"#100b12\",\n bgSurface: \"#1b151d\",\n bgSurface2: \"#251f27\",\n border: \"#453b48\",\n textPrimary: \"#d0cad2\",\n textSecondary: \"#afa9b1\",\n textMuted: \"#8d8790\",\n brand: \"#9154a6\",\n brandHover: \"#7f4293\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#009980\",\n moneyExpense: \"#b77b29\",\n moneyNet: \"#9679c9\",\n moneyNeutral: \"#a8a2aa\",\n chart: PAUL_TOL.dark,\n heat: {\n neutral: \"#251f27\",\n under: \"#009980\",\n over: \"#b77b29\",\n seqLow: \"#331f05\",\n seqHigh: \"#b77b29\",\n empty: \"rgba(160,170,190,0.10)\",\n },\n },\n },\n {\n id: \"contrast\",\n name: \"High contrast\",\n blurb: \"Near-neutral ground · text solved to 13:1 / 8.5:1 / 5.5:1\",\n light: {\n bgPage: \"#e1e2e3\",\n bgSurface: \"#ecedee\",\n bgSurface2: \"#e1e2e3\",\n border: \"#b8babc\",\n textPrimary: \"#1b1d21\",\n textSecondary: \"#3a3c40\",\n textMuted: \"#55585c\",\n brand: \"#1f2937\",\n brandHover: \"#111b28\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#00715e\",\n moneyExpense: \"#8d5800\",\n moneyNet: \"#7255a1\",\n moneyNeutral: \"#616467\",\n chart: PAUL_TOL.light,\n heat: {\n neutral: \"#e1e2e3\",\n under: \"#00715e\",\n over: \"#8d5800\",\n seqLow: \"#fee3c5\",\n seqHigh: \"#8d5800\",\n empty: \"rgba(120,110,95,0.14)\",\n },\n },\n dark: {\n bgPage: \"#0c0d0e\",\n bgSurface: \"#171718\",\n bgSurface2: \"#212122\",\n border: \"#3d3e3f\",\n textPrimary: \"#e4e8ec\",\n textSecondary: \"#b9bdc1\",\n textMuted: \"#95979c\",\n brand: \"#556c8e\",\n brandHover: \"#455b7c\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#009a80\",\n moneyExpense: \"#b77b29\",\n moneyNet: \"#9679c9\",\n moneyNeutral: \"#a2a5a8\",\n chart: PAUL_TOL.dark,\n heat: {\n neutral: \"#212122\",\n under: \"#009a80\",\n over: \"#b77b29\",\n seqLow: \"#331f05\",\n seqHigh: \"#b77b29\",\n empty: \"rgba(160,170,190,0.10)\",\n },\n },\n },\n];\n\nexport const PALETTES: PalettePreset[] = [DEFAULT_PRESET, IMPRINT_PRESET, ...DERIVED_PRESETS];\n\nexport function presetById(id: string): PalettePreset {\n return PALETTES.find((p) => p.id === id) ?? DEFAULT_PRESET;\n}\n\n/**\n * Write a token set onto an element's inline style as CSS custom properties.\n *\n * This is the only writer, and there is no un-writer: `presetById` falls back to\n * `DEFAULT_PRESET` and this then writes the full set, so returning to the default\n * APPLIES it rather than clearing anything. A `clearTokenSet` and the hand-kept\n * 24-name `TOKEN_VARS` list it looped over used to live here, both exported, both\n * called by nobody in either consumer — a second copy of these property names with\n * nothing comparing the two, so adding a token here and forgetting it there would\n * have been silent and only a dead function would have noticed. The list is gone;\n * the test beside this asserts instead that every field of a `TokenSet` reaches the\n * element, which is what that list was standing in for.\n *\n * **More contrast (0.32, docs/text-size-harmonization.md §5, §10.5).** With `contrast`\n * the text and border tokens are written one step stronger — in a light set the well and\n * the four money colours too (0.36, docs/colour-roles-harmonization.md §13) — and `--text-placeholder` —\n * otherwise derived in tokens.css — is written inline too; without it that inline\n * placeholder is removed again, so the stylesheet's formula applies. The step is made\n * HERE because these tokens are inline: no `[data-contrast=more]` rule could beat them.\n *\n * `contrast` defaults to the element's own `data-contrast=\"more\"`, which the contrast\n * layer (`applyContrast`, `useApplyContrast`) sets first. That is how the palette and the\n * contrast cooperate without knowing each other: a palette change re-applies through\n * here and keeps the contrast, and a contrast change re-applies the set remembered here.\n */\nexport function applyTokenSet(\n el: HTMLElement,\n t: TokenSet,\n contrast: boolean = el.getAttribute(\"data-contrast\") === \"more\",\n): void {\n rememberTokenSet(el, t);\n const step = contrast ? contrastStep(t) : null;\n el.style.setProperty(\"--bg-page\", t.bgPage);\n el.style.setProperty(\"--bg-surface\", t.bgSurface);\n // The light well and money step under More contrast (0.36, colour-roles §13); in dark\n // and at Standard `well` is null and the set's own are written.\n el.style.setProperty(\"--bg-surface-2\", step?.well?.bgSurface2 ?? t.bgSurface2);\n el.style.setProperty(\"--border\", step?.border ?? t.border);\n el.style.setProperty(\"--text-primary\", t.textPrimary);\n el.style.setProperty(\"--text-secondary\", step?.textSecondary ?? t.textSecondary);\n el.style.setProperty(\"--text-muted\", step?.textMuted ?? t.textMuted);\n if (step) el.style.setProperty(\"--text-placeholder\", step.textPlaceholder);\n else el.style.removeProperty(\"--text-placeholder\");\n el.style.setProperty(\"--brand\", t.brand);\n el.style.setProperty(\"--brand-hover\", t.brandHover);\n el.style.setProperty(\"--brand-contrast\", t.brandContrast);\n el.style.setProperty(\"--money-income\", step?.well?.moneyIncome ?? t.moneyIncome);\n el.style.setProperty(\"--money-expense\", step?.well?.moneyExpense ?? t.moneyExpense);\n el.style.setProperty(\"--money-net\", step?.well?.moneyNet ?? t.moneyNet);\n el.style.setProperty(\"--money-neutral\", step?.well?.moneyNeutral ?? t.moneyNeutral);\n t.chart.forEach((c, i) => el.style.setProperty(`--chart-${i + 1}`, c));\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/theme/palette-presets.ts"],"sourcesContent":["// Appearance presets — the single source of truth for the \"palette switcher\"\n// (feedback #307). Each preset is a full set of design-token values for BOTH\n// light and dark, covering the page/surface backgrounds, the brand accent, the\n// semantic money trio and the categorical chart palette (anyplot's eight \"Imprint\"\n// hues by default since 0.49, Paul Tol's nine in `PAUL_TOL_PRESET`), plus the\n// heatmap stops. A preset is applied at runtime by writing these as CSS custom\n// properties onto <html> (see palette-store.ts), which instantly re-skins every\n// token-driven surface and chart. The two heatmaps and the treemap interpolate\n// concrete hex in JS, so they read the same values from here via the hooks in\n// palette-store.\n//\n// The default preset here mirrors the :root/.dark blocks in tokens.css exactly. The\n// five hand-picked alternatives of #307 (`ALTERNATIVE_PRESETS`, a reference bank that\n// `presetById` never resolved) were removed in 0.35 (refactor audit 2026-10, API-6c;\n// deprecated in 0.34): `PALETTES` is what an app offers, and `derivePalette` makes a\n// palette of its own.\n\nimport type { HeatStops } from \"./chart-palette\";\nimport { contrastStep, rememberTokenSet } from \"./contrast-tokens\";\n\nexport interface TokenSet {\n // Backgrounds & chrome\n bgPage: string;\n bgSurface: string;\n bgSurface2: string;\n border: string;\n textPrimary: string;\n // The two quieter text roles. Derived per preset by blending `textPrimary` toward\n // that preset's own surfaces until the contrast against the WORST of bgPage /\n // bgSurface / bgSurface2 hits 7:1 and 4.8:1 — so both clear WCAG AA for normal text\n // (4.5:1) on every surface they can land on, and both inherit the preset's warmth\n // instead of importing a cool grey from Tailwind's palette.\n textSecondary: string;\n textMuted: string;\n // Interactive brand accent\n brand: string;\n brandHover: string;\n brandContrast: string;\n // Semantic money (never red/green — CVD-safe, paired with +/- cues elsewhere)\n moneyIncome: string;\n moneyExpense: string;\n moneyNet: string;\n moneyNeutral: string;\n // Categorical chart series, written as `--chart-1…9`. anyplot's eight \"Imprint\" hues by\n // default (0.49), Paul Tol \"Muted\"'s nine in `PAUL_TOL_PRESET`. `paletteFor` cycles\n // eight; a shorter ramp is repeated to fill `--chart-9` (see `applyTokenSet`).\n chart: string[];\n // Heatmap interpolation stops (variance diverging + spending sequential)\n heat: HeatStops;\n}\n\nexport interface PalettePreset {\n id: string;\n name: string;\n blurb: string;\n light: TokenSet;\n dark: TokenSet;\n}\n\n// ── \"Imprint\" chart hues (feedback #119; the default since 0.49) ─────────────\n// anyplot's categorical palette (https://anyplot.ai/palette), by a colleague of\n// Marcel's. 8 hues + an amber semantic anchor, derived from Wong 2011 by a\n// Petroff-style max-min ΔE search in CAM02-UCS with Machado 2009 CVD simulation —\n// the same lineage as Paul Tol \"Muted\", one generation on, and tuned for exactly the\n// warm cream paper our light theme uses.\n//\n// 0.49 (Marcel, 2026-10-22): the DEFAULT, in anyplot's slot order, eight slots — amber\n// #DDCC77 left the pool, it is anyplot's semantic warning anchor, not a series colour.\n// The SAME hues in both themes: 0.48 lifted matte red and rose for the dark ground\n// (#BF413E, #A25083), which made the dark chart a different palette from the light one.\n// anyplot answers a hue under 3:1 with a 1px ink edge instead, and so does the kit now\n// (`chartEdge`, drawn by SeriesChart's bars and areas and by Treemap's tiles).\n//\n// Measured on our surfaces (CIEDE2000, Machado severity-100, 8 like-for-like slots on\n// the cream light surface #f6ecd9) — neither palette dominates:\n// Paul Tol Muted min-contrast 1.38 · worst-CVD ΔE00 11.8 · normal ΔE00 16.1\n// imprint min-contrast 1.95 · worst-CVD ΔE00 7.2 · normal ΔE00 22.2\n// i.e. imprint is punchier and has no near-invisible pale slot (Tol's #88ccee sits at\n// 1.5:1 on cream), while Tol separates better under colour-vision deficiency — which is\n// why `paletteFor` offers anyplot's CVD-optimal order (`{ order: \"cvd\" }`).\nconst IMPRINT_HUES = [\n \"#009e73\", // brand green — first series, always\n \"#c475fd\", // lavender — creative\n \"#4467a3\", // blue — cool / info\n \"#bd8233\", // ochre — earth / commodity\n \"#ae3030\", // matte red — bad / loss / error\n \"#2abccd\", // cyan — sky / tech-cool\n \"#954477\", // rose — wellness / health\n \"#99b314\", // lime — growth / nature\n];\n\n/** anyplot's scales (0.49): sequential green → blue, diverging blue (under) ↔ paper or\n * ink (0) ↔ matte red (over). `chart-palette.ts`'s `HEATMAP_HEX` holds the same. */\nconst ANYPLOT_HEAT: Record<\"light\" | \"dark\", HeatStops> = {\n light: {\n neutral: \"#faf8f1\",\n under: \"#4467a3\",\n over: \"#ae3030\",\n seqLow: \"#009e73\",\n seqHigh: \"#4467a3\",\n empty: \"rgba(148,163,184,0.14)\",\n },\n dark: {\n neutral: \"#1a1a17\",\n under: \"#4467a3\",\n over: \"#ae3030\",\n seqLow: \"#009e73\",\n seqHigh: \"#4467a3\",\n empty: \"rgba(148,163,184,0.10)\",\n },\n};\n\n// The shipped default (feedback #328): SOLAR-DUSK warm light + INDIGO-NOIR deep\n// dark surfaces — the two curated presets the user picked per mode — but with a\n// SINGLE unified brand accent (indigo) across both modes rather than each\n// preset's own accent (the user asked for the brand accent to stay the same).\n// So the light block is Solar Dusk with its teal brand overridden to indigo, and\n// the dark block is Indigo Noir (already indigo). The money trio\n// (income/expense/net) drives the chart bars and stays palette-driven so those\n// semantic colours adapt to each mode's contrast (best practice — feedback #328).\n//\n// 0.49: its chart ramp and heat stops are anyplot's (\"Imprint\", above) — the money\n// trio stays the kit's own (Marcel, 2026-10-22: chart income/expense/net/neutral keep\n// the money tokens, never anyplot's green/red). The 0.48 default, the same surfaces\n// with Paul Tol's ramp, is `PAUL_TOL_PRESET`.\nexport const DEFAULT_PRESET: PalettePreset = {\n id: \"default\",\n name: \"Imprint\",\n blurb: \"anyplot.ai chart hues · solar-dusk light · indigo-noir dark\",\n light: {\n // Solar Dusk (light) surfaces, with the brand unified to indigo (see above).\n bgPage: \"#ede3cf\",\n bgSurface: \"#f6ecd9\",\n // The well is the page in light (0.33, k26): #f3ead6 stood 1.02:1 from the card it\n // is inset in. Every light preset does the same; see SURFACE_L in palette-derive.ts.\n bgSurface2: \"#ede3cf\",\n border: \"#e2d6bd\",\n textPrimary: \"#463f33\",\n textSecondary: \"#50493c\",\n textMuted: \"#696153\",\n brand: \"#4f46e5\",\n brandHover: \"#4338ca\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#0b6650\",\n moneyExpense: \"#905902\",\n moneyNet: \"#7a4fa3\",\n moneyNeutral: \"#6b6453\",\n chart: IMPRINT_HUES,\n heat: ANYPLOT_HEAT.light,\n },\n dark: {\n // Indigo Noir (dark)\n bgPage: \"#0e0f1c\",\n bgSurface: \"#181a2c\",\n bgSurface2: \"#21243a\",\n border: \"#2e3252\",\n textPrimary: \"#e6e8f4\",\n textSecondary: \"#adafbe\",\n textMuted: \"#8d90a0\",\n brand: \"#8b93f8\",\n brandHover: \"#aab1fb\",\n brandContrast: \"#16182b\",\n moneyIncome: \"#22c3b6\",\n // Amber-400 (#fbbf24) sat at OKLab L 0.84 while every other dark token lives\n // at 0.68–0.74, so outflows outshouted the inflows they are paired with. Same\n // hue and chroma, pulled to L 0.785 (dev#434). The heat stops below keep the\n // brighter amber on purpose: a gradient endpoint is meant to be the loudest\n // thing in its scale, and it is a fill, not a figure.\n moneyExpense: \"#e4b035\",\n moneyNet: \"#b39aef\",\n moneyNeutral: \"#9aa1bd\",\n chart: IMPRINT_HUES,\n heat: ANYPLOT_HEAT.dark,\n },\n};\n\n\n/**\n * The 0.48 default: the same surfaces, brand and money, with Paul Tol's \"Muted\" nine\n * as the chart ramp and the teal/amber heat stops that went with it. Selectable, no\n * longer the default (0.49). `paletteFor` cycles eight, so its ninth hue (#aa4499) is\n * reachable only as `var(--chart-9)`.\n */\nexport const PAUL_TOL_PRESET: PalettePreset = {\n id: \"paul-tol\",\n name: \"Paul Tol muted\",\n blurb: \"Paul Tol's CVD-safe chart hues · solar-dusk light · indigo-noir dark\",\n light: {\n ...DEFAULT_PRESET.light,\n chart: [\"#332288\", \"#88ccee\", \"#44aa99\", \"#117733\", \"#999933\", \"#ddcc77\", \"#cc6677\", \"#882255\", \"#aa4499\"],\n heat: {\n neutral: \"#f1e7d2\",\n under: \"#0b6650\",\n over: \"#9c6418\",\n seqLow: \"#f6ecd0\",\n seqHigh: \"#9c6418\",\n empty: \"rgba(148,163,184,0.14)\",\n },\n },\n dark: {\n ...DEFAULT_PRESET.dark,\n chart: [\"#7e72d6\", \"#9fd8f2\", \"#5fc4b0\", \"#3fa45f\", \"#bfbf5e\", \"#e8dda0\", \"#e08c9a\", \"#c25a78\", \"#cc78be\"],\n heat: {\n neutral: \"#363a5a\",\n under: \"#22c3b6\",\n over: \"#fbbf24\",\n seqLow: \"#3a2c14\",\n seqHigh: \"#fbbf24\",\n empty: \"rgba(148,163,184,0.10)\",\n },\n },\n};\n\n/** @deprecated 0.49 — use `DEFAULT_PRESET` (Imprint IS the default now); removed in 0.51.\n * A persisted `\"imprint\"` id resolves to it through `presetById`'s fallback. */\nexport const IMPRINT_PRESET: PalettePreset = DEFAULT_PRESET;\n\n// The full-theme switcher from #307 stayed retired (feedback #328) — the default\n// is still the single source of truth for surfaces, brand and money (its five\n// alternatives are gone, see the header). What IS selectable is\n// the categorical chart ramp (feedback #119), so Imprint (the default) and Paul Tol are\n// the live set; presetById falls back to the default for any stale persisted id.\n/**\n * The categorical chart ramp, shared by every derived preset below.\n *\n * The default's ramp (anyplot's eight since 0.49, Paul Tol's \"Muted\" before), and\n * deliberately NOT re-derived per preset. A\n * categorical ramp solves a different problem from a UI palette — separability among\n * nine unknown siblings, rather than contrast against one known surface — and a set\n * optimised against real dichromat confusion lines beats one spaced evenly by formula.\n * `auditChartRamp` in palette-derive.ts measures it: 0.059 minimum separation in the\n * light variant, which is the number MIN_SEPARATION was calibrated under.\n *\n * It pays for that in contrast: four of the nine light hues sit below the 3:1 WCAG\n * 1.4.11 asks of a filled shape. That is not fixable by darkening them — see\n * SINGLE_LIGHTNESS_MAX_SERIES — so a chart with more than four series must carry a\n * second channel (a direct label, a pattern, a legend adjacent to the mark).\n */\nconst KIT_RAMP = {\n light: DEFAULT_PRESET.light.chart,\n dark: DEFAULT_PRESET.dark.chart,\n} as const;\n\n/**\n * Presets DERIVED rather than picked, by `derivePalette` from one brand colour each.\n *\n * Every text role here was solved to a contrast target against the worst of the three\n * surfaces it can land on, every semantic colour against both the page and its own badge\n * tint, and the whole set is re-checked by `__tests__/palette-audit.test.ts` (\"derived\n * presets\") — which re-runs the deriver and fails if these committed values drift from\n * what it now produces.\n *\n * They are committed rather than derived at import because deriving eight token sets\n * costs ~34ms, and charging every consumer that at startup for palettes most of them\n * will never select is the wrong trade. The test is what keeps the two in agreement.\n *\n * Regenerated in 0.34 (round 0.34 BUG-8): the solve now measures the hex it ships rather\n * than the float before rounding, and the audit no longer lets a hex pair pass 0.05 under\n * its threshold. 52 values moved one step (66 counting the heat stops that repeat them);\n * Contrast's neutrals lost half their slate tint, its brand having half the chroma at\n * which the neutrals carry a hue in full.\n */\nexport const DERIVED_PRESETS: PalettePreset[] = [\n {\n id: \"ink\",\n name: \"Ink\",\n blurb: \"Cool blue-grey ground · solved for AAA body text\",\n light: {\n bgPage: \"#dce2ef\",\n bgSurface: \"#e6edfa\",\n bgSurface2: \"#dce2ef\",\n border: \"#b0bace\",\n textPrimary: \"#2e3139\",\n textSecondary: \"#454850\",\n textMuted: \"#5f636c\",\n brand: \"#2f5fd0\",\n brandHover: \"#1f4cbc\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#00725f\",\n moneyExpense: \"#8e5900\",\n moneyNet: \"#7356a2\",\n moneyNeutral: \"#61646c\",\n chart: KIT_RAMP.light,\n heat: {\n neutral: \"#dce2ef\",\n under: \"#00725f\",\n over: \"#8e5900\",\n seqLow: \"#fee3c5\",\n seqHigh: \"#8e5900\",\n empty: \"rgba(120,110,95,0.14)\",\n },\n },\n dark: {\n bgPage: \"#090d15\",\n bgSurface: \"#131720\",\n bgSurface2: \"#1d212b\",\n border: \"#363e4f\",\n textPrimary: \"#c8ccd6\",\n textSecondary: \"#a7abb5\",\n textMuted: \"#858a92\",\n brand: \"#3466d7\",\n brandHover: \"#2353c3\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#009a80\",\n moneyExpense: \"#b77b29\",\n moneyNet: \"#9679c9\",\n moneyNeutral: \"#a1a5ac\",\n chart: KIT_RAMP.dark,\n heat: {\n neutral: \"#1d212b\",\n under: \"#009a80\",\n over: \"#b77b29\",\n seqLow: \"#331f05\",\n seqHigh: \"#b77b29\",\n empty: \"rgba(160,170,190,0.10)\",\n },\n },\n },\n {\n id: \"moss\",\n name: \"Moss\",\n blurb: \"Green ground · solved for AAA body text\",\n light: {\n bgPage: \"#d8e6dd\",\n bgSurface: \"#e3f1e8\",\n bgSurface2: \"#d8e6dd\",\n border: \"#abbfb2\",\n textPrimary: \"#2c332e\",\n textSecondary: \"#424b45\",\n textMuted: \"#5d6660\",\n brand: \"#2f7a52\",\n brandHover: \"#196842\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#00725f\",\n moneyExpense: \"#8e5900\",\n moneyNet: \"#7356a2\",\n moneyNeutral: \"#5f6662\",\n chart: KIT_RAMP.light,\n heat: {\n neutral: \"#d8e6dd\",\n under: \"#00725f\",\n over: \"#8e5900\",\n seqLow: \"#fee3c5\",\n seqHigh: \"#8e5900\",\n empty: \"rgba(120,110,95,0.14)\",\n },\n },\n dark: {\n bgPage: \"#060f0a\",\n bgSurface: \"#101a14\",\n bgSurface2: \"#1a241e\",\n border: \"#314337\",\n textPrimary: \"#c6cfc9\",\n textSecondary: \"#a5aea8\",\n textMuted: \"#838c86\",\n brand: \"#317b53\",\n brandHover: \"#1c6943\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#009a80\",\n moneyExpense: \"#b87c2a\",\n moneyNet: \"#977ac9\",\n moneyNeutral: \"#9fa7a2\",\n chart: KIT_RAMP.dark,\n heat: {\n neutral: \"#1a241e\",\n under: \"#009a80\",\n over: \"#b87c2a\",\n seqLow: \"#331f05\",\n seqHigh: \"#b87c2a\",\n empty: \"rgba(160,170,190,0.10)\",\n },\n },\n },\n {\n id: \"plum\",\n name: \"Plum\",\n blurb: \"Violet ground · solved for AAA body text\",\n light: {\n bgPage: \"#e7dfea\",\n bgSurface: \"#f2e9f5\",\n bgSurface2: \"#e7dfea\",\n border: \"#c2b5c6\",\n textPrimary: \"#352f36\",\n textSecondary: \"#4c464e\",\n textMuted: \"#676169\",\n brand: \"#7b3f8f\",\n brandHover: \"#692d7d\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#00715e\",\n moneyExpense: \"#8d5800\",\n moneyNet: \"#7355a2\",\n moneyNeutral: \"#676269\",\n chart: KIT_RAMP.light,\n heat: {\n neutral: \"#e7dfea\",\n under: \"#00715e\",\n over: \"#8d5800\",\n seqLow: \"#fee3c5\",\n seqHigh: \"#8d5800\",\n empty: \"rgba(120,110,95,0.14)\",\n },\n },\n dark: {\n bgPage: \"#100b12\",\n bgSurface: \"#1b151d\",\n bgSurface2: \"#251f27\",\n border: \"#453b48\",\n textPrimary: \"#d0cad2\",\n textSecondary: \"#afa9b1\",\n textMuted: \"#8d8790\",\n brand: \"#9154a6\",\n brandHover: \"#7f4293\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#009980\",\n moneyExpense: \"#b77b29\",\n moneyNet: \"#9679c9\",\n moneyNeutral: \"#a8a2aa\",\n chart: KIT_RAMP.dark,\n heat: {\n neutral: \"#251f27\",\n under: \"#009980\",\n over: \"#b77b29\",\n seqLow: \"#331f05\",\n seqHigh: \"#b77b29\",\n empty: \"rgba(160,170,190,0.10)\",\n },\n },\n },\n {\n id: \"contrast\",\n name: \"High contrast\",\n blurb: \"Near-neutral ground · text solved to 13:1 / 8.5:1 / 5.5:1\",\n light: {\n bgPage: \"#e1e2e3\",\n bgSurface: \"#ecedee\",\n bgSurface2: \"#e1e2e3\",\n border: \"#b8babc\",\n textPrimary: \"#1b1d21\",\n textSecondary: \"#3a3c40\",\n textMuted: \"#55585c\",\n brand: \"#1f2937\",\n brandHover: \"#111b28\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#00715e\",\n moneyExpense: \"#8d5800\",\n moneyNet: \"#7255a1\",\n moneyNeutral: \"#616467\",\n chart: KIT_RAMP.light,\n heat: {\n neutral: \"#e1e2e3\",\n under: \"#00715e\",\n over: \"#8d5800\",\n seqLow: \"#fee3c5\",\n seqHigh: \"#8d5800\",\n empty: \"rgba(120,110,95,0.14)\",\n },\n },\n dark: {\n bgPage: \"#0c0d0e\",\n bgSurface: \"#171718\",\n bgSurface2: \"#212122\",\n border: \"#3d3e3f\",\n textPrimary: \"#e4e8ec\",\n textSecondary: \"#b9bdc1\",\n textMuted: \"#95979c\",\n brand: \"#556c8e\",\n brandHover: \"#455b7c\",\n brandContrast: \"#ffffff\",\n moneyIncome: \"#009a80\",\n moneyExpense: \"#b77b29\",\n moneyNet: \"#9679c9\",\n moneyNeutral: \"#a2a5a8\",\n chart: KIT_RAMP.dark,\n heat: {\n neutral: \"#212122\",\n under: \"#009a80\",\n over: \"#b77b29\",\n seqLow: \"#331f05\",\n seqHigh: \"#b77b29\",\n empty: \"rgba(160,170,190,0.10)\",\n },\n },\n },\n];\n\nexport const PALETTES: PalettePreset[] = [DEFAULT_PRESET, PAUL_TOL_PRESET, ...DERIVED_PRESETS];\n\nexport function presetById(id: string): PalettePreset {\n return PALETTES.find((p) => p.id === id) ?? DEFAULT_PRESET;\n}\n\n/**\n * Write a token set onto an element's inline style as CSS custom properties.\n *\n * This is the only writer, and there is no un-writer: `presetById` falls back to\n * `DEFAULT_PRESET` and this then writes the full set, so returning to the default\n * APPLIES it rather than clearing anything. A `clearTokenSet` and the hand-kept\n * 24-name `TOKEN_VARS` list it looped over used to live here, both exported, both\n * called by nobody in either consumer — a second copy of these property names with\n * nothing comparing the two, so adding a token here and forgetting it there would\n * have been silent and only a dead function would have noticed. The list is gone;\n * the test beside this asserts instead that every field of a `TokenSet` reaches the\n * element, which is what that list was standing in for.\n *\n * **More contrast (0.32, docs/text-size-harmonization.md §5, §10.5).** With `contrast`\n * the text and border tokens are written one step stronger — in a light set the well and\n * the four money colours too (0.36, docs/colour-roles-harmonization.md §13) — and `--text-placeholder` —\n * otherwise derived in tokens.css — is written inline too; without it that inline\n * placeholder is removed again, so the stylesheet's formula applies. The step is made\n * HERE because these tokens are inline: no `[data-contrast=more]` rule could beat them.\n *\n * `contrast` defaults to the element's own `data-contrast=\"more\"`, which the contrast\n * layer (`applyContrast`, `useApplyContrast`) sets first. That is how the palette and the\n * contrast cooperate without knowing each other: a palette change re-applies through\n * here and keeps the contrast, and a contrast change re-applies the set remembered here.\n */\nexport function applyTokenSet(\n el: HTMLElement,\n t: TokenSet,\n contrast: boolean = el.getAttribute(\"data-contrast\") === \"more\",\n): void {\n rememberTokenSet(el, t);\n const step = contrast ? contrastStep(t) : null;\n el.style.setProperty(\"--bg-page\", t.bgPage);\n el.style.setProperty(\"--bg-surface\", t.bgSurface);\n // The light well and money step under More contrast (0.36, colour-roles §13); in dark\n // and at Standard `well` is null and the set's own are written.\n el.style.setProperty(\"--bg-surface-2\", step?.well?.bgSurface2 ?? t.bgSurface2);\n el.style.setProperty(\"--border\", step?.border ?? t.border);\n el.style.setProperty(\"--text-primary\", t.textPrimary);\n el.style.setProperty(\"--text-secondary\", step?.textSecondary ?? t.textSecondary);\n el.style.setProperty(\"--text-muted\", step?.textMuted ?? t.textMuted);\n if (step) el.style.setProperty(\"--text-placeholder\", step.textPlaceholder);\n else el.style.removeProperty(\"--text-placeholder\");\n el.style.setProperty(\"--brand\", t.brand);\n el.style.setProperty(\"--brand-hover\", t.brandHover);\n el.style.setProperty(\"--brand-contrast\", t.brandContrast);\n el.style.setProperty(\"--money-income\", step?.well?.moneyIncome ?? t.moneyIncome);\n el.style.setProperty(\"--money-expense\", step?.well?.moneyExpense ?? t.moneyExpense);\n el.style.setProperty(\"--money-net\", step?.well?.moneyNet ?? t.moneyNet);\n el.style.setProperty(\"--money-neutral\", step?.well?.moneyNeutral ?? t.moneyNeutral);\n // All nine `--chart-N`, a shorter ramp repeated: Imprint's eight write `--chart-9` as\n // slot 0 — what `paletteFor(8)` names — so a host addressing `var(--chart-9)` directly\n // follows the cycle, and switching away from Paul Tol's nine leaves no stale ninth hue.\n // An empty ramp (a `derivePalette` set) leaves whatever was there, deliberately.\n if (t.chart.length > 0) {\n for (let i = 0; i < 9; i++) el.style.setProperty(`--chart-${i + 1}`, t.chart[i % t.chart.length]);\n }\n}\n"],"mappings":";AAkBA,SAAS,cAAc,wBAAwB;AA8D/C,MAAM,eAAe;AAAA,EACnB;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAIA,MAAM,eAAoD;AAAA,EACxD,OAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AACF;AAeO,MAAM,iBAAgC;AAAA,EAC3C,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA;AAAA,IAEL,QAAQ;AAAA,IACR,WAAW;AAAA;AAAA;AAAA,IAGX,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,cAAc;AAAA,IACd,OAAO;AAAA,IACP,MAAM,aAAa;AAAA,EACrB;AAAA,EACA,MAAM;AAAA;AAAA,IAEJ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,cAAc;AAAA,IACd,OAAO;AAAA,IACP,MAAM,aAAa;AAAA,EACrB;AACF;AASO,MAAM,kBAAiC;AAAA,EAC5C,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,IACL,GAAG,eAAe;AAAA,IAClB,OAAO,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzG,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,MAAM;AAAA,IACJ,GAAG,eAAe;AAAA,IAClB,OAAO,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzG,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AACF;AAIO,MAAM,iBAAgC;AAuB7C,MAAM,WAAW;AAAA,EACf,OAAO,eAAe,MAAM;AAAA,EAC5B,MAAM,eAAe,KAAK;AAC5B;AAqBO,MAAM,kBAAmC;AAAA,EAC9C;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,SAAS;AAAA,MAChB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,SAAS;AAAA,MAChB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,SAAS;AAAA,MAChB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,SAAS;AAAA,MAChB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,SAAS;AAAA,MAChB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,SAAS;AAAA,MAChB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,SAAS;AAAA,MAChB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,SAAS;AAAA,MAChB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,WAA4B,CAAC,gBAAgB,iBAAiB,GAAG,eAAe;AAEtF,SAAS,WAAW,IAA2B;AACpD,SAAO,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK;AAC9C;AA2BO,SAAS,cACd,IACA,GACA,WAAoB,GAAG,aAAa,eAAe,MAAM,QACnD;AACN,mBAAiB,IAAI,CAAC;AACtB,QAAM,OAAO,WAAW,aAAa,CAAC,IAAI;AAC1C,KAAG,MAAM,YAAY,aAAa,EAAE,MAAM;AAC1C,KAAG,MAAM,YAAY,gBAAgB,EAAE,SAAS;AAGhD,KAAG,MAAM,YAAY,kBAAkB,MAAM,MAAM,cAAc,EAAE,UAAU;AAC7E,KAAG,MAAM,YAAY,YAAY,MAAM,UAAU,EAAE,MAAM;AACzD,KAAG,MAAM,YAAY,kBAAkB,EAAE,WAAW;AACpD,KAAG,MAAM,YAAY,oBAAoB,MAAM,iBAAiB,EAAE,aAAa;AAC/E,KAAG,MAAM,YAAY,gBAAgB,MAAM,aAAa,EAAE,SAAS;AACnE,MAAI,KAAM,IAAG,MAAM,YAAY,sBAAsB,KAAK,eAAe;AAAA,MACpE,IAAG,MAAM,eAAe,oBAAoB;AACjD,KAAG,MAAM,YAAY,WAAW,EAAE,KAAK;AACvC,KAAG,MAAM,YAAY,iBAAiB,EAAE,UAAU;AAClD,KAAG,MAAM,YAAY,oBAAoB,EAAE,aAAa;AACxD,KAAG,MAAM,YAAY,kBAAkB,MAAM,MAAM,eAAe,EAAE,WAAW;AAC/E,KAAG,MAAM,YAAY,mBAAmB,MAAM,MAAM,gBAAgB,EAAE,YAAY;AAClF,KAAG,MAAM,YAAY,eAAe,MAAM,MAAM,YAAY,EAAE,QAAQ;AACtE,KAAG,MAAM,YAAY,mBAAmB,MAAM,MAAM,gBAAgB,EAAE,YAAY;AAKlF,MAAI,EAAE,MAAM,SAAS,GAAG;AACtB,aAAS,IAAI,GAAG,IAAI,GAAG,IAAK,IAAG,MAAM,YAAY,WAAW,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,MAAM,MAAM,CAAC;AAAA,EAClG;AACF;","names":[]}
package/dist/tour/tour.js CHANGED
@@ -480,7 +480,7 @@ function TourCard({
480
480
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
481
481
  /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap text-xs tabular-nums text-placeholder", children: labels.step(index + 1, total) }),
482
482
  !isFirst && /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onBack, className: "px-2.5 py-1 text-xs", children: labels.back }),
483
- !((step.awaitClick || step.awaitInput) && step.target && rect) && /* @__PURE__ */ jsx(Button, { variant: "brand", onClick: onNext, className: cn("px-2.5 py-1 text-xs"), children: isLast ? labels.done : labels.next })
483
+ !((step.awaitClick || step.awaitInput) && step.target && rect) && /* @__PURE__ */ jsx(Button, { variant: "accent", onClick: onNext, className: cn("px-2.5 py-1 text-xs"), children: isLast ? labels.done : labels.next })
484
484
  ] })
485
485
  ] }),
486
486
  (step.awaitClick || step.awaitInput) && step.target && rect && /* @__PURE__ */ jsx("div", { className: "text-center text-xs italic text-placeholder", children: step.awaitInput && !step.awaitClick ? labels.awaitInputHint : labels.awaitClickHint })