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

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 (185) hide show
  1. package/.claude/settings.local.json +18 -0
  2. package/.gitattributes +4 -0
  3. package/.github/workflows/deploy.yml +59 -0
  4. package/.idea/copilot.data.migration.agent.xml +6 -0
  5. package/.idea/copilot.data.migration.ask.xml +6 -0
  6. package/.idea/copilot.data.migration.ask2agent.xml +6 -0
  7. package/.idea/copilot.data.migration.edit.xml +6 -0
  8. package/.idea/custom-element-dist.iml +2 -0
  9. package/.storybook/main.ts +20 -17
  10. package/.storybook/preview.ts +23 -23
  11. package/.yarn/install-state.gz +0 -0
  12. package/.yarnrc.yml +1 -0
  13. package/README.md +6 -4
  14. package/coverage/block-navigation.js +1 -1
  15. package/coverage/coverage-final.json +4 -3
  16. package/coverage/index.html +34 -19
  17. package/coverage/sorter.js +21 -7
  18. package/coverage/src/custom-element/coverage.svg +1 -1
  19. package/coverage/src/custom-element/custom-element.js/coverage.svg +1 -1
  20. package/coverage/src/custom-element/custom-element.js.html +448 -391
  21. package/coverage/src/custom-element/http-request.js/coverage.svg +1 -1
  22. package/coverage/src/custom-element/http-request.js.html +38 -17
  23. package/coverage/src/custom-element/index.html +26 -26
  24. package/coverage/src/custom-element/local-storage.js.html +1 -1
  25. package/coverage/src/custom-element/location-element.js.html +1 -1
  26. package/coverage/src/custom-element/module-url.js.html +1 -1
  27. package/coverage/src/index.html +1 -1
  28. package/coverage/src/material/theme/colors.js/coverage.svg +10 -0
  29. package/coverage/src/material/theme/colors.js.html +217 -0
  30. package/coverage/src/material/theme/coverage.svg +10 -0
  31. package/coverage/src/material/theme/index.html +116 -0
  32. package/coverage/src/mocks/handlers.ts.html +1 -1
  33. package/coverage/src/mocks/index.html +1 -1
  34. package/coverage/src/stories/frame.canvas.ts.html +1 -1
  35. package/coverage/src/stories/http-request.stories.ts.html +1 -1
  36. package/coverage/src/stories/index.html +1 -1
  37. package/coverage/src/stories/testStoryBook.ts.html +12 -12
  38. package/coverage/src/sum.ts.html +1 -1
  39. package/dist/custom-element-Bssk9jRy.cjs +97 -0
  40. package/dist/{custom-element-WnOqmEOe.js → custom-element-BzDjIYMe.js} +193 -183
  41. package/dist/custom-element-bundle.cjs +1 -1
  42. package/dist/custom-element-bundle.js +3 -3
  43. package/dist/demo/a.html +10 -3
  44. package/dist/demo/a.svg +26 -26
  45. package/dist/demo/html-template.html +4 -3
  46. package/dist/demo/s.xml +1 -75
  47. package/dist/demo/s.xslt +351 -72
  48. package/dist/demo/s1.xml +3706 -0
  49. package/dist/http-request-DSaowcG1.cjs +1 -0
  50. package/dist/{http-request-BOvP4KTl.js → http-request-DTCzZ1gc.js} +15 -9
  51. package/dist/mockServiceWorker.js +105 -63
  52. package/package.json +5 -4
  53. package/public/demo/a.html +10 -3
  54. package/public/demo/a.svg +26 -26
  55. package/public/demo/html-template.html +4 -3
  56. package/public/demo/s.xml +1 -75
  57. package/public/demo/s.xslt +351 -72
  58. package/public/demo/s1.xml +3706 -0
  59. package/public/mockServiceWorker.js +105 -63
  60. package/src/custom-element/custom-element.js +28 -9
  61. package/src/custom-element/demo/a.html +10 -3
  62. package/src/custom-element/demo/a.svg +26 -26
  63. package/src/custom-element/demo/html-template.html +4 -3
  64. package/src/custom-element/demo/s.xml +1 -75
  65. package/src/custom-element/demo/s.xslt +351 -72
  66. package/src/custom-element/demo/s1.xml +3706 -0
  67. package/src/custom-element/http-request.js +7 -0
  68. package/src/custom-element/ide/customData-dce.json +123 -0
  69. package/src/custom-element/ide/web-types-dce.json +128 -1
  70. package/src/custom-element/ide/web-types-xsl.json +1 -1
  71. package/src/material/angular.css +987 -987
  72. package/src/material/components/action.html +262 -0
  73. package/src/material/components/autocomplete.html +167 -239
  74. package/src/material/components/badge.html +238 -239
  75. package/src/material/components/dropdown.html +0 -1
  76. package/src/material/components/icon-link.html +160 -161
  77. package/src/material/components/icon.html +251 -252
  78. package/src/material/components/input.html +569 -570
  79. package/src/material/components/menu.html +235 -236
  80. package/src/material/components.html +157 -158
  81. package/src/material/demo.css +36 -36
  82. package/src/material/index.html +109 -110
  83. package/src/material/material.css +356 -356
  84. package/src/material/theme/Base-Principles.md +339 -0
  85. package/src/material/theme/README.md +298 -18
  86. package/src/material/theme/UI Domain Model in web applications.svg +1 -0
  87. package/src/material/theme/User Semantic Theme tokens.svg +1 -0
  88. package/src/material/theme/action-pending-poc.html +62 -0
  89. package/src/material/theme/actions-color.html +141 -0
  90. package/src/material/theme/colors-light.html +631 -0
  91. package/src/material/theme/colors-native.html +51 -0
  92. package/src/material/theme/colors-poc.html +66 -0
  93. package/src/material/theme/colors.html +297 -0
  94. package/src/material/theme/colors.js +44 -0
  95. package/src/material/theme/consumer-theme.css +745 -0
  96. package/src/material/theme/semantic.css +132 -132
  97. package/src/material/theme/style-bug.html +123 -0
  98. package/src/material/theme/theme-data.css +43 -0
  99. package/src/material/theme/theme-data.xhtml +2926 -0
  100. package/src/material/theme/todo.md +274 -0
  101. package/src/material/theme/tokens/action-colors.png +0 -0
  102. package/src/material/theme/tokens/cem-article-illustration-4x1-letterbox-2000x500.png +0 -0
  103. package/src/material/theme/tokens/cem-breakpoints.md +519 -0
  104. package/src/material/theme/tokens/cem-colors.md +715 -0
  105. package/src/material/theme/tokens/cem-consumerflow-typography-matrix.svg +198 -0
  106. package/src/material/theme/tokens/cem-coupling.md +372 -0
  107. package/src/material/theme/tokens/cem-data-vs-reading-numerals.svg +164 -0
  108. package/src/material/theme/tokens/cem-dimension.md +625 -0
  109. package/src/material/theme/tokens/cem-layering.md +562 -0
  110. package/src/material/theme/tokens/cem-m3-parity.md +343 -0
  111. package/src/material/theme/tokens/cem-responsive.md +238 -0
  112. package/src/material/theme/tokens/cem-shape.md +691 -0
  113. package/src/material/theme/tokens/cem-stroke-density-illustration-4to1-v3.svg +102 -0
  114. package/src/material/theme/tokens/cem-stroke.md +480 -0
  115. package/src/material/theme/tokens/cem-timing.md +198 -0
  116. package/src/material/theme/tokens/cem-typography-model-stack.svg +64 -0
  117. package/src/material/theme/tokens/cem-voice-fonts-typography.md +718 -0
  118. package/src/material/theme/tokens/cem-voice-ladder.svg +91 -0
  119. package/src/material/theme/tokens/chips.png +0 -0
  120. package/src/material/theme/tokens/columns-page.png +0 -0
  121. package/src/material/theme/tokens/initials.png +0 -0
  122. package/src/material/theme/tokens/nav-buttons.png +0 -0
  123. package/src/material/theme/tokens/script.png +0 -0
  124. package/src/material/theme/tokens/sufler.png +0 -0
  125. package/src/material/theme/tokens/typography-icons.png +0 -0
  126. package/src/mocks/versions.mock.ts +1 -1
  127. package/src/stories/__screenshots__/dom-merge.test.stories.ts/dom-merge-dom-merge-OrderPreservingOn2ndTransform-1.png +0 -0
  128. package/src/stories/__screenshots__/xslt-conditionals.test.stories.ts/xslt-conditionals-xslt-conditionals-MultipleIfOrderingWorkaround-1.png +0 -0
  129. package/src/stories/dom-merge.test.stories.ts +25 -1
  130. package/src/stories/xslt-conditionals.test.stories.ts +492 -0
  131. package/src/stories/xslt-for-each.test.stories.ts +336 -0
  132. package/src/stories/xslt-if.test.stories.ts +89 -0
  133. package/storybook-static/assets/{Color-F6OSRLHC-Cbp293x2.js → Color-F6OSRLHC-DeDlDLjU.js} +1 -1
  134. package/storybook-static/assets/{Configure-BrFr4SLE.js → Configure-CH_tIP5N.js} +1 -1
  135. package/storybook-static/assets/{DocsRenderer-CFRXHY34-DhHzJiIO.js → DocsRenderer-CFRXHY34-Bc9EPsUI.js} +2 -2
  136. package/storybook-static/assets/{attributes.test.stories-Gg9LQTEK.js → attributes.test.stories-BtamFQkF.js} +1 -1
  137. package/storybook-static/assets/{css.test.stories-B_3ltOrx.js → css.test.stories-BfNxLgwr.js} +1 -1
  138. package/storybook-static/assets/{custom-element-CPnvJnn8.js → custom-element-CnmjNo0g.js} +6 -6
  139. package/storybook-static/assets/{dom-merge.test.stories-nQxcgLoM.js → dom-merge.test.stories-DxnitrLK.js} +47 -6
  140. package/storybook-static/assets/entry-preview-BNCt9WBs.js +26 -0
  141. package/storybook-static/assets/{entry-preview-docs-Dwczwtsc.js → entry-preview-docs-CbF8-81D.js} +2 -2
  142. package/storybook-static/assets/{external-template.test.stories-DZ-rjnfd.js → external-template.test.stories-BTsww7B0.js} +1 -1
  143. package/storybook-static/assets/{form.test.stories-DQhPYtMj.js → form.test.stories-DNJFtPJb.js} +1 -1
  144. package/storybook-static/assets/{frame.canvas-ClTqYyMN.js → frame.canvas-E5n9h6j1.js} +1 -1
  145. package/storybook-static/assets/{handlers-CLkps6Nz.js → handlers-Dvg8CAeR.js} +1 -1
  146. package/storybook-static/assets/http-request-BWeEEBkP.js +1 -0
  147. package/storybook-static/assets/{http-request.stories-jo0f73nw.js → http-request.stories-DgrBNle8.js} +1 -1
  148. package/storybook-static/assets/{iframe-CZwRpnn9.js → iframe-DiVWehoI.js} +11 -11
  149. package/storybook-static/assets/{index-Dr4PwNfd.js → index-CGuyH0k-.js} +87 -87
  150. package/storybook-static/assets/{index-CJQtnF9V.js → index-CdEbhcV9.js} +1 -1
  151. package/storybook-static/assets/index-DO1nmyvI.js +11 -0
  152. package/storybook-static/assets/{index-B68YUdzy.js → index-w6iX3YlR.js} +3 -3
  153. package/storybook-static/assets/{local-storage.test.stories-uA5EKRPf.js → local-storage.test.stories-Hwq80yUr.js} +1 -1
  154. package/storybook-static/assets/{location-element.test.stories-Cu-6Elcg.js → location-element.test.stories-mEhZzm7x.js} +1 -1
  155. package/storybook-static/assets/{module-url.test.stories-CD_wusXQ.js → module-url.test.stories-Bj46iT0V.js} +1 -1
  156. package/storybook-static/assets/{preview-CuCH40jj.js → preview-BjbXcJci.js} +2 -2
  157. package/storybook-static/assets/{preview-BFlNN3Wj.js → preview-Bn8igYMp.js} +1 -1
  158. package/storybook-static/assets/{preview-Cm4PPhHS.js → preview-CfuT8gak.js} +1 -1
  159. package/storybook-static/assets/{set-url.test.stories-CY7B9BVZ.js → set-url.test.stories-hzxLcqmm.js} +1 -1
  160. package/storybook-static/assets/{slice-events.test.stories-BVnPXm6e.js → slice-events.test.stories-DVyXFRU1.js} +1 -1
  161. package/storybook-static/assets/{slots.test.stories-Dxsa9KdA.js → slots.test.stories-CS544nS4.js} +1 -1
  162. package/storybook-static/assets/{version-select.test.stories-Buga1PAa.js → version-select.test.stories-D36nfYBq.js} +1 -1
  163. package/storybook-static/assets/xslt-conditionals.test.stories-BS1PTIHe.js +633 -0
  164. package/storybook-static/assets/xslt-for-each.test.stories-CtPS20RK.js +329 -0
  165. package/storybook-static/assets/xslt-if.test.stories-DcHrAMSY.js +71 -0
  166. package/storybook-static/demo/a.html +10 -3
  167. package/storybook-static/demo/a.svg +26 -26
  168. package/storybook-static/demo/html-template.html +4 -3
  169. package/storybook-static/demo/s.xml +1 -75
  170. package/storybook-static/demo/s.xslt +351 -72
  171. package/storybook-static/demo/s1.xml +3706 -0
  172. package/storybook-static/iframe.html +2 -2
  173. package/storybook-static/index.json +1 -1
  174. package/storybook-static/mockServiceWorker.js +105 -63
  175. package/storybook-static/project.json +1 -1
  176. package/storybook-static/sb-addons/essentials-controls-1/manager-bundle.js +69 -66
  177. package/storybook-static/sb-addons/essentials-docs-3/manager-bundle.js +62 -59
  178. package/dist/custom-element-6slVaFEs.cjs +0 -97
  179. package/dist/http-request-DPrY7mGh.cjs +0 -1
  180. package/storybook-static/assets/attributes.test.stories-CzWkKw0e.js +0 -1
  181. package/storybook-static/assets/entry-preview-DHVXbf3x.js +0 -26
  182. package/storybook-static/assets/external-template.test.stories-BivZqBTp.js +0 -1
  183. package/storybook-static/assets/http-request-DNq59pnj.js +0 -1
  184. package/storybook-static/assets/index-BwkS7JH_.js +0 -8
  185. package/storybook-static/assets/module-url.test.stories-CTjUAk3J.js +0 -1
