@heyramzi/ui 1.54.2 → 2.0.1

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/COMPONENTS.md +3 -2
  2. package/README.md +34 -9
  3. package/package.json +205 -13
  4. package/scripts/sync-shadcn.mjs +2 -0
  5. package/src/ai/generation-progress/GenerationProgress.svelte +12 -12
  6. package/src/ambient.d.ts +8 -0
  7. package/src/brand/brand.test.ts +67 -0
  8. package/src/brand/index.ts +137 -0
  9. package/src/canvas/README.md +236 -0
  10. package/src/canvas/card/card-frame.svelte +61 -0
  11. package/src/canvas/card/card.css +39 -0
  12. package/src/canvas/card/resize-handles.svelte +119 -0
  13. package/src/canvas/card/resize.ts +33 -0
  14. package/src/canvas/chrome/chrome-zoom.svelte +120 -0
  15. package/src/canvas/chrome/chrome.css +231 -0
  16. package/src/canvas/chrome/lock-badge.svelte +18 -0
  17. package/src/canvas/chrome/side-handles.svelte +30 -0
  18. package/src/canvas/chrome/size-chip.svelte +45 -0
  19. package/src/canvas/chrome/snap-guides.svelte +69 -0
  20. package/src/canvas/components/icons/ToolIcon.svelte +30 -0
  21. package/src/canvas/components/shared/svg/PreviewSvg.svelte +67 -0
  22. package/src/canvas/components/shared/svg/ShapeOutline.svelte +76 -0
  23. package/src/canvas/components/shared/svg/StrokeNode.svelte +69 -0
  24. package/src/canvas/components/shared/svg/TextRule.svelte +37 -0
  25. package/src/canvas/edges/bend-handle.svelte +76 -0
  26. package/src/canvas/edges/edge-gradient.svelte +30 -0
  27. package/src/canvas/edges/edge-path.test.ts +58 -0
  28. package/src/canvas/edges/edge-path.ts +293 -0
  29. package/src/canvas/edges/gradient-edge.svelte +43 -0
  30. package/src/canvas/editor/context-menu.test.ts +65 -0
  31. package/src/canvas/editor/context-menu.ts +48 -0
  32. package/src/canvas/editor/dispatch.svelte.test.ts +243 -0
  33. package/src/canvas/editor/dispatch.svelte.ts +205 -0
  34. package/src/canvas/editor/editor-context.ts +62 -0
  35. package/src/canvas/editor/editor-mode.ts +67 -0
  36. package/src/canvas/editor/frame.ts +98 -0
  37. package/src/canvas/editor/hand-context.ts +15 -0
  38. package/src/canvas/editor/history-core.test.ts +239 -0
  39. package/src/canvas/editor/history-core.ts +247 -0
  40. package/src/canvas/editor/keymap.test.ts +161 -0
  41. package/src/canvas/editor/keymap.ts +151 -0
  42. package/src/canvas/editor/layout-actions.test.ts +156 -0
  43. package/src/canvas/editor/layout-actions.ts +219 -0
  44. package/src/canvas/editor/lock.test.ts +68 -0
  45. package/src/canvas/editor/lock.ts +87 -0
  46. package/src/canvas/editor/rebase.test.ts +208 -0
  47. package/src/canvas/editor/rebase.ts +272 -0
  48. package/src/canvas/editor/style.ts +184 -0
  49. package/src/canvas/editor/text-field-context.ts +41 -0
  50. package/src/canvas/editor/z-order.test.ts +75 -0
  51. package/src/canvas/editor/z-order.ts +87 -0
  52. package/src/canvas/headless/alignment.test.ts +59 -0
  53. package/src/canvas/headless/alignment.ts +23 -0
  54. package/src/canvas/headless/break-apart-find.ts +418 -0
  55. package/src/canvas/headless/break-apart-pieces.ts +104 -0
  56. package/src/canvas/headless/break-apart-plan.ts +439 -0
  57. package/src/canvas/headless/break-apart-style.ts +106 -0
  58. package/src/canvas/headless/break-apart.ts +244 -0
  59. package/src/canvas/headless/canvas-cleanup.test.ts +181 -0
  60. package/src/canvas/headless/canvas-cleanup.ts +102 -0
  61. package/src/canvas/headless/edge-anchors.test.ts +70 -0
  62. package/src/canvas/headless/edge-anchors.ts +143 -0
  63. package/src/canvas/headless/edge-memo.test.ts +58 -0
  64. package/src/canvas/headless/edge-memo.ts +32 -0
  65. package/src/canvas/headless/edge-serialization.test.ts +55 -0
  66. package/src/canvas/headless/edge-serialization.ts +32 -0
  67. package/src/canvas/headless/figure-geometry.ts +293 -0
  68. package/src/canvas/headless/fit-viewport.test.ts +85 -0
  69. package/src/canvas/headless/fit-viewport.ts +137 -0
  70. package/src/canvas/headless/grid.test.ts +34 -0
  71. package/src/canvas/headless/grid.ts +94 -0
  72. package/src/canvas/headless/icon-node.test.ts +23 -0
  73. package/src/canvas/headless/icon-node.ts +66 -0
  74. package/src/canvas/headless/index.ts +9 -0
  75. package/src/canvas/headless/linkify.test.ts +23 -0
  76. package/src/canvas/headless/linkify.ts +25 -0
  77. package/src/canvas/headless/pen-marks.ts +133 -0
  78. package/src/canvas/headless/sketch.test.ts +99 -0
  79. package/src/canvas/headless/sketch.ts +302 -0
  80. package/src/canvas/headless/snap-guides.test.ts +61 -0
  81. package/src/canvas/headless/snap-guides.ts +146 -0
  82. package/src/canvas/headless/svg-figure.test.ts +49 -0
  83. package/src/canvas/headless/svg-figure.ts +176 -0
  84. package/src/canvas/headless/table-layout.test.ts +158 -0
  85. package/src/canvas/headless/table-layout.ts +309 -0
  86. package/src/canvas/index.ts +35 -0
  87. package/src/canvas/lod/lod-mode.svelte.ts +30 -0
  88. package/src/canvas/lod/lod-switch.svelte +140 -0
  89. package/src/canvas/lod/render-all.svelte.ts +52 -0
  90. package/src/canvas/ops/arrange.ts +108 -0
  91. package/src/canvas/ops/ops.test.ts +98 -0
  92. package/src/canvas/ops/ops.ts +347 -0
  93. package/src/canvas/pen/PenField.svelte +128 -0
  94. package/src/canvas/pen/PenField.test.ts +87 -0
  95. package/src/canvas/pen/PenOverlay.svelte +172 -0
  96. package/src/canvas/pen/ShapeNode.svelte +64 -0
  97. package/src/canvas/pen/TextNode.svelte +97 -0
  98. package/src/canvas/pen/colors.ts +28 -0
  99. package/src/canvas/pen/eraser.ts +46 -0
  100. package/src/canvas/pen/geometry.ts +148 -0
  101. package/src/canvas/pen/host-field.test.svelte +13 -0
  102. package/src/canvas/pen/index.ts +40 -0
  103. package/src/canvas/pen/ops.ts +16 -0
  104. package/src/canvas/pen/pen-session.ts +177 -0
  105. package/src/canvas/pen/pen.css +149 -0
  106. package/src/canvas/pen/plugin.ts +139 -0
  107. package/src/canvas/pen/shapes.ts +104 -0
  108. package/src/canvas/pen/stroke-path.ts +54 -0
  109. package/src/canvas/pen/types.ts +96 -0
  110. package/src/canvas/pen/ui.ts +26 -0
  111. package/src/canvas/plugin.test.ts +45 -0
  112. package/src/canvas/plugin.ts +159 -0
  113. package/src/canvas/screen/GlyphIcon.svelte +25 -0
  114. package/src/canvas/screen/PartView.svelte +176 -0
  115. package/src/canvas/screen/ScreenBody.svelte +142 -0
  116. package/src/canvas/screen/ScreenCard.svelte +32 -0
  117. package/src/canvas/screen/glyphs/button.svg +1 -0
  118. package/src/canvas/screen/glyphs/close.svg +1 -0
  119. package/src/canvas/screen/glyphs/down.svg +1 -0
  120. package/src/canvas/screen/glyphs/header.svg +1 -0
  121. package/src/canvas/screen/glyphs/hills.svg +1 -0
  122. package/src/canvas/screen/glyphs/image.svg +1 -0
  123. package/src/canvas/screen/glyphs/input.svg +1 -0
  124. package/src/canvas/screen/glyphs/list.svg +1 -0
  125. package/src/canvas/screen/glyphs/modal.svg +1 -0
  126. package/src/canvas/screen/glyphs/plus.svg +1 -0
  127. package/src/canvas/screen/glyphs/up.svg +1 -0
  128. package/src/canvas/screen/glyphs.ts +40 -0
  129. package/src/canvas/screen/labels.ts +41 -0
  130. package/src/canvas/screen/parts.ts +164 -0
  131. package/src/canvas/screen/plugin.ts +67 -0
  132. package/src/canvas/screen/screen.css +593 -0
  133. package/src/canvas/screen/types.ts +47 -0
  134. package/src/canvas/screen/ui.ts +13 -0
  135. package/src/canvas/test-utils.ts +18 -0
  136. package/src/canvas/types.ts +53 -0
  137. package/src/canvas/ui/CanvasToolbar.svelte +169 -0
  138. package/src/canvas/ui/FrameLayer.svelte +116 -0
  139. package/src/canvas/ui/PenLayer.svelte +39 -0
  140. package/src/canvas/ui/StylePanel.svelte +268 -0
  141. package/src/canvas/ui/canvas-grid.svelte +156 -0
  142. package/src/canvas/ui/canvas-ui.css +350 -0
  143. package/src/canvas/ui/forward-wheel.ts +29 -0
  144. package/src/canvas/ui/icons.ts +124 -0
  145. package/src/canvas/ui/place-panel.ts +80 -0
  146. package/src/canvas/ui/shortcut-tip.test.ts +16 -0
  147. package/src/canvas/ui/shortcut-tip.ts +17 -0
  148. package/src/canvas/ui/tools.ts +146 -0
  149. package/src/charts/README.md +104 -0
  150. package/src/charts/ambient.d.ts +4 -0
  151. package/src/charts/animated-value.css +7 -0
  152. package/src/charts/animated-value.svelte +110 -0
  153. package/src/charts/area-chart.css +29 -0
  154. package/src/charts/area-chart.svelte +204 -0
  155. package/src/charts/bar-chart.css +119 -0
  156. package/src/charts/bar-chart.svelte +275 -0
  157. package/src/charts/charts.css +201 -0
  158. package/src/charts/crosshair.svelte +35 -0
  159. package/src/charts/dashboard/chart.ts +5 -0
  160. package/src/charts/dashboard/dashboard-empty.svelte +55 -0
  161. package/src/charts/dashboard/dashboard-section.svelte +58 -0
  162. package/src/charts/dashboard/data-panel.svelte +81 -0
  163. package/src/charts/dashboard/data-sort-head.svelte +102 -0
  164. package/src/charts/dashboard/data-table.svelte +278 -0
  165. package/src/charts/dashboard/data-table.ts +26 -0
  166. package/src/charts/dashboard/index.ts +25 -0
  167. package/src/charts/dashboard/panel-grid.svelte +43 -0
  168. package/src/charts/dashboard/period-filter.svelte +53 -0
  169. package/src/charts/dashboard/rating-chip.svelte +35 -0
  170. package/src/charts/dashboard/stat-band.svelte +47 -0
  171. package/src/charts/dashboard/stat-tile.svelte +176 -0
  172. package/src/charts/dashboard/windows.ts +8 -0
  173. package/src/charts/donut-chart.css +56 -0
  174. package/src/charts/donut-chart.svelte +158 -0
  175. package/src/charts/edge-fade.svelte +43 -0
  176. package/src/charts/edge-fade.ts +16 -0
  177. package/src/charts/figure.css +100 -0
  178. package/src/charts/figure.svelte +122 -0
  179. package/src/charts/gauge-chart.css +94 -0
  180. package/src/charts/gauge-chart.svelte +302 -0
  181. package/src/charts/hover-band.test.ts +30 -0
  182. package/src/charts/hover-band.ts +21 -0
  183. package/src/charts/hover-focus.svelte +85 -0
  184. package/src/charts/index.ts +31 -0
  185. package/src/charts/legend.css +136 -0
  186. package/src/charts/legend.svelte +112 -0
  187. package/src/charts/line-chart.css +26 -0
  188. package/src/charts/line-chart.svelte +256 -0
  189. package/src/charts/motion.ts +19 -0
  190. package/src/charts/number-chart.css +179 -0
  191. package/src/charts/number-chart.svelte +187 -0
  192. package/src/charts/primitives/chart-container.svelte +57 -0
  193. package/src/charts/primitives/chart-style.svelte +36 -0
  194. package/src/charts/primitives/chart-tooltip.svelte +161 -0
  195. package/src/charts/primitives/chart-utils.ts +54 -0
  196. package/src/charts/primitives/index.ts +11 -0
  197. package/src/charts/reference-line.css +18 -0
  198. package/src/charts/reference-line.svelte +31 -0
  199. package/src/charts/reveal.svelte +61 -0
  200. package/src/charts/ring-chart.css +104 -0
  201. package/src/charts/ring-chart.svelte +166 -0
  202. package/src/charts/sparkline.css +45 -0
  203. package/src/charts/sparkline.svelte +141 -0
  204. package/src/charts/stat-card.css +105 -0
  205. package/src/charts/stat-card.svelte +267 -0
  206. package/src/charts/time-series-chart.css +28 -0
  207. package/src/charts/time-series-chart.svelte +179 -0
  208. package/src/charts/trend-pill.css +38 -0
  209. package/src/charts/trend-pill.svelte +48 -0
  210. package/src/components/copy/copy-button.svelte +1 -1
  211. package/src/components/docs/doc-page.svelte +1 -1
  212. package/src/components/docs/on-this-page.svelte +2 -2
  213. package/src/components/list-page/empty-state.svelte +1 -1
  214. package/src/components/list-page/filter-popover.svelte +1 -1
  215. package/src/components/list-page/section-label.svelte +1 -1
  216. package/src/components/segmented/segment.svelte +4 -4
  217. package/src/components/theme/theme-provider.svelte +6 -4
  218. package/src/components/toolbar/index.ts +5 -0
  219. package/src/components/toolbar/toolbar.svelte +168 -0
  220. package/src/components/toolbar/toolbar.test.ts +66 -0
  221. package/src/editor/README.md +58 -0
  222. package/src/editor/ambient.d.ts +1 -0
  223. package/src/editor/block-id.ts +77 -0
  224. package/src/editor/block-ops.test.ts +237 -0
  225. package/src/editor/block-ops.ts +157 -0
  226. package/src/editor/content.css +418 -0
  227. package/src/editor/editor-toolbar.svelte +303 -0
  228. package/src/editor/editor.svelte +469 -0
  229. package/src/editor/extensions.ts +145 -0
  230. package/src/editor/image-toolbar.svelte +123 -0
  231. package/src/editor/index.ts +17 -0
  232. package/src/editor/inline-editor.svelte +261 -0
  233. package/src/editor/markdown-escaping.test.ts +158 -0
  234. package/src/editor/markdown-marks.test.ts +89 -0
  235. package/src/editor/markdown-test-helpers.ts +13 -0
  236. package/src/editor/markdown-youtube.test.ts +93 -0
  237. package/src/editor/markdown.test.ts +250 -0
  238. package/src/editor/markdown.ts +511 -0
  239. package/src/editor/renderer.svelte +92 -0
  240. package/src/editor/serializer.test.ts +133 -0
  241. package/src/editor/serializer.ts +370 -0
  242. package/src/editor/slash-items.ts +115 -0
  243. package/src/editor/slash-menu.svelte +159 -0
  244. package/src/editor/youtube-url.ts +35 -0
  245. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +13 -13
  246. package/src/gallery.test.ts +20 -1
  247. package/src/lib/result.ts +19 -0
  248. package/src/onboarding/README.md +120 -0
  249. package/src/onboarding/define-tours.test.ts +50 -0
  250. package/src/onboarding/define-tours.ts +31 -0
  251. package/src/onboarding/demo.svelte +86 -0
  252. package/src/onboarding/index.ts +12 -0
  253. package/src/onboarding/onboarding-provider.svelte +120 -0
  254. package/src/onboarding/onboarding.svelte.ts +24 -0
  255. package/src/onboarding/pick.test.ts +79 -0
  256. package/src/onboarding/pick.ts +36 -0
  257. package/src/onboarding/stores.test.ts +103 -0
  258. package/src/onboarding/stores.ts +58 -0
  259. package/src/onboarding/tour-card.svelte +70 -0
  260. package/src/onboarding/tour-runner.svelte +197 -0
  261. package/src/onboarding/types.ts +34 -0
  262. package/src/onboarding/wait.ts +29 -0
  263. package/src/shadcn/command/command-input.svelte +1 -1
  264. package/src/slides/Controls.svelte +138 -0
  265. package/src/slides/Deck.svelte +271 -0
  266. package/src/slides/Fragment.svelte +71 -0
  267. package/src/slides/Overview.svelte +113 -0
  268. package/src/slides/Presenter.svelte +292 -0
  269. package/src/slides/README.md +89 -0
  270. package/src/slides/Slide.svelte +179 -0
  271. package/src/slides/SlideList.svelte +19 -0
  272. package/src/slides/ambient.d.ts +1 -0
  273. package/src/slides/bridges.ts +69 -0
  274. package/src/slides/deck-controller.svelte.ts +292 -0
  275. package/src/slides/demo-slides.svelte +358 -0
  276. package/src/slides/demo.svelte +176 -0
  277. package/src/slides/export/capture.ts +113 -0
  278. package/src/slides/export/ffmpeg.ts +120 -0
  279. package/src/slides/export/index.ts +9 -0
  280. package/src/slides/export/launch.ts +10 -0
  281. package/src/slides/export/pdf.ts +152 -0
  282. package/src/slides/export/types.ts +48 -0
  283. package/src/slides/index.ts +19 -0
  284. package/src/slides/labels.ts +48 -0
  285. package/src/slides/layout.ts +51 -0
  286. package/src/slides/model.ts +47 -0
  287. package/src/slides/navigation.ts +100 -0
  288. package/src/slides/theme.css +205 -0
  289. package/src/slides/types.ts +86 -0
  290. package/src/tasks/README.md +312 -0
  291. package/src/tasks/ambient.d.ts +3 -0
  292. package/src/tasks/board-order.ts +137 -0
  293. package/src/tasks/dates.ts +31 -0
  294. package/src/tasks/define-statuses.ts +32 -0
  295. package/src/tasks/demo.svelte +389 -0
  296. package/src/tasks/detail/detail-demo.svelte +186 -0
  297. package/src/tasks/detail/detail-types.ts +54 -0
  298. package/src/tasks/detail/task-chip.svelte +28 -0
  299. package/src/tasks/detail/task-detail.svelte +315 -0
  300. package/src/tasks/detail/task-property.svelte +17 -0
  301. package/src/tasks/detail/task-thread.svelte +258 -0
  302. package/src/tasks/gantt/gantt-bar.svelte +243 -0
  303. package/src/tasks/gantt/gantt-grid.svelte +94 -0
  304. package/src/tasks/gantt/gantt-group-row.svelte +55 -0
  305. package/src/tasks/gantt/gantt-header.svelte +71 -0
  306. package/src/tasks/gantt/gantt-task-row.svelte +186 -0
  307. package/src/tasks/gantt/gantt.css +22 -0
  308. package/src/tasks/gantt/gantt.test.ts +77 -0
  309. package/src/tasks/gantt/logic.test.ts +163 -0
  310. package/src/tasks/gantt/logic.ts +248 -0
  311. package/src/tasks/inbox/inbox-card.svelte +283 -0
  312. package/src/tasks/inbox/inbox-draft.svelte +84 -0
  313. package/src/tasks/inbox/inbox-logic.ts +55 -0
  314. package/src/tasks/inbox/inbox-statuses.ts +48 -0
  315. package/src/tasks/inbox/inbox-trace.svelte +45 -0
  316. package/src/tasks/inbox/inbox-types.ts +108 -0
  317. package/src/tasks/inbox/inbox.svelte +203 -0
  318. package/src/tasks/inbox/index.ts +23 -0
  319. package/src/tasks/index.ts +85 -0
  320. package/src/tasks/kanban-board.svelte +561 -0
  321. package/src/tasks/kanban-column.svelte +117 -0
  322. package/src/tasks/kanban-drag.ts +38 -0
  323. package/src/tasks/kanban-types.ts +65 -0
  324. package/src/tasks/presets/sales.ts +16 -0
  325. package/src/tasks/record/demo-data.ts +286 -0
  326. package/src/tasks/record/field-section.svelte +53 -0
  327. package/src/tasks/record/fields.ts +142 -0
  328. package/src/tasks/record/format.ts +87 -0
  329. package/src/tasks/record/gutter.ts +2 -0
  330. package/src/tasks/record/index.ts +54 -0
  331. package/src/tasks/record/info-list.svelte +316 -0
  332. package/src/tasks/record/kinds.ts +42 -0
  333. package/src/tasks/record/logic.ts +324 -0
  334. package/src/tasks/record/next-up.svelte +70 -0
  335. package/src/tasks/record/project-list.svelte +133 -0
  336. package/src/tasks/record/record-demo.svelte +324 -0
  337. package/src/tasks/record/record-header.svelte +70 -0
  338. package/src/tasks/record/record-shell.svelte +138 -0
  339. package/src/tasks/record/record-stats.svelte +48 -0
  340. package/src/tasks/record/record-timeline.svelte +231 -0
  341. package/src/tasks/record/record.test.ts +350 -0
  342. package/src/tasks/record/steps-rail.svelte +474 -0
  343. package/src/tasks/record/types.ts +280 -0
  344. package/src/tasks/record/where-we-are.svelte +121 -0
  345. package/src/tasks/reorder.ts +19 -0
  346. package/src/tasks/side-panel-types.ts +16 -0
  347. package/src/tasks/side-panel.svelte +193 -0
  348. package/src/tasks/status-badge.svelte +63 -0
  349. package/src/tasks/status-dot.svelte +228 -0
  350. package/src/tasks/status-icon.svelte +30 -0
  351. package/src/tasks/status-types.ts +40 -0
  352. package/src/tasks/task-gantt.svelte +230 -0
  353. package/src/tasks/task-list.svelte +470 -0
  354. package/src/tasks/task-types.ts +33 -0
  355. package/src/tasks/time/duration.ts +69 -0
  356. package/src/tasks/time/time-chip.svelte +62 -0
  357. package/src/tasks/time/time-dot.svelte +58 -0
  358. package/src/tasks/time/time-ring.svelte +74 -0
  359. package/src/tasks/time/time-tracker.svelte +565 -0
  360. package/src/tasks/time/time-types.ts +74 -0
  361. package/src/tasks/use-kanban-dnd.svelte.ts +173 -0
  362. package/src/tokens/base.css +5 -5
  363. package/src/tokens/palette.css +115 -120
