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,541 @@
1
+ # Spatial Design Language
2
+
3
+ Comprehensive spatial intelligence for Decantr. Every spacing, sizing, and layout decision an LLM makes should be traceable to a rule in this document. Spacing is not decoration — it encodes meaning.
4
+
5
+ ## The Four Functions of Whitespace
6
+
7
+ | Function | What it communicates | Primary tool |
8
+ |----------|---------------------|-------------|
9
+ | **Grouping** | Related elements are close; unrelated are far | Proximity tiers (§4) |
10
+ | **Hierarchy** | More whitespace = more importance | Visual weight rules (§10) |
11
+ | **Rhythm** | Consistent spacing = scannable, predictable | Vertical rhythm (§9) |
12
+ | **Density** | Less spacing = more information | Density zones (§6), density classes (§17) |
13
+
14
+ In the Decantation Process vocabulary, this is the **Clarity** layer — whitespace, density, and compound spacing derived from the Character trait.
15
+
16
+ ---
17
+
18
+ ## 1. The Spacing Scale
19
+
20
+ Decantr's spacing scale (defined in `css/derive.js` as `--d-sp-*` tokens):
21
+
22
+ | Token | Value | Atom | Usage scope |
23
+ |-------|-------|------|-------------|
24
+ | `--d-sp-0-5` | 2px (0.125rem) | `_p0` | Hairline gaps, badge offsets |
25
+ | `--d-sp-1` | 4px (0.25rem) | `_p1` | Icon-text gaps, helper text, micro-spacing |
26
+ | `--d-sp-1-5` | 6px (0.375rem) | — | Button-sm padding, chip gap |
27
+ | `--d-sp-2` | 8px (0.5rem) | `_p2` | Input padding, control gaps, touch target spacing |
28
+ | `--d-sp-2-5` | 10px (0.625rem) | — | Button-lg padding, tab padding |
29
+ | `--d-sp-3` | 12px (0.75rem) | `_p3` | Cell padding, compound-gap default |
30
+ | `--d-sp-4` | 16px (1rem) | `_p4` | **Anchor value.** Default container padding, form field gaps |
31
+ | `--d-sp-5` | 20px (1.25rem) | `_p5` | Compound-pad (dark themes) |
32
+ | `--d-sp-6` | 24px (1.5rem) | `_p6` | Compound-pad (light themes), card padding |
33
+ | `--d-sp-8` | 32px (2rem) | `_p8` | Section inline padding, hero margins |
34
+ | `--d-sp-10` | 40px (2.5rem) | `_p10` | Large layout spacing |
35
+ | `--d-sp-12` | 48px (3rem) | `_p12` | Section block padding |
36
+ | `--d-sp-16` | 64px (4rem) | `_p16` | Hero block padding, landmark spacing |
37
+
38
+ ### Why non-linear
39
+
40
+ The scale follows the Weber-Fechner law: human perception requires proportionally larger differences to notice change at larger magnitudes. The jumps (2→4→8→12→16→24→32→48→64) increase because a 4px difference at 8px is noticeable, but a 4px difference at 48px is invisible.
41
+
42
+ ### The 16px anchor
43
+
44
+ 16px (`--d-sp-4` / `_p4`) is the gravitational center of the spacing system. It is: the default font size, the default container padding, the default form field gap, and a factor of all common screen widths (320, 768, 1024, 1280, 1440, 1920). When in doubt, 16px is the safe default for general component spacing.
45
+
46
+ ### Two scopes
47
+
48
+ | Scope | Range | Purpose | Examples |
49
+ |-------|-------|---------|---------|
50
+ | **Component** | 2-24px (sp-0-5 to sp-6) | Internal padding, gaps between sub-elements | Button padding, icon-text gap, input padding |
51
+ | **Layout** | 24-64px+ (sp-6 to sp-16) | Section margins, page structure, major separators | Hero padding, section gaps, page margins |
52
+
53
+ ---
54
+
55
+ ## 2. Spatial Taxonomy
56
+
57
+ Six concepts that cover nearly all CSS spacing rules (adapted from EightShapes):
58
+
59
+ | Concept | Definition | Ratio | Decantr Pattern | Use Cases |
60
+ |---------|-----------|-------|-----------------|-----------|
61
+ | **Inset** | Equal padding all sides | 1:1:1:1 | `_p4`, `_p6` | Cards, panels, modals, containers, tooltips |
62
+ | **Squish Inset** | Vertical ≈ 50% of horizontal | 0.5:1 | `_py2 _px4`, `_py1 _px3` | Buttons, table cells, list items, chips, tabs |
63
+ | **Stretch Inset** | Vertical > horizontal | 1.5:1 | `_py3 _px2` | Text inputs, textareas, form fields |
64
+ | **Stack** | Vertical gap between siblings | — | `_gap4`, `d-spacey-4` | Vertical content flow (most common) |
65
+ | **Inline** | Horizontal gap between siblings | — | `_gap2`, `d-spacex-2` | Tags, breadcrumbs, button groups, nav items |
66
+ | **Grid** | Layout margins + gutters | — | `_p4 _gap4`, `_gc3 _gap6` | Page layouts, card grids, dashboards |
67
+
68
+ ### When to use which
69
+
70
+ - Building a **button or table cell**? → Squish inset (`_py2 _px4`)
71
+ - Building a **text input**? → Stretch inset (`_py3 _px2`)
72
+ - Building a **card or panel**? → Inset (`_p4` or `_p6`)
73
+ - Stacking **vertical items**? → Stack (`_gap4` on flex column)
74
+ - Arranging **horizontal items**? → Inline (`_gap2` on flex row)
75
+ - Building a **page layout**? → Grid (`_gc3 _gap6 _p4`)
76
+
77
+ ---
78
+
79
+ ## 3. Gestalt Proximity Rules
80
+
81
+ Elements closer together are perceived as related. This is the master spacing principle — it determines which scale value to use based on the semantic relationship between elements.
82
+
83
+ | Tier | Relationship | Scale | Atoms | Examples |
84
+ |------|-------------|-------|-------|---------|
85
+ | **Intimate** | Label→input, icon→text, helper→field | 4-8px | `_gap1`–`_gap2` | Form label above input, icon beside button text, error text below input |
86
+ | **Related** | Field→field, item→item, sibling controls | 12-16px | `_gap3`–`_gap4` | Adjacent form fields, list items, card elements, toolbar buttons |
87
+ | **Grouped** | Group→group, section-header→content | 20-24px | `_gap5`–`_gap6` | Form group → action bar, sidebar sections, card body → footer |
88
+ | **Sectional** | Section→section on a page | 32-48px | `_py8`–`_py12` | Features → testimonials, pricing → CTA, dashboard widgets |
89
+ | **Landmark** | Hero emphasis, page-level breathing | 64-96px | `_py16`–`_py24` | Hero vertical padding, landing page section separation |
90
+
91
+ ### The 50% rule
92
+
93
+ Inner-group spacing must be ≤ 50% of inter-group spacing. If items within a group are `_gap2` (8px) apart, groups themselves must be at least `_gap4` (16px) apart, ideally `_gap6` (24px). This ensures visual grouping is unambiguous.
94
+
95
+ ### Quick decision flow
96
+
97
+ 1. Are these elements part of the **same control**? (icon + label, input + helper) → Intimate
98
+ 2. Are they **siblings of the same type**? (field + field, card + card) → Related
99
+ 3. Are they **distinct groups** within a section? (form + action bar) → Grouped
100
+ 4. Are they **different sections** of a page? → Sectional
101
+ 5. Is this a **hero or primary attention area**? → Landmark
102
+
103
+ ---
104
+
105
+ ## 4. Containment Principle
106
+
107
+ Inner spacing must always be less than outer spacing. This creates visual containment — the Gestalt principle of closure makes padded containers feel like distinct objects.
108
+
109
+ | Container Padding | Internal Gap | Nested Item Gap | Typical Use |
110
+ |-------------------|-------------|-----------------|-------------|
111
+ | `_p8` (32px) | `_gap4`–`_gap6` | `_gap2`–`_gap3` | Page sections, large panels |
112
+ | `_p6` (24px) | `_gap3`–`_gap4` | `_gap2` | Cards, modals, drawers |
113
+ | `_p4` (16px) | `_gap2`–`_gap3` | `_gap1` | Dropdowns, popovers, compact cards |
114
+ | `_p3` (12px) | `_gap2` | `_gap1` | Tooltips, toast bodies, dense panels |
115
+ | `_p2` (8px) | `_gap1` | — | Badges, chips, inline containers |
116
+
117
+ **Rule**: Reduce by 1-2 scale steps per nesting level. If you can't reduce further, the nesting is too deep — flatten the structure.
118
+
119
+ ---
120
+
121
+ ## 5. Functional Density Zones
122
+
123
+ Different UI regions serve different purposes and demand different spacing:
124
+
125
+ | Zone | Intent | Gap | Padding | Applies To |
126
+ |------|--------|-----|---------|-----------|
127
+ | **Chrome** | Scannable tools, navigation | `_gap1`–`_gap2` | `_p1`–`_p2` | Toolbars, nav bars, breadcrumbs, status bars, tab bars |
128
+ | **Controls** | Interactive efficiency | `_gap3`–`_gap4` | `_p3`–`_p4` | Filter sidebars, form groups, settings panels |
129
+ | **Content** | Readable comfort | `_gap4`–`_gap6` | `_p4`–`_p6` | Card bodies, feature grids, article sections |
130
+ | **Showcase** | Visual impact, breathing room | `_gap6`–`_gap8` | `_py12`–`_py16` | Heroes, CTAs, pricing tables, landing sections |
131
+ | **Data-dense** | Maximum information density | `_gap1`–`_gap2` | `_p2`–`_p3` | Data tables, dashboards, analyst tools, monitoring |
132
+
133
+ ### Key rules
134
+
135
+ - Components **inherit their zone's density** — a chip inside chrome doesn't need extra gap
136
+ - A **dashboard page** mixes zones: the toolbar is chrome, the sidebar is controls, the main area is data-dense, and a KPI row might be content
137
+ - **Marketing pages** are mostly showcase + content zones
138
+ - **Application UIs** are mostly controls + content + chrome zones
139
+
140
+ ---
141
+
142
+ ## 6. Responsive Spatial Behavior
143
+
144
+ ### Breakpoint mapping
145
+
146
+ | Class | Width | Grid Columns | Page Margin | Gutter | Nav Pattern |
147
+ |-------|-------|-------------|-------------|--------|-------------|
148
+ | Compact | <640px | 4 | `_px4` (16px) | `_gap4` (16px) | Bottom bar or hamburger |
149
+ | Medium | 640-1023px | 8 | `_px6` (24px) | `_gap4`–`_gap6` | Rail (80px) or collapsible sidebar |
150
+ | Expanded | 1024-1439px | 12 | `_px6`–`_px8` | `_gap6` (24px) | Persistent sidebar (220-360px) |
151
+ | Large | ≥1440px | 12 | auto (centered `_ctrxl`) | `_gap6` (24px) | Persistent sidebar + extra panes |
152
+
153
+ ### What reduces at smaller screens
154
+
155
+ | Property | Desktop | Tablet | Mobile | Reduction |
156
+ |----------|---------|--------|--------|-----------|
157
+ | Page margins | 32px | 24px | 16px | ~50% |
158
+ | Grid gutters | 24px | 16-24px | 16px | ~33% |
159
+ | Section padding | `_py16` (64px) | `_py12` (48px) | `_py8` (32px) | ~50% |
160
+ | Card-to-card spacing | 48px | 32px | 16px | ~67% |
161
+ | Display heading size | Scales down | Scales down | Scales down | Per type scale |
162
+
163
+ ### What stays constant across breakpoints
164
+
165
+ - Component internal padding (button padding doesn't change)
166
+ - Label-to-input gap (always intimate: `_gap1`–`_gap2`)
167
+ - Body-copy-to-button gap (always ~24px / `_gap6`)
168
+ - Card-title-to-body gap (always ~16px / `_gap4`)
169
+ - Touch target minimums (44px on touch devices)
170
+
171
+ ### What transforms (not just shrinks)
172
+
173
+ - **Navigation**: persistent sidebar → rail → bottom bar or hamburger
174
+ - **Side-by-side panes** → stacked vertically
175
+ - **Horizontal tabs** → scrollable tabs or vertical list
176
+ - **Multi-column grid** → fewer columns (not smaller columns)
177
+ - **Decorative elements** may be removed entirely
178
+ - **Content order** may shift via flex direction changes
179
+
180
+ ### Canonical responsive layouts (mapped to blend spec)
181
+
182
+ | Layout | <640px | 640-1023px | ≥1024px | Blend Spec |
183
+ |--------|--------|-----------|---------|-----------|
184
+ | **List-Detail** | One pane at a time | One pane at a time | Both side-by-side | `{ "cols": ["list", "detail"], "at": "lg" }` |
185
+ | **Supporting Panel** | Stacked or bottom sheet | 50/50 split | 70/30 split | `{ "cols": ["main", "support"], "span": {"main": 7, "support": 3}, "at": "md" }` |
186
+ | **Feed** | Single column | Auto-fit grid | Auto-fit grid | `_gcaf220` or `_gcaf280` |
187
+
188
+ ---
189
+
190
+ ## 7. Component Sizing
191
+
192
+ Height is the primary constraint. Padding, font-size, and gap derive from it.
193
+
194
+ ### Field sizing tiers
195
+
196
+ | Tier | Height | Pad-Y | Pad-X | Font | Gap | Touch-safe? |
197
+ |------|--------|-------|-------|------|-----|-------------|
198
+ | **xs** | 24px | 4px | 8px | 10px | 4px | No (desktop only) |
199
+ | **sm** | 28px | 4px | 10px | 12px | 6px | No (desktop only) |
200
+ | **md** | 36px | 8px | 16px | 14px | 8px | Acceptable (with invisible padding to 44px) |
201
+ | **lg** | 44px | 10px | 24px | 16px | 10px | Yes (≥44px) |
202
+
203
+ ### Inset patterns for components
204
+
205
+ | Component Type | Inset Pattern | Example Atoms | Rationale |
206
+ |---------------|---------------|--------------|-----------|
207
+ | **Buttons, chips, table cells** | Squish (vert ≈ 50% horiz) | `_py2 _px4` | Horizontal text needs room; vertical is constrained by line-height |
208
+ | **Text inputs, textareas** | Stretch (vert > horiz) | `_py3 _px2` | Vertical room for text entry; horizontal edge less critical |
209
+ | **Cards, panels, modals** | Inset (equal all sides) | `_p4`, `_p6` | Even containment boundary |
210
+ | **Tooltips, toasts** | Inset (compact) | `_p2`–`_p3` | Minimal chrome for transient content |
211
+
212
+ ### Touch target rules
213
+
214
+ - **WCAG 2.2 AA minimum**: 24×24 CSS px
215
+ - **Recommended**: 44×44px (Apple) / 48×48px (Material)
216
+ - **Minimum gap between adjacent targets**: 8px (`_gap2`)
217
+ - **Compact density is desktop-only** — never apply `.d-compact` to touch-primary interfaces
218
+ - If visible size < 44px, invisible padding must extend the hit area to meet the target
219
+
220
+ ### Icon sizing relative to text
221
+
222
+ | Context | Icon Size | Text Size | Line-Height | Icon-Text Gap |
223
+ |---------|-----------|-----------|-------------|--------------|
224
+ | Small (compact) | 16px | 12-14px | 16px | 4px (`_gap1`) |
225
+ | Default | 20-24px | 14-16px | 20-24px | 8px (`_gap2`) |
226
+ | Large | 24-32px | 16-20px | 24-32px | 8-12px (`_gap2`–`_gap3`) |
227
+
228
+ **Rule**: Icon size matches line-height, not font-size. Icon-to-text gap ≈ icon-size / 3.
229
+
230
+ ---
231
+
232
+ ## 8. Typographic Spatial System
233
+
234
+ ### Baseline grid
235
+
236
+ All line-heights should be divisible by 4. This aligns with Decantr's 4px half-step (`--d-sp-1`) and ensures vertical rhythm across mixed text sizes.
237
+
238
+ ### Heading spacing asymmetry
239
+
240
+ Top-margin > bottom-margin. Ratio: approximately 3:1. This binds headings to the content that follows them, not the content above.
241
+
242
+ | Heading Level | Top Margin | Bottom Margin | Decantr Atoms |
243
+ |--------------|------------|---------------|--------------|
244
+ | Display / Hero | 64px | 16px | `_mt16 _mb4` |
245
+ | Section (h2) | 48px | 16px | `_mt12 _mb4` |
246
+ | Subsection (h3) | 32px | 12px | `_mt8 _mb3` |
247
+ | Minor (h4-h6) | 24px | 8px | `_mt6 _mb2` |
248
+
249
+ ### Type-to-CTA spacing
250
+
251
+ | Content Before CTA | Gap | Decantr | Responsive? |
252
+ |--------------------|-----|---------|-------------|
253
+ | Display headline | 32px | `_mt8` | Reduces to 24px on mobile |
254
+ | Section headline | 24px | `_mt6` | Stays constant |
255
+ | Body copy | 24px | `_mt6` | Stays constant |
256
+ | Helper/description text | 16px | `_mt4` | Stays constant |
257
+
258
+ ### Prose rhythm
259
+
260
+ The `.d-prose` class handles vertical rhythm for text-heavy content automatically:
261
+ - `> * + *` gets `margin-top: var(--d-sp-4)` (16px)
262
+ - Headings get graduated spacing (larger headings → more top margin)
263
+ - Lists get left padding with per-item spacing
264
+ - Blockquotes get left border + padding
265
+
266
+ **Rule**: Never manually space text blocks within a `.d-prose` container.
267
+
268
+ ---
269
+
270
+ ## 9. Visual Weight & Whitespace
271
+
272
+ Heavier visual elements need more surrounding whitespace to feel balanced.
273
+
274
+ ### Weight factors (by impact)
275
+
276
+ 1. **Size** — Larger elements have more weight, need proportionally more margin
277
+ 2. **Contrast** — Dark elements on light backgrounds (or vice versa) carry high weight
278
+ 3. **Color saturation** — Vivid/saturated colors weigh more than muted
279
+ 4. **Texture/Detail** — Images, dense text, filled icons weigh more than simple shapes
280
+ 5. **Shape** — Compact regular shapes (squares) weigh more than open/irregular shapes
281
+
282
+ ### Spacing rules by weight
283
+
284
+ | Element | Weight | Surrounding Space | Example |
285
+ |---------|--------|-------------------|---------|
286
+ | Display heading (32px+) | Heavy | 1.5-2× normal gap | `_mt12` vs body's `_mt6` |
287
+ | Hero image | Heavy | `_my8`–`_my16` from neighbors | Full-bleed needs large vertical margin |
288
+ | Data table (aggregate) | Heavy | `_my6`–`_my8` from surrounding content | Dense tables need breathing room |
289
+ | Icon-heavy toolbar | Medium (aggregate) | `_p2` internal (icons create density) | Light padding, icons fill the space |
290
+ | Body paragraph | Light | Standard gap (`_gap4`) | No extra space needed |
291
+ | Metadata (timestamp, tags) | Very light | Minimal (`_gap1`–`_gap2`) | Compact, subordinate |
292
+
293
+ ### The asymmetry rule
294
+
295
+ More space **above** heavy elements, less **below**:
296
+ - Headings: `_mt8 _mb3` (not `_my6`) — binds heading to its section
297
+ - Section dividers: more space above than below
298
+ - Cards with bottom actions: actions provide visual weight at the bottom, reducing the need for bottom padding
299
+
300
+ ---
301
+
302
+ ## 10. Optical Alignment Corrections
303
+
304
+ Mathematical spacing sometimes looks wrong. These corrections account for human perception:
305
+
306
+ | Situation | Correction | Notes |
307
+ |-----------|-----------|-------|
308
+ | **All-caps button text** | Reduce bottom padding ~2px | No descenders → mathematical center looks bottom-heavy |
309
+ | **Rounded corners** | Add ~2px more internal padding | Prevents content appearing to touch the curve; especially relevant with `--d-radius-lg` |
310
+ | **Icons in containers** | Shift ~2px down from mathematical center | Most icons have more visual weight in upper portion |
311
+ | **Play/arrow icons** | Shift 2-4px right of center | Visual weight is on the left/base of the triangle |
312
+ | **Buttons with leading icon** | Icon-side padding can be 2-4px less | Icon provides visual fill that padding would duplicate |
313
+ | **Cards with full-bleed top image** | No top padding for the image | Compound-pad applies only to text sections |
314
+ | **Circle vs square** at same dimensions | Circle appears ~2-4% smaller | Enlarge circles slightly to appear equal |
315
+
316
+ **Concentric radius rule:** When a rounded-rect child is nested inside a rounded-rect parent with padding between them, the inner radius MUST equal `outer radius − padding`. This produces concentric curves that look intentional. Mismatched radii (e.g., `8px` inner inside `16px` outer with `2px` padding) create a flat-inside-round artifact. In Decantr this is enforced via the `--d-radius-panel` / `--d-radius-inner` token pair in the RADIUS presets in `derive.js`. When adding a new preset, always compute `inner = panel − container padding`.
317
+
318
+ **In Decantr**: Most optical corrections are handled in `_base.js` component CSS. When building new components, visually verify alignment — don't assume mathematical centering is optically correct.
319
+
320
+ ---
321
+
322
+ ## 11. Z-Axis Spatial Rules
323
+
324
+ Elevation determines how far floating elements sit from their triggers. Higher elevation = more offset + more shadow.
325
+
326
+ | Component | Offset Token | Value | Z-Index Token | Elevation |
327
+ |-----------|-------------|-------|--------------|-----------|
328
+ | Form dropdowns (Select, Combobox) | `--d-offset-dropdown` | 2px | `--d-z-dropdown` (1000) | Low |
329
+ | Menus, context menus | `--d-offset-menu` | 4px | `--d-z-dropdown` (1000) | Low-medium |
330
+ | Tooltips | `--d-offset-tooltip` | 6px | `--d-z-tooltip` (1500) | Medium |
331
+ | Popovers, hover cards | `--d-offset-popover` | 8px | `--d-z-popover` (1300) | Medium-high |
332
+ | Toasts | Fixed, 24px from viewport edge | — | `--d-z-toast` (1400) | High |
333
+ | Modals, dialogs | Centered with overlay | — | `--d-z-modal` (1200) | Highest |
334
+ | Drawers, sheets | Slide from edge, 0px offset | — | `--d-z-modal` (1200) | Highest |
335
+
336
+ ### Rules
337
+
338
+ - **Offset direction**: Floating elements appear in the direction of action — dropdowns go down, tooltips go contextually (prefer above, then flip)
339
+ - **Collision handling**: When a floating element would overflow the viewport, flip to opposite side maintaining the same offset distance
340
+ - **Never hardcode offsets** — always use `--d-offset-*` tokens
341
+
342
+ ---
343
+
344
+ ## 12. Component Anatomy Rules
345
+
346
+ ### Header / Body / Footer (compound components)
347
+
348
+ All compound components (Card, Modal, Drawer) follow the compound spacing contract:
349
+
350
+ | Section | Padding Rule | Border |
351
+ |---------|-------------|--------|
352
+ | **Header** | `var(--d-compound-pad) var(--d-compound-pad) 0` | No bottom border (unless body scrolls beneath) |
353
+ | **Body** | `var(--d-compound-gap) var(--d-compound-pad)` | None |
354
+ | **Body:last-child** | Adds `padding-bottom: var(--d-compound-pad)` | None |
355
+ | **Footer** | `var(--d-compound-gap) var(--d-compound-pad) var(--d-compound-pad)` | Top separation via compound-gap (not a visible border) — see bordered exception below |
356
+
357
+ **Bordered footer exception:** When a compound footer has a visible `border-top` (e.g. Card), the border already provides inter-section separation. In this case, the footer uses symmetric padding — `var(--d-compound-pad)` on all sides — so content is vertically centered within the bordered zone. The asymmetric `compound-gap` top padding exists only for borderless footers (Modal, Drawer), where the gap itself acts as the separator and the asymmetry is invisible.
358
+
359
+ ### Divider placement
360
+
361
+ - **Between siblings**: Use `d-dividey` on parent (never manual `<hr>` above first or below last child)
362
+ - **Footer top**: Always has visual separation from body (compound-gap provides it)
363
+ - **Header bottom**: Only add a border when the body scrolls beneath the header
364
+ - **Inset dividers in lists**: Indent to align with text start, not leading icon
365
+ - **Never**: place a divider between the last item and container edge — padding handles this
366
+
367
+ ### Leading / Trailing content
368
+
369
+ | Position | Width | Gap to Main | Alignment |
370
+ |----------|-------|-------------|-----------|
371
+ | **Leading** (icon, avatar, checkbox) | Fixed | `_gap2` (8px) | Center (single-line), top (multi-line) |
372
+ | **Main** (title, description) | Flex-grow | — | Start |
373
+ | **Trailing** (action, badge, chevron) | Fixed | `_gap2` (8px) | Center (single-line), top (multi-line) |
374
+
375
+ ### Action placement
376
+
377
+ | Context | Primary Action | Secondary Action | Destructive Action |
378
+ |---------|---------------|-----------------|-------------------|
379
+ | **Dialogs/modals** | Rightmost | Left of primary | Leftmost (with larger gap) |
380
+ | **Cards** | In footer, consistent alignment | Same row | Separate row or leftmost |
381
+ | **Forms** | Submit right-aligned (or left — pick one, never mix) | Cancel left of submit, `_gap2` | — |
382
+ | **Button groups** | `_gap2` between related | `_gap4`–`_gap6` between groups | Isolated with `_mla` (margin-left: auto) |
383
+
384
+ ---
385
+
386
+ ## 13. Navigation & Chrome Spacing
387
+
388
+ Navigation is chrome — it's scanned, not read. Tight density zone applies.
389
+
390
+ ### Rules
391
+
392
+ - **Grouped nav items** (segmented controls, chip filters) form a single visual unit → `_gap0` to `_gap1`
393
+ - **Internal padding creates separation** — when nav items have their own padding (`_px2 _py1`), external gap between them is redundant or minimal
394
+ - **Logo gets asymmetric spacing** — use `_mr4`–`_mr6` on the logo vs `_gap2` between nav items. This separates identity from navigation
395
+ - **Toolbar grouping** — related tools cluster together (bold/italic/underline: `_gap0` or `_gap1`); unrelated groups separate with `_gap3`–`_gap4` or a `Separator` component
396
+ - **Breadcrumbs** — separator character gets `_gap1`–`_gap2` on each side; breadcrumb items themselves have no extra gap
397
+ - **Tab bars** — tabs use squish inset internally (`_py2 _px4`); the tab container uses `_gap0` because tab borders/indicators handle visual separation
398
+
399
+ ---
400
+
401
+ ## 14. Grid & Column System
402
+
403
+ ### Decantr grid atoms
404
+
405
+ | Atom | CSS | Use |
406
+ |------|-----|-----|
407
+ | `_gc1`–`_gc12` | `grid-template-columns: repeat(N, minmax(0, 1fr))` | Fixed column count |
408
+ | `_gcaf160`–`_gcaf320` | `repeat(auto-fit, minmax(Npx, 1fr))` | Responsive auto-fit |
409
+ | `_span1`–`_span12` | `grid-column: span N` | Column span |
410
+ | `_spanfull` | `grid-column: 1 / -1` | Full row |
411
+
412
+ ### Column count by content type
413
+
414
+ | Content | Desktop Columns | Auto-fit Min | Rationale |
415
+ |---------|----------------|-------------|-----------|
416
+ | Cards/tiles | 3-4 (`_gc3`, `_gc4`) | `_gcaf280` (280px) | Cards need ~280px to show content |
417
+ | KPI/stats | 4 (`_gc4`) | `_gcaf220` (220px) | Compact metrics, smaller minimum |
418
+ | Product grid | 3-4 | `_gcaf220` (220px) | Product cards with image + title + price |
419
+ | Article/documentation | 1 (centered `_ctr`) | — | Single column for readability |
420
+ | Dashboard widgets | 12 with variable `_span` | — | Mixed widget sizes in master grid |
421
+ | Photo/media | 3-6 | `_gcaf160` (160px) | Thumbnails can be small |
422
+
423
+ ### Container widths
424
+
425
+ | Atom | Max-width | Use |
426
+ |------|-----------|-----|
427
+ | `_ctrsm` | 640px | Auth forms, settings pages, narrow content |
428
+ | `_ctr` | 960px | Article content, documentation, focused UIs |
429
+ | `_ctrlg` | 1080px | Standard app content, general pages |
430
+ | `_ctrxl` | 1280px | Wide app layouts, dashboards, multi-column |
431
+
432
+ ### Max line length
433
+
434
+ Target ~60 characters per line for readability. `_ctr` (960px) with default body font achieves this. For wider containers, use multi-column layouts rather than stretching text across the full width.
435
+
436
+ ---
437
+
438
+ ## 15. Micro-Spacing Rules
439
+
440
+ Fine-grained spacing for small elements and intra-component gaps:
441
+
442
+ | Context | Gap (px) | Decantr | Notes |
443
+ |---------|----------|---------|-------|
444
+ | Icon to text (standard) | 8px | `_gap2` | Most common: buttons, list items, badges |
445
+ | Icon to text (compact) | 4px | `_gap1` | Small/dense buttons, breadcrumbs |
446
+ | Label above input | 4-8px | `_gap1`–`_gap2` | Intimate tier — label binds to its field |
447
+ | Helper/error text below input | 4px | `_gap1` | Intimate tier — subordinate to the input |
448
+ | Between form fields | 16px | `_gap4` | Related tier — siblings of same type |
449
+ | Chips/tags gap | 4-8px | `_gap1`–`_gap2` | Inline items, tight grouping |
450
+ | Breadcrumb separator margin | 4-8px each side | `_gap1`–`_gap2` | Separator is not a grouping boundary |
451
+ | Button group gap (related) | 8px | `_gap2` | Related actions (Save / Cancel) |
452
+ | Button group gap (unrelated groups) | 16-24px | `_gap4`–`_gap6` | Separate button clusters |
453
+ | Badge overlap on parent | 25-50% of badge diameter | `_-mt1 _-mr1` | Badge partially covers parent corner |
454
+ | Inline `Kbd` padding | 2-4px horizontal | `_px1` | Minimal chrome |
455
+
456
+ ---
457
+
458
+ ## 16. Density System Integration
459
+
460
+ Decantr's three density classes cascade all spacing tokens to children:
461
+
462
+ | Density | Class | Compound Pad | Compound Gap | Field Height | Field Pad-X | Field Pad-Y |
463
+ |---------|-------|-------------|-------------|-------------|-------------|-------------|
464
+ | **Compact** | `.d-compact` | sp-3 (12px) | sp-2 (8px) | sm (28px) | sp-2-5 (10px) | sp-1 (4px) |
465
+ | **Comfortable** | `.d-comfortable` | sp-5 (20px) | sp-3 (12px) | md (36px) | sp-4 (16px) | sp-2 (8px) |
466
+ | **Spacious** | `.d-spacious` | sp-8 (32px) | sp-4 (16px) | lg (44px) | sp-6 (24px) | sp-2-5 (10px) |
467
+
468
+ ### When to use which
469
+
470
+ | Density | When | Examples |
471
+ |---------|------|---------|
472
+ | **Compact** | Data-dense views, mouse/keyboard-primary, scan/compare workflows | Data tables, dashboards, analyst tools, IDE-like UIs |
473
+ | **Comfortable** | General application UI, mixed input modalities | Forms, settings, content pages, standard app views |
474
+ | **Spacious** | Marketing, onboarding, touch-primary, accessibility priority | Landing pages, wizards, mobile-first UIs, accessible contexts |
475
+
476
+ ### Rules
477
+
478
+ - **Always default to comfortable.** Compact is opt-in.
479
+ - **Compact is desktop-only** — never apply to touch-primary interfaces
480
+ - **Density cascades** — set `.d-compact` on a parent container and all children (buttons, inputs, selects, cards) adapt automatically
481
+ - **Don't mix densities** in the same visual group — all siblings should share the same density
482
+
483
+ ---
484
+
485
+ ## 17. Clarity Profile (Decantation Process)
486
+
487
+ The **Clarity** layer in the Decantation vocabulary governs whitespace. During SETTLE, the LLM determines Character traits which imply a Clarity profile:
488
+
489
+ | Character Trait | Density | Section Padding | Content Gap | Chrome Gap | Zone Emphasis |
490
+ |----------------|---------|-----------------|-------------|------------|--------------|
491
+ | "minimal", "clean" | Spacious | Landmark (`_py16`) | `_gap6` | `_gap2` | Showcase + Content |
492
+ | "professional", "balanced" | Comfortable | Sectional (`_py12`) | `_gap4` | `_gap2` | Content + Controls |
493
+ | "tactical", "dense" | Compact | Grouped (`_py8`) | `_gap3` | `_gap1` | Data-dense + Chrome |
494
+ | "editorial", "luxurious" | Spacious | Landmark (`_py24`) | `_gap8` | `_gap2` | Showcase |
495
+ | "technical", "utilitarian" | Compact | Sectional (`_py8`) | `_gap3` | `_gap1` | Controls + Data-dense |
496
+
497
+ During DECANT, each page's blend spec inherits the Clarity profile. The `surface` atoms on each page should reflect the zone and the Character-derived density.
498
+
499
+ ### Cork rule (anti-drift)
500
+
501
+ Once a Clarity profile is established in the Essence, all subsequent pages must maintain it. A "minimal" site should never suddenly have compact chrome gaps. Drift is detected by comparing new page atoms against the Clarity profile.
502
+
503
+ ---
504
+
505
+ ## 18. Quick Reference Decision Table
506
+
507
+ When you need to decide spacing, use this lookup:
508
+
509
+ | I'm spacing... | Tier | Gap | Padding | Reference |
510
+ |----------------|------|-----|---------|-----------|
511
+ | Icon next to its label | Intimate | `_gap1`–`_gap2` | — | §15 Micro-spacing |
512
+ | Form label above its input | Intimate | `_gap1` | — | §3 Proximity |
513
+ | Adjacent form fields | Related | `_gap4` | — | §3 Proximity |
514
+ | A button's content | — | — | `_py2 _px4` (squish) | §2 Taxonomy |
515
+ | A text input's content | — | — | `_py3 _px2` (stretch) | §2 Taxonomy |
516
+ | Inside a card | — | — | `_p4`–`_p6` (inset) | §2 Taxonomy |
517
+ | Between card sections (header/body) | Grouped | compound-gap | compound-pad | §12 Anatomy |
518
+ | Nav bar items | Chrome | `_gap1`–`_gap2` | `_p1`–`_p2` | §5 Zones, §13 Chrome |
519
+ | Dashboard widgets | Data-dense | `_gap3`–`_gap4` | `_p3` | §5 Zones |
520
+ | Sections on a landing page | Sectional/Landmark | — | `_py12`–`_py16` | §3 Proximity |
521
+ | A hero section | Landmark | `_gap6` internal | `_py16`–`_py24` | §3 Proximity |
522
+ | Heading above its content | Asymmetric | `_mt8 _mb3` | — | §8 Typography |
523
+ | A floating dropdown from trigger | Z-axis | 2px offset | — | §11 Elevation |
524
+ | A tooltip from trigger | Z-axis | 6px offset | — | §11 Elevation |
525
+ | Page layout margins | Grid | — | `_px4` (mobile) → `_px8` (desktop) | §6 Responsive |
526
+
527
+ ---
528
+
529
+ ## 19. Density Zone Quick Selection
530
+
531
+ | Page Purpose | Zone | Default Gap | Default Padding | Example |
532
+ |--------------|------|-------------|-----------------|---------|
533
+ | Navigation bar, toolbar | Chrome | `_gap1`–`_gap2` | `_p1`–`_p2` | Top nav, breadcrumbs, status bar |
534
+ | Forms, settings, filters | Controls | `_gap3`–`_gap4` | `_p3`–`_p4` | Filter sidebar, settings panel |
535
+ | Articles, features, cards | Content | `_gap4`–`_gap6` | `_p4`–`_p6` | Blog post, feature grid |
536
+ | Hero, CTA, pricing | Showcase | `_gap6`–`_gap8` | `_py12`–`_py16` | Landing page sections |
537
+ | Tables, dashboards, monitoring | Data-dense | `_gap1`–`_gap2` | `_p2`–`_p3` | Analytics dashboard, log viewer |
538
+
539
+ ---
540
+
541
+ **See also:** `reference/atoms.md`, `reference/compound-spacing.md`, `reference/tokens.md`, `reference/decantation-process.md`