decantr 0.9.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 (382) hide show
  1. package/AGENTS.md +868 -0
  2. package/CHANGELOG.md +255 -0
  3. package/CLAUDE.md +178 -0
  4. package/LICENSE +21 -0
  5. package/README.md +229 -0
  6. package/cli/art.js +127 -0
  7. package/cli/commands/a11y.js +61 -0
  8. package/cli/commands/audit.js +225 -0
  9. package/cli/commands/build.js +38 -0
  10. package/cli/commands/dev.js +18 -0
  11. package/cli/commands/doctor.js +197 -0
  12. package/cli/commands/figma-sync.js +48 -0
  13. package/cli/commands/figma-tokens.js +55 -0
  14. package/cli/commands/generate.js +26 -0
  15. package/cli/commands/init.js +116 -0
  16. package/cli/commands/lint.js +209 -0
  17. package/cli/commands/mcp.js +530 -0
  18. package/cli/commands/migrate.js +175 -0
  19. package/cli/commands/test.js +38 -0
  20. package/cli/commands/validate.js +354 -0
  21. package/cli/index.js +113 -0
  22. package/package.json +95 -0
  23. package/reference/atoms.md +517 -0
  24. package/reference/behaviors.md +384 -0
  25. package/reference/build-tooling.md +275 -0
  26. package/reference/color-guidelines.md +965 -0
  27. package/reference/component-lifecycle.md +137 -0
  28. package/reference/compound-spacing.md +95 -0
  29. package/reference/decantation-process.md +499 -0
  30. package/reference/dev-server-routes.md +93 -0
  31. package/reference/form-system.md +253 -0
  32. package/reference/i18n.md +336 -0
  33. package/reference/icons.md +576 -0
  34. package/reference/llm-primer.md +953 -0
  35. package/reference/plugins.md +252 -0
  36. package/reference/registry-consumption.md +76 -0
  37. package/reference/router.md +217 -0
  38. package/reference/shells.md +116 -0
  39. package/reference/spatial-guidelines.md +541 -0
  40. package/reference/ssr.md +234 -0
  41. package/reference/state-data.md +215 -0
  42. package/reference/state-patterns.md +166 -0
  43. package/reference/state.md +194 -0
  44. package/reference/style-system.md +110 -0
  45. package/reference/tokens.md +460 -0
  46. package/src/app.js +19 -0
  47. package/src/chart/_animate.js +266 -0
  48. package/src/chart/_base.js +109 -0
  49. package/src/chart/_data.js +209 -0
  50. package/src/chart/_format.js +106 -0
  51. package/src/chart/_interact.js +364 -0
  52. package/src/chart/_palette.js +105 -0
  53. package/src/chart/_renderer.js +52 -0
  54. package/src/chart/_scene.js +262 -0
  55. package/src/chart/_shared.js +371 -0
  56. package/src/chart/index.js +637 -0
  57. package/src/chart/layouts/_layout-base.js +328 -0
  58. package/src/chart/layouts/cartesian.js +148 -0
  59. package/src/chart/layouts/hierarchy.js +562 -0
  60. package/src/chart/layouts/polar.js +101 -0
  61. package/src/chart/renderers/canvas.js +179 -0
  62. package/src/chart/renderers/svg.js +256 -0
  63. package/src/chart/renderers/webgpu.js +715 -0
  64. package/src/chart/types/_type-base.js +26 -0
  65. package/src/chart/types/area.js +134 -0
  66. package/src/chart/types/bar.js +173 -0
  67. package/src/chart/types/box-plot.js +125 -0
  68. package/src/chart/types/bubble.js +63 -0
  69. package/src/chart/types/candlestick.js +115 -0
  70. package/src/chart/types/chord.js +85 -0
  71. package/src/chart/types/combination.js +108 -0
  72. package/src/chart/types/funnel.js +68 -0
  73. package/src/chart/types/gauge.js +163 -0
  74. package/src/chart/types/heatmap.js +98 -0
  75. package/src/chart/types/histogram.js +71 -0
  76. package/src/chart/types/line.js +111 -0
  77. package/src/chart/types/org-chart.js +93 -0
  78. package/src/chart/types/pie.js +81 -0
  79. package/src/chart/types/radar.js +96 -0
  80. package/src/chart/types/radial.js +68 -0
  81. package/src/chart/types/range-area.js +55 -0
  82. package/src/chart/types/range-bar.js +61 -0
  83. package/src/chart/types/sankey.js +73 -0
  84. package/src/chart/types/scatter.js +66 -0
  85. package/src/chart/types/sparkline.js +81 -0
  86. package/src/chart/types/sunburst.js +69 -0
  87. package/src/chart/types/swimlane.js +88 -0
  88. package/src/chart/types/treemap.js +62 -0
  89. package/src/chart/types/waterfall.js +100 -0
  90. package/src/components/_base.js +1658 -0
  91. package/src/components/_behaviors.js +1140 -0
  92. package/src/components/_primitives.js +534 -0
  93. package/src/components/_qr-encoder.js +539 -0
  94. package/src/components/accordion.js +207 -0
  95. package/src/components/affix.js +62 -0
  96. package/src/components/alert-dialog.js +75 -0
  97. package/src/components/alert.js +47 -0
  98. package/src/components/aspect-ratio.js +24 -0
  99. package/src/components/avatar-group.js +55 -0
  100. package/src/components/avatar.js +38 -0
  101. package/src/components/back-top.js +75 -0
  102. package/src/components/badge.js +74 -0
  103. package/src/components/banner.js +68 -0
  104. package/src/components/breadcrumb.js +162 -0
  105. package/src/components/button.js +115 -0
  106. package/src/components/calendar.js +131 -0
  107. package/src/components/card.js +192 -0
  108. package/src/components/carousel.js +98 -0
  109. package/src/components/cascader.js +261 -0
  110. package/src/components/checkbox.js +80 -0
  111. package/src/components/chip.js +81 -0
  112. package/src/components/code-block.js +82 -0
  113. package/src/components/collapsible.js +50 -0
  114. package/src/components/color-palette.js +438 -0
  115. package/src/components/color-picker.js +314 -0
  116. package/src/components/combobox.js +181 -0
  117. package/src/components/command.js +174 -0
  118. package/src/components/comment.js +206 -0
  119. package/src/components/context-menu.js +76 -0
  120. package/src/components/data-table.js +724 -0
  121. package/src/components/date-picker.js +217 -0
  122. package/src/components/date-range-picker.js +244 -0
  123. package/src/components/datetime-picker.js +271 -0
  124. package/src/components/descriptions.js +68 -0
  125. package/src/components/drawer.js +179 -0
  126. package/src/components/dropdown.js +88 -0
  127. package/src/components/empty.js +41 -0
  128. package/src/components/float-button.js +90 -0
  129. package/src/components/form.js +106 -0
  130. package/src/components/hover-card.js +49 -0
  131. package/src/components/icon.js +87 -0
  132. package/src/components/image.js +97 -0
  133. package/src/components/index.js +117 -0
  134. package/src/components/input-group.js +75 -0
  135. package/src/components/input-number.js +155 -0
  136. package/src/components/input-otp.js +178 -0
  137. package/src/components/input.js +91 -0
  138. package/src/components/kbd.js +36 -0
  139. package/src/components/label.js +25 -0
  140. package/src/components/list.js +118 -0
  141. package/src/components/masked-input.js +236 -0
  142. package/src/components/mentions.js +165 -0
  143. package/src/components/menu.js +259 -0
  144. package/src/components/message.js +80 -0
  145. package/src/components/modal.js +147 -0
  146. package/src/components/navigation-menu.js +166 -0
  147. package/src/components/notification.js +84 -0
  148. package/src/components/pagination.js +104 -0
  149. package/src/components/placeholder.js +132 -0
  150. package/src/components/popconfirm.js +70 -0
  151. package/src/components/popover.js +58 -0
  152. package/src/components/progress.js +61 -0
  153. package/src/components/qrcode.js +251 -0
  154. package/src/components/radiogroup.js +120 -0
  155. package/src/components/range-slider.js +176 -0
  156. package/src/components/rate.js +186 -0
  157. package/src/components/resizable.js +83 -0
  158. package/src/components/result.js +57 -0
  159. package/src/components/scroll-area.js +43 -0
  160. package/src/components/segmented.js +97 -0
  161. package/src/components/select.js +165 -0
  162. package/src/components/separator.js +31 -0
  163. package/src/components/shell.js +407 -0
  164. package/src/components/skeleton.js +39 -0
  165. package/src/components/slider.js +141 -0
  166. package/src/components/sortable-list.js +176 -0
  167. package/src/components/space.js +42 -0
  168. package/src/components/spinner.js +112 -0
  169. package/src/components/splitter.js +147 -0
  170. package/src/components/statistic.js +136 -0
  171. package/src/components/steps.js +99 -0
  172. package/src/components/switch.js +95 -0
  173. package/src/components/table.js +44 -0
  174. package/src/components/tabs.js +216 -0
  175. package/src/components/tag.js +115 -0
  176. package/src/components/textarea.js +82 -0
  177. package/src/components/time-picker.js +153 -0
  178. package/src/components/time-range-picker.js +170 -0
  179. package/src/components/timeline.js +226 -0
  180. package/src/components/toast.js +71 -0
  181. package/src/components/toggle.js +213 -0
  182. package/src/components/tooltip.js +57 -0
  183. package/src/components/tour.js +159 -0
  184. package/src/components/transfer.js +163 -0
  185. package/src/components/tree-select.js +274 -0
  186. package/src/components/tree.js +141 -0
  187. package/src/components/typography.js +136 -0
  188. package/src/components/upload.js +118 -0
  189. package/src/components/visually-hidden.js +20 -0
  190. package/src/components/watermark.js +124 -0
  191. package/src/core/index.js +539 -0
  192. package/src/core/lifecycle.js +69 -0
  193. package/src/css/atoms.js +651 -0
  194. package/src/css/components.js +940 -0
  195. package/src/css/derive.js +1296 -0
  196. package/src/css/index.js +265 -0
  197. package/src/css/runtime.js +268 -0
  198. package/src/css/styles/addons/bioluminescent.js +93 -0
  199. package/src/css/styles/addons/clay.js +70 -0
  200. package/src/css/styles/addons/clean.js +57 -0
  201. package/src/css/styles/addons/command-center.js +143 -0
  202. package/src/css/styles/addons/dopamine.js +83 -0
  203. package/src/css/styles/addons/editorial.js +80 -0
  204. package/src/css/styles/addons/glassmorphism.js +99 -0
  205. package/src/css/styles/addons/liquid-glass.js +105 -0
  206. package/src/css/styles/addons/prismatic.js +100 -0
  207. package/src/css/styles/addons/retro.js +63 -0
  208. package/src/css/styles/auradecantism.js +96 -0
  209. package/src/css/theme-registry.js +444 -0
  210. package/src/data/entity.js +281 -0
  211. package/src/data/index.js +13 -0
  212. package/src/data/persist.js +225 -0
  213. package/src/data/query.js +839 -0
  214. package/src/data/realtime.js +299 -0
  215. package/src/data/url.js +177 -0
  216. package/src/data/worker.js +134 -0
  217. package/src/explorer/archetypes.js +243 -0
  218. package/src/explorer/atoms.js +228 -0
  219. package/src/explorer/charts.js +497 -0
  220. package/src/explorer/components.js +129 -0
  221. package/src/explorer/foundations.js +949 -0
  222. package/src/explorer/icons.js +178 -0
  223. package/src/explorer/patterns.js +247 -0
  224. package/src/explorer/recipes.js +194 -0
  225. package/src/explorer/shared/pattern-examples.js +1337 -0
  226. package/src/explorer/shared/showcase-renderer.js +958 -0
  227. package/src/explorer/shared/spec-table.js +41 -0
  228. package/src/explorer/shared/usage-links.js +87 -0
  229. package/src/explorer/shell-config.js +10 -0
  230. package/src/explorer/shells.js +551 -0
  231. package/src/explorer/styles.js +161 -0
  232. package/src/explorer/tokens.js +262 -0
  233. package/src/explorer/tools.js +525 -0
  234. package/src/form/index.js +804 -0
  235. package/src/i18n/index.js +251 -0
  236. package/src/icons/essential.js +479 -0
  237. package/src/icons/index.js +53 -0
  238. package/src/plugins/index.js +282 -0
  239. package/src/registry/archetypes/content-site.json +71 -0
  240. package/src/registry/archetypes/docs-explorer.json +23 -0
  241. package/src/registry/archetypes/ecommerce.json +104 -0
  242. package/src/registry/archetypes/financial-dashboard.json +77 -0
  243. package/src/registry/archetypes/index.json +41 -0
  244. package/src/registry/archetypes/portfolio.json +82 -0
  245. package/src/registry/archetypes/recipe-community.json +159 -0
  246. package/src/registry/archetypes/saas-dashboard.json +86 -0
  247. package/src/registry/architect/cross-cutting.json +45 -0
  248. package/src/registry/architect/domains/ecommerce.json +294 -0
  249. package/src/registry/architect/domains/financial-services.json +302 -0
  250. package/src/registry/architect/index.json +26 -0
  251. package/src/registry/architect/traits.json +379 -0
  252. package/src/registry/atoms.json +16 -0
  253. package/src/registry/chart-showcase.json +160 -0
  254. package/src/registry/chart.json +136 -0
  255. package/src/registry/components.json +8616 -0
  256. package/src/registry/core.json +216 -0
  257. package/src/registry/css.json +319 -0
  258. package/src/registry/data.json +135 -0
  259. package/src/registry/foundations.json +11 -0
  260. package/src/registry/icons.json +463 -0
  261. package/src/registry/index.json +101 -0
  262. package/src/registry/patterns/activity-feed.json +37 -0
  263. package/src/registry/patterns/article-content.json +27 -0
  264. package/src/registry/patterns/auth-form.json +37 -0
  265. package/src/registry/patterns/author-card.json +20 -0
  266. package/src/registry/patterns/card-grid.json +127 -0
  267. package/src/registry/patterns/category-nav.json +26 -0
  268. package/src/registry/patterns/chart-grid.json +36 -0
  269. package/src/registry/patterns/chat-interface.json +37 -0
  270. package/src/registry/patterns/checklist-card.json +55 -0
  271. package/src/registry/patterns/comparison-panel.json +27 -0
  272. package/src/registry/patterns/component-showcase.json +24 -0
  273. package/src/registry/patterns/contact-form.json +31 -0
  274. package/src/registry/patterns/cta-section.json +20 -0
  275. package/src/registry/patterns/data-table.json +37 -0
  276. package/src/registry/patterns/detail-header.json +83 -0
  277. package/src/registry/patterns/detail-panel.json +27 -0
  278. package/src/registry/patterns/explorer-shell.json +22 -0
  279. package/src/registry/patterns/filter-bar.json +33 -0
  280. package/src/registry/patterns/filter-sidebar.json +27 -0
  281. package/src/registry/patterns/form-sections.json +110 -0
  282. package/src/registry/patterns/goal-tracker.json +27 -0
  283. package/src/registry/patterns/hero.json +107 -0
  284. package/src/registry/patterns/index.json +47 -0
  285. package/src/registry/patterns/kpi-grid.json +36 -0
  286. package/src/registry/patterns/media-gallery.json +20 -0
  287. package/src/registry/patterns/order-history.json +20 -0
  288. package/src/registry/patterns/pagination.json +19 -0
  289. package/src/registry/patterns/photo-to-recipe.json +36 -0
  290. package/src/registry/patterns/pipeline-tracker.json +28 -0
  291. package/src/registry/patterns/post-list.json +27 -0
  292. package/src/registry/patterns/pricing-table.json +32 -0
  293. package/src/registry/patterns/scorecard.json +28 -0
  294. package/src/registry/patterns/search-bar.json +20 -0
  295. package/src/registry/patterns/specimen-grid.json +19 -0
  296. package/src/registry/patterns/stat-card.json +55 -0
  297. package/src/registry/patterns/stats-bar.json +55 -0
  298. package/src/registry/patterns/steps-card.json +55 -0
  299. package/src/registry/patterns/table-of-contents.json +19 -0
  300. package/src/registry/patterns/testimonials.json +21 -0
  301. package/src/registry/patterns/timeline.json +27 -0
  302. package/src/registry/patterns/token-inspector.json +21 -0
  303. package/src/registry/patterns/wizard.json +27 -0
  304. package/src/registry/recipe-auradecantism.json +69 -0
  305. package/src/registry/recipe-clean.json +65 -0
  306. package/src/registry/recipe-command-center.json +78 -0
  307. package/src/registry/router.json +73 -0
  308. package/src/registry/schema/README.md +197 -0
  309. package/src/registry/skeletons.json +259 -0
  310. package/src/registry/state.json +137 -0
  311. package/src/registry/tokens.json +40 -0
  312. package/src/router/hash.js +17 -0
  313. package/src/router/history.js +18 -0
  314. package/src/router/index.js +598 -0
  315. package/src/ssr/index.js +922 -0
  316. package/src/state/arrays.js +181 -0
  317. package/src/state/devtools.js +647 -0
  318. package/src/state/index.js +498 -0
  319. package/src/state/middleware.js +288 -0
  320. package/src/state/scheduler.js +206 -0
  321. package/src/state/store.js +300 -0
  322. package/src/tags/index.js +19 -0
  323. package/src/tannins/auth.js +396 -0
  324. package/src/test/dom.js +352 -0
  325. package/src/test/index.js +62 -0
  326. package/src/test/state.js +306 -0
  327. package/tools/a11y-audit.js +487 -0
  328. package/tools/analyzer.js +315 -0
  329. package/tools/audit.js +706 -0
  330. package/tools/builder.js +1422 -0
  331. package/tools/css-extract.js +188 -0
  332. package/tools/dev-server.js +316 -0
  333. package/tools/dts-gen.js +1260 -0
  334. package/tools/figma-components.js +329 -0
  335. package/tools/figma-patterns.js +516 -0
  336. package/tools/figma-plugin/code.js +453 -0
  337. package/tools/figma-plugin/manifest.json +14 -0
  338. package/tools/figma-plugin/ui.html +268 -0
  339. package/tools/figma-render.js +293 -0
  340. package/tools/figma-tokens.js +712 -0
  341. package/tools/figma-upload.js +318 -0
  342. package/tools/generate.js +738 -0
  343. package/tools/icons.js +133 -0
  344. package/tools/init-templates.js +265 -0
  345. package/tools/install-hooks.sh +5 -0
  346. package/tools/migrations/0.5.0.js +53 -0
  347. package/tools/migrations/0.6.0.js +95 -0
  348. package/tools/minify.js +170 -0
  349. package/tools/pre-commit +4 -0
  350. package/tools/registry.js +662 -0
  351. package/tools/reset-playground.js +61 -0
  352. package/tools/starter-templates/content-site/app.js +49 -0
  353. package/tools/starter-templates/content-site/essence.js +19 -0
  354. package/tools/starter-templates/content-site/pages.js +31 -0
  355. package/tools/starter-templates/ecommerce/app.js +50 -0
  356. package/tools/starter-templates/ecommerce/essence.js +19 -0
  357. package/tools/starter-templates/ecommerce/pages.js +31 -0
  358. package/tools/starter-templates/landing-page/app.js +38 -0
  359. package/tools/starter-templates/landing-page/essence.js +18 -0
  360. package/tools/starter-templates/landing-page/pages.js +21 -0
  361. package/tools/starter-templates/portfolio/app.js +45 -0
  362. package/tools/starter-templates/portfolio/essence.js +19 -0
  363. package/tools/starter-templates/portfolio/pages.js +33 -0
  364. package/tools/starter-templates/saas-dashboard/app.js +70 -0
  365. package/tools/starter-templates/saas-dashboard/essence.js +19 -0
  366. package/tools/starter-templates/saas-dashboard/pages.js +31 -0
  367. package/tools/verify-pack.js +203 -0
  368. package/types/chart.d.ts +77 -0
  369. package/types/components.d.ts +587 -0
  370. package/types/core.d.ts +89 -0
  371. package/types/css.d.ts +149 -0
  372. package/types/data.d.ts +238 -0
  373. package/types/form.d.ts +164 -0
  374. package/types/i18n.d.ts +51 -0
  375. package/types/icons.d.ts +27 -0
  376. package/types/index.d.ts +13 -0
  377. package/types/router.d.ts +116 -0
  378. package/types/ssr.d.ts +102 -0
  379. package/types/state.d.ts +83 -0
  380. package/types/tags.d.ts +62 -0
  381. package/types/tannins.d.ts +63 -0
  382. package/types/test.d.ts +48 -0