@@ -0,0 +1,198 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="1400" height="860" viewBox="0 0 1400 860" role="img" aria-label="Consumer-flow mapping matrix: purpose by semantic typography roles with default voice levels">
3
+ <defs>
4
+ <style>
5
+ :root {
6
+ --cem-ink: #111;
7
+ --cem-surface: #fff;
8
+ --cem-outline: #c7c7c7;
9
+ --cem-muted: #666;
10
+ --cem-accent: #005a9c;
11
+ --cem-soft: #f6f7f9;
12
+ }
13
+ .frame { fill: var(--cem-surface); stroke: var(--cem-outline); stroke-width: 2; rx: 18; }
14
+ .cell { fill: var(--cem-surface); stroke: var(--cem-outline); stroke-width: 1.5; rx: 12; }
15
+ .cell-soft { fill: var(--cem-soft); stroke: var(--cem-outline); stroke-width: 1.5; rx: 12; }
16
+ .cell-accent { fill: var(--cem-surface); stroke: var(--cem-accent); stroke-width: 2.2; rx: 12; }
17
+ .title { font: 700 32px system-ui, -apple-system, "Segoe UI", Arial, sans-serif; fill: var(--cem-ink); }
18
+ .muted { font: 400 16px system-ui, -apple-system, "Segoe UI", Arial, sans-serif; fill: var(--cem-muted); }
19
+ .h { font: 650 18px system-ui, -apple-system, "Segoe UI", Arial, sans-serif; fill: var(--cem-ink); }
20
+ .t { font: 400 16px system-ui, -apple-system, "Segoe UI", Arial, sans-serif; fill: var(--cem-ink); }
21
+ .tag { font: 600 14px ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; fill: var(--cem-accent); }
22
+ </style>
23
+ </defs>
24
+
25
+ <rect x="30" y="30" width="1340" height="800" class="frame"/>
26
+
27
+ <text x="70" y="92" class="title">Consumer flow → semantic typography roles → default voice</text>
28
+ <text x="70" y="125" class="muted">Roles are “what the content is”; flow is “what the user is doing”.</text>
29
+
30
+ <rect x="70" y="170" width="260" height="60" class="cell-soft"/>
31
+ <text x="90" y="208" class="h">Consumer flow purpose</text>
32
+
33
+ <g>
34
+ <rect x="340" y="170" width="170" height="60" class="cell-soft"/>
35
+ <text x="360" y="198" class="h">Reading</text>
36
+ <text x="360" y="220" class="tag">voice: regular</text>
37
+
38
+ <rect x="520" y="170" width="170" height="60" class="cell-soft"/>
39
+ <text x="540" y="198" class="h">UI</text>
40
+ <text x="540" y="220" class="tag">voice: gentle</text>
41
+
42
+ <rect x="700" y="170" width="170" height="60" class="cell-soft"/>
43
+ <text x="720" y="198" class="h">Data</text>
44
+ <text x="720" y="220" class="tag">voice: regular</text>
45
+
46
+ <rect x="880" y="170" width="170" height="60" class="cell-soft"/>
47
+ <text x="900" y="198" class="h">Tag</text>
48
+ <text x="900" y="220" class="tag">voice: firm</text>
49
+
50
+ <rect x="1060" y="170" width="170" height="60" class="cell-soft"/>
51
+ <text x="1080" y="198" class="h">Script</text>
52
+ <text x="1080" y="220" class="tag">voice: gentle</text>
53
+
54
+ <rect x="1240" y="170" width="120" height="60" class="cell-soft"/>
55
+ <text x="1255" y="198" class="h">Init.</text>
56
+ <text x="1255" y="220" class="tag">voice: firm</text>
57
+ </g>
58
+
59
+ <!-- Row 1 -->
60
+ <g>
61
+ <rect x="70" y="245" width="260" height="80" class="cell-soft"/>
62
+ <text x="90" y="285" class="h">Orient / Navigate</text>
63
+ <text x="90" y="310" class="muted">Where am I? Where do I go?</text>
64
+
65
+ <rect x="340" y="245" width="170" height="80" class="cell"/>
66
+ <text x="360" y="292" class="t">Sometimes</text>
67
+
68
+ <rect x="520" y="245" width="170" height="80" class="cell-accent"/>
69
+ <text x="540" y="280" class="t">Primary</text>
70
+ <text x="540" y="305" class="tag">voice: gentle</text>
71
+
72
+ <rect x="700" y="245" width="170" height="80" class="cell"/>
73
+ <text x="720" y="292" class="t">Rare</text>
74
+
75
+ <rect x="880" y="245" width="170" height="80" class="cell-accent"/>
76
+ <text x="900" y="280" class="t">Often</text>
77
+ <text x="900" y="305" class="tag">voice: firm</text>
78
+
79
+ <rect x="1060" y="245" width="170" height="80" class="cell"/>
80
+ <text x="1080" y="292" class="t">Sometimes</text>
81
+
82
+ <rect x="1240" y="245" width="120" height="80" class="cell-accent"/>
83
+ <text x="1255" y="280" class="t">Often</text>
84
+ <text x="1255" y="305" class="tag">voice: firm</text>
85
+ </g>
86
+
87
+ <!-- Row 2 -->
88
+ <g>
89
+ <rect x="70" y="345" width="260" height="80" class="cell-soft"/>
90
+ <text x="90" y="385" class="h">Scan / Compare</text>
91
+ <text x="90" y="410" class="muted">What differs? Which option wins?</text>
92
+
93
+ <rect x="340" y="345" width="170" height="80" class="cell"/>
94
+ <text x="360" y="392" class="t">Sometimes</text>
95
+
96
+ <rect x="520" y="345" width="170" height="80" class="cell-accent"/>
97
+ <text x="540" y="380" class="t">Often</text>
98
+ <text x="540" y="405" class="tag">voice: gentle</text>
99
+
100
+ <rect x="700" y="345" width="170" height="80" class="cell-accent"/>
101
+ <text x="720" y="380" class="t">Primary</text>
102
+ <text x="720" y="405" class="tag">voice: regular</text>
103
+
104
+ <rect x="880" y="345" width="170" height="80" class="cell-accent"/>
105
+ <text x="900" y="380" class="t">Often</text>
106
+ <text x="900" y="405" class="tag">voice: firm</text>
107
+
108
+ <rect x="1060" y="345" width="170" height="80" class="cell"/>
109
+ <text x="1080" y="392" class="t">Rare</text>
110
+
111
+ <rect x="1240" y="345" width="120" height="80" class="cell"/>
112
+ <text x="1255" y="392" class="t">Sometimes</text>
113
+ </g>
114
+
115
+ <!-- Row 3 -->
116
+ <g>
117
+ <rect x="70" y="445" width="260" height="80" class="cell-soft"/>
118
+ <text x="90" y="485" class="h">Read / Learn</text>
119
+ <text x="90" y="510" class="muted">Understand and retain</text>
120
+
121
+ <rect x="340" y="445" width="170" height="80" class="cell-accent"/>
122
+ <text x="360" y="480" class="t">Primary</text>
123
+ <text x="360" y="505" class="tag">voice: regular</text>
124
+
125
+ <rect x="520" y="445" width="170" height="80" class="cell"/>
126
+ <text x="540" y="492" class="t">Sometimes</text>
127
+
128
+ <rect x="700" y="445" width="170" height="80" class="cell"/>
129
+ <text x="720" y="492" class="t">Sometimes</text>
130
+
131
+ <rect x="880" y="445" width="170" height="80" class="cell"/>
132
+ <text x="900" y="492" class="t">Sometimes</text>
133
+
134
+ <rect x="1060" y="445" width="170" height="80" class="cell"/>
135
+ <text x="1080" y="492" class="t">Sometimes</text>
136
+
137
+ <rect x="1240" y="445" width="120" height="80" class="cell"/>
138
+ <text x="1255" y="492" class="t">Rare</text>
139
+ </g>
140
+
141
+ <!-- Row 4 -->
142
+ <g>
143
+ <rect x="70" y="545" width="260" height="80" class="cell-soft"/>
144
+ <text x="90" y="585" class="h">Act</text>
145
+ <text x="90" y="610" class="muted">Commit: click, submit, approve</text>
146
+
147
+ <rect x="340" y="545" width="170" height="80" class="cell"/>
148
+ <text x="360" y="592" class="t">Rare</text>
149
+
150
+ <rect x="520" y="545" width="170" height="80" class="cell-accent"/>
151
+ <text x="540" y="580" class="t">Primary</text>
152
+ <text x="540" y="605" class="tag">voice: firm</text>
153
+
154
+ <rect x="700" y="545" width="170" height="80" class="cell"/>
155
+ <text x="720" y="592" class="t">Sometimes</text>
156
+
157
+ <rect x="880" y="545" width="170" height="80" class="cell-accent"/>
158
+ <text x="900" y="580" class="t">Often</text>
159
+ <text x="900" y="605" class="tag">voice: firm</text>
160
+
161
+ <rect x="1060" y="545" width="170" height="80" class="cell"/>
162
+ <text x="1080" y="592" class="t">Rare</text>
163
+
164
+ <rect x="1240" y="545" width="120" height="80" class="cell"/>
165
+ <text x="1255" y="592" class="t">Rare</text>
166
+ </g>
167
+
168
+ <!-- Row 5 -->
169
+ <g>
170
+ <rect x="70" y="645" width="260" height="80" class="cell-soft"/>
171
+ <text x="90" y="685" class="h">Confirm / Reflect</text>
172
+ <text x="90" y="710" class="muted">Understand outcomes and status</text>
173
+
174
+ <rect x="340" y="645" width="170" height="80" class="cell-accent"/>
175
+ <text x="360" y="680" class="t">Often</text>
176
+ <text x="360" y="705" class="tag">voice: regular</text>
177
+
178
+ <rect x="520" y="645" width="170" height="80" class="cell-accent"/>
179
+ <text x="540" y="680" class="t">Often</text>
180
+ <text x="540" y="705" class="tag">voice: gentle</text>
181
+
182
+ <rect x="700" y="645" width="170" height="80" class="cell-accent"/>
183
+ <text x="720" y="680" class="t">Often</text>
184
+ <text x="720" y="705" class="tag">voice: regular</text>
185
+
186
+ <rect x="880" y="645" width="170" height="80" class="cell-accent"/>
187
+ <text x="900" y="680" class="t">Often</text>
188
+ <text x="900" y="705" class="tag">voice: firm</text>
189
+
190
+ <rect x="1060" y="645" width="170" height="80" class="cell"/>
191
+ <text x="1080" y="692" class="t">Rare</text>
192
+
193
+ <rect x="1240" y="645" width="120" height="80" class="cell"/>
194
+ <text x="1255" y="692" class="t">Sometimes</text>
195
+ </g>
196
+
197
+ <text x="70" y="792" class="muted">Tip: Treat alerts and safety-critical announcements as separate semantics (not just typography). Use ARIA live regions appropriately.</text>
198
+ </svg>
@@ -0,0 +1,372 @@
1
+ # Semantic Density and Coupling Tokens (CEM) — Canonical Spec
2
+
3
+ **Status:** Canonical (v1.0)
4
+
5
+ **Last updated:** December 17, 2025
6
+
7
+ **Audience:** Design Systems, Product Design, Front-End Engineering
8
+
9
+ **Applies to:** Modality-neutral interactive operability (pointer, touch, stylus, gaze, switch, remote)
10
+
11
+ **Companion specs:**
12
+ - **D0. Color (Emotional Palette)** ([`cem-colors.md`](./cem-colors.md)) — color intensity perception affected by density
13
+ - **D1. Space & Rhythm** ([`cem-dimension.md`](./cem-dimension.md)) — gaps/insets/rhythm; must never violate D2 safety minimums
14
+ - **D3. Shape — Bend** ([`cem-shape.md`](./cem-shape.md)) — bend interacts with control height for round-ends
15
+ - **D4. Layering** ([`cem-layering.md`](./cem-layering.md)) — overlay/modal control sizing
16
+ - **D5. Stroke & Separation** ([`cem-stroke.md`](./cem-stroke.md)) — focus ring offset; D2 constrains adjacent zones so indicators have room
17
+ - **D7. Time & Motion** ([`cem-timing.md`](./cem-timing.md)) — timing for density transitions
18
+
19
+ ---
20
+
21
+ ## 1. Why "Coupling"
22
+
23
+ In CEM terms, **coupling** names the moment when **user intent successfully binds to an interactive affordance**—independent of input modality:
24
+
25
+ - pointer (mouse/trackpad/stylus)
26
+ - direct touch (touchscreen)
27
+ - gaze (eye tracking + dwell)
28
+ - switch scanning (highlight + select)
29
+ - remote / gamepad focus navigation
30
+
31
+ This supports the UI-space meaning you called out: proximity implies **relationship/coupling between controls**, and insufficient distancing causes **interference**.
32
+
33
+ ---
34
+
35
+ ## 2. Taxonomy placement
36
+
37
+ - **D2. Coupling & Compactness** (this canvas)
38
+ - operable zone minimums
39
+ - interference/isolation minimums
40
+ - halo/expansion policy (visual size vs operable size)
41
+ - control geometry endpoints that affect operability (heights/paddings/row sizes)
42
+
43
+ - **D1. Space & Rhythm** (from [`cem-dimension.md`](./cem-dimension.md))
44
+ - gaps/insets/rhythm
45
+ - may *suggest* coupling semantics, but must never violate D2 safety minimums
46
+
47
+ - **D5. Stroke & Separation** (from [`cem-stroke.md`](./cem-stroke.md))
48
+ - focus/selection/target indicator thickness and indicator placement (e.g., `--cem-stroke-focus`, `--cem-stroke-indicator-offset`, zebra ring tokens)
49
+ - D2 does not define focus-ring offset; D2 constrains adjacent operable zones so D5 indicators have room and do not create interference
50
+
51
+ Boundary heuristic:
52
+
53
+ - If it changes **distance between items** → D1
54
+ - If it changes **operable geometry of an interactive element** → D2
55
+ - If it changes **indicator thickness or indicator offset** → D5 (e.g., `--cem-stroke-focus`, `--cem-stroke-indicator-offset`)
56
+
57
+ ---
58
+
59
+ ## 3. Coupling vocabulary (semantic + dimensional)
60
+
61
+ To keep the naming dimensional and unambiguous, use three core nouns:
62
+
63
+ - **Zone**: the operable area where intent can couple
64
+ - **Halo**: invisible expansion beyond visuals (to meet zone minimums without enlarging chrome)
65
+ - **Guard**: the minimum distancing preventing interference between adjacent zones
66
+
67
+ ---
68
+
69
+ ## 4. Canonical D2 coupling tokens
70
+
71
+ ### 4.1 Hard safety minimums (policy anchors)
72
+
73
+ ```css
74
+ :root {
75
+ /* Minimum operable zone (layout-level). Keep invariant across density modes. */
76
+ --cem-coupling-zone-min: 3rem; /* nominally 48px @ 16px root */
77
+
78
+ /* Minimum distancing between adjacent operable zones (prevents interference). */
79
+ --cem-coupling-guard-min: 0.5rem; /* nominally 8px */
80
+
81
+ /* Invisible expansion beyond visuals (halo). */
82
+ --cem-coupling-halo: 0.25rem; /* nominally 4px */
83
+ }
84
+ ```
85
+
86
+ Interpretation:
87
+
88
+ - **Zone** answers: “Can the user reliably couple intent to this control?”
89
+ - **Guard** answers: “Will adjacent controls accidentally steal intent?”
90
+ - **Halo** answers: “Can we keep visuals compact while preserving operability?”
91
+
92
+ ### 4.1.1 D2/D5 compatibility: guard must cover indicator outset (normative)
93
+
94
+ When D5 indicators render **outside** the control edge (e.g., `outline-offset`, zebra rings),
95
+ `--cem-coupling-guard-min` SHOULD be large enough to prevent indicator collisions between adjacent controls.
96
+
97
+ Define the worst-case outward indicator extent as:
98
+
99
+ - Zebra ring (contrast): `4 * --cem-zebra-strip-size`
100
+ - Outline ring: `--cem-stroke-indicator-offset + --cem-stroke-focus`
101
+
102
+ Compatibility guideline:
103
+
104
+ `--cem-coupling-guard-min` SHOULD be ≥
105
+ `max(4 * --cem-zebra-strip-size, --cem-stroke-indicator-offset + --cem-stroke-focus)`
106
+
107
+ Default CEM values satisfy this (8px guard vs 8px zebra extent when `--cem-zebra-strip-size = 2px`).
108
+
109
+ ### 4.2 Control geometry endpoints (typical mapping layer)
110
+
111
+ ```css
112
+ :root {
113
+ /* Generic control geometry */
114
+ --cem-control-height: 2.5rem;
115
+ --cem-control-padding-x: 0.75rem;
116
+ --cem-control-padding-y: 0.5rem;
117
+
118
+ /* Icon buttons: typically make the visible container meet the operable zone */
119
+ --cem-icon-button-size: var(--cem-coupling-zone-min);
120
+ --cem-icon-button-icon-size: 1.25rem;
121
+
122
+ /* Lists / menus */
123
+ --cem-list-row-height: 3rem;
124
+ --cem-menu-row-height: 3rem;
125
+
126
+ /* Data tables */
127
+ --cem-table-row-height: 2.5rem;
128
+ }
129
+ ```
130
+
131
+ Note: control geometry can vary by mode; coupling minimums should remain invariant.
132
+
133
+ ---
134
+
135
+ ## 5. Coupling modes (consumer semantics)
136
+
137
+ ### 5.1 Mode meanings
138
+
139
+ - **forgiving**
140
+ - optimized for imprecise input: thumbs, gloves, kiosks, gaze/dwell
141
+ - larger visual controls; halo may be smaller because visuals already provide the zone
142
+
143
+ - **balanced**
144
+ - default for mixed mouse/touch usage
145
+
146
+ - **compact**
147
+ - optimized for scan-heavy/data-rich screens
148
+ - visuals may get tighter, but **coupling remains safe via halo + guard**
149
+
150
+ ### 5.2 Mode switch
151
+
152
+ ```css
153
+ :root { --cem-coupling: balanced; }
154
+
155
+ :root[data-cem-coupling="balanced"] { /* baseline */ }
156
+
157
+ :root[data-cem-coupling="forgiving"] {
158
+ --cem-control-height: 2.75rem;
159
+ --cem-control-padding-x: 1rem;
160
+ --cem-control-padding-y: 0.625rem;
161
+
162
+ --cem-list-row-height: 3.25rem;
163
+ --cem-menu-row-height: 3.25rem;
164
+
165
+ /* Coupling remains safe; halo can be smaller because visuals are larger */
166
+ --cem-coupling-halo: 0.125rem;
167
+ }
168
+
169
+ :root[data-cem-coupling="compact"] {
170
+ --cem-control-height: 2.25rem;
171
+ --cem-control-padding-x: 0.625rem;
172
+ --cem-control-padding-y: 0.375rem;
173
+
174
+ --cem-list-row-height: 2.75rem;
175
+ --cem-menu-row-height: 2.75rem;
176
+
177
+ /* Keep coupling safe when visuals shrink */
178
+ --cem-coupling-halo: 0.375rem;
179
+ }
180
+ ```
181
+
182
+ Governance rule: **do not reduce** `--cem-coupling-zone-min` or `--cem-coupling-guard-min` per mode.
183
+
184
+ ---
185
+
186
+ ## 6. Implementation patterns
187
+
188
+ ### 6.1 Halo-based operability (compact visuals, safe coupling)
189
+
190
+ ```css
191
+ .cem-control {
192
+ min-block-size: var(--cem-coupling-zone-min);
193
+ padding-inline: var(--cem-control-padding-x);
194
+ padding-block: var(--cem-control-padding-y);
195
+ }
196
+
197
+ /* Optional: halo expansion when visible chrome is smaller than the operable contract */
198
+ .cem-coupling-halo {
199
+ position: relative;
200
+ }
201
+
202
+ .cem-coupling-halo::after {
203
+ content: "";
204
+ position: absolute;
205
+ inset: calc(-1 * var(--cem-coupling-halo));
206
+ background: transparent;
207
+ }
208
+ ```
209
+
210
+ ### 6.2 D1/D2 enforcement: spacing must not violate coupling guard
211
+
212
+ ```css
213
+ .cem-actions {
214
+ display: flex;
215
+ gap: max(var(--cem-gap-related, 0px), var(--cem-coupling-guard-min));
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ## 7. Optional: coupling semantics between controls (proximity implies relatedness)
222
+
223
+ If you want proximity to intentionally communicate relationship, add an optional D1/D2 bridge token set:
224
+
225
+ ```css
226
+ :root {
227
+ /* Within this distance, controls are perceived as a group (segmented, paired actions). */
228
+ --cem-coupling-affinity-max: 0.375rem;
229
+
230
+ /* Beyond this distance, controls read as independent. */
231
+ --cem-coupling-decouple-min: 0.75rem;
232
+ }
233
+ ```
234
+
235
+ Guidance:
236
+
237
+ - Keep **affinity/decouple** separate from **guard**.
238
+ - `guard` is safety; `affinity/decouple` is meaning.
239
+
240
+ ---
241
+
242
+ ---
243
+
244
+ ## 8. Material / Angular Material mapping (implementation layer)
245
+
246
+ - Map `data-cem-coupling="forgiving|balanced|compact"` to the library’s density knob.
247
+ - Keep **CEM public semantics** stable; keep library numeric scales in the adapter.
248
+
249
+ Example mapping guidance:
250
+
251
+ - forgiving → comfortable / default density
252
+ - balanced → slightly denser
253
+ - compact → compact / denser
254
+
255
+ (Exact numeric mapping remains an implementation choice per Angular Material version.)
256
+
257
+ ---
258
+
259
+ ## 9. Finalization checklist (what “done” means)
260
+
261
+ ### 9.1 Canonical decisions to lock
262
+
263
+ - **Category name:** D2. Coupling & Compactness (or D2. Coupling Safety)
264
+ - **Public axis name:** `coupling` (semantic), with exactly **three modes**: `forgiving | balanced | compact`
265
+ - **Core nouns:** zone / halo / guard
266
+ - **Units:** `rem` for all coupling and geometry values
267
+
268
+ ### 9.2 Token set acceptance criteria
269
+
270
+ A draft becomes “canonical” when all of the following are true:
271
+
272
+ 1) **Minimal core:** only these coupling policy anchors are required:
273
+ - `--cem-coupling-zone-min`
274
+ - `--cem-coupling-guard-min`
275
+ - `--cem-coupling-halo`
276
+
277
+ 2) **Invariants are explicit:**
278
+ - `zone-min` and `guard-min` are **mode-invariant**
279
+ - mode changes may adjust **visual geometry** and **halo** only
280
+
281
+ 3) **Orthogonality is enforceable:**
282
+ - a normative rule exists for layout code: `gap = max(D1 gap, D2 guard)`
283
+
284
+ 4) **Component mapping is possible without special cases:**
285
+ - for each major control family (buttons, icon buttons, chips, list rows, menu rows, table rows), you can map either:
286
+ - visible size ≥ zone-min, or
287
+ - visible size < zone-min with halo expansion
288
+
289
+ 5) **Accessibility posture is documented:**
290
+ - how zone-min relates to your a11y baseline
291
+ - how halo avoids overlap and preserves guard
292
+
293
+ ### 9.3 Mode matrix (canonical)
294
+
295
+ | Mode | Product intent | Visual geometry | Halo (`--cem-coupling-halo`) | Typical surfaces |
296
+ |---|---|---|---|---|
297
+ | `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 |
298
+ | `balanced` | General default across modalities | Baseline control heights/rows | Baseline | mixed pointer + touch, general app UI |
299
+ | `compact` | Increase information density without breaking operability | Smaller visual heights/rows; reduced chrome | Larger (use halo to preserve zone) | data grids, admin tools, scan-heavy panels |
300
+
301
+ Normative rule:
302
+
303
+ - `--cem-coupling-zone-min` and `--cem-coupling-guard-min` are **mode-invariant**.
304
+ - Modes may adjust **visual geometry** and **halo** only.
305
+
306
+ ### 9.4 Component mapping checklist (how to apply)
307
+
308
+ Use this checklist to implement Coupling consistently. The same rules apply whether input is pointer, touch, stylus, gaze, switch scanning, or remote focus.
309
+
310
+ #### Common rules (apply to all components)
311
+
312
+ - **Zone rule:** each interactive affordance must provide an operable zone of at least `--cem-coupling-zone-min` in both dimensions *or* be wrapped/expanded so the operable zone meets the minimum.
313
+ - **Guard rule:** adjacent interactive affordances must not violate `--cem-coupling-guard-min` *between their operable zones*.
314
+ - **Halo rule:** if halo expansion is used, ensure halos do not overlap adjacent operable zones. For dense clusters, compute layout spacing with halo in mind.
315
+ - **State legibility:** focus/hover/pressed affordances must remain legible across modes (especially in `compact`).
316
+
317
+ #### Buttons
318
+
319
+ - Map `min-block-size` to `--cem-coupling-zone-min` (or set visible height ≥ zone-min).
320
+ - Use `--cem-control-height` and `--cem-control-padding-*` for visual sizing; do not shrink below operability.
321
+ - For grouped buttons, enforce **guard** using layout `gap` (or dividers) that respects `--cem-coupling-guard-min`.
322
+
323
+ #### Icon buttons
324
+
325
+ - Prefer visible container size = `--cem-coupling-zone-min`.
326
+ - If the visible icon container is smaller, implement halo expansion on a wrapper.
327
+ - In clusters (toolbars), validate guard and halo non-overlap explicitly.
328
+
329
+ #### Chips / tags
330
+
331
+ - Visual chip height may be below `zone-min` in `compact`, but operability must still meet `zone-min` via:
332
+ - a halo wrapper, or
333
+ - additional padding on the interactive container.
334
+ - Ensure dismiss icons (×) meet the zone rule independently if separately interactive.
335
+
336
+ #### List rows / menu rows
337
+
338
+ - Ensure row **height** maps to at least `zone-min` where the row itself is the interactive affordance.
339
+ - If only a sub-region is interactive (e.g., trailing actions), each action must meet zone/guard rules.
340
+ - For trailing action clusters, apply guard via `gap` or reserved spacing to avoid interference.
341
+
342
+ #### Table rows / data grids
343
+
344
+ - It is acceptable for `--cem-table-row-height` to be below `zone-min` *only if* row actions / selection / checkboxes still meet the zone rule via:
345
+ - larger interactive containers within cells, or
346
+ - halo expansion that does not overlap neighbors.
347
+ - Validate dense rows with:
348
+ - selection controls (checkbox/radio)
349
+ - row-level actions (kebab, inline icons)
350
+ - row click targets (if the row is clickable)
351
+
352
+ ### 9.5 Implementation proof points (required) (required)
353
+
354
+ Validate each mode on at least one representative surface:
355
+
356
+ - **Forms:** text field + primary button + icon button cluster
357
+ - **Navigation list:** list rows + trailing actions
358
+ - **Data-heavy:** table with row actions and selection
359
+
360
+ Pass criteria:
361
+
362
+ - adjacent operable zones never violate `guard-min`
363
+ - no halo overlap between neighbors
364
+ - focus ring / hover affordances remain legible when visuals are compact (see [`cem-stroke.md`](./cem-stroke.md) §5 for focus indicator thickness)
365
+
366
+ ---
367
+
368
+ ## 10. Change management (canonical governance)
369
+ - Treat coupling tokens as **contract-level**: changes should be versioned (SemVer or equivalent).
370
+ - Avoid renaming tokens once canonical; prefer adding new tokens or revising mode values.
371
+ - Keep the public axis semantic; keep library-specific numeric scales in adapters.
372
+