@epa-wg/custom-element-dist 0.0.33 → 0.0.34

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 (175) hide show
  1. package/.claude/settings.local.json +18 -0
  2. package/.github/workflows/deploy.yml +59 -0
  3. package/.idea/copilot.data.migration.agent.xml +6 -0
  4. package/.idea/copilot.data.migration.ask.xml +6 -0
  5. package/.idea/copilot.data.migration.edit.xml +6 -0
  6. package/.idea/custom-element-dist.iml +2 -0
  7. package/.storybook/main.ts +20 -17
  8. package/.storybook/preview.ts +23 -23
  9. package/README.md +6 -4
  10. package/coverage/block-navigation.js +1 -1
  11. package/coverage/coverage-final.json +4 -3
  12. package/coverage/index.html +34 -19
  13. package/coverage/sorter.js +21 -7
  14. package/coverage/src/custom-element/coverage.svg +1 -1
  15. package/coverage/src/custom-element/custom-element.js/coverage.svg +1 -1
  16. package/coverage/src/custom-element/custom-element.js.html +435 -378
  17. package/coverage/src/custom-element/http-request.js/coverage.svg +1 -1
  18. package/coverage/src/custom-element/http-request.js.html +38 -17
  19. package/coverage/src/custom-element/index.html +26 -26
  20. package/coverage/src/custom-element/local-storage.js.html +1 -1
  21. package/coverage/src/custom-element/location-element.js.html +1 -1
  22. package/coverage/src/custom-element/module-url.js.html +1 -1
  23. package/coverage/src/index.html +1 -1
  24. package/coverage/src/material/theme/colors.js/coverage.svg +10 -0
  25. package/coverage/src/material/theme/colors.js.html +217 -0
  26. package/coverage/src/material/theme/coverage.svg +10 -0
  27. package/coverage/src/material/theme/index.html +116 -0
  28. package/coverage/src/mocks/handlers.ts.html +1 -1
  29. package/coverage/src/mocks/index.html +1 -1
  30. package/coverage/src/stories/frame.canvas.ts.html +1 -1
  31. package/coverage/src/stories/http-request.stories.ts.html +1 -1
  32. package/coverage/src/stories/index.html +1 -1
  33. package/coverage/src/stories/testStoryBook.ts.html +12 -12
  34. package/coverage/src/sum.ts.html +1 -1
  35. package/dist/{custom-element-WnOqmEOe.js → custom-element-BoYMoUtP.js} +193 -183
  36. package/dist/custom-element-BqtjrCRF.cjs +97 -0
  37. package/dist/custom-element-bundle.cjs +1 -1
  38. package/dist/custom-element-bundle.js +3 -3
  39. package/dist/demo/a.html +10 -3
  40. package/dist/demo/a.svg +26 -26
  41. package/dist/demo/html-template.html +4 -3
  42. package/dist/demo/s.xml +3856 -67
  43. package/dist/demo/s.xslt +13 -72
  44. package/dist/demo/s1.xml +3706 -0
  45. package/dist/http-request-DSaowcG1.cjs +1 -0
  46. package/dist/{http-request-BOvP4KTl.js → http-request-DTCzZ1gc.js} +15 -9
  47. package/package.json +2 -2
  48. package/public/demo/a.html +10 -3
  49. package/public/demo/a.svg +26 -26
  50. package/public/demo/html-template.html +4 -3
  51. package/public/demo/s.xml +3856 -67
  52. package/public/demo/s.xslt +13 -72
  53. package/public/demo/s1.xml +3706 -0
  54. package/src/custom-element/custom-element.js +28 -9
  55. package/src/custom-element/demo/a.html +10 -3
  56. package/src/custom-element/demo/a.svg +26 -26
  57. package/src/custom-element/demo/html-template.html +4 -3
  58. package/src/custom-element/demo/s.xml +3856 -67
  59. package/src/custom-element/demo/s.xslt +13 -72
  60. package/src/custom-element/demo/s1.xml +3706 -0
  61. package/src/custom-element/http-request.js +7 -0
  62. package/src/custom-element/ide/web-types-dce.json +1 -1
  63. package/src/custom-element/ide/web-types-xsl.json +1 -1
  64. package/src/material/angular.css +987 -987
  65. package/src/material/components/action.html +262 -0
  66. package/src/material/components/autocomplete.html +167 -239
  67. package/src/material/components/badge.html +238 -239
  68. package/src/material/components/dropdown.html +0 -1
  69. package/src/material/components/icon-link.html +160 -161
  70. package/src/material/components/icon.html +251 -252
  71. package/src/material/components/input.html +569 -570
  72. package/src/material/components/menu.html +235 -236
  73. package/src/material/components.html +157 -158
  74. package/src/material/demo.css +36 -36
  75. package/src/material/index.html +109 -110
  76. package/src/material/material.css +356 -356
  77. package/src/material/theme/Base-Principles.md +339 -0
  78. package/src/material/theme/README.md +298 -18
  79. package/src/material/theme/UI Domain Model in web applications.svg +1 -0
  80. package/src/material/theme/User Semantic Theme tokens.svg +1 -0
  81. package/src/material/theme/action-pending-poc.html +62 -0
  82. package/src/material/theme/actions-color.html +141 -0
  83. package/src/material/theme/colors-light.html +631 -0
  84. package/src/material/theme/colors-native.html +51 -0
  85. package/src/material/theme/colors-poc.html +66 -0
  86. package/src/material/theme/colors.html +297 -0
  87. package/src/material/theme/colors.js +44 -0
  88. package/src/material/theme/consumer-theme.css +745 -0
  89. package/src/material/theme/semantic.css +132 -132
  90. package/src/material/theme/style-bug.html +123 -0
  91. package/src/material/theme/theme-data.css +43 -0
  92. package/src/material/theme/theme-data.xhtml +2926 -0
  93. package/src/material/theme/todo.md +274 -0
  94. package/src/material/theme/tokens/action-colors.png +0 -0
  95. package/src/material/theme/tokens/cem-article-illustration-4x1-letterbox-2000x500.png +0 -0
  96. package/src/material/theme/tokens/cem-breakpoints.md +519 -0
  97. package/src/material/theme/tokens/cem-colors.md +715 -0
  98. package/src/material/theme/tokens/cem-consumerflow-typography-matrix.svg +198 -0
  99. package/src/material/theme/tokens/cem-coupling.md +372 -0
  100. package/src/material/theme/tokens/cem-data-vs-reading-numerals.svg +164 -0
  101. package/src/material/theme/tokens/cem-dimension.md +625 -0
  102. package/src/material/theme/tokens/cem-layering.md +562 -0
  103. package/src/material/theme/tokens/cem-m3-parity.md +343 -0
  104. package/src/material/theme/tokens/cem-responsive.md +238 -0
  105. package/src/material/theme/tokens/cem-shape.md +691 -0
  106. package/src/material/theme/tokens/cem-stroke-density-illustration-4to1-v3.svg +102 -0
  107. package/src/material/theme/tokens/cem-stroke.md +480 -0
  108. package/src/material/theme/tokens/cem-timing.md +198 -0
  109. package/src/material/theme/tokens/cem-typography-model-stack.svg +64 -0
  110. package/src/material/theme/tokens/cem-voice-fonts-typography.md +718 -0
  111. package/src/material/theme/tokens/cem-voice-ladder.svg +91 -0
  112. package/src/material/theme/tokens/chips.png +0 -0
  113. package/src/material/theme/tokens/columns-page.png +0 -0
  114. package/src/material/theme/tokens/initials.png +0 -0
  115. package/src/material/theme/tokens/nav-buttons.png +0 -0
  116. package/src/material/theme/tokens/script.png +0 -0
  117. package/src/material/theme/tokens/sufler.png +0 -0
  118. package/src/material/theme/tokens/typography-icons.png +0 -0
  119. package/src/mocks/versions.mock.ts +1 -1
  120. package/src/stories/__screenshots__/dom-merge.test.stories.ts/dom-merge-dom-merge-OrderPreservingOn2ndTransform-1.png +0 -0
  121. package/src/stories/__screenshots__/xslt-conditionals.test.stories.ts/xslt-conditionals-xslt-conditionals-MultipleIfOrderingWorkaround-1.png +0 -0
  122. package/src/stories/dom-merge.test.stories.ts +25 -1
  123. package/src/stories/xslt-conditionals.test.stories.ts +492 -0
  124. package/src/stories/xslt-if.test.stories.ts +89 -0
  125. package/storybook-static/assets/{Color-F6OSRLHC-Cbp293x2.js → Color-F6OSRLHC-CzTOSlqB.js} +1 -1
  126. package/storybook-static/assets/{Configure-BrFr4SLE.js → Configure-7GqRsAoJ.js} +1 -1
  127. package/storybook-static/assets/{DocsRenderer-CFRXHY34-DhHzJiIO.js → DocsRenderer-CFRXHY34-Duc5rSIm.js} +2 -2
  128. package/storybook-static/assets/{attributes.test.stories-Gg9LQTEK.js → attributes.test.stories-DYuxF8h1.js} +1 -1
  129. package/storybook-static/assets/{css.test.stories-B_3ltOrx.js → css.test.stories-LOmvINyb.js} +1 -1
  130. package/storybook-static/assets/{custom-element-CPnvJnn8.js → custom-element-Bwx7otrT.js} +6 -6
  131. package/storybook-static/assets/{dom-merge.test.stories-nQxcgLoM.js → dom-merge.test.stories-CEKhWjaS.js} +47 -6
  132. package/storybook-static/assets/entry-preview-BNCt9WBs.js +26 -0
  133. package/storybook-static/assets/{entry-preview-docs-Dwczwtsc.js → entry-preview-docs-CbF8-81D.js} +2 -2
  134. package/storybook-static/assets/{external-template.test.stories-DZ-rjnfd.js → external-template.test.stories-jHu0wsJ-.js} +1 -1
  135. package/storybook-static/assets/{form.test.stories-DQhPYtMj.js → form.test.stories-CUyUnmwP.js} +1 -1
  136. package/storybook-static/assets/{frame.canvas-ClTqYyMN.js → frame.canvas-E5n9h6j1.js} +1 -1
  137. package/storybook-static/assets/{handlers-CLkps6Nz.js → handlers-F7GUfMqr.js} +1 -1
  138. package/storybook-static/assets/http-request-BWeEEBkP.js +1 -0
  139. package/storybook-static/assets/{http-request.stories-jo0f73nw.js → http-request.stories-wyX5-QOv.js} +1 -1
  140. package/storybook-static/assets/{iframe-CZwRpnn9.js → iframe-BS_DPWl0.js} +11 -11
  141. package/storybook-static/assets/{index-Dr4PwNfd.js → index-CGuyH0k-.js} +87 -87
  142. package/storybook-static/assets/{index-CJQtnF9V.js → index-DB7LLObI.js} +1 -1
  143. package/storybook-static/assets/index-DO1nmyvI.js +11 -0
  144. package/storybook-static/assets/{index-B68YUdzy.js → index-V1EGs-wm.js} +3 -3
  145. package/storybook-static/assets/{local-storage.test.stories-uA5EKRPf.js → local-storage.test.stories-BxOhsf1k.js} +1 -1
  146. package/storybook-static/assets/{location-element.test.stories-Cu-6Elcg.js → location-element.test.stories-DqhvvUoa.js} +1 -1
  147. package/storybook-static/assets/{module-url.test.stories-CD_wusXQ.js → module-url.test.stories-C1gG9G7Y.js} +1 -1
  148. package/storybook-static/assets/{preview-BFlNN3Wj.js → preview-Bn8igYMp.js} +1 -1
  149. package/storybook-static/assets/{preview-CuCH40jj.js → preview-Cwy1XFu2.js} +2 -2
  150. package/storybook-static/assets/{preview-Cm4PPhHS.js → preview-D6sehqkw.js} +1 -1
  151. package/storybook-static/assets/{set-url.test.stories-CY7B9BVZ.js → set-url.test.stories-BKQNdknJ.js} +1 -1
  152. package/storybook-static/assets/{slice-events.test.stories-BVnPXm6e.js → slice-events.test.stories-ChqULCeA.js} +1 -1
  153. package/storybook-static/assets/{slots.test.stories-Dxsa9KdA.js → slots.test.stories-BlyLoCRe.js} +1 -1
  154. package/storybook-static/assets/{version-select.test.stories-Buga1PAa.js → version-select.test.stories-CPGSh1tR.js} +1 -1
  155. package/storybook-static/assets/xslt-conditionals.test.stories-YC6QPqWZ.js +633 -0
  156. package/storybook-static/assets/xslt-if.test.stories-BRSWy2-x.js +71 -0
  157. package/storybook-static/demo/a.html +10 -3
  158. package/storybook-static/demo/a.svg +26 -26
  159. package/storybook-static/demo/html-template.html +4 -3
  160. package/storybook-static/demo/s.xml +3856 -67
  161. package/storybook-static/demo/s.xslt +13 -72
  162. package/storybook-static/demo/s1.xml +3706 -0
  163. package/storybook-static/iframe.html +2 -2
  164. package/storybook-static/index.json +1 -1
  165. package/storybook-static/project.json +1 -1
  166. package/storybook-static/sb-addons/essentials-controls-1/manager-bundle.js +69 -66
  167. package/storybook-static/sb-addons/essentials-docs-3/manager-bundle.js +62 -59
  168. package/dist/custom-element-6slVaFEs.cjs +0 -97
  169. package/dist/http-request-DPrY7mGh.cjs +0 -1
  170. package/storybook-static/assets/attributes.test.stories-CzWkKw0e.js +0 -1
  171. package/storybook-static/assets/entry-preview-DHVXbf3x.js +0 -26
  172. package/storybook-static/assets/external-template.test.stories-BivZqBTp.js +0 -1
  173. package/storybook-static/assets/http-request-DNq59pnj.js +0 -1
  174. package/storybook-static/assets/index-BwkS7JH_.js +0 -8
  175. package/storybook-static/assets/module-url.test.stories-CTjUAk3J.js +0 -1