@@ -0,0 +1,173 @@
1
+ import { boardOrderAt } from "./board-order.js";
2
+ import type { KanbanMove } from "./kanban-types.js";
3
+
4
+ export type KanbanDragOver = { columnId: string; overId: string | null };
5
+
6
+ export type KanbanDndConfig<T> = {
7
+ items: () => readonly T[];
8
+ getId: (item: T) => string;
9
+ getColumn: (item: T) => string;
10
+ getColumnItems: (columnId: string) => readonly T[];
11
+ /** The active sort. `"manual"` orders by `boardOrder`; anything else is a move only. */
12
+ getSortKey: () => string;
13
+ boardOrder?: (item: T) => string | null | undefined;
14
+ onMove: (id: string, move: KanbanMove) => void | Promise<void>;
15
+ /** A capped column hides its tail, so a drop on its empty space should land on top. */
16
+ dropAtTop?: (columnId: string) => boolean;
17
+ /**
18
+ * Return false for display-only lanes (e.g. an Overdue lane). The board then
19
+ * never calls preventDefault for that column, so it is not a drop target.
20
+ */
21
+ isDroppable?: (columnId: string) => boolean;
22
+ };
23
+
24
+ /**
25
+ * The drag state and handlers for a board. Native HTML5 drag is deliberate:
26
+ * it reuses the browser's own drop targets, so a card can leave the board and
27
+ * land on any other element a caller wired up.
28
+ */
29
+ export function createKanbanDnd<T>(config: KanbanDndConfig<T>) {
30
+ let draggedId = $state<string | null>(null);
31
+ let dragOver = $state<KanbanDragOver | null>(null);
32
+
33
+ function readDraggedId(e: DragEvent): string | null {
34
+ const raw = e.dataTransfer?.getData("text/plain");
35
+ if (!raw) return null;
36
+ try {
37
+ const parsed = JSON.parse(raw) as { id?: string };
38
+ return parsed.id ?? null;
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+
44
+ function onDragStart(e: DragEvent, id: string): void {
45
+ if (e.dataTransfer) {
46
+ e.dataTransfer.effectAllowed = "move";
47
+ e.dataTransfer.setData("text/plain", JSON.stringify({ id }));
48
+ }
49
+ // Defer: marking the source during the dragstart event makes some browsers
50
+ // snapshot the faded state instead of the card.
51
+ requestAnimationFrame(() => {
52
+ draggedId = id;
53
+ });
54
+ }
55
+
56
+ function onItemDragOver(
57
+ e: DragEvent,
58
+ columnId: string,
59
+ overId: string,
60
+ nextId: string | null,
61
+ ): void {
62
+ if (config.isDroppable && !config.isDroppable(columnId)) return;
63
+ e.preventDefault();
64
+ e.stopPropagation();
65
+ if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
66
+
67
+ const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
68
+ const insertAfter = e.clientY > rect.top + rect.height / 2;
69
+ const targetOverId = insertAfter ? nextId : overId;
70
+
71
+ if (targetOverId === draggedId) return;
72
+ if (dragOver?.columnId === columnId && dragOver.overId === targetOverId) return;
73
+ dragOver = { columnId, overId: targetOverId };
74
+ }
75
+
76
+ function onColumnDragOver(e: DragEvent, columnId: string): void {
77
+ if (config.isDroppable && !config.isDroppable(columnId)) return;
78
+ e.preventDefault();
79
+ if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
80
+ if (dragOver?.columnId !== columnId || dragOver.overId !== null) {
81
+ dragOver = { columnId, overId: null };
82
+ }
83
+ }
84
+
85
+ function onDragLeave(e: DragEvent): void {
86
+ if (!(e.currentTarget as HTMLElement).contains(e.relatedTarget as Node)) {
87
+ dragOver = null;
88
+ }
89
+ }
90
+
91
+ function clearDragOver(): void {
92
+ dragOver = null;
93
+ }
94
+
95
+ function resetDrag(): void {
96
+ draggedId = null;
97
+ dragOver = null;
98
+ }
99
+
100
+ /** Where a manual drop lands: on the hovered card, else the top or the end. */
101
+ function manualInsertIndex(
102
+ column: readonly T[],
103
+ overId: string | null,
104
+ columnId: string,
105
+ ): number {
106
+ const overIndex = overId ? column.findIndex((item) => config.getId(item) === overId) : -1;
107
+ if (overIndex !== -1) return overIndex;
108
+ return config.dropAtTop?.(columnId) ? 0 : column.length;
109
+ }
110
+
111
+ function onDrop(e: DragEvent, targetColumnId: string): void {
112
+ e.preventDefault();
113
+ if (config.isDroppable && !config.isDroppable(targetColumnId)) return;
114
+ const overId = dragOver?.overId ?? null;
115
+ dragOver = null;
116
+ draggedId = null;
117
+
118
+ const id = readDraggedId(e);
119
+ const item = id ? config.items().find((entry) => config.getId(entry) === id) : undefined;
120
+ if (!item) return;
121
+
122
+ const movedId = config.getId(item);
123
+
124
+ if (config.getSortKey() !== "manual") {
125
+ if (config.getColumn(item) !== targetColumnId) {
126
+ void config.onMove(movedId, { columnId: targetColumnId });
127
+ }
128
+ return;
129
+ }
130
+
131
+ const column = config
132
+ .getColumnItems(targetColumnId)
133
+ .filter((entry) => config.getId(entry) !== movedId);
134
+ const index = manualInsertIndex(column, overId, targetColumnId);
135
+ const before = column[index - 1];
136
+ const after = column[index];
137
+ const orderOf = config.boardOrder;
138
+ void config.onMove(movedId, {
139
+ columnId: targetColumnId,
140
+ ...(orderOf ? { boardOrder: boardOrderAt(column, index, orderOf) } : {}),
141
+ beforeId: before === undefined ? null : config.getId(before),
142
+ afterId: after === undefined ? null : config.getId(after),
143
+ });
144
+ }
145
+
146
+ return {
147
+ get draggedId() {
148
+ return draggedId;
149
+ },
150
+ get dragOver() {
151
+ return dragOver;
152
+ },
153
+ set dragOver(value: KanbanDragOver | null) {
154
+ dragOver = value;
155
+ },
156
+ onDragStart,
157
+ onItemDragOver,
158
+ onColumnDragOver,
159
+ onDragLeave,
160
+ onDrop,
161
+ clearDragOver,
162
+ resetDrag,
163
+ isDragSource(id: string): boolean {
164
+ return draggedId === id;
165
+ },
166
+ showIndicatorBefore(columnId: string, itemId: string): boolean {
167
+ return dragOver?.columnId === columnId && dragOver.overId === itemId && draggedId !== null;
168
+ },
169
+ showIndicatorEnd(columnId: string): boolean {
170
+ return dragOver?.columnId === columnId && dragOver.overId === null && draggedId !== null;
171
+ },
172
+ };
173
+ }
@@ -101,7 +101,7 @@
101
101
  }
102
102
  .dark html,
103
103
  html.dark {
104
- scrollbar-color: var(--brand-veil) transparent;
104
+ scrollbar-color: var(--brand-line) transparent;
105
105
  }
106
106
  h1,
107
107
  h2,
@@ -112,14 +112,14 @@
112
112
  font-family: var(--font-heading);
113
113
  }