@@ -0,0 +1,965 @@
1
+ # Color Design Language
2
+
3
+ Comprehensive color intelligence for Decantr. Every color, palette, and token decision an LLM makes should be traceable to a rule in this document. Color is not decoration -- it encodes meaning.
4
+
5
+ ## The Five Functions of Color
6
+
7
+ | Function | What it communicates | Primary tool |
8
+ |----------|---------------------|-------------|
9
+ | **Identity** | Brand recognition, product personality | Palette roles: primary, accent, tertiary |
10
+ | **Hierarchy** | Visual importance, reading order | Surface tiers, foreground weight |
11
+ | **State** | Interactive feedback, enabled/disabled/focus | Hover, active, subtle tokens |
12
+ | **Feedback** | Success, warning, error, information | Semantic roles: success, warning, error, info |
13
+ | **Aesthetics** | Mood, atmosphere, polish | Gradients, mesh backgrounds, glow effects |
14
+
15
+ In the Decantation Process vocabulary, this is the **Bouquet** layer -- palette tokens from `derive()`. The Bouquet resolves during SETTLE based on the chosen Vintage and Character traits.
16
+
17
+ ---
18
+
19
+ ## 1. The Seed-to-Token Pipeline
20
+
21
+ Authors never write hex values. All color flows through a deterministic pipeline:
22
+
23
+ ```
24
+ 10 seed colors + 6 personality traits
25
+ |
26
+ derive() (src/css/derive.js)
27
+ |
28
+ color math (OKLCH) lighten/darken/alpha/mix/rotateHue (perceptually uniform)
29
+ |
30
+ validateContrast() WCAG AA auto-adjustment
31
+ |
32
+ 171+ CSS custom properties (injected into :root)
33
+ |
34
+ atoms (css()) _fgprimary, _bgmuted, _surface2 ...
35
+ |
36
+ DOM rendered via var(--d-*)
37
+ ```
38
+
39
+ ### The 10 seed colors
40
+
41
+ | Seed | Purpose | Required |
42
+ |------|---------|----------|
43
+ | `primary` | Brand action color -- buttons, links, active states | Yes |
44
+ | `accent` | Secondary brand color -- complementary to primary | Auto-derived if missing (primary + 60deg) |
45
+ | `tertiary` | Third palette entry -- charts, badges, variety | Auto-derived if missing (primary - 60deg) |
46
+ | `neutral` | Chrome, muted text, borders | Yes |
47
+ | `success` | Positive feedback | Yes |
48
+ | `warning` | Caution feedback | Yes |
49
+ | `error` | Destructive/error feedback | Yes |
50
+ | `info` | Informational feedback | Auto-derived if missing (primary + 20deg) |
51
+ | `bg` | Light mode page background | Yes |
52
+ | `bgDark` | Dark mode page background | Yes |
53
+
54
+ ### The 6 personality traits
55
+
56
+ | Trait | Values | Color impact |
57
+ |-------|--------|-------------|
58
+ | `radius` | sharp, rounded, pill | None (spatial only) |
59
+ | `elevation` | flat, subtle, raised, glass, brutalist | Hover/active shift intensity, subtle alpha, border alpha |
60
+ | `motion` | instant, snappy, smooth, bouncy | None (temporal only) |
61
+ | `borders` | none, thin, bold | Focus ring width (2px vs 3px) |
62
+ | `density` | compact, comfortable, spacious | None (spatial only) |
63
+ | `gradient` | none, subtle, vivid, mesh | Gradient token values, `--d-gradient-intensity` |
64
+
65
+ The `palette` meta-trait (`standard` or `monochrome`) controls whether all 7 role colors derive independently or from a single hue.
66
+
67
+ **Cross-ref:** `reference/style-system.md` for style definitions, `src/css/derive.js` for implementation.
68
+
69
+ ---
70
+
71
+ ## 2. Palette Roles and Semantic Meaning
72
+
73
+ 7 roles x 7 modifiers = 49 palette tokens. Each role carries a semantic meaning that must not be misused.
74
+
75
+ ### Role definitions
76
+
77
+ | Role | Semantic meaning | Typical usage |
78
+ |------|-----------------|---------------|
79
+ | `primary` | Brand action | Buttons, links, active indicators, focus rings |
80
+ | `accent` | Secondary brand | Complementary highlights, secondary CTAs, tags |
81
+ | `tertiary` | Third palette | Charts, badges, variety indicators |
82
+ | `success` | Positive outcome | Confirmation, completed steps, valid input |
83
+ | `warning` | Caution needed | Alerts, approaching limits, unsaved changes |
84
+ | `error` | Destructive/failed | Errors, deletion, validation failure |
85
+ | `info` | Neutral information | Tooltips, informational banners, help text |
86
+
87
+ ### The 7 modifiers per role
88
+
89
+ | Modifier | Token pattern | Purpose | Example usage |
90
+ |----------|--------------|---------|--------------|
91
+ | `base` | `--d-{role}` | Solid fill | Button background, active tab indicator |
92
+ | `fg` | `--d-{role}-fg` | Text on base | Button text, badge text on solid fill |
93
+ | `hover` | `--d-{role}-hover` | Hover state fill | Button hover background |
94
+ | `active` | `--d-{role}-active` | Pressed state fill | Button active/pressed background |
95
+ | `subtle` | `--d-{role}-subtle` | Tinted background | Alert background, inline badge background |
96
+ | `subtle-fg` | `--d-{role}-subtle-fg` | Text on subtle | Alert text, badge text on tinted fill |
97
+ | `border` | `--d-{role}-border` | Semi-transparent border | Alert border, card accent border |
98
+
99
+ ### Decision table: "I need a color for X"
100
+
101
+ | I need to color... | Token | Atom |
102
+ |-------------------|-------|------|
103
+ | A primary CTA button fill | `--d-primary` | `_bgprimary` |
104
+ | Text on that button | `--d-primary-fg` | `_fgprimaryon` |
105
+ | A primary button on hover | `--d-primary-hover` | N/A (handled by `_base.js`) |
106
+ | A success inline alert background | `--d-success-subtle` | `_bgsuccesssub` |
107
+ | Text in that alert | `--d-success-subtle-fg` | `_fgsuccesssub` |
108
+ | Border on that alert | `--d-success-border` | `_bcsuccessbdr` |
109
+ | An error badge (solid) | `--d-error` | `_bgerror` |
110
+ | Text on that error badge | `--d-error-fg` | `_fgerroron` |
111
+ | A generic informational tag | `--d-info-subtle` | `_bginfosub` |
112
+
113
+ ---
114
+
115
+ ## 3. The 60-30-10 Distribution Rule
116
+
117
+ Color distribution follows a proportional hierarchy that ensures visual balance:
118
+
119
+ | Proportion | Role | Token families | Where it appears |
120
+ |-----------|------|---------------|-----------------|
121
+ | **60%** | Neutrals and surfaces | `--d-bg`, `--d-fg`, `--d-surface-*`, `--d-muted-*`, `--d-border-*` | Page background, card backgrounds, text, borders, chrome |
122
+ | **30%** | Secondary palette | `--d-accent`, `--d-tertiary`, `--d-*-subtle` | Section accents, tags, badges, tinted backgrounds, charts |
123
+ | **10%** | Primary action | `--d-primary`, `--d-success`, `--d-warning`, `--d-error` | CTAs, notifications, active indicators, focus rings |
124
+
125
+ ### Per density-zone breakdown
126
+
127
+ | Zone | 60% (neutrals) | 30% (secondary) | 10% (action) |
128
+ |------|----------------|-----------------|-------------|
129
+ | **Chrome** | Surface-0/1 bg, muted-fg text | Accent badges, icon tints | Active nav indicator |
130
+ | **Controls** | Surface-1 bg, borders, label text | Subtle tints on selected filters | Submit button, validation states |
131
+ | **Content** | Surface-0 bg, fg body text | Accent highlights, chart colors | Links, inline CTAs |
132
+ | **Showcase** | bg/surface-0 breathing space | Gradient backgrounds, accent decoration | Hero CTA button |
133
+ | **Data-dense** | Surface-0/1 bg, grid lines, text | Chart palette, status badges | Error cells, action icons |
134
+
135
+ ### Rules
136
+
137
+ - If primary appears in more than ~15% of the viewport, the UI feels overwhelming. Reduce usage.
138
+ - If neutrals drop below ~50%, the page looks like a color wheel. Add more surface area.
139
+ - Semantic colors (success, warning, error) should appear only when their meaning is present -- never as decoration.
140
+ - The 60-30-10 ratio applies per viewport, not per component. A Button is 100% primary -- but it occupies a small fraction of the screen.
141
+
142
+ ---
143
+
144
+ ## 4. Surface Lightness Architecture
145
+
146
+ Four surface tiers create depth via monotonic lightness progression. The direction depends on mode and elevation type.
147
+
148
+ ### Non-glass styles (clean, retro, command-center)
149
+
150
+ **Dark mode** -- surfaces get progressively lighter:
151
+
152
+ | Surface | Lightness shift | Derivation | Purpose |
153
+ |---------|----------------|-----------|---------|
154
+ | `--d-surface-0` | Base (bgDark) | `bgHex` | Page canvas |
155
+ | `--d-surface-1` | +4 L (OKLCH) | `lighten(bgHex, 4)` | Cards, panels |
156
+ | `--d-surface-2` | +7 L (OKLCH) | `lighten(bgHex, 7)` | Modals, drawers, elevated panels |
157
+ | `--d-surface-3` | +10 L (OKLCH) | `lighten(bgHex, 10)` | Tooltips, popovers, highest emphasis |
158
+
159
+ **Light mode** -- surfaces get progressively tinted:
160
+
161
+ | Surface | Mix ratio | Derivation | Purpose |
162
+ |---------|----------|-----------|---------|
163
+ | `--d-surface-0` | Base (bg) | `bgHex` | Page canvas |
164
+ | `--d-surface-1` | 4% neutral | `mixColors(bgHex, neutralHex, 0.04)` | Cards, panels |
165
+ | `--d-surface-2` | 7% neutral | `mixColors(bgHex, neutralHex, 0.07)` | Elevated panels |
166
+ | `--d-surface-3` | 10% neutral | `mixColors(bgHex, neutralHex, 0.10)` | Highest emphasis |
167
+
168
+ ### Glass styles (auradecantism, glassmorphism)
169
+
170
+ Glass surfaces use alpha transparency + backdrop-filter instead of lightness shifts:
171
+
172
+ | Surface | Dark alpha | Light alpha | Backdrop-filter |
173
+ |---------|-----------|-------------|----------------|
174
+ | `--d-surface-0` | 1.0 (base) | 1.0 (base) | None |
175
+ | `--d-surface-1` | 0.55-0.70 | 0.60 | `blur(12-16px) saturate(1.4-1.6)` |
176
+ | `--d-surface-2` | 0.70-0.78 | 0.72 | `blur(16-20px) saturate(1.5-1.8)` |
177
+ | `--d-surface-3` | 0.80-0.85 | 0.82 | `blur(20-24px) saturate(1.6-2.0)` |
178
+
179
+ ### Surface-specific tokens
180
+
181
+ Each surface tier has three companions:
182
+
183
+ | Token | Purpose |
184
+ |-------|---------|
185
+ | `--d-surface-{N}` | Background color |
186
+ | `--d-surface-{N}-fg` | Text color on that surface |
187
+ | `--d-surface-{N}-border` | Border color appropriate for that surface |
188
+ | `--d-surface-{N}-filter` | Backdrop-filter (glass styles only, tiers 1-3) |
189
+
190
+ ### Rules
191
+
192
+ - **Monotonic progression**: Surface-0 is always the base. Each tier adds exactly one level of visual elevation. Never skip tiers (surface-0 directly to surface-3).
193
+ - **Containment holds**: A surface-2 element should contain surface-1 or surface-0 children -- never surface-3.
194
+ - **Never pure black**: The darkest dark-mode background (`bgDark`) should be at least `#050a10` (command-center) or `#060918` (auradecantism). Pure `#000000` causes eye strain and removes all depth perception.
195
+ - **Never pure white**: The lightest light-mode background should be `#ffffff` at most, but surfaces tint away from it. Pure white `#fff` for the base is acceptable; surfaces must be tinted.
196
+
197
+ ---
198
+
199
+ ## 5. Color Harmony Types
200
+
201
+ Color harmony describes how seed colors relate on the color wheel. Decantr's built-in styles demonstrate five harmony types:
202
+
203
+ | Harmony type | Hue relationship | Built-in example | Character feel |
204
+ |-------------|-----------------|-----------------|---------------|
205
+ | **Monochromatic** | Single hue, varies by L/S | command-center (cyan only) | Technical, focused, military |
206
+ | **Complementary** | 180deg apart | N/A (too high contrast for full UI) | Bold, dramatic (use sparingly) |
207
+ | **Analogous** | Within 60deg | glassmorphism (sky-blue + cyan + green) | Calm, harmonious, natural |
208
+ | **Triadic** | 120deg apart | auradecantism (pink + cyan + purple) | Vibrant, energetic, creative |
209
+ | **Analogous-cool** | Within ~80deg | clean (blue + violet + teal) | Balanced, versatile, professional |
210
+ | **Tetradic** | Two complementary pairs | retro (red + blue + teal + orange) | Complex, eclectic, maximalist |
211
+
212
+ ### Decision table: personality to harmony
213
+
214
+ | Character traits | Recommended harmony | Reasoning |
215
+ |-----------------|-------------------|-----------|
216
+ | minimal, clean, focused | Monochromatic or analogous | Restraint; fewer hue contrasts reduce visual noise |
217
+ | professional, balanced, corporate | Analogous-cool or split-complementary | Versatility without chaos; distinct accent |
218
+ | bold, creative, playful | Triadic | Energy and variety from evenly spaced hues |
219
+ | tactical, operational, technical | Monochromatic | Single-hue focus communicates precision |
220
+ | luxurious, editorial, premium | Analogous | Sophisticated restraint with depth |
221
+ | eclectic, retro, maximalist | Tetradic | High variety enables neobrutalist expression |
222
+
223
+ ### Hue distance rules
224
+
225
+ - **Palette roles** (primary, accent, tertiary) should be at least 30deg apart on the hue wheel for distinguishability.
226
+ - **Semantic roles** (success, warning, error) have fixed hue associations (green, amber, red) regardless of harmony. Never reassign red to success or green to error.
227
+ - The `info` role should be blue-adjacent. If primary is already blue, info can match primary.
228
+
229
+ ---
230
+
231
+ ## 6. Light vs Dark Mode Color Math
232
+
233
+ The `derive()` function branches on mode for every derived token. The core differences:
234
+
235
+ ### Foreground/Background
236
+
237
+ | Token | Light mode | Dark mode |
238
+ |-------|-----------|----------|
239
+ | `--d-bg` | `seed.bg` (e.g. `#ffffff`) | `seed.bgDark` (e.g. `#0a0a0a`) |
240
+ | `--d-fg` | `#09090b` (near-black) | `#fafafa` (near-white) |
241
+ | `--d-overlay` | `rgba(0,0,0,0.5)` | `rgba(0,0,0,0.7)` |
242
+
243
+ ### Palette color derivation (per role)
244
+
245
+ | Modifier | Light mode | Dark mode |
246
+ |----------|-----------|----------|
247
+ | `hover` | `darken(base, hoverShift)` | `lighten(base, hoverShift)` |
248
+ | `active` | `darken(base, activeShift)` | `lighten(base, hoverShift/2)` |
249
+ | `subtle` | `alpha(base, subtleAlphaLight)` | `alpha(base, subtleAlphaDark)` |
250
+ | `subtle-fg` | `darken(base, 10)` | `lighten(base, 15)` |
251
+ | `border` | `alpha(base, borderAlphaLight)` | `alpha(base, borderAlphaDark)` |
252
+ | `fg` | `pickForeground(base)` -- white or near-black | `pickForeground(base)` -- same logic |
253
+
254
+ ### Shift intensities by elevation type
255
+
256
+ | Elevation | Hover shift | Active shift | Subtle alpha (L/D) | Border alpha (L/D) |
257
+ |-----------|-----------|-------------|--------------------|--------------------|
258
+ | flat | 8 | 15 | 0.10 / 0.15 | 0.30 / 0.40 |
259
+ | subtle | 8 | 15 | 0.10 / 0.15 | 0.30 / 0.40 |
260
+ | raised | 8 | 15 | 0.10 / 0.15 | 0.30 / 0.40 |
261
+ | glass | 5 | 10 | 0.20 / 0.25 | 0.20 / 0.30 |
262
+ | brutalist | 12 | 20 | 0.15 / 0.20 | 0.80 / 0.80 |
263
+
264
+ ### Neutral derivation
265
+
266
+ | Token | Light mode | Dark mode |
267
+ |-------|-----------|----------|
268
+ | `--d-muted` | `neutralHex` (unchanged) | `lighten(neutralHex, 10)` |
269
+ | `--d-muted-fg` | `darken(neutralHex, 10)` | `lighten(neutralHex, 25)` |
270
+ | `--d-border` | `darken(bgHex, 12)` | `lighten(bgHex, 12)` |
271
+ | `--d-border-strong` | `darken(bgHex, 30)` | `lighten(bgHex, 25)` |
272
+
273
+ ### Chart tokens
274
+
275
+ | Token | Light mode | Dark mode |
276
+ |-------|-----------|----------|
277
+ | `--d-chart-grid` | `rgba(0,0,0,0.06)` | `rgba(255,255,255,0.08)` |
278
+ | `--d-chart-axis` | `rgba(0,0,0,0.3)` | `rgba(255,255,255,0.3)` |
279
+ | `--d-chart-crosshair` | `rgba(0,0,0,0.3)` | `rgba(255,255,255,0.4)` |
280
+
281
+ ### Rules
282
+
283
+ - **Never pure black** in dark mode: use `#09090b` for text or `#0a0a0a` for backgrounds. Pure `#000` creates infinite contrast that is harsh on eyes.
284
+ - **Elevation via lightness**: In dark mode, "higher" surfaces are lighter -- opposite of real-world shadows. This is correct perceptually because screens emit light.
285
+ - **Hover direction inverts**: Light mode darkens on hover (pressing into surface), dark mode lightens on hover (illuminating surface). The shift magnitudes are identical.
286
+ - **Subtle alpha increases in dark mode**: Dark backgrounds need higher alpha to achieve the same perceived tint. Glass styles use higher base alpha for this reason.
287
+
288
+ ---
289
+
290
+ ## 7. Contrast and Accessibility Requirements
291
+
292
+ ### WCAG 2.1 AA thresholds
293
+
294
+ | Content type | Minimum contrast ratio | Applies to |
295
+ |-------------|----------------------|-----------|
296
+ | Normal text (<18px or <14px bold) | 4.5:1 | Body text, labels, descriptions, button text |
297
+ | Large text (>=18px or >=14px bold) | 3:1 | Headings, display text |
298
+ | Non-text (UI components, icons) | 3:1 | Borders, icons, focus indicators, form outlines |
299
+
300
+ ### The 24 validated pairs (20 text + 4 non-text)
301
+
302
+ `validateContrast()` in `derive.js` checks and auto-adjusts these pairs at token generation time:
303
+
304
+ | Foreground token | Background token | Min ratio |
305
+ |-----------------|-----------------|-----------|
306
+ | `--d-primary-fg` | `--d-primary` | 4.5 |
307
+ | `--d-accent-fg` | `--d-accent` | 4.5 |
308
+ | `--d-tertiary-fg` | `--d-tertiary` | 4.5 |
309
+ | `--d-success-fg` | `--d-success` | 4.5 |
310
+ | `--d-warning-fg` | `--d-warning` | 4.5 |
311
+ | `--d-error-fg` | `--d-error` | 4.5 |
312
+ | `--d-info-fg` | `--d-info` | 4.5 |
313
+ | `--d-fg` | `--d-bg` | 4.5 |
314
+ | `--d-muted-fg` | `--d-bg` | 4.5 |
315
+ | `--d-surface-0-fg` | `--d-surface-0` | 4.5 |
316
+ | `--d-surface-1-fg` | `--d-surface-1` | 4.5 |
317
+ | `--d-surface-2-fg` | `--d-surface-2` | 4.5 |
318
+ | `--d-surface-3-fg` | `--d-surface-3` | 4.5 |
319
+ | `--d-primary-subtle-fg` | `--d-primary-subtle` | 4.5 |
320
+ | `--d-error-subtle-fg` | `--d-error-subtle` | 4.5 |
321
+ | `--d-success-subtle-fg` | `--d-success-subtle` | 4.5 |
322
+ | `--d-warning-subtle-fg` | `--d-warning-subtle` | 4.5 |
323
+ | `--d-info-subtle-fg` | `--d-info-subtle` | 4.5 |
324
+ | `--d-accent-subtle-fg` | `--d-accent-subtle` | 4.5 |
325
+ | `--d-tertiary-subtle-fg` | `--d-tertiary-subtle` | 4.5 |
326
+ | **Non-text (3:1)** | | |
327
+ | `--d-border` | `--d-bg` | 3 |
328
+ | `--d-surface-1-border` | `--d-surface-1` | 3 |
329
+ | `--d-surface-2-border` | `--d-surface-2` | 3 |
330
+ | `--d-surface-3-border` | `--d-surface-3` | 3 |
331
+
332
+ ### Auto-adjustment algorithm
333
+
334
+ When a pair fails the threshold, `adjustForContrast()` iteratively adjusts the foreground:
335
+
336
+ 1. Determine direction: if background luminance < 0.5, lighten foreground; otherwise darken it.
337
+ 2. Shift L by 2% per iteration (up to 50 iterations).
338
+ 3. If contrast threshold is met, use the adjusted value.
339
+ 4. Fallback: pure white (`#ffffff`) for dark backgrounds, near-black (`#09090b`) for light backgrounds.
340
+
341
+ ### Rules
342
+
343
+ - **Never assume a color pair passes**: Always use paired tokens (`--d-{role}` with `--d-{role}-fg`). The derive engine guarantees contrast only for declared pairs.
344
+ - **Opacity reduces contrast**: `_bgprimary/50` on a white background halves the effective contrast. Validate manually when using opacity modifiers.
345
+ - **Focus indicators**: Must have 3:1 contrast against adjacent colors. The `--d-ring` token defaults to `var(--d-primary)`, which is validated against `--d-bg`.
346
+ - **Placeholder text**: Should use `--d-muted` (NOT `--d-muted-fg`). The WCAG requirement for placeholder is 3:1 (non-text), not 4.5:1.
347
+
348
+ ### APCA reference (future consideration)
349
+
350
+ APCA (Accessible Perceptual Contrast Algorithm) provides perceptually linear contrast measurement. When browser support matures, Decantr may adopt APCA thresholds (Lc 60+ for body text, Lc 45+ for large text). Current implementation uses WCAG 2.1 relative luminance.
351
+
352
+ ---
353
+
354
+ ## 8. Colorblind Safety and Colorblind Mode
355
+
356
+ ### Prevalence
357
+
358
+ Approximately 8% of males and 0.5% of females have some form of color vision deficiency (CVD). The three primary types:
359
+
360
+ | Type | Affected cone | Prevalence (male) | Colors confused |
361
+ |------|-------------|-------------------|----------------|
362
+ | Deuteranopia | Green (M-cone) | ~6% | Red-green |
363
+ | Protanopia | Red (L-cone) | ~2% | Red-green |
364
+ | Tritanopia | Blue (S-cone) | ~0.01% | Blue-yellow |
365
+
366
+ ### Architecture: colorblind mode as orthogonal axis
367
+
368
+ Colorblind mode is a new orthogonal axis in the token system:
369
+
370
+ ```
371
+ Style x Mode x Shape x ColorblindMode
372
+ ```
373
+
374
+ API (planned):
375
+ ```javascript
376
+ setColorblindMode('protanopia' | 'deuteranopia' | 'tritanopia' | 'off');
377
+ getColorblindMode();
378
+ ```
379
+
380
+ ### Seed transformation approach
381
+
382
+ Rather than maintaining separate palettes, colorblind mode transforms the existing seeds before passing them to `derive()`. This preserves all 171+ token derivations -- only the input changes.
383
+
384
+ | Original role | Protanopia shift | Deuteranopia shift | Tritanopia shift |
385
+ |-------------|-----------------|-------------------|-----------------|
386
+ | success (green) | Shift toward blue-green (+30deg H) | Shift toward blue-green (+30deg H) | Shift toward green (-20deg H) |
387
+ | error (red) | Increase L contrast, add orange shift | Increase L contrast, add orange shift | Keep red (unaffected) |
388
+ | warning (amber) | Keep amber (distinguishable) | Keep amber (distinguishable) | Shift toward red-orange (-15deg H) |
389
+
390
+ ### Wong/Okabe-Ito chart palette (CVD-safe)
391
+
392
+ For chart data with colorblind mode active, use these 8 colors that remain distinguishable under all CVD types:
393
+
394
+ | Index | Hex | Name |
395
+ |-------|-----|------|
396
+ | 0 | `#E69F00` | Orange |
397
+ | 1 | `#56B4E9` | Sky blue |
398
+ | 2 | `#009E73` | Bluish green |
399
+ | 3 | `#F0E442` | Yellow |
400
+ | 4 | `#0072B2` | Blue |
401
+ | 5 | `#D55E00` | Vermilion |
402
+ | 6 | `#CC79A7` | Reddish purple |
403
+ | 7 | `#000000` | Black |
404
+
405
+ ### Design rules for CVD safety (always, not just in CB mode)
406
+
407
+ - **Never encode meaning with color alone**: Always pair color with shape (icons), text (labels), or pattern (hatching on charts).
408
+ - **Red-green is the danger zone**: Never use red vs green as the only differentiator. Use red vs blue, or add iconography.
409
+ - **Test with simulators**: Chrome DevTools > Rendering > Emulate vision deficiencies.
410
+ - **Lightness is the safest channel**: When two colors must be distinguishable, ensure they differ in lightness by at least 30 L* (CIELAB).
411
+
412
+ ---
413
+
414
+ ## 9. Chart Color Guidelines
415
+
416
+ ### Token inventory (37 total)
417
+
418
+ | Token family | Count | Purpose |
419
+ |-------------|-------|---------|
420
+ | `--d-chart-{0-7}` | 8 | Base series colors (resolved hex for SVG/canvas) |
421
+ | `--d-chart-{0-7}-ext-{1-3}` | 24 | Extended palette per base (lightness/hue variations) |
422
+ | `--d-chart-tooltip-bg` | 1 | Tooltip background (`var(--d-surface-2)`) |
423
+ | `--d-chart-grid` | 1 | Grid line color (low-alpha black/white) |
424
+ | `--d-chart-axis` | 1 | Axis line color |
425
+ | `--d-chart-crosshair` | 1 | Interactive crosshair color |
426
+ | `--d-chart-selection` | 1 | Selection highlight area |
427
+
428
+ ### Base chart colors (derived from seeds)
429
+
430
+ | Token | Source seed | Rationale |
431
+ |-------|-----------|-----------|
432
+ | `--d-chart-0` | `primary` | Primary data series |
433
+ | `--d-chart-1` | `accent` | Secondary series |
434
+ | `--d-chart-2` | `tertiary` | Third series |
435
+ | `--d-chart-3` | `success` | Positive/growth series |
436
+ | `--d-chart-4` | `warning` | Caution series |
437
+ | `--d-chart-5` | `error` | Negative/loss series |
438
+ | `--d-chart-6` | `info` | Informational series |
439
+ | `--d-chart-7` | `neutral` | Baseline/reference series |
440
+
441
+ ### Extended palette derivation
442
+
443
+ Each base color gets 3 variations for sub-series:
444
+
445
+ | Extension | Dark mode | Light mode |
446
+ |-----------|----------|-----------|
447
+ | `ext-1` | `lighten(base, 15)` | `darken(base, 15)` |
448
+ | `ext-2` | `rotateHue(base, +30deg)` | `rotateHue(base, +30deg)` |
449
+ | `ext-3` | `lighten(rotateHue(base, -30deg), 10)` | `darken(rotateHue(base, -30deg), 10)` |
450
+
451
+ ### Rules
452
+
453
+ - **Maximum 8 distinguishable series**: Human perception reliably differentiates ~7 colors in a chart. Beyond 8, use grouping, highlighting, or interactive filtering.
454
+ - **Chart colors are resolved hex**: Unlike most tokens, `--d-chart-*` values are plain hex (not `var()` references) because SVG `fill`/`stroke` and Canvas APIs require resolved values.
455
+ - **Sequential data**: Use a single hue with lightness ramp (e.g., `--d-chart-0`, `--d-chart-0-ext-1`, `--d-chart-0-ext-3`).
456
+ - **Categorical data**: Use base colors 0-7 for maximum hue separation.
457
+ - **Diverging data**: Use two hues from opposite ends (e.g., `--d-chart-5` for negative, `--d-chart-3` for positive) with neutral midpoint.
458
+ - **Chart backgrounds**: Use `transparent` or inherit from the surface. Never give charts their own background color.
459
+ - **Grid and axis colors**: Use the provided low-alpha tokens. Never use solid lines for chart grids.
460
+
461
+ ### Style-specific chart overrides
462
+
463
+ Auradecantism, glassmorphism, and command-center provide dark-mode chart color overrides for optimal vibrancy on dark backgrounds. These are specified in the style's `overrides.dark` block and take precedence over the derived defaults.
464
+
465
+ ---
466
+
467
+ ## 10. Gradient Token Usage
468
+
469
+ ### Token inventory (10 total)
470
+
471
+ | Token | Value (gradient=vivid) | Value (gradient=none) | Purpose |
472
+ |-------|----------------------|---------------------|---------|
473
+ | `--d-gradient-brand` | `linear-gradient(135deg, primary, accent)` | `var(--d-primary)` | Primary brand gradient (buttons, heroes) |
474
+ | `--d-gradient-brand-alt` | `linear-gradient(135deg, accent, tertiary)` | `var(--d-accent)` | Alternative brand gradient |
475
+ | `--d-gradient-brand-full` | `linear-gradient(135deg, primary, accent, tertiary)` | `var(--d-primary)` | Full spectrum brand gradient |
476
+ | `--d-gradient-surface` | `linear-gradient(180deg, surface-0, surface-1)` | `var(--d-surface-0)` | Subtle surface depth gradient |
477
+ | `--d-gradient-overlay` | `linear-gradient(180deg, transparent, overlay)` | Same | Image overlay / scrim |
478
+ | `--d-gradient-subtle` | `linear-gradient(180deg, transparent, primary-subtle)` | `transparent` | Section fade-in accent |
479
+ | `--d-gradient-text` | `linear-gradient(135deg, primary, accent)` | `var(--d-primary)` | Gradient text fill |
480
+ | `--d-gradient-text-alt` | `linear-gradient(135deg, accent, tertiary)` | `var(--d-accent)` | Alternative gradient text fill |
481
+ | `--d-gradient-angle` | `135deg` | `135deg` | Base gradient angle |
482
+ | `--d-gradient-intensity` | `1` | `0` | Binary flag: 0=solid, 1=gradient |
483
+
484
+ ### When to use which
485
+
486
+ | Scenario | Token | Notes |
487
+ |----------|-------|-------|
488
+ | Hero headline text | `--d-gradient-text` with `.d-gradient-text` class | Only with vivid/mesh gradient personality |
489
+ | Primary CTA on hero | `--d-gradient-brand` as background | Attention-grabbing; use sparingly |
490
+ | Section ambient tint | `--d-gradient-subtle` | Barely visible; use for section differentiation |
491
+ | Image card overlay | `--d-gradient-overlay` | Makes text readable over images |
492
+ | Surface depth effect | `--d-gradient-surface` | Adds depth without color; safe for all contexts |
493
+ | Check if gradients active | `--d-gradient-intensity` | `0` = solid fills preferred; `1` = gradients enabled |
494
+
495
+ ### Composable gradient atoms
496
+
497
+ For custom gradients beyond tokens, use the composable gradient system:
498
+
499
+ ```javascript
500
+ css('_gradBR _fromPrimary _toAccent') // bottom-right gradient
501
+ css('_gradR _fromPrimary _viaSuccess _toTransparent') // three-stop gradient
502
+ ```
503
+
504
+ See `reference/atoms.md` for the full list of direction, from, via, and to atoms.
505
+
506
+ ### Mesh gradient composition
507
+
508
+ Mesh backgrounds (used by auradecantism, glassmorphism, command-center) layer multiple radial gradients:
509
+
510
+ ```css
511
+ /* auradecantism .d-mesh */
512
+ background:
513
+ radial-gradient(ellipse at 20% 50%, rgba(primary, 0.15), transparent 50%),
514
+ radial-gradient(ellipse at 80% 20%, rgba(accent, 0.10), transparent 50%),
515
+ radial-gradient(ellipse at 60% 80%, rgba(tertiary, 0.08), transparent 50%),
516
+ var(--d-bg);
517
+ ```
518
+
519
+ Rules: always layer on top of `var(--d-bg)` as the final stop; use low opacity (0.04-0.15); position ellipses off-center for organic feel.
520
+
521
+ ---
522
+
523
+ ## 11. Color Psychology and Brand Application
524
+
525
+ ### Color-emotion associations (Western cultural context)
526
+
527
+ | Hue range | Primary associations | Secondary associations | Caution |
528
+ |-----------|---------------------|----------------------|---------|
529
+ | Red (0-15deg) | Energy, urgency, passion | Danger, error, stop | Universally associated with error/danger in UI |
530
+ | Orange (15-45deg) | Warmth, enthusiasm, creativity | Warning, attention | Can feel less serious; good for CTAs |
531
+ | Yellow (45-70deg) | Optimism, clarity, caution | Warning, highlight | Low contrast on white; needs dark text |
532
+ | Green (70-165deg) | Growth, success, nature | Go/proceed, safety, money | Universal positive indicator in UI |
533
+ | Teal/Cyan (165-195deg) | Trust, technology, calm | Info, coolness | Good primary for SaaS/tech |
534
+ | Blue (195-255deg) | Trust, stability, professionalism | Corporate, communication | Most common primary in enterprise UI |
535
+ | Purple (255-300deg) | Creativity, luxury, wisdom | Premium, spiritual | Often reads as "creative" or "premium" |
536
+ | Pink/Magenta (300-345deg) | Playfulness, boldness, warmth | Fashion, emotion | High energy; use as accent or primary |
537
+
538
+ ### Cultural differences (non-exhaustive)
539
+
540
+ | Color | Western | East Asian | Middle Eastern |
541
+ |-------|---------|-----------|---------------|
542
+ | Red | Danger, passion | Luck, prosperity, celebration | Danger, caution |
543
+ | White | Purity, clean | Death, mourning (some contexts) | Purity, peace |
544
+ | Green | Nature, go | Youth, growth | Islam, paradise |
545
+ | Yellow | Warning, optimism | Royalty (imperial China) | Happiness, wealth |
546
+ | Black | Elegance, death | Power, mystery | Death, evil (some contexts) |
547
+
548
+ ### Decision table: brand archetype to seed hue
549
+
550
+ | Brand archetype | Primary hue range | Accent strategy | Example styles |
551
+ |----------------|------------------|----------------|---------------|
552
+ | **Trustworthy / Corporate** | Blue (210-240deg) | Complementary warm (orange/amber) | clean |
553
+ | **Innovative / Tech** | Cyan-blue (180-210deg) | Analogous cool (teal/purple) | glassmorphism |
554
+ | **Bold / Disruptive** | Red-pink (330-15deg) | Triadic (cyan + purple) | auradecantism |
555
+ | **Natural / Sustainable** | Green (120-150deg) | Analogous earth (brown/amber) | clean with green seed |
556
+ | **Premium / Luxury** | Purple-violet (270-300deg) | Monochromatic or gold accent | glassmorphism with purple seed |
557
+ | **Operational / Military** | Cyan (180-195deg) | Monochromatic | command-center |
558
+ | **Playful / Creative** | Pink-orange (330-30deg) | Split-complementary | auradecantism or retro |
559
+
560
+ ---
561
+
562
+ ## 12. Bouquet Layer (Decantation Process)
563
+
564
+ In the Decantation Process, the **Bouquet** is the color personality derived from Character traits. During SETTLE, Character words map to palette preferences:
565
+
566
+ ### Character trait to palette mapping
567
+
568
+ | Character trait | Chroma preference | Hue temperature | Gradient intensity | Surface contrast |
569
+ |----------------|-------------------|-----------------|-------------------|-----------------|
570
+ | minimal | Low | Cool-neutral | none | Low (surfaces close in lightness) |
571
+ | clean | Medium-low | Neutral | none | Medium |
572
+ | professional | Medium | Cool blue | none or subtle | Medium |
573
+ | bold | High | Warm or triadic | vivid | High |
574
+ | playful | High | Warm multicolor | vivid or mesh | Medium-high |
575
+ | luxurious | Medium | Cool or warm purple | subtle or vivid | Low-medium |
576
+ | technical | Low-medium | Cool cyan | none | Medium (high in data-dense) |
577
+ | tactical | Low | Cool monochrome | none | High (sharp boundaries) |
578
+ | editorial | Medium | Warm neutral | subtle | Low (content-focused) |
579
+ | energetic | High | Warm triadic | vivid or mesh | High |
580
+
581
+ ### Chroma and saturation rules
582
+
583
+ - **Low chroma** (minimal, tactical): Seed colors should have HSL saturation < 60%. Muted palettes. Neutrals dominate.
584
+ - **Medium chroma** (professional, clean): Seed saturation 40-70%. Primary stands out; other roles are muted.
585
+ - **High chroma** (bold, playful): Seed saturation > 65%. Vivid palette. Multiple roles compete for attention -- the 60-30-10 rule becomes critical.
586
+
587
+ ### Cork rule (anti-drift)
588
+
589
+ Once a Bouquet profile is established in the Essence, all generated code must maintain it. A "minimal" project should never produce vivid gradient buttons. A "tactical" project should never use warm pink accents. The cork validates:
590
+
591
+ 1. Gradient usage matches `--d-gradient-intensity` from the Vintage.
592
+ 2. Color atoms used in generated code stay within the declared role tokens.
593
+ 3. Custom `define()` colors do not introduce hues outside the seed palette.
594
+
595
+ ---
596
+
597
+ ## 13. OKLCH Color Space and P3 Gamut
598
+
599
+ ### Why OKLCH
600
+
601
+ OKLCH (Oklab Lightness, Chroma, Hue) is a perceptually uniform color space. Unlike HSL:
602
+
603
+ | Property | HSL | OKLCH |
604
+ |----------|-----|-------|
605
+ | Perceptual uniformity | No -- equal L shifts produce unequal perceived brightness | Yes -- L 0.5 looks equally bright across all hues |
606
+ | Gamut | sRGB only | Supports P3 and Rec.2020 |
607
+ | Hue stability | Hue shifts affect perceived lightness | Hue shifts preserve perceived lightness |
608
+ | Chroma behavior | Saturation 100% means different vividness per hue | Chroma is absolute -- comparable across hues |
609
+
610
+ ### OKLCH channel meanings
611
+
612
+ | Channel | Range | Meaning |
613
+ |---------|-------|---------|
614
+ | L (Lightness) | 0-1 | Perceived brightness (0 = black, 1 = white) |
615
+ | C (Chroma) | 0-0.4+ | Color intensity / saturation (0 = gray) |
616
+ | H (Hue) | 0-360deg | Color angle on the perceptual color wheel |
617
+
618
+ ### Implementation
619
+
620
+ Decantr's `derive.js` uses OKLCH for all color math. Key functions in `src/css/derive.js`:
621
+
622
+ - `rgbToOklch(r, g, b)` — Convert sRGB (0-255) to OKLCH `{ L, C, H }`
623
+ - `oklchToRgb(L, C, H)` — Convert OKLCH back to sRGB with gamut mapping
624
+ - `gamutMap(L, C, H)` — Clamp out-of-gamut OKLCH colors to sRGB via binary search on chroma
625
+ - `lighten(hex, amount)` — Shift OKLCH L upward (perceptually uniform)
626
+ - `darken(hex, amount)` — Shift OKLCH L downward (perceptually uniform)
627
+ - `mixColors(hex1, hex2, weight)` — Interpolate two colors in OKLCH space
628
+ - `rotateHue(hex, degrees)` — Rotate OKLCH H while preserving L and C
629
+
630
+ All operations are perceptually uniform -- a 4-unit lightness shift looks the same whether the hue is yellow (H=100) or blue (H=260). Seed colors remain hex (sRGB) for backward compatibility; derived tokens output hex via `oklchToRgb()` + `gamutMap()`.
631
+
632
+ ### P3 gamut opportunity
633
+
634
+ Display P3 gamut enables colors 25% more vivid than sRGB -- particularly in cyan, green, and deep red/magenta ranges. Since `derive.js` already operates in OKLCH, a future P3 output path would add `oklch()` or `color(display-p3 ...)` CSS with sRGB fallbacks. Relevant styles:
635
+
636
+ - **Auradecantism**: Neon cyan (`#0AF3EB`) and hot pink (`#FE4474`) approach sRGB gamut boundaries.
637
+ - **Glassmorphism**: Sky-blue and green accents benefit from P3 chroma.
638
+ - **Command-center**: Cyan (`#00e5ff`) is near-P3-only at full chroma.
639
+
640
+ ### Rules
641
+
642
+ - Use `lighten(hex, amount)` and `darken(hex, amount)` for lightness shifts. The amount is an OKLCH L shift (perceptually uniform across all hues).
643
+ - All hue rotations preserve perceived lightness -- no HSL-era compensation needed.
644
+ - When choosing seed colors, verify that hover/active states derived from them remain visually distinct. `validateContrast()` in `derive.js` auto-adjusts pairs that fail WCAG AA.
645
+
646
+ ---
647
+
648
+ ## 14. Style Seed Inventories
649
+
650
+ Complete seed tables for all 5 built-in styles.
651
+
652
+ ### Auradecantism (default)
653
+
654
+ | Seed | Hex | OKLCH approx (L, C, H) | Character |
655
+ |------|-----|------------------------|-----------|
656
+ | primary | `#FE4474` | 0.63, 0.22, 12deg | Hot pink -- energetic, bold |
657
+ | accent | `#0AF3EB` | 0.87, 0.15, 195deg | Electric cyan -- futuristic |
658
+ | tertiary | `#6500C6` | 0.35, 0.24, 303deg | Deep purple -- creative |
659
+ | neutral | `#8892a4` | 0.63, 0.03, 255deg | Cool gray-blue |
660
+ | success | `#00C388` | 0.70, 0.16, 165deg | Emerald |
661
+ | warning | `#FDA303` | 0.78, 0.17, 75deg | Amber |
662
+ | error | `#EF233C` | 0.55, 0.23, 25deg | Crimson |
663
+ | info | `#0AF3EB` | 0.87, 0.15, 195deg | Same as accent |
664
+ | bg | `#f0f4ff` | 0.96, 0.02, 265deg | Cool blue-tinted white |
665
+ | bgDark | `#060918` | 0.07, 0.03, 265deg | Deep navy-black |
666
+
667
+ **Identity**: Vibrant triadic harmony (pink/cyan/purple). High chroma. Gradient=vivid. Glass elevation. Pill radius. The most expressive built-in style.
668
+
669
+ ### Clean
670
+
671
+ | Seed | Hex | OKLCH approx (L, C, H) | Character |
672
+ |------|-----|------------------------|-----------|
673
+ | primary | `#1366D9` | 0.50, 0.17, 255deg | Classic blue |
674
+ | accent | `#7c3aed` | 0.49, 0.24, 295deg | Violet |
675
+ | tertiary | `#0891b2` | 0.57, 0.11, 215deg | Teal |
676
+ | neutral | `#71717a` | 0.52, 0.01, 265deg | True gray |
677
+ | success | `#22c55e` | 0.70, 0.18, 150deg | Green |
678
+ | warning | `#f59e0b` | 0.76, 0.17, 75deg | Amber |
679
+ | error | `#ef4444` | 0.59, 0.22, 25deg | Red |
680
+ | info | `#3b82f6` | 0.59, 0.18, 260deg | Blue |
681
+ | bg | `#ffffff` | 1.00, 0.00, 0deg | Pure white |
682
+ | bgDark | `#0a0a0a` | 0.07, 0.00, 0deg | Near-black |
683
+
684
+ **Identity**: Analogous-cool (blue/violet/teal within ~80deg hue span). Medium chroma. No gradients. Subtle elevation. Rounded radius. The professional safe choice.
685
+
686
+ ### Retro
687
+
688
+ | Seed | Hex | OKLCH approx (L, C, H) | Character |
689
+ |------|-----|------------------------|-----------|
690
+ | primary | `#e63946` | 0.57, 0.21, 22deg | Bold red |
691
+ | accent | `#457b9d` | 0.53, 0.07, 230deg | Dusty blue |
692
+ | tertiary | `#2a9d8f` | 0.60, 0.10, 180deg | Teal |
693
+ | neutral | `#6b7280` | 0.52, 0.02, 255deg | Cool gray |
694
+ | success | `#1a7a42` | 0.47, 0.13, 155deg | Deep green |
695
+ | warning | `#e06600` | 0.61, 0.18, 50deg | Burnt orange |
696
+ | error | `#c41e1e` | 0.47, 0.20, 25deg | Deep red |
697
+ | info | `#2e6b8a` | 0.47, 0.07, 230deg | Steel blue |
698
+ | bg | `#fffef5` | 0.99, 0.01, 95deg | Warm cream |
699
+ | bgDark | `#1a1a1a` | 0.14, 0.00, 0deg | Dark gray |
700
+
701
+ **Identity**: Tetradic (red/blue/teal/orange). Medium-high chroma but desaturated compared to auradecantism. No gradients. Brutalist elevation. Sharp radius. Physical, tactile feel.
702
+
703
+ ### Glassmorphism
704
+
705
+ | Seed | Hex | OKLCH approx (L, C, H) | Character |
706
+ |------|-----|------------------------|-----------|
707
+ | primary | `#38bdf8` | 0.75, 0.14, 230deg | Sky blue |
708
+ | accent | `#22d3ee` | 0.79, 0.13, 210deg | Cyan |
709
+ | tertiary | `#4ade80` | 0.79, 0.18, 150deg | Mint green |
710
+ | neutral | `#6b7a94` | 0.54, 0.03, 250deg | Blue-gray |
711
+ | success | `#4ade80` | 0.79, 0.18, 150deg | Same as tertiary |
712
+ | warning | `#fbbf24` | 0.82, 0.16, 80deg | Gold |
713
+ | error | `#f87171` | 0.66, 0.17, 20deg | Light red |
714
+ | info | `#38bdf8` | 0.75, 0.14, 230deg | Same as primary |
715
+ | bg | `#f0f4f9` | 0.96, 0.01, 245deg | Cool blue-tinted |
716
+ | bgDark | `#0a0c10` | 0.07, 0.01, 250deg | Deep blue-black |
717
+
718
+ **Identity**: Analogous (sky-blue/cyan/green). Cool palette. Vivid gradients. Glass elevation. Pill radius. Atmospheric and stormy.
719
+
720
+ ### Command Center
721
+
722
+ | Seed | Hex | OKLCH approx (L, C, H) | Character |
723
+ |------|-----|------------------------|-----------|
724
+ | primary | `#00e5ff` | 0.84, 0.15, 205deg | Cyan |
725
+ | neutral | `#1a2a3a` | 0.21, 0.03, 245deg | Dark navy |
726
+ | bg | `#c8d6e0` | 0.86, 0.02, 230deg | Light steel |
727
+ | bgDark | `#050a10` | 0.06, 0.02, 250deg | Near-black navy |
728
+
729
+ **Identity**: Monochromatic. Single cyan hue. All 7 palette roles derived from primary via `deriveMonochromeSeed()` within +/-20deg hue. No gradients. Flat elevation. Sharp radius. Monospace font. Military/operational.
730
+
731
+ **Missing seeds** (auto-derived from primary by monochrome palette):
732
+ - accent: H+15deg, S*0.8, L+8
733
+ - tertiary: H-15deg, S*0.7, L-5
734
+ - success: H+10deg, S*0.9, L+12
735
+ - warning: H-8deg, S*1.1, L+5
736
+ - error: H-20deg, S*1.2, L-3
737
+ - info: H+5deg, S*0.6, L+15
738
+
739
+ ---
740
+
741
+ ## 15. Custom Style Color Selection Guide
742
+
743
+ For authors using `registerStyle()` to create custom styles.
744
+
745
+ ### Step 1: Choose primary hue
746
+
747
+ The primary hue sets the brand identity. Reference the color psychology table in section 11. Verify the hue produces sufficient contrast for `--d-primary-fg` on both light and dark backgrounds.
748
+
749
+ ### Step 2: Choose harmony strategy
750
+
751
+ Based on Character traits (section 12), select a harmony type (section 5). Then determine accent and tertiary:
752
+
753
+ | Harmony | Accent formula | Tertiary formula |
754
+ |---------|---------------|-----------------|
755
+ | Monochromatic | Omit (auto-derived within +/-20deg) | Omit (auto-derived) |
756
+ | Analogous | Primary +/- 30-40deg | Primary +/- 60-80deg (same direction) |
757
+ | Split-complementary | Primary + 150deg | Primary - 150deg |
758
+ | Triadic | Primary + 120deg | Primary + 240deg |
759
+
760
+ ### Step 3: Set bg and bgDark
761
+
762
+ | Requirement | Light bg | Dark bgDark |
763
+ |-------------|---------|-------------|
764
+ | Pure neutral | `#ffffff` | `#0a0a0a` |
765
+ | Warm tint | `#fffef5` to `#fef6ee` | `#1a1a1a` |
766
+ | Cool tint | `#f0f4ff` to `#f0f4f9` | `#050a10` to `#060918` |
767
+ | Minimum lightness (dark) | -- | L >= 0.03 (OKLCH) to avoid pure black |
768
+ | Maximum lightness (light) | L <= 100% | -- |
769
+
770
+ ### Step 4: Choose personality traits
771
+
772
+ Personality traits affect how colors are derived (shift intensities, alpha values). Key interactions:
773
+
774
+ | Trait | Color impact |
775
+ |-------|-------------|
776
+ | `elevation: 'glass'` | Lower hover/active shifts (5/10 vs 8/15); higher subtle alpha (0.20/0.25); lower border alpha (0.20/0.30) |
777
+ | `elevation: 'brutalist'` | Higher hover/active shifts (12/20); high border alpha (0.80); high-contrast, bold feel |
778
+ | `gradient: 'vivid'` | Enables gradient tokens; `--d-gradient-intensity: 1` |
779
+ | `gradient: 'none'` | All gradient tokens fall back to solid colors; `--d-gradient-intensity: 0` |
780
+ | `palette: 'monochrome'` | Forces all roles to derive from primary within +/-20deg hue |
781
+
782
+ ### Step 5: Verify and override
783
+
784
+ After calling `derive()`, check:
785
+
786
+ 1. All 24 contrast pairs pass (automatic via `validateContrast()`).
787
+ 2. Surfaces form a visible progression (test visually).
788
+ 3. Hover states are perceptibly different from base (especially for light yellows/greens).
789
+ 4. Use `overrides: { light: {}, dark: {} }` for manual corrections.
790
+
791
+ ### Example: custom warm premium style
792
+
793
+ ```javascript
794
+ registerStyle({
795
+ id: 'premium',
796
+ name: 'Premium',
797
+ seed: {
798
+ primary: '#8b5cf6', // violet
799
+ accent: '#d946ef', // magenta (analogous +30deg)
800
+ tertiary: '#6366f1', // indigo (analogous -30deg)
801
+ neutral: '#71717a',
802
+ success: '#22c55e', warning: '#f59e0b', error: '#ef4444', info: '#8b5cf6',
803
+ bg: '#faf9fc', // warm purple-tinted white
804
+ bgDark: '#0c0a12', // deep purple-black
805
+ },
806
+ personality: { radius: 'pill', elevation: 'glass', motion: 'smooth', borders: 'thin', gradient: 'vivid' },
807
+ });
808
+ ```
809
+
810
+ ---
811
+
812
+ ## 16. DOs and DON'Ts (Enforcement Rules)
813
+
814
+ ### DOs
815
+
816
+ | # | Rule | Rationale |
817
+ |---|------|-----------|
818
+ | 1 | DO use semantic tokens (`--d-primary`, `--d-error`) for all color values | Colors adapt to style/mode changes automatically |
819
+ | 2 | DO pair foreground and background tokens (`--d-{role}` with `--d-{role}-fg`) | Guarantees WCAG AA contrast |
820
+ | 3 | DO use `_fgfg` for primary text, `_fgmutedfg` for secondary text, `_fgmuted` for tertiary text | Three-level text hierarchy via atoms |
821
+ | 4 | DO use subtle variants (`--d-{role}-subtle` + `--d-{role}-subtle-fg`) for inline alerts and badges | Lower visual weight than solid fills |
822
+ | 5 | DO use surface tokens for container backgrounds (`_surface0` through `_surface3`) | Automatic depth progression per style |
823
+ | 6 | DO use `--d-border` for default borders and `--d-border-strong` for emphasis borders | Consistent border system across modes |
824
+ | 7 | DO use `--d-ring` for focus indicators | Coordinated with primary color |
825
+ | 8 | DO use opacity modifiers (`_bgprimary/50`) for transparent overlays | Maintained within the atom system |
826
+ | 9 | DO use `--d-overlay` for modal/dialog backdrops | Correct alpha per mode (0.5 light, 0.7 dark) |
827
+ | 10 | DO use the composable gradient system (`_gradBR _fromPrimary _toAccent`) for custom gradients | Token-backed, responsive-compatible |
828
+ | 11 | DO check `--d-gradient-intensity` before applying gradients | Respects the style's gradient personality |
829
+ | 12 | DO pair color with non-color indicators (icons, text, patterns) | CVD safety; never color alone for meaning |
830
+ | 13 | DO test color choices in both light and dark modes | Colors that work in one mode may fail in the other |
831
+ | 14 | DO use chart tokens (`--d-chart-*`) for all data visualization colors | Resolved hex for SVG/canvas; coordinated per style |
832
+ | 15 | DO respect the 60-30-10 distribution rule | Visual balance and hierarchy |
833
+
834
+ ### DON'Ts
835
+
836
+ | # | Rule | Rationale |
837
+ |---|------|-----------|
838
+ | 1 | DON'T hardcode hex values in component or consumer code | Breaks style/mode switching; bypasses contrast validation |
839
+ | 2 | DON'T use `style: 'color:red'` or `style: 'background:#1a1a1a'` for static colors | Always use atoms or tokens. See `CLAUDE.md` inline-style prohibition |
840
+ | 3 | DON'T use `--d-error` for non-error semantics (e.g., a red brand color) | Error red must mean "error." Use `--d-primary` with a red seed instead |
841
+ | 4 | DON'T use `--d-success` for decoration | Green must mean "positive outcome" |
842
+ | 5 | DON'T mix surface tiers out of order (surface-3 inside surface-0 is wrong) | Breaks monotonic depth perception |
843
+ | 6 | DON'T assume opacity modifiers pass contrast | `_bgprimary/30` on white has ~30% effective contrast of solid |
844
+ | 7 | DON'T use `rgba()` or `hsla()` directly in component code | Not token-backed; won't adapt to style/mode changes |
845
+ | 8 | DON'T use more than 8 colors in a single chart | Beyond 8, humans cannot reliably distinguish colors |
846
+ | 9 | DON'T assign semantic meaning to chart colors (e.g., chart-3 = "revenue") | Chart color indices may change per style |
847
+ | 10 | DON'T use white text on yellow/lime backgrounds | Extremely low contrast; `pickForeground()` will choose dark |
848
+ | 11 | DON'T use `--d-fg` on `--d-primary` (it is white-on-color, not guaranteed) | Use `--d-primary-fg` on `--d-primary` |
849
+ | 12 | DON'T create per-component color variables (`--my-card-bg`) | Use existing surface/palette tokens; custom variables fragment the system |
850
+ | 13 | DON'T lighten/darken tokens at usage site (`color-mix(--d-primary, white 20%)`) | The derive engine handles all variants. Use `--d-{role}-hover` or `--d-{role}-subtle` |
851
+ | 14 | DON'T use pure black (`#000000`) as a background or text color | Use `#09090b` (fg) or `#0a0a0a` (bg) for near-black |
852
+ | 15 | DON'T use gradients when `--d-gradient-intensity` is `0` | The style explicitly opts out of gradients; respect it |
853
+
854
+ ---
855
+
856
+ ## 17. Token-to-Atom Quick Reference
857
+
858
+ Lookup: "I want this visual effect, which atom do I use, and what token backs it?"
859
+
860
+ ### Foreground (text) atoms
861
+
862
+ | Atom | CSS output | Token | Usage |
863
+ |------|-----------|-------|-------|
864
+ | `_fgfg` | `color:var(--d-fg)` | `--d-fg` | Primary body text |
865
+ | `_fgmutedfg` | `color:var(--d-muted-fg)` | `--d-muted-fg` | Secondary/label text |
866
+ | `_fgmuted` | `color:var(--d-muted)` | `--d-muted` | Tertiary/disabled text |
867
+ | `_fgprimary` | `color:var(--d-primary)` | `--d-primary` | Accent text, links |
868
+ | `_fgaccent` | `color:var(--d-accent)` | `--d-accent` | Secondary accent text |
869
+ | `_fgsuccess` | `color:var(--d-success)` | `--d-success` | Success indicator text |
870
+ | `_fgwarning` | `color:var(--d-warning)` | `--d-warning` | Warning indicator text |
871
+ | `_fgerror` | `color:var(--d-error)` | `--d-error` | Error message text |
872
+ | `_fginfo` | `color:var(--d-info)` | `--d-info` | Informational text |
873
+ | `_fgprimaryon` | `color:var(--d-primary-fg)` | `--d-primary-fg` | Text on primary fill |
874
+ | `_fgsuccesssub` | `color:var(--d-success-subtle-fg)` | `--d-success-subtle-fg` | Text on success subtle bg |
875
+
876
+ ### Background atoms
877
+
878
+ | Atom | CSS output | Token | Usage |
879
+ |------|-----------|-------|-------|
880
+ | `_bgbg` | `background:var(--d-bg)` | `--d-bg` | Page background |
881
+ | `_bgmuted` | `background:var(--d-muted)` | `--d-muted` | Muted/disabled background |
882
+ | `_bgprimary` | `background:var(--d-primary)` | `--d-primary` | Primary action fill |
883
+ | `_bgaccent` | `background:var(--d-accent)` | `--d-accent` | Accent fill |
884
+ | `_bgsuccess` | `background:var(--d-success)` | `--d-success` | Success indicator fill |
885
+ | `_bgwarning` | `background:var(--d-warning)` | `--d-warning` | Warning indicator fill |
886
+ | `_bgerror` | `background:var(--d-error)` | `--d-error` | Error indicator fill |
887
+ | `_bgprimarysub` | `background:var(--d-primary-subtle)` | `--d-primary-subtle` | Tinted primary background |
888
+ | `_bgerrorsub` | `background:var(--d-error-subtle)` | `--d-error-subtle` | Tinted error background |
889
+
890
+ ### Surface atoms
891
+
892
+ | Atom | CSS output | Token | Usage |
893
+ |------|-----------|-------|-------|
894
+ | `_surface0` | `background:var(--d-surface-0)` | `--d-surface-0` | Page canvas level |
895
+ | `_surface1` | `background:var(--d-surface-1)` | `--d-surface-1` | Cards, panels |
896
+ | `_surface2` | `background:var(--d-surface-2)` | `--d-surface-2` | Modals, elevated panels |
897
+ | `_surface3` | `background:var(--d-surface-3)` | `--d-surface-3` | Tooltips, highest emphasis |
898
+ | `_fgsurface0` | `color:var(--d-surface-0-fg)` | `--d-surface-0-fg` | Text on surface-0 |
899
+ | `_bcsurface1` | `border-color:var(--d-surface-1-border)` | `--d-surface-1-border` | Border for surface-1 |
900
+
901
+ ### Border color atoms
902
+
903
+ | Atom | CSS output | Token | Usage |
904
+ |------|-----------|-------|-------|
905
+ | `_bcborder` | `border-color:var(--d-border)` | `--d-border` | Default borders |
906
+ | `_bcstrong` | `border-color:var(--d-border-strong)` | `--d-border-strong` | Emphasis borders |
907
+ | `_bcprimary` | `border-color:var(--d-primary)` | `--d-primary` | Primary accent border |
908
+ | `_bcsuccess` | `border-color:var(--d-success)` | `--d-success` | Success state border |
909
+ | `_bcerror` | `border-color:var(--d-error)` | `--d-error` | Error state border |
910
+ | `_bcsuccessbdr` | `border-color:var(--d-success-border)` | `--d-success-border` | Success subtle border |
911
+ | `_bcerrorbdr` | `border-color:var(--d-error-border)` | `--d-error-border` | Error subtle border |
912
+
913
+ ### Opacity modifiers
914
+
915
+ Append `/N` to any color atom for alpha transparency via `color-mix()`:
916
+
917
+ ```javascript
918
+ css('_bgprimary/50') // 50% opacity primary background
919
+ css('_fgaccent/30') // 30% opacity accent text
920
+ css('_bcborder/80') // 80% opacity border
921
+ ```
922
+
923
+ Valid opacities: 5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 75, 80, 90, 95.
924
+
925
+ ---
926
+
927
+ ## 18. Quick Reference Decision Table
928
+
929
+ Master lookup: "I am coloring X -- what token/atom do I use?"
930
+
931
+ | I am coloring... | Token | Atom | Section |
932
+ |-----------------|-------|------|---------|
933
+ | Page background | `--d-bg` | `_bgbg` | S4 Surface |
934
+ | Primary body text | `--d-fg` | `_fgfg` | S2 Roles |
935
+ | Secondary/label text | `--d-muted-fg` | `_fgmutedfg` | S2 Roles |
936
+ | Disabled/tertiary text | `--d-muted` | `_fgmuted` | S2 Roles |
937
+ | Link text | `--d-primary` | `_fgprimary` | S2 Roles |
938
+ | Primary CTA button bg | `--d-primary` | `_bgprimary` | S2 Roles |
939
+ | Primary CTA button text | `--d-primary-fg` | `_fgprimaryon` | S2 Roles |
940
+ | Secondary button bg | `--d-surface-1` or `--d-muted` | `_surface1` or `_bgmuted` | S4 Surface |
941
+ | Card background | `--d-surface-1` | `_surface1` | S4 Surface |
942
+ | Modal background | `--d-surface-2` | `_surface2` | S4 Surface |
943
+ | Tooltip background | `--d-surface-3` | `_surface3` | S4 Surface |
944
+ | Modal backdrop | `--d-overlay` | N/A | S6 Mode Math |
945
+ | Default border | `--d-border` | `_bcborder` | S2 Roles |
946
+ | Emphasis border | `--d-border-strong` | `_bcstrong` | S2 Roles |
947
+ | Focus ring | `--d-ring` | N/A (handled by `_base.js`) | S7 Contrast |
948
+ | Success alert bg | `--d-success-subtle` | `_bgsuccesssub` | S2 Roles |
949
+ | Success alert text | `--d-success-subtle-fg` | `_fgsuccesssub` | S2 Roles |
950
+ | Success alert border | `--d-success-border` | `_bcsuccessbdr` | S2 Roles |
951
+ | Error message text | `--d-error` | `_fgerror` | S2 Roles |
952
+ | Error input border | `--d-error` | `_bcerror` | S2 Roles |
953
+ | Warning badge bg (solid) | `--d-warning` | `_bgwarning` | S2 Roles |
954
+ | Warning badge text | `--d-warning-fg` | `_fgwarningon` | S2 Roles |
955
+ | Chart primary series | `--d-chart-0` | N/A (use token directly) | S9 Charts |
956
+ | Chart grid lines | `--d-chart-grid` | N/A | S9 Charts |
957
+ | Gradient hero text | `--d-gradient-text` | `.d-gradient-text` class | S10 Gradients |
958
+ | Brand gradient bg | `--d-gradient-brand` | N/A (use token as background) | S10 Gradients |
959
+ | Transparent overlay on image | `--d-gradient-overlay` | N/A | S10 Gradients |
960
+ | Selection highlight | `--d-selection-bg` / `--d-selection-fg` | N/A (automatic) | S6 Mode Math |
961
+ | Scrollbar thumb | Style-defined in `components` CSS | N/A | S14 Style Inventories |
962
+
963
+ ---
964
+
965
+ **See also:** `reference/tokens.md`, `reference/atoms.md`, `reference/style-system.md`, `reference/spatial-guidelines.md`, `reference/decantation-process.md`