@@ -0,0 +1,625 @@
1
+ # Semantic Spacing and Layout Rhythm Tokens (CEM × M3)
2
+
3
+ **Status:** Canonical (D1 v1.0)
4
+
5
+ **Last updated:** December 19, 2025
6
+
7
+ **Audience:** Design Systems, Product Design, Front-End Engineering
8
+
9
+ **Taxonomy placement:** D1. Space & Rhythm (part of the 7-dimensional CEM token framework)
10
+
11
+ **Companion specs:**
12
+ - **D0. Color (Emotional Palette)** ([`cem-colors.md`](./cem-colors.md)) — color weight pairs with spacing rhythm
13
+ - **D2. Coupling & Compactness** ([`cem-coupling.md`](./cem-coupling.md)) — normative for interactive operability
14
+ - **D3. Shape & Bend** ([`cem-shape.md`](./cem-shape.md)) — bend/inset harmony rules
15
+ - **D4. Layering** ([`cem-layering.md`](./cem-layering.md)) — prominent layers "earn" breathing room
16
+ - **D5. Stroke & Separation** ([`cem-stroke.md`](./cem-stroke.md)) — boundaries, dividers, focus indicators
17
+ - **D6. Typography** ([`cem-voice-fonts-typography.md`](./cem-voice-fonts-typography.md)) — reading rhythm validation
18
+ - **D7. Time & Motion** ([`cem-timing.md`](./cem-timing.md)) — rhythm perception
19
+
20
+ ---
21
+
22
+ ## Table of Contents
23
+
24
+ 1. [Scope](#1-scope)
25
+ 2. [CEM alignment principles applied to spacing](#2-cem-alignment-principles-applied-to-spacing)
26
+ - [2.1 Semantic intent first](#21-semantic-intent-first)
27
+ - [2.2 Bounded variation](#22-bounded-variation)
28
+ - [2.3 Accessibility and operability by construction](#23-accessibility-and-operability-by-construction)
29
+ 3. [Token model](#3-token-model)
30
+ 4. [Relation to Dimensional Tokens](#4-relation-to-dimensional-tokens)
31
+ - [4.1 Dimensional Tokens: where spacing lives](#41-dimensional-tokens-where-spacing-lives)
32
+ - [4.2 Governance rules (cross-category contracts)](#42-governance-rules-cross-category-contracts)
33
+ 5. [Reference spacing scale (semantic)](#5-reference-spacing-scale-semantic)
34
+ - [5.1 Primary dimension scale](#51-primary-dimension-scale-semanticcss)
35
+ - [5.2 Mapping to M3 rhythm](#52-mapping-to-m3-rhythm)
36
+ 6. [Consumer-semantic spacing taxonomy](#6-consumer-semantic-spacing-taxonomy)
37
+ - [6.1 Relationship gaps (between items)](#61-relationship-gaps-between-items)
38
+ - [6.2 Insets (inside a surface)](#62-insets-inside-a-surface)
39
+ - [6.3 Coupling and interaction safety (D2 cross-reference)](#63-coupling-and-interaction-safety-d2-cross-reference)
40
+ - [6.4 Reading rhythm (vertical cadence for prose)](#64-reading-rhythm-vertical-cadence-for-prose)
41
+ - [6.5 Data/scan rhythm (dense but legible)](#65-datascan-rhythm-dense-but-legible)
42
+ 7. [Layout rhythm tokens (compositional semantics)](#7-layout-rhythm-tokens-compositional-semantics)
43
+ - [7.1 Stack rhythm (vertical composition)](#71-stack-rhythm-vertical-composition)
44
+ - [7.2 Cluster rhythm (horizontal groups)](#72-cluster-rhythm-horizontal-groups)
45
+ - [7.3 Page gutters (responsive breathing room)](#73-page-gutters-responsive-breathing-room)
46
+ 8. [Spacing modes knob (dense / normal / sparse)](#8-spacing-modes-knob-dense--normal--sparse)
47
+ - [8.1 Adjustment policy](#81-adjustment-policy)
48
+ - [8.2 Concrete overrides](#82-concrete-overrides-recommended-default-mapping)
49
+ - [8.3 Notes on component mapping](#83-notes-on-component-mapping)
50
+ - [8.4 Layout mapping checklist](#84-layout-mapping-checklist-how-to-apply)
51
+ 9. [Mapping notes: M3 ↔ CEM](#9-mapping-notes-m3--cem)
52
+ 10. [Quick adoption checklist](#10-quick-adoption-checklist)
53
+
54
+ **Appendices**
55
+ - [Appendix A. D2 Coupling Mode Matrix (excerpt)](#appendix-a-d2-coupling-mode-matrix-excerpt)
56
+ - [Appendix B. Governance and versioning](#appendix-b-governance-and-versioning)
57
+
58
+ ---
59
+
60
+ ## 1. Scope
61
+
62
+ This document defines a **consumer-semantic** spacing and layout rhythm token set that:
63
+
64
+ - Preserves the **Material 3 rhythm** (4dp increments, common 8dp cadence) as a *reference lattice*.
65
+ - Exposes **semantic endpoints** that describe *intent* (relationship, grouping, task flow) rather than
66
+ *implementation* (e.g., `margin: 16px`).
67
+ - Supports an optional D1 knob for **spacing modes** (`dense | normal | sparse`) **without** conflating it with D2
68
+ operability.
69
+
70
+ This document is **D1 (Space & Rhythm)**. It intentionally does *not* define interactive minimums; it **consumes** D2
71
+ coupling minimums as hard constraints.
72
+
73
+ ---
74
+
75
+ ## 2. CEM alignment principles applied to spacing
76
+
77
+ ### 2.1 Semantic intent first
78
+
79
+ Developers should apply tokens like:
80
+
81
+ - `gap-related`, `gap-group`, `gap-section` (relationship semantics)
82
+ - `inset-control`, `inset-container` (surface semantics)
83
+ - `coupling-guard-min` (interaction safety contract; defined in D2)
84
+
85
+ …and not value-centric names like `space-16` in component code.
86
+
87
+ ### 2.2 Bounded variation
88
+
89
+ A small set of *distinct, repeatable* space steps should cover most UI. Extended values exist but are intentionally
90
+ "rare".
91
+
92
+ ### 2.3 Accessibility and operability by construction
93
+
94
+ Spacing must preserve:
95
+
96
+ - **Modality-neutral operability** (pointer, touch, stylus, gaze, switch, remote) via D2 coupling minimums
97
+ - **Readability** (line/paragraph rhythm)
98
+ - **User scaling** (prefer `rem` / `em` and allow platform scaling)
99
+
100
+ ---
101
+
102
+ ## 3. Token model
103
+
104
+ We use three layers:
105
+
106
+ 1. **Reference scale tokens** (M3-aligned numeric steps; safe to map to dp/px)
107
+ 2. **System/semantic tokens** (consumer-intent endpoints; what teams apply)
108
+ 3. **Component mapping** (component-specific tokens map to semantic tokens; typically owned in component adapters)
109
+
110
+ ---
111
+
112
+ ## 4. Relation to Dimensional Tokens
113
+
114
+ ### 4.1 Dimensional Tokens: where spacing lives
115
+
116
+ In CEM, spacing/rhythm is not "just layout." It is a primary subset of **Dimensional Tokens** (the physical layer: size,
117
+ distance, bend, stroke, depth).
118
+
119
+ Use this **legend-level** dimensional taxonomy to keep token categories coherent:
120
+
121
+ - **D1. Space & Rhythm** (this document)
122
+ - gaps, insets, gutters, composition cadence, reading cadence, scan cadence
123
+
124
+ - **D2. Coupling & Compactness** (adjacent; constrains D1) — see [`cem-coupling.md`](./cem-coupling.md)
125
+ - operable zone minimums
126
+ - interference/isolation minimums
127
+ - halo/expansion policy (visual size vs operable size)
128
+ - control geometry endpoints that affect operability (heights/paddings/row sizes)
129
+
130
+ - **D3. Shape & Bend** — see [`cem-shape.md`](./cem-shape.md)
131
+ - bend / corner radius roles
132
+ - bend-inset harmony (see §4.2 rule 5)
133
+
134
+ - **D4. Layering** — see [`cem-layering.md`](./cem-layering.md)
135
+ - signed 7-tier ladder (recess → base → raised → floating → overlay → command)
136
+ - tonal shift, shadow, contour, scrim as depth channels
137
+ - state-driven lift (hover, drag)
138
+
139
+ - **D5. Stroke & Separation** — see [`cem-stroke.md`](./cem-stroke.md)
140
+ - boundaries (control container edges), dividers (sibling separation)
141
+ - focus/selection/target indicators (including zebra pattern)
142
+ - stroke basis (`--cem-stroke-none`, `--cem-stroke-hair`, `--cem-stroke-standard`, `--cem-stroke-strong`)
143
+
144
+ - **D6. Typography Thickness** — see [`cem-voice-fonts-typography.md`](./cem-voice-fonts-typography.md)
145
+ - weight/mass roles that affect perceived density and hierarchy
146
+
147
+ - **D7. Time & Motion Timing** — see [`cem-timing.md`](./cem-timing.md)
148
+ - durations/easing groups (not geometry, but participates in "rhythm" perception)
149
+
150
+ ### 4.2 Governance rules (cross-category contracts)
151
+
152
+ These rules prevent spacing changes from degrading operability, accessibility, or visual hierarchy:
153
+
154
+ 1. **Spacing modes are a D1 adjustment; never a D2 coupling regression**
155
+
156
+ - `dense | normal | sparse` may adjust *gaps/insets/gutters* (D1) selectively.
157
+ - D1 changes must not reduce the D2 safety minimums (**zone**, **guard**) and must not cause halo overlap.
158
+
159
+ 2. **Normative layout contract for interactive adjacency**
160
+
161
+ When spacing occurs **between two interactive affordances**, layout must respect D2 guard:
162
+
163
+ ```css
164
+ /* If the gap separates adjacent interactive affordances: */
165
+ .cem-gap-interactive {
166
+ gap: max(var(--cem-gap-related), var(--cem-coupling-guard-min));
167
+ }
168
+ ```
169
+
170
+ 3. **When D1 can't grow, D5 may need to compensate**
171
+
172
+ - In tight layouts or contrast themes, increase stroke/separation to maintain scannability.
173
+
174
+ 4. **Elevated/prominent surfaces "earn" breathing room**
175
+
176
+ - Higher layer prominence (D4) should generally correlate with more surrounding space (D1).
177
+
178
+ 5. **Bend and inset should harmonize** (D1 × D3)
179
+
180
+ - Larger bend (D3) with very tight inset (D1) reads crowded; prefer stepping inset up.
181
+ - See [`cem-shape.md`](./cem-shape.md) §8.5 for detailed guidance on bend vs inset readability.
182
+
183
+ 6. **Reading cadence is jointly governed by typography + spacing**
184
+
185
+ - Reading rhythm tokens (D1) must be validated against typescale/line-height policy (D6).
186
+ - See [`cem-voice-fonts-typography.md`](./cem-voice-fonts-typography.md) for typography tokens.
187
+
188
+ ---
189
+
190
+ ## 5. Reference spacing scale (semantic)
191
+
192
+ The spacing scale uses semantic size names rather than pixel values, making intent clear while preserving M3 rhythm (4dp
193
+ increments).
194
+
195
+ ### 5.1 Primary dimension scale (semantic.css)
196
+
197
+ Eight steps covering common UI needs:
198
+
199
+ ```css
200
+ :root {
201
+ --cem-dim-xx-small : 0.25rem; /* 4px — micro gaps, icon padding */
202
+ --cem-dim-x-small : 0.5rem; /* 8px — related item gaps, control insets */
203
+ --cem-dim-small : 0.75rem; /* 12px — group gaps, inline rhythm */
204
+ --cem-dim-medium : 1rem; /* 16px — block gaps, container insets */
205
+ --cem-dim-large : 1.5rem; /* 24px — section gaps, surface insets */
206
+ --cem-dim-x-large : 2rem; /* 32px — page gaps, wide gutters */
207
+ --cem-dim-xx-large : 4rem; /* 64px — extended layout, hero spacing */
208
+ --cem-dim-xxx-large : 8rem; /* 128px — maximum breathing room */
209
+ }
210
+ ```
211
+
212
+ **Cross-reference:** These tokens are consumed by D3 Shape ([`cem-shape.md`](./cem-shape.md)) for bend values:
213
+ - `--cem-bend-smooth` uses `--cem-dim-x-small` (8px)
214
+ - `--cem-bend-surface` uses `--cem-dim-small` (12px)
215
+ - `--cem-bend-modal` uses `--cem-dim-large` + `--cem-dim-xx-small` (~28px)
216
+
217
+ ### 5.2 Mapping to M3 rhythm
218
+
219
+ | Semantic token | Value | M3 dp equivalent | Typical use |
220
+ |-----------------------|---------|------------------|-------------------------------|
221
+ | `--cem-dim-xx-small` | 0.25rem | 4dp | Micro gaps, tight padding |
222
+ | `--cem-dim-x-small` | 0.5rem | 8dp | Related items, control insets |
223
+ | `--cem-dim-small` | 0.75rem | 12dp | Group gaps, inline spacing |
224
+ | `--cem-dim-medium` | 1rem | 16dp | Block gaps, container insets |
225
+ | `--cem-dim-large` | 1.5rem | 24dp | Section gaps, surface padding |
226
+ | `--cem-dim-x-large` | 2rem | 32dp | Page gaps, wide gutters |
227
+ | `--cem-dim-xx-large` | 4rem | 64dp | Extended layout spacing |
228
+ | `--cem-dim-xxx-large` | 8rem | 128dp | Maximum layout spacing |
229
+
230
+ ---
231
+
232
+ ## 6. Consumer-semantic spacing taxonomy
233
+
234
+ The taxonomy is organized by what the space *means to the user*.
235
+
236
+ ### 6.1 Relationship gaps (between items)
237
+
238
+ Use when arranging siblings.
239
+
240
+ ```css
241
+ :root {
242
+ /* Siblings that are clearly part of the same unit */
243
+ --cem-gap-related: var(--cem-dim-x-small); /* 8px */
244
+
245
+ /* Items in the same group, but distinct */
246
+ --cem-gap-group: var(--cem-dim-small); /* 12px */
247
+
248
+ /* Between groups/blocks inside one surface */
249
+ --cem-gap-block: var(--cem-dim-medium); /* 16px */
250
+
251
+ /* Between major sections (cards, panels, page regions) */
252
+ --cem-gap-section: var(--cem-dim-large); /* 24px */
253
+
254
+ /* Between page-level regions */
255
+ --cem-gap-page: var(--cem-dim-x-large); /* 32px */
256
+ }
257
+ ```
258
+
259
+ **Guideline:** if users perceive two things as "one unit," use `gap-related`. If they perceive "these are separate
260
+ things," move up to `gap-group` or `gap-block`.
261
+
262
+ > Important: for interactive adjacency, apply the D2 guard contract (`gap = max(D1 gap, D2 guard)`).
263
+
264
+ ### 6.2 Insets (inside a surface)
265
+
266
+ Use when padding content within a container.
267
+
268
+ ```css
269
+ :root {
270
+ /* Smallest safe inset for tight controls */
271
+ --cem-inset-control: var(--cem-dim-x-small); /* 8px */
272
+
273
+ /* Default inset for common containers */
274
+ --cem-inset-container: var(--cem-dim-medium); /* 16px */
275
+
276
+ /* Comfortable inset for reading surfaces and prominent cards */
277
+ --cem-inset-surface: var(--cem-dim-large); /* 24px */
278
+ }
279
+ ```
280
+
281
+ **Cross-reference:** When combining insets with bend (D3), ensure inset is large enough to prevent content crowding in
282
+ rounded corners. See [`cem-shape.md`](./cem-shape.md) §8.5 for guidance.
283
+
284
+ ### 6.3 Coupling and interaction safety (D2 cross-reference)
285
+
286
+ These tokens are **defined and governed in D2** ([`cem-coupling.md`](./cem-coupling.md)). They are listed here as a **normative constraint**
287
+ because they bound how far D1 spacing modes can compress interactive adjacency. **Do not set or tune these in D1**;
288
+ treat them as sourced from the D2 theme.
289
+
290
+ ```css
291
+ :root {
292
+ /* Minimum distancing between adjacent operable zones (prevents interference). */
293
+ --cem-coupling-guard-min: 0.5rem; /* nominally 8px */
294
+
295
+ /* Minimum operable zone (layout-level). Keep invariant across modes. */
296
+ --cem-coupling-zone-min: 3rem; /* nominally 48px @ 16px root */
297
+
298
+ /* Invisible expansion beyond visuals (halo). */
299
+ --cem-coupling-halo: 0.25rem; /* nominally 4px */
300
+
301
+ /* Legacy aliases (deprecated): keep only while migrating older code */
302
+ --cem-touch-separation-min: var(--cem-coupling-guard-min);
303
+ --cem-touch-target-min: var(--cem-coupling-zone-min);
304
+ }
305
+ ```
306
+
307
+ Interpretation (summary):
308
+
309
+ - **Zone**: can the user reliably couple intent to the control?
310
+ - **Guard**: will adjacent controls accidentally steal intent?
311
+ - **Halo**: can we keep visuals compact while preserving operability?
312
+
313
+ ### 6.4 Reading rhythm (vertical cadence for prose)
314
+
315
+ This is distinct from UI rhythm.
316
+
317
+ ```css
318
+ :root {
319
+ /* Default paragraph spacing for prose (pairs with typography) */
320
+ --cem-rhythm-reading-paragraph: 0.75em;
321
+
322
+ /* Space between reading sections within one surface */
323
+ --cem-rhythm-reading-section: var(--cem-dim-large); /* 24px */
324
+ }
325
+ ```
326
+
327
+ **Cross-reference:** Reading rhythm must be validated against typography tokens. See [`cem-voice-fonts-typography.md`](./cem-voice-fonts-typography.md).
328
+
329
+ ### 6.5 Data/scan rhythm (dense but legible)
330
+
331
+ Optimized for scan/compare flows (tables, metrics).
332
+
333
+ ```css
334
+ :root {
335
+ /* Table-like, scan-first row padding */
336
+ --cem-rhythm-data-row: var(--cem-dim-x-small); /* 8px */
337
+
338
+ /* Scan grouping (subtotals, row groups, metric clusters) */
339
+ --cem-rhythm-data-group: var(--cem-dim-medium); /* 16px */
340
+ }
341
+ ```
342
+
343
+ ---
344
+
345
+ ## 7. Layout rhythm tokens (compositional semantics)
346
+
347
+ These describe **layout structures** without baking in specific components.
348
+
349
+ ### 7.1 Stack rhythm (vertical composition)
350
+
351
+ ```css
352
+ :root {
353
+ /* Default vertical stack gap for general UI stacks */
354
+ --cem-layout-stack-gap: var(--cem-gap-block);
355
+
356
+ /* Optional derived endpoints (rare): keep if your system needs tight/loose variants */
357
+ --cem-layout-stack-tight: var(--cem-gap-related);
358
+ --cem-layout-stack-loose: var(--cem-gap-section);
359
+ }
360
+ ```
361
+
362
+ ### 7.2 Cluster rhythm (horizontal groups)
363
+
364
+ ```css
365
+ :root {
366
+ /* Default cluster gap for inline groups (icons + text, toolbars, button clusters) */
367
+ --cem-layout-cluster-gap: var(--cem-gap-related);
368
+
369
+ /* Optional legacy aliases (deprecated): */
370
+ --cem-layout-inline-tight: var(--cem-dim-x-small); /* 8px */
371
+ --cem-layout-inline: var(--cem-dim-small); /* 12px */
372
+ --cem-layout-inline-loose: var(--cem-dim-medium); /* 16px */
373
+ }
374
+ ```
375
+
376
+ ### 7.3 Page gutters (responsive breathing room)
377
+
378
+ These are *responsive* and should be treated as semantics, not fixed numbers.
379
+
380
+ ```css
381
+ :root {
382
+ /* Default content gutter */
383
+ --cem-layout-gutter: var(--cem-dim-medium); /* 16px */
384
+
385
+ /* Wide screens */
386
+ --cem-layout-gutter-wide: var(--cem-dim-x-large); /* 32px */
387
+
388
+ /* Maximum breathing room */
389
+ --cem-layout-gutter-max: var(--cem-dim-xx-large); /* 64px */
390
+ }
391
+ ```
392
+
393
+ ---
394
+
395
+ ## 8. Spacing modes knob (dense / normal / sparse)
396
+
397
+ Material often frames this as "density." In CEM, treat this explicitly as a **D1 spacing mode** that shifts Space &
398
+ Rhythm while preserving D2 coupling invariants.
399
+
400
+ ```css
401
+ :root {
402
+ /* dense | normal | sparse */
403
+ --cem-layout-spacing: normal;
404
+ }
405
+ ```
406
+
407
+ ### 8.1 Adjustment policy
408
+
409
+ Mode intent summary:
410
+
411
+ | D1 spacing mode | Primary goal | What changes | What must not change |
412
+ |-----------------|------------------------------|--------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|
413
+ | `dense` | Increase information density | Step down gaps/insets/gutters ~1 step where safe | D2 coupling invariants (zone/guard), and any gap that separates interactive affordances must still satisfy `gap = max(D1 gap, D2 guard)` |
414
+ | `normal` | Baseline | Use canonical endpoints as defined | Same invariants |
415
+ | `sparse` | Increase calm/readability | Step up gaps/insets/gutters ~1 step | Same invariants |
416
+
417
+ - **normal**: baseline values as defined in Sections 6–7.
418
+ - **dense**: reduce gaps/insets by ~1 step where it does not harm reading cadence or interactive coupling.
419
+ - **sparse**: increase gaps/insets by ~1 step to improve readability and perceived calm.
420
+
421
+ Hard constraints (never override):
422
+
423
+ - `--cem-coupling-zone-min`
424
+ - `--cem-coupling-guard-min` (may force some "gaps" to stay at or above the minimum)
425
+ - `--cem-coupling-halo` (must be considered when validating dense clusters)
426
+
427
+ ### 8.2 Concrete overrides (recommended default mapping)
428
+
429
+ ```css
430
+ /* NORMAL is the baseline already defined above */
431
+
432
+ :root[data-cem-spacing="dense"] {
433
+ /* Relationship gaps — step down by one level */
434
+ --cem-gap-related: var(--cem-dim-x-small); /* 8px */
435
+ --cem-gap-group: var(--cem-dim-x-small); /* 8px */
436
+ --cem-gap-block: var(--cem-dim-small); /* 12px */
437
+ --cem-gap-section: var(--cem-dim-medium); /* 16px */
438
+ --cem-gap-page: var(--cem-dim-large); /* 24px */
439
+
440
+ /* Insets */
441
+ --cem-inset-control: var(--cem-dim-x-small); /* 8px */
442
+ --cem-inset-container: var(--cem-dim-small); /* 12px */
443
+ --cem-inset-surface: var(--cem-dim-medium); /* 16px */
444
+
445
+ /* Layout gutters */
446
+ --cem-layout-gutter: var(--cem-dim-small); /* 12px */
447
+ --cem-layout-gutter-wide: var(--cem-dim-large); /* 24px */
448
+ --cem-layout-gutter-max: var(--cem-dim-x-large); /* 32px */
449
+
450
+ /* Content cadence */
451
+ --cem-rhythm-reading-paragraph: 0.6em;
452
+ --cem-rhythm-reading-section: var(--cem-dim-medium); /* 16px */
453
+ --cem-rhythm-data-row: var(--cem-dim-xx-small); /* 4px */
454
+ --cem-rhythm-data-group: var(--cem-dim-small); /* 12px */
455
+ }
456
+
457
+ :root[data-cem-spacing="sparse"] {
458
+ /* Relationship gaps — step up by one level */
459
+ --cem-gap-related: var(--cem-dim-small); /* 12px */
460
+ --cem-gap-group: var(--cem-dim-medium); /* 16px */
461
+ --cem-gap-block: var(--cem-dim-large); /* 24px */
462
+ --cem-gap-section: var(--cem-dim-x-large); /* 32px */
463
+ --cem-gap-page: var(--cem-dim-xx-large); /* 64px */
464
+
465
+ /* Insets */
466
+ --cem-inset-control: var(--cem-dim-small); /* 12px */
467
+ --cem-inset-container: var(--cem-dim-large); /* 24px */
468
+ --cem-inset-surface: var(--cem-dim-x-large); /* 32px */
469
+
470
+ /* Layout gutters */
471
+ --cem-layout-gutter: var(--cem-dim-large); /* 24px */
472
+ --cem-layout-gutter-wide: var(--cem-dim-xx-large); /* 64px */
473
+ --cem-layout-gutter-max: var(--cem-dim-xxx-large); /* 128px */
474
+
475
+ /* Content cadence */
476
+ --cem-rhythm-reading-paragraph: 1em;
477
+ --cem-rhythm-reading-section: var(--cem-dim-x-large); /* 32px */
478
+ --cem-rhythm-data-row: var(--cem-dim-small); /* 12px */
479
+ --cem-rhythm-data-group: var(--cem-dim-large); /* 24px */
480
+ }
481
+ ```
482
+
483
+ ### 8.3 Notes on component mapping
484
+
485
+ * Components should bind to semantic endpoints (`gap-*`, `inset-*`, `rhythm-*`) and inherit spacing mode automatically.
486
+
487
+ * If a component is interactive and uses layout gaps between peer affordances, resolve its gap as:
488
+ `gap = max(D1 semantic gap, D2 coupling guard)`.
489
+ * If a component must remain stable across spacing modes (rare), bind it to reference steps explicitly and document why.
490
+
491
+ ### 8.4 Layout mapping checklist (how to apply)
492
+
493
+ Use these patterns so teams can implement screens without inventing spacing semantics.
494
+
495
+ **Stacks (vertical composition)**
496
+
497
+ - Default: use `--cem-layout-stack-gap` (maps to `--cem-gap-block`).
498
+ - Within a group of tightly related elements (e.g., label + control + helper): use `--cem-gap-related`.
499
+
500
+ **Clusters (horizontal composition)**
501
+
502
+ - Default: use `--cem-layout-cluster-gap` (maps to `--cem-gap-related`).
503
+ - If cluster members are independently interactive (e.g., icon button groups), resolve as:
504
+ - `gap: max(var(--cem-layout-cluster-gap), var(--cem-coupling-guard-min))`.
505
+
506
+ **Cards / panels / surfaces**
507
+
508
+ - Container padding: `--cem-inset-container`.
509
+ - Reading- or emphasis-first surfaces: `--cem-inset-surface`.
510
+ - Tight control trays: `--cem-inset-control` (only when content remains legible).
511
+ - **Note:** When using rounded surfaces, ensure inset accommodates bend. See [`cem-shape.md`](./cem-shape.md) §8.5.
512
+
513
+ **Sections and page regions**
514
+
515
+ - Between blocks: `--cem-gap-block`.
516
+ - Between major sections: `--cem-gap-section`.
517
+ - Between page regions: `--cem-gap-page`.
518
+
519
+ **Gutters (responsive framing)**
520
+
521
+ - Default: `--cem-layout-gutter`.
522
+ - Wide screens: `--cem-layout-gutter-wide`.
523
+ - Maximum breathing room: `--cem-layout-gutter-max`.
524
+
525
+ **Reading and data cadence**
526
+
527
+ - Prose: use `--cem-rhythm-reading-paragraph` and `--cem-rhythm-reading-section`.
528
+ - Scan-heavy: use `--cem-rhythm-data-row` and `--cem-rhythm-data-group`.
529
+
530
+ ---
531
+
532
+ ## 9. Mapping notes: M3 ↔ CEM
533
+
534
+ ### 9.1 Where this matches Material 3
535
+
536
+ - 4dp-based reference steps provide the same rhythmic lattice.
537
+ - "Micro/standard/macro/extended" groupings align with common M3 guidance.
538
+
539
+ ### 9.2 Where this differs (intentionally)
540
+
541
+ - CEM exposes **consumer-intent** tokens as the *primary interface*.
542
+ - Value-centric tokens are kept as **reference** only.
543
+ - Component tokens should map to semantic tokens, not to raw numbers.
544
+
545
+ ---
546
+
547
+ ## 10. Quick adoption checklist
548
+
549
+ 1. Use the dimension scale (`--cem-dim-*`) as the foundation.
550
+ 2. Map semantic endpoints (`gap-*`, `inset-*`, `rhythm-*`) to dimension tokens.
551
+ 3. Treat D2 coupling (`zone/guard/halo`) as **hard constraints** for interactive adjacency — see [`cem-coupling.md`](./cem-coupling.md).
552
+ 4. Update component tokens to use semantic endpoints.
553
+ 5. Add optional `data-cem-spacing="dense|normal|sparse"` only if product needs spacing modes.
554
+ 6. Validate on representative surfaces:
555
+ - interactive clusters: guard is respected and no halo overlap occurs
556
+ - reading rhythm (articles/help)
557
+ - scan rhythm (tables/metric panels)
558
+ - responsive gutters
559
+ 7. Validate bend-inset harmony on rounded surfaces — see [`cem-shape.md`](./cem-shape.md) §8.5.
560
+
561
+ ---
562
+
563
+ ## Appendix A. D2 Coupling Mode Matrix (excerpt)
564
+
565
+ This excerpt is provided for convenience when working in D1. The canonical definitions and governance live in **D2.
566
+ Coupling & Compactness** ([`cem-coupling.md`](./cem-coupling.md)).
567
+
568
+ | D2 coupling mode | Product intent | Visual geometry trend | Halo (`--cem-coupling-halo`) trend | Typical surfaces |
569
+ |------------------|-----------------------------------------------------------|---------------------------------------------|-------------------------------------|-------------------------------------------------------|
570
+ | `forgiving` | Minimize mis-coupling for imprecise input | Larger controls/rows; more internal padding | Smaller (visuals already meet zone) | mobile-first, kiosks, accessibility-first, gaze/dwell |
571
+ | `balanced` | Default across modalities | Baseline control heights/rows | Baseline | mixed pointer + touch, general app UI |
572
+ | `compact` | Increase information density without breaking operability | Smaller visuals; reduced chrome | Larger (use halo to preserve zone) | data grids, admin tools, scan-heavy panels |
573
+
574
+ Normative invariants (do not override in D1):
575
+
576
+ - `--cem-coupling-zone-min` is mode-invariant.
577
+ - `--cem-coupling-guard-min` is mode-invariant.
578
+ - D1 gaps between interactive affordances must resolve as: `gap = max(D1 semantic gap, D2 coupling guard)`.
579
+
580
+ ---
581
+
582
+ ## Appendix B. Governance and versioning
583
+
584
+ This D1 spec is a **contract**. Changes must be intentional, reviewable, and versioned.
585
+
586
+ ### B.1 What counts as breaking
587
+
588
+ Treat as **major** (breaking) if you:
589
+
590
+ - Rename or remove any canonical D1 semantic endpoint (`gap-*`, `inset-*`, `layout-*`, `rhythm-*`).
591
+ - Change the semantic meaning of an endpoint (e.g., `gap-group` stops meaning "within a group").
592
+ - Change mode names or add/remove spacing modes.
593
+ - Weaken the D1↔D2 constraint model (anything that could permit violating D2 coupling guard/zone).
594
+
595
+ ### B.2 What is non-breaking
596
+
597
+ Treat as **minor/patch** if you:
598
+
599
+ - Adjust numeric values within a mode while preserving semantics and invariants.
600
+ - Add new semantic endpoints that are clearly scoped, optional, and do not redefine existing meaning.
601
+ - Clarify documentation, examples, or mapping guidance.
602
+
603
+ ### B.3 Versioning guidance
604
+
605
+ - **PATCH**: documentation clarifications; no token/value changes.
606
+ - **MINOR**: additive tokens or additive examples; safe value tuning.
607
+ - **MAJOR**: renames, removals, meaning shifts, or mode changes.
608
+
609
+ ### B.4 Canonical cross-spec invariants
610
+
611
+ D1 is subordinate to D2 for operability. The following must hold in every release:
612
+
613
+ - D2 coupling invariants remain enforceable from D1.
614
+ - Any D1 spacing used between interactive affordances must resolve as `gap = max(D1 semantic gap, D2 coupling guard)`.
615
+
616
+ ---
617
+
618
+ ## References
619
+
620
+ **Local CEM documentation**
621
+ - [D2. Coupling & Compactness](./cem-coupling.md) — interactive operability constraints
622
+ - [D3. Shape & Bend](./cem-shape.md) — bend tokens, bend-inset harmony
623
+ - [D5. Stroke & Separation](./cem-stroke.md) — boundaries, dividers, focus/selection/target indicators
624
+ - [D6. Typography](./cem-voice-fonts-typography.md) — reading rhythm validation
625
+ - [D7. Time & Motion](./cem-timing.md) — rhythm perception