114
114
 
115
- /* WHY: the browser's default highlight is a system blue from no theme. Indigo
116
- at 18% keeps text at its own contrast in both modes. */
115
+ /* WHY: the browser's default highlight is a system blue from no theme.
116
+ The brand colour at 18% keeps text at its own contrast in both modes. */
117
117
  ::selection {
118
- background-color: color-mix(in oklab, var(--brand-indigo) 18%, transparent);
118
+ background-color: color-mix(in oklab, var(--brand) 18%, transparent);
119
119
  }
120
120
  .dark ::selection,
121
121
  html.dark ::selection {
122
- background-color: color-mix(in oklab, var(--brand-indigo-light) 26%, transparent);
122
+ background-color: color-mix(in oklab, var(--brand-on-dark) 26%, transparent);
123
123
  }
124
124
 
125
125
  /* ── Touch input ───────────────────────────────────────
@@ -2,22 +2,16 @@
2
2
 
3
3
  /* Font families */
4
4
  @theme {
5
- --font-sans: var(--font-satoshi), system-ui, sans-serif;
6
- --font-heading: var(--font-manrope), system-ui, sans-serif;
7
- --font-mono: var(--font-space-grotesk), ui-monospace, monospace;
8
- --font-quote: var(--font-space-grotesk), ui-monospace, monospace;
5
+ --font-sans: system-ui, sans-serif;
6
+ --font-heading: var(--font-sans);
7
+ --font-mono: ui-monospace, monospace;
8
+ --font-quote: var(--font-mono);
9
9
  }
10
10
 
11
11
  /* OKLCH Color Variables - Single source of truth for all colors */
12
- /* Palette: indigo, sand and terra, with a neutral gray scale. */
12
+ /* Neutral by default: a gray scale, four brand roles and the surface system, all replaceable. */
13
13
  :root {
14
14
  color-scheme: light;
15
- /* === Font Variables === */
16
- /* Each consuming app defines @font-face and sets these to the actual font family names */
17
- --font-satoshi: "Satoshi", system-ui, sans-serif;
18
- --font-manrope: "Manrope", system-ui, sans-serif;
19
- --font-space-grotesk: "Space Grotesk", ui-monospace, monospace;
20
-
21
15
  /* === Core Gray Scale (7 shades, zero-chroma neutral) === */
22
16
  --gray-50: oklch(0.98 0 0); /* Almost white — backgrounds */
23
17
  --gray-100: oklch(0.94 0 0); /* Very light gray — subtle backgrounds */
@@ -27,44 +21,46 @@
27
21
  --gray-700: oklch(0.45 0 0); /* Dark gray — body text */
28
22
  --gray-900: oklch(0.15 0 0); /* Near-black — headings, primary text */
29
23
 
30
- /* === Accent Colors (3 chromatic) — 60/30/10 split === */
31
- --brand-indigo: oklch(0.5 0.2 272); /* Primary 60% — CTAs, links, active states, brand mark */
32
- --brand-indigo-light: oklch(0.68 0.16 272); /* Dark mode variant */
33
- --brand-sand: oklch(0.78 0.08 40); /* Warmth 30% — highlights, badges, soft accents */
34
- --brand-terra: oklch(0.65 0.2 30); /* Signal 10% — warnings, attention, energy */
35
-
36
- /* === Surface System (6 named colors) === */
37
- /* Dark surfaces (indigo-tinted, h258-264) Light pendants (warm-tinted, h55) */
38
- --brand-ink: oklch(0.12 0.04 258); /* Base — page background */
39
- --brand-night: oklch(0.18 0.05 262); /* Surface — cards, panels ↔ Linen */
40
- --brand-veil: oklch(0.28 0.06 264); /* Borders, dividers ↔ Mist */
41
- --brand-dusk: oklch(0.22 0.05 262); /* Between night/veil — hover surfaces, inputs */
42
- --brand-cream: oklch(0.97 0.01 55); /* On-dark text, light backgrounds */
43
- --brand-linen: oklch(0.985 0.003 55); /* Light surface — cards ↔ Night */
44
- --brand-mist: oklch(0.9 0.006 55); /* Light borders, dividers ↔ Veil */
45
-
46
- /* === Indigo Tint Scale (5-step, core = 600) === */
47
- --indigo-100: oklch(0.92 0.04 272);
48
- --indigo-200: oklch(0.82 0.08 272);
49
- --indigo-400: oklch(0.68 0.16 272);
50
- --indigo-600: oklch(0.5 0.2 272); /* = --brand-indigo */
51
- --indigo-800: oklch(0.34 0.18 272);
52
-
53
- /* === Sand Tint Scale (5-step, core = 400) === */
54
- --sand-100: oklch(0.94 0.02 40);
55
- --sand-200: oklch(0.88 0.04 40);
56
- --sand-400: oklch(0.78 0.08 40); /* = --brand-sand */
57
- --sand-600: oklch(0.64 0.1 40);
58
- --sand-800: oklch(0.5 0.08 40);
59
-
60
- /* === Terra Tint Scale (5-step, core = 400) === */
61
- --terra-100: oklch(0.92 0.05 30);
62
- --terra-200: oklch(0.82 0.1 30);
63
- --terra-400: oklch(0.65 0.2 30); /* = --brand-terra */
64
- --terra-600: oklch(0.52 0.2 30);
65
- --terra-800: oklch(0.38 0.15 30);
66
-
67
- /* === Status Tint Scales (5-step, mirror indigo/sand/terra) === */
24
+ /* === Brand roles ===
25
+ The look of a product, named by what each colour does. These defaults are neutral, and a
26
+ brand replaces them through `@heyramzi/ui/brand` (typed colours, no build step). Every
27
+ other token below reads from these, so nothing else in the package names a hue. */
28
+ --brand: oklch(0.28 0 0); /* The signature colour: focus ring, links, active states, the mark */
29
+ --brand-on-dark: oklch(0.92 0 0); /* The same colour lifted for a dark page */
30
+ --brand-highlight: oklch(0.78 0 0); /* Warmth: badges, highlights, soft accents */
31
+ --brand-signal: oklch(0.62 0.2 28); /* Attention: warnings, errors, energy */
32
+
33
+ /* Dark surfaces. Light pendants are surface-light, line-light and paper. */
34
+ --brand-ink: oklch(0.145 0 0); /* Page background */
35
+ --brand-surface: oklch(0.19 0 0); /* Cards, panels */
36
+ --brand-line: oklch(0.29 0 0); /* Borders, dividers */
37
+ --brand-raised: oklch(0.24 0 0); /* Hover surfaces, inputs, between surface and line */
38
+ --brand-paper: oklch(0.97 0 0); /* Text on dark, light backgrounds */
39
+ --brand-surface-light: oklch(0.99 0 0); /* Cards on a light page */
40
+ --brand-line-light: oklch(0.91 0 0); /* Borders on a light page */
41
+
42
+ /* === Tint scales, derived from the three hues so a brand types one colour each ===
43
+ WHY mixes and not typed steps: a brand that sets `--brand` gets a matching 100 to 800
44
+ with nothing else to maintain. 400 is the colour lifted for dark, 600 the colour itself. */
45
+ --brand-100: color-mix(in oklab, var(--brand) 12%, white);
46
+ --brand-200: color-mix(in oklab, var(--brand) 28%, white);
47
+ --brand-400: var(--brand-on-dark);
48
+ --brand-600: var(--brand);
49
+ --brand-800: color-mix(in oklab, var(--brand) 70%, black);
50
+
51
+ --highlight-100: color-mix(in oklab, var(--brand-highlight) 22%, white);
52
+ --highlight-200: color-mix(in oklab, var(--brand-highlight) 45%, white);
53
+ --highlight-400: var(--brand-highlight);
54
+ --highlight-600: color-mix(in oklab, var(--brand-highlight) 80%, black);
55
+ --highlight-800: color-mix(in oklab, var(--brand-highlight) 55%, black);
56
+
57
+ --signal-100: color-mix(in oklab, var(--brand-signal) 16%, white);
58
+ --signal-200: color-mix(in oklab, var(--brand-signal) 36%, white);
59
+ --signal-400: var(--brand-signal);
60
+ --signal-600: color-mix(in oklab, var(--brand-signal) 80%, black);
61
+ --signal-800: color-mix(in oklab, var(--brand-signal) 55%, black);
62
+
63
+ /* === Status Tint Scales (5-step, same shape as the brand scales) === */
68
64
  /* WHY: status badges use bg-X-100 text-X-600 dark:bg-X-800/30 dark:text-X-400 */
69
65
  /* Success (green) — positive states */
70
66
  --success-100: oklch(0.94 0.05 150);
@@ -101,7 +97,7 @@
101
97
 
102
98
  /* === Semantic Colors === */
103
99
  --success: oklch(0.62 0.17 145); /* Green — positive states */
104
- --error: oklch(0.6 0.2 25); /* Terra-dark — destructive actions */
100
+ --error: oklch(0.6 0.2 25); /* Red — destructive actions */
105
101
  --warning: oklch(0.78 0.14 75); /* Amber — warnings, attention */
106
102
  --info: oklch(0.68 0.16 250); /* Blue — informational */
107
103
 
@@ -118,12 +114,12 @@
118
114
  --sidebar-accent: oklch(0.92 0 0);
119
115
  --sidebar-accent-foreground: oklch(0.15 0 0);
120
116
  --sidebar-border: oklch(0.91 0 0);
121
- --sidebar-ring: var(--brand-indigo);
117
+ --sidebar-ring: var(--brand);
122
118
 
123
119
  /* === Shadow tint ===
124
120
  The one knob the design layer exposes. Pure black greys out warm surfaces,
125
121
  so the shadow takes the darkest surface's hue. Radius, focus and motion live there. */
126
- --elev-tint: oklch(0.12 0.04 258); /* = --brand-ink */
122
+ --elev-tint: var(--brand-ink);
127
123
  }
128
124
 
129
125
  @theme {
@@ -136,36 +132,35 @@
136
132
  --color-gray-700: var(--gray-700);
137
133
  --color-gray-900: var(--gray-900);
138
134
 
139
- /* Brand colors (V6 names) */
140
- --color-brand-indigo: var(--brand-indigo);
141
- --color-brand-indigo-light: var(--brand-indigo-light);
142
- --color-brand-sand: var(--brand-sand);
143
- --color-brand-terra: var(--brand-terra);
144
- /* Surface system */
145
- --color-brand-ink: var(--brand-ink);
146
- --color-brand-night: var(--brand-night);
147
- --color-brand-veil: var(--brand-veil);
148
- --color-brand-dusk: var(--brand-dusk);
149
- --color-brand-cream: var(--brand-cream);
150
- --color-brand-linen: var(--brand-linen);
151
- --color-brand-mist: var(--brand-mist);
152
-
153
- /* Tint scales */
154
- --color-indigo-100: var(--indigo-100);
155
- --color-indigo-200: var(--indigo-200);
156
- --color-indigo-400: var(--indigo-400);
157
- --color-indigo-600: var(--indigo-600);
158
- --color-indigo-800: var(--indigo-800);
159
- --color-sand-100: var(--sand-100);
160
- --color-sand-200: var(--sand-200);
161
- --color-sand-400: var(--sand-400);
162
- --color-sand-600: var(--sand-600);
163
- --color-sand-800: var(--sand-800);
164
- --color-terra-100: var(--terra-100);
165
- --color-terra-200: var(--terra-200);
166
- --color-terra-400: var(--terra-400);
167
- --color-terra-600: var(--terra-600);
168
- --color-terra-800: var(--terra-800);
135
+ /* Brand roles. bg-brand, text-ink, border-line and the rest read these. */
136
+ --color-brand: var(--brand);
137
+ --color-brand-on-dark: var(--brand-on-dark);
138
+ --color-highlight: var(--brand-highlight);
139
+ --color-signal: var(--brand-signal);
140
+ --color-ink: var(--brand-ink);
141
+ --color-surface: var(--brand-surface);
142
+ --color-line: var(--brand-line);
143
+ --color-raised: var(--brand-raised);
144
+ --color-paper: var(--brand-paper);
145
+ --color-surface-light: var(--brand-surface-light);
146
+ --color-line-light: var(--brand-line-light);
147
+
148
+ /* Tint scales: bg-brand-100, text-signal-600, dark:bg-highlight-800/30 */
149
+ --color-brand-100: var(--brand-100);
150
+ --color-brand-200: var(--brand-200);
151
+ --color-brand-400: var(--brand-400);
152
+ --color-brand-600: var(--brand-600);
153
+ --color-brand-800: var(--brand-800);
154
+ --color-highlight-100: var(--highlight-100);
155
+ --color-highlight-200: var(--highlight-200);
156
+ --color-highlight-400: var(--highlight-400);
157
+ --color-highlight-600: var(--highlight-600);
158
+ --color-highlight-800: var(--highlight-800);
159
+ --color-signal-100: var(--signal-100);
160
+ --color-signal-200: var(--signal-200);
161
+ --color-signal-400: var(--signal-400);
162
+ --color-signal-600: var(--signal-600);
163
+ --color-signal-800: var(--signal-800);
169
164
 
170
165
  /* Semantic colors */
171
166
  --color-success: var(--success);
@@ -212,15 +207,15 @@
212
207
  --color-success-ink: color-mix(in oklab, var(--color-success) 60%, var(--color-foreground));
213
208
  --color-destructive-ink: color-mix(in oklab, var(--color-destructive) 60%, var(--color-foreground));
214
209
 
215
- /* Light theme color system — uses named surface colors (linen/mist pendants of night/veil) */
210
+ /* Light theme color system: the light surfaces and lines of the brand roles */
216
211
  --color-background: var(--gray-50);
217
212
  --color-foreground: var(--gray-900);
218
213
  --color-foreground-muted: var(--gray-700);
219
214
 
220
- --color-card: var(--brand-linen); /* Surface — pendant of night */
215
+ --color-card: var(--brand-surface-light);
221
216
  --color-card-foreground: var(--gray-900);
222
217
 
223
- --color-popover: var(--brand-linen);
218
+ --color-popover: var(--brand-surface-light);
224
219
  --color-popover-foreground: var(--gray-900);
225
220
 
226
221
  --color-primary: var(--gray-900);
@@ -238,11 +233,11 @@
238
233
  --color-destructive: var(--error);
239
234
  --color-destructive-foreground: var(--gray-50);
240
235
 
241
- --color-border: var(--brand-mist); /* Borders — pendant of veil */
242
- --color-input: var(--brand-mist);
236
+ --color-border: var(--brand-line-light);
237
+ --color-input: var(--brand-line-light);
243
238
  /* WHY the accent, not gray-900: a near-black halo reads as an error first.
244
239
  Focus is the one moment the brand speaks in chrome. */
245
- --color-ring: var(--brand-indigo);
240
+ --color-ring: var(--brand);
246
241
 
247
242
  /* Sidebar colors */
248
243
  --color-sidebar: var(--sidebar);
@@ -312,48 +307,48 @@
312
307
  .dark {
313
308
  /* WHY: LayerChart halos axis labels with light-dark(), which reads color-scheme, not the .dark class. */
314
309
  color-scheme: dark;
315
- /* Dark theme — named surface system (ink/night/veil) */
316
- --color-background: var(--brand-ink); /* Base — page background */
317
- --color-foreground: var(--brand-cream);
310
+ /* Dark theme: the brand's dark surfaces, ink on the page and paper on the text */
311
+ --color-background: var(--brand-ink);
312
+ --color-foreground: var(--brand-paper);
318
313
  --color-foreground-muted: var(--gray-300);
319
314
 
320
- --color-card: var(--brand-night); /* Surface — cards, panels */
321
- --color-card-foreground: var(--brand-cream);
315
+ --color-card: var(--brand-surface);
316
+ --color-card-foreground: var(--brand-paper);
322
317
 
323
- --color-popover: var(--brand-night);
324
- --color-popover-foreground: var(--brand-cream);
318
+ --color-popover: var(--brand-surface);
319
+ --color-popover-foreground: var(--brand-paper);
325
320
 
326
- --color-primary: var(--brand-cream);
321
+ --color-primary: var(--brand-paper);
327
322
  --color-primary-foreground: var(--gray-900);
328
323
 
329
- --color-secondary: var(--brand-dusk); /* Between night (0.18) and veil (0.28) */
330
- --color-secondary-foreground: var(--brand-cream);
324
+ --color-secondary: var(--brand-raised);
325
+ --color-secondary-foreground: var(--brand-paper);
331
326
 
332
- --color-muted: var(--brand-dusk); /* Between night and veil — hover surfaces */
327
+ --color-muted: var(--brand-raised);
333
328
  --color-muted-foreground: var(--gray-300);
334
329
 
335
- --color-accent: var(--brand-dusk); /* Between night and veil — accent surfaces */
336
- --color-accent-foreground: var(--brand-cream);
330
+ --color-accent: var(--brand-raised);
331
+ --color-accent-foreground: var(--brand-paper);
337
332
 
338
- --color-destructive: var(--terra-400); /* Lighter terra for dark bg */
339
- --color-destructive-foreground: var(--brand-cream);
333
+ --color-destructive: var(--signal-400);
334
+ --color-destructive-foreground: var(--brand-paper);
340
335
 
341
- --color-border: var(--brand-veil); /* Named border color */
342
- --color-input: var(--brand-dusk); /* Between night and veil — input surfaces */
343
- --color-ring: var(--brand-indigo-light);
336
+ --color-border: var(--brand-line);
337
+ --color-input: var(--brand-raised);
338
+ --color-ring: var(--brand-on-dark);
344
339
 
345
- /* Brand colors for dark theme — lighter variants for contrast on ink bg */
346
- --color-brand-indigo: var(--brand-indigo-light); /* L=0.68 on ink L=0.12 = ΔL 0.56 ✓ */
340
+ /* The brand colour lifts for contrast on the dark page. */
341
+ --color-brand: var(--brand-on-dark);
347
342
 
348
- /* Dark sidebar — uses named surface system */
349
- --sidebar: var(--brand-night);
350
- --sidebar-foreground: var(--brand-cream);
351
- --sidebar-primary: var(--brand-indigo-light);
343
+ /* Dark sidebar */
344
+ --sidebar: var(--brand-surface);
345
+ --sidebar-foreground: var(--brand-paper);
346
+ --sidebar-primary: var(--brand-on-dark);
352
347
  --sidebar-primary-foreground: oklch(1 0 0);
353
- --sidebar-accent: oklch(0.24 0.05 262); /* Between night and veil */
354
- --sidebar-accent-foreground: var(--brand-cream);
355
- --sidebar-border: var(--brand-veil);
356
- --sidebar-ring: var(--brand-indigo-light);
348
+ --sidebar-accent: var(--brand-raised);
349
+ --sidebar-accent-foreground: var(--brand-paper);
350
+ --sidebar-border: var(--brand-line);
351
+ --sidebar-ring: var(--brand-on-dark);
357
352
 
358
353
  --color-sidebar: var(--sidebar);
359
354
  --color-sidebar-foreground: var(--sidebar-foreground);
@@ -400,11 +395,11 @@
400
395
  --input: var(--color-input);
401
396
  --ring: var(--color-ring);
402
397
 
403
- /* Chart series. Indigo leads, green second. Terra sits at 4 since a rate gauge
398
+ /* Chart series. The brand leads, green second. Signal sits at 4 since a rate gauge
404
399
  reads as caution, not identity. Every value has a dark variant. */
405
- --chart-1: var(--color-brand-indigo);
400
+ --chart-1: var(--color-brand);
406
401
  --chart-2: var(--cat-green);
407
- --chart-3: var(--brand-sand);
408
- --chart-4: var(--brand-terra);
402
+ --chart-3: var(--brand-highlight);
403
+ --chart-4: var(--brand-signal);
409
404
  --chart-5: var(--cat-cyan);
410
405
  }