@motion-proto/live-tokens 0.1.1 → 0.3.2

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 (224) hide show
  1. package/README.md +168 -21
  2. package/dist-plugin/index.cjs +823 -336
  3. package/dist-plugin/index.d.cts +9 -7
  4. package/dist-plugin/index.d.ts +9 -7
  5. package/dist-plugin/index.js +822 -335
  6. package/package.json +46 -20
  7. package/src/assets/newspaper.webp +0 -0
  8. package/src/assets/offering.webp +0 -0
  9. package/src/component-editor/BadgeEditor.svelte +170 -0
  10. package/src/component-editor/CalloutEditor.svelte +103 -0
  11. package/src/component-editor/CardEditor.svelte +184 -0
  12. package/src/component-editor/CollapsibleSectionEditor.svelte +167 -0
  13. package/src/component-editor/CornerBadgeEditor.svelte +207 -0
  14. package/src/component-editor/DialogEditor.svelte +172 -0
  15. package/src/component-editor/ImageEditor.svelte +72 -0
  16. package/src/component-editor/InlineEditActionsEditor.svelte +83 -0
  17. package/src/component-editor/NotificationEditor.svelte +160 -0
  18. package/src/component-editor/ProgressBarEditor.svelte +124 -0
  19. package/src/component-editor/RadioButtonEditor.svelte +140 -0
  20. package/src/component-editor/SectionDividerEditor.svelte +263 -0
  21. package/src/component-editor/SegmentedControlEditor.svelte +154 -0
  22. package/src/component-editor/StandardButtonsEditor.svelte +178 -0
  23. package/src/component-editor/TabBarEditor.svelte +137 -0
  24. package/src/component-editor/TableEditor.svelte +128 -0
  25. package/src/component-editor/TooltipEditor.svelte +122 -0
  26. package/src/component-editor/editorTokens.test.ts +93 -0
  27. package/src/component-editor/groupKeySlots.test.ts +67 -0
  28. package/src/component-editor/groupKeySnapshot.test.ts +52 -0
  29. package/src/component-editor/index.ts +5 -0
  30. package/src/component-editor/registry.ts +246 -0
  31. package/src/component-editor/scaffolding/AngleDial.svelte +185 -0
  32. package/src/component-editor/scaffolding/ComponentEditorBase.svelte +96 -0
  33. package/src/component-editor/scaffolding/ComponentFileManager.svelte +682 -0
  34. package/src/component-editor/scaffolding/ComponentFileMenu.svelte +312 -0
  35. package/src/component-editor/scaffolding/ComponentsTab.svelte +69 -0
  36. package/src/component-editor/scaffolding/CopyFromMenu.svelte +246 -0
  37. package/src/component-editor/scaffolding/DemoHeader.svelte +21 -0
  38. package/src/component-editor/scaffolding/DividerEditor.svelte +81 -0
  39. package/src/component-editor/scaffolding/FieldsetWrapper.svelte +46 -0
  40. package/src/component-editor/scaffolding/GradientCard.svelte +291 -0
  41. package/src/component-editor/scaffolding/LinkageChart.svelte +297 -0
  42. package/src/component-editor/scaffolding/LinkedBlock.svelte +418 -0
  43. package/src/component-editor/scaffolding/NonStylableConfig.svelte +57 -0
  44. package/src/component-editor/scaffolding/SaveAsDialog.svelte +177 -0
  45. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +25 -0
  46. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +56 -0
  47. package/src/component-editor/scaffolding/StateBlock.svelte +115 -0
  48. package/src/component-editor/scaffolding/TokenLayout.svelte +511 -0
  49. package/src/component-editor/scaffolding/TypeEditor.svelte +82 -0
  50. package/src/component-editor/scaffolding/VariantGroup.svelte +277 -0
  51. package/src/component-editor/scaffolding/buildTypeGroupTokens.ts +97 -0
  52. package/src/component-editor/scaffolding/componentSectionType.ts +8 -0
  53. package/src/component-editor/scaffolding/componentSources.ts +9 -0
  54. package/src/component-editor/scaffolding/defaultSections.ts +16 -0
  55. package/src/component-editor/scaffolding/editorContext.ts +44 -0
  56. package/src/component-editor/scaffolding/linkedBlock.ts +226 -0
  57. package/src/component-editor/scaffolding/siblings.ts +33 -0
  58. package/src/component-editor/scaffolding/types.ts +39 -0
  59. package/src/components/Badge.svelte +231 -42
  60. package/src/components/Button.svelte +324 -124
  61. package/src/components/Callout.svelte +145 -0
  62. package/src/components/Card.svelte +123 -25
  63. package/src/components/CollapsibleSection.svelte +213 -35
  64. package/src/components/CornerBadge.svelte +224 -0
  65. package/src/components/Dialog.svelte +137 -114
  66. package/src/components/Image.svelte +43 -0
  67. package/src/components/InlineEditActions.svelte +74 -14
  68. package/src/components/Notification.svelte +184 -163
  69. package/src/components/ProgressBar.svelte +216 -22
  70. package/src/components/RadioButton.svelte +110 -40
  71. package/src/components/SectionDivider.svelte +428 -74
  72. package/src/components/SegmentedControl.svelte +203 -0
  73. package/src/components/TabBar.svelte +146 -21
  74. package/src/components/Table.svelte +102 -0
  75. package/src/components/Tooltip.svelte +45 -19
  76. package/src/components/types.ts +51 -0
  77. package/src/data/google-fonts.json +75 -0
  78. package/src/lib/ColumnsOverlay.svelte +20 -7
  79. package/src/lib/LiveEditorOverlay.svelte +257 -78
  80. package/src/lib/columnsOverlay.ts +21 -17
  81. package/src/lib/componentConfig.test.ts +204 -0
  82. package/src/lib/componentConfigKeys.ts +19 -0
  83. package/src/lib/componentConfigService.ts +88 -0
  84. package/src/lib/copyPopover.ts +30 -0
  85. package/src/lib/cssVarSync.ts +59 -7
  86. package/src/lib/editorConfigStore.ts +0 -10
  87. package/src/lib/editorCore.ts +402 -0
  88. package/src/lib/editorKeybindings.ts +52 -0
  89. package/src/lib/editorPersistence.ts +106 -0
  90. package/src/lib/editorRenderer.ts +74 -0
  91. package/src/lib/editorStore.test.ts +328 -0
  92. package/src/lib/editorStore.ts +412 -0
  93. package/src/lib/editorTypes.ts +100 -0
  94. package/src/lib/editorViewStore.ts +55 -0
  95. package/src/lib/files/versionedFileResource.ts +140 -0
  96. package/src/lib/fontLoader.ts +130 -0
  97. package/src/lib/fontMigration.ts +140 -0
  98. package/src/lib/fontParse.ts +168 -0
  99. package/src/lib/index.ts +48 -30
  100. package/src/lib/lazyConfig.test.ts +54 -0
  101. package/src/lib/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +64 -0
  102. package/src/lib/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +71 -0
  103. package/src/lib/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +43 -0
  104. package/src/lib/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +68 -0
  105. package/src/lib/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +35 -0
  106. package/src/lib/migrations/2026-05-10-sectiondivider-gradient-stops.ts +50 -0
  107. package/src/lib/migrations/2026-05-13-primary-to-brand.ts +90 -0
  108. package/src/lib/migrations/index.ts +93 -0
  109. package/src/lib/migrations/migrations.test.ts +341 -0
  110. package/src/lib/navLinkTypes.ts +1 -0
  111. package/src/lib/overlayState.ts +3 -0
  112. package/src/lib/paletteDerivation.ts +300 -0
  113. package/src/lib/parentRouteStore.ts +42 -0
  114. package/src/lib/parsers/globalRootBlock.ts +32 -0
  115. package/src/lib/presetService.ts +94 -0
  116. package/src/lib/router.ts +42 -10
  117. package/src/lib/scrollSection.ts +45 -0
  118. package/src/lib/slices/columns.ts +59 -0
  119. package/src/lib/slices/components.ts +362 -0
  120. package/src/lib/slices/domainVars.ts +15 -0
  121. package/src/lib/slices/fonts.ts +30 -0
  122. package/src/lib/slices/gradients.ts +153 -0
  123. package/src/lib/slices/overlays.ts +132 -0
  124. package/src/lib/slices/palettes.ts +26 -0
  125. package/src/lib/slices/shadows.ts +123 -0
  126. package/src/lib/storage.ts +88 -0
  127. package/src/lib/themeInit.ts +74 -0
  128. package/src/lib/themeService.ts +101 -0
  129. package/src/lib/themeTypes.ts +146 -0
  130. package/src/lib/tokenRegistry.ts +148 -0
  131. package/src/pages/ComponentEditorPage.svelte +384 -0
  132. package/src/pages/ComponentEditorPage.svelte.d.ts +2 -0
  133. package/src/pages/Editor.svelte +98 -0
  134. package/src/pages/Editor.svelte.d.ts +2 -0
  135. package/src/pages/EditorShell.svelte +348 -0
  136. package/src/styles/_padding.scss +34 -0
  137. package/src/styles/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
  138. package/src/styles/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
  139. package/src/styles/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
  140. package/src/styles/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
  141. package/src/styles/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
  142. package/src/styles/fonts/Manrope/Manrope-latin.woff2 +0 -0
  143. package/src/styles/fonts.css +22 -10
  144. package/src/styles/form-controls.css +14 -16
  145. package/src/styles/tokens.css +1322 -0
  146. package/src/styles/ui-editor.css +126 -0
  147. package/src/{showcase → ui}/BezierCurveEditor.svelte +14 -14
  148. package/src/{showcase → ui}/ColorEditPanel.svelte +42 -36
  149. package/src/ui/EditorViewSwitcher.svelte +180 -0
  150. package/src/ui/FontStackEditor.svelte +360 -0
  151. package/src/ui/GradientEditor.svelte +461 -0
  152. package/src/ui/GradientStopPicker.svelte +74 -0
  153. package/src/ui/PaletteEditor.svelte +1590 -0
  154. package/src/ui/PaletteEditor.test.ts +108 -0
  155. package/src/ui/PresetFileManager.svelte +567 -0
  156. package/src/ui/ProjectFontsSection.svelte +645 -0
  157. package/src/{showcase → ui}/SurfacesTab.svelte +39 -39
  158. package/src/{showcase → ui}/TextTab.svelte +27 -27
  159. package/src/{showcase/TokenFileManager.svelte → ui/ThemeFileManager.svelte} +196 -112
  160. package/src/ui/Toggle.svelte +108 -0
  161. package/src/ui/UICopyPopover.svelte +78 -0
  162. package/src/{showcase/EditorDialog.svelte → ui/UIDialog.svelte} +66 -25
  163. package/src/ui/UIFontFamilySelector.svelte +309 -0
  164. package/src/ui/UIFontSizeSelector.svelte +165 -0
  165. package/src/ui/UIFontWeightSelector.svelte +52 -0
  166. package/src/ui/UILineHeightSelector.svelte +47 -0
  167. package/src/ui/UILinkToggle.svelte +60 -0
  168. package/src/ui/UIOptionItem.svelte +74 -0
  169. package/src/ui/UIOptionList.svelte +27 -0
  170. package/src/ui/UIPaddingSelector.svelte +661 -0
  171. package/src/ui/UIPaletteSelector.svelte +1084 -0
  172. package/src/ui/UIRadio.svelte +72 -0
  173. package/src/ui/UIRadioGroup.svelte +59 -0
  174. package/src/ui/UIRelinkConfirmPopover.svelte +235 -0
  175. package/src/ui/UITokenSelector.svelte +509 -0
  176. package/src/ui/UIVariantSelector.svelte +145 -0
  177. package/src/ui/VariablesTab.svelte +252 -0
  178. package/src/ui/index.ts +31 -0
  179. package/src/ui/keepInViewport.ts +84 -0
  180. package/src/ui/palette/GradientStopEditor.svelte +482 -0
  181. package/src/ui/palette/OverridesPanel.svelte +526 -0
  182. package/src/ui/palette/PaletteBase.svelte +165 -0
  183. package/src/ui/palette/ScaleCurveEditor.svelte +38 -0
  184. package/src/ui/palette/paletteEditorState.ts +89 -0
  185. package/src/ui/sections/ColumnsSection.svelte +273 -0
  186. package/src/ui/sections/GradientsSection.svelte +147 -0
  187. package/src/ui/sections/OverlaysSection.svelte +670 -0
  188. package/src/ui/sections/ShadowsSection.svelte +1250 -0
  189. package/src/ui/sections/TokenScaleTable.svelte +332 -0
  190. package/src/ui/sections/tokenScales.ts +81 -0
  191. package/src/ui/variantScales.ts +108 -0
  192. package/src/components/DetailNav.svelte +0 -78
  193. package/src/components/Toggle.svelte +0 -86
  194. package/src/lib/tokenInit.ts +0 -29
  195. package/src/lib/tokenService.ts +0 -144
  196. package/src/lib/tokenTypes.ts +0 -45
  197. package/src/pages/Admin.svelte +0 -100
  198. package/src/pages/ShowcasePage.svelte +0 -144
  199. package/src/showcase/BackupBrowser.svelte +0 -617
  200. package/src/showcase/ComponentsTab.svelte +0 -105
  201. package/src/showcase/PaletteEditor.svelte +0 -2579
  202. package/src/showcase/PaletteSelector.svelte +0 -627
  203. package/src/showcase/TokenMap.svelte +0 -54
  204. package/src/showcase/VariablesTab.svelte +0 -2655
  205. package/src/showcase/VisualsTab.svelte +0 -231
  206. package/src/showcase/demos/BadgeDemo.svelte +0 -56
  207. package/src/showcase/demos/CardDemo.svelte +0 -50
  208. package/src/showcase/demos/ChoiceButtonsDemo.svelte +0 -192
  209. package/src/showcase/demos/CollapsibleSectionDemo.svelte +0 -54
  210. package/src/showcase/demos/DialogDemo.svelte +0 -42
  211. package/src/showcase/demos/InlineEditActionsDemo.svelte +0 -25
  212. package/src/showcase/demos/NotificationDemo.svelte +0 -147
  213. package/src/showcase/demos/ProgressBarDemo.svelte +0 -54
  214. package/src/showcase/demos/RadioButtonDemo.svelte +0 -56
  215. package/src/showcase/demos/SectionDividerDemo.svelte +0 -77
  216. package/src/showcase/demos/StandardButtonsDemo.svelte +0 -455
  217. package/src/showcase/demos/TabBarDemo.svelte +0 -58
  218. package/src/showcase/demos/TooltipDemo.svelte +0 -52
  219. package/src/showcase/editor.css +0 -93
  220. package/src/showcase/index.ts +0 -17
  221. package/src/styles/fonts/Domine/Domine-VariableFont_wght.ttf +0 -0
  222. package/src/styles/fonts/Domine/OFL.txt +0 -97
  223. package/src/styles/fonts/Domine/README.txt +0 -66
  224. /package/src/{showcase → ui}/curveEngine.ts +0 -0
@@ -0,0 +1,297 @@
1
+ <script context="module" lang="ts">
2
+ type CellStatus = 'linked' | 'broken' | 'absent';
3
+ type RowEntry = { label: string; key: string };
4
+ type Axes =
5
+ | { kind: '1d'; rows: RowEntry[] }
6
+ | { kind: '2d'; rows: string[]; cols: string[] };
7
+
8
+ function deriveAxes(contexts: string[]): Axes {
9
+ if (contexts.length === 0) return { kind: '1d', rows: [] };
10
+ const split = contexts.map((c) => c.split(/\s+/));
11
+ const arity = split[0].length;
12
+ const consistent = arity === 2 && split.every((s) => s.length === 2);
13
+ if (!consistent) {
14
+ return { kind: '1d', rows: contexts.map((c) => ({ label: c, key: c })) };
15
+ }
16
+ const rowSet = new Set<string>();
17
+ const colSet = new Set<string>();
18
+ const rows: string[] = [];
19
+ const cols: string[] = [];
20
+ for (const [r, c] of split) {
21
+ if (!rowSet.has(r)) { rowSet.add(r); rows.push(r); }
22
+ if (!colSet.has(c)) { colSet.add(c); cols.push(c); }
23
+ }
24
+ // Keep the full context string as the label so row clicks still match the editor's tab strip.
25
+ if (cols.length === 1) {
26
+ return { kind: '1d', rows: rows.map((r) => ({ label: `${r} ${cols[0]}`, key: `${r} ${cols[0]}` })) };
27
+ }
28
+ if (rows.length === 1) {
29
+ return { kind: '1d', rows: cols.map((c) => ({ label: `${rows[0]} ${c}`, key: `${rows[0]} ${c}` })) };
30
+ }
31
+ return { kind: '2d', rows, cols };
32
+ }
33
+
34
+ </script>
35
+
36
+ <script lang="ts">
37
+ import { createEventDispatcher } from 'svelte';
38
+
39
+ export let contexts: string[] = [];
40
+ export let broken: string[] = [];
41
+ export let singleAxisLabel: string = '';
42
+ /** Caption rendered above the grid. Use to describe the linkage scope
43
+ (e.g. "Links across variants and states"). Defaults to the legacy
44
+ "Linked Properties" label so consumers that don't pass a caption
45
+ keep their existing rendering. */
46
+ export let caption: string = 'Linked Properties';
47
+ /** Currently focused variant (matches a row in 2d / a row label in 1d). When set,
48
+ the matching row is highlighted with the same active style as the variant tab strip. */
49
+ export let selectedRow: string | null = null;
50
+ /** Currently focused state (matches a column in 2d). The cell at (selectedRow, selectedCol)
51
+ gets an additional accent. Ignored in 1d charts. */
52
+ export let selectedCol: string | null = null;
53
+
54
+ const dispatch = createEventDispatcher<{ select: string }>();
55
+
56
+ $: axes = deriveAxes(contexts);
57
+ $: status = (() => {
58
+ const brokenSet = new Set(broken);
59
+ const m = new Map<string, CellStatus>();
60
+ for (const c of contexts) m.set(c, brokenSet.has(c) ? 'broken' : 'linked');
61
+ return m;
62
+ })();
63
+
64
+ let hoveredRow: number = -1;
65
+
66
+ function key2d(r: string, c: string): string { return `${r} ${c}`; }
67
+ function selectRow(label: string) { dispatch('select', label); }
68
+ /** True when this 1d row's key matches focus — either as a bare label
69
+ (`"primary"` matches focusedVariant `"primary"`) or as a compound
70
+ `"variant state"` matching the focused pair. */
71
+ function isRowSelected1d(key: string, row: string | null, col: string | null): boolean {
72
+ if (!row) return false;
73
+ if (key === row) return true;
74
+ if (col && key === `${row} ${col}`) return true;
75
+ if (col && key === `${col} ${row}`) return true;
76
+ return false;
77
+ }
78
+ </script>
79
+
80
+ <div class="chart">
81
+ <span class="chart-label">{caption}</span>
82
+ <div class="chart-grid-wrap" role="grid" aria-label="Linked contexts">
83
+ {#if axes.kind === '2d'}
84
+ <div class="grid grid-2d" style="--cols: {axes.cols.length};">
85
+ <div class="corner"></div>
86
+ {#each axes.cols as c (c)}
87
+ <div class="col-h">{c}</div>
88
+ {/each}
89
+ {#each axes.rows as r, i (r)}
90
+ <button
91
+ type="button"
92
+ class="row-h row-target"
93
+ class:hovered={hoveredRow === i}
94
+ class:selected={selectedRow === r}
95
+ on:click={() => selectRow(r)}
96
+ on:mouseenter={() => (hoveredRow = i)}
97
+ on:mouseleave={() => (hoveredRow = -1)}
98
+ on:focus={() => (hoveredRow = i)}
99
+ on:blur={() => (hoveredRow = -1)}
100
+ >{r}</button>
101
+ {#each axes.cols as c (c)}
102
+ {@const st = status.get(key2d(r, c)) ?? 'absent'}
103
+ <button
104
+ type="button"
105
+ tabindex="-1"
106
+ class="cell row-target {st}"
107
+ class:hovered={hoveredRow === i}
108
+ class:selected={selectedRow === r && selectedCol === c}
109
+ class:in-selected-row={selectedRow === r && selectedCol !== c}
110
+ aria-label="{r} {c}: {st}"
111
+ on:click={() => selectRow(r)}
112
+ on:mouseenter={() => (hoveredRow = i)}
113
+ on:mouseleave={() => (hoveredRow = -1)}
114
+ >
115
+ {#if st === 'linked'}
116
+ <span class="dot" aria-hidden="true"></span>
117
+ {:else if st === 'broken'}
118
+ <svg class="lock" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
119
+ <rect x="3.5" y="7.5" width="9" height="6" rx="1.2"/>
120
+ <path d="M5.5 7.5V5.2a2.5 2.5 0 0 1 4.6-1.4"/>
121
+ </svg>
122
+ {:else}
123
+ <span class="absent" aria-hidden="true"></span>
124
+ {/if}
125
+ </button>
126
+ {/each}
127
+ {/each}
128
+ </div>
129
+ {:else}
130
+ <div class="grid grid-1d">
131
+ <div class="corner"></div>
132
+ <div class="col-h">{singleAxisLabel}</div>
133
+ {#each axes.rows as r, i (r.key)}
134
+ {@const st = status.get(r.key) ?? 'absent'}
135
+ {@const isSel = isRowSelected1d(r.key, selectedRow, selectedCol)}
136
+ <button
137
+ type="button"
138
+ class="row-h row-target"
139
+ class:hovered={hoveredRow === i}
140
+ class:selected={isSel}
141
+ on:click={() => selectRow(r.label)}
142
+ on:mouseenter={() => (hoveredRow = i)}
143
+ on:mouseleave={() => (hoveredRow = -1)}
144
+ on:focus={() => (hoveredRow = i)}
145
+ on:blur={() => (hoveredRow = -1)}
146
+ >{r.label}</button>
147
+ <button
148
+ type="button"
149
+ tabindex="-1"
150
+ class="cell row-target {st}"
151
+ class:hovered={hoveredRow === i}
152
+ class:selected={isSel}
153
+ aria-label="{r.label}: {st}"
154
+ on:click={() => selectRow(r.label)}
155
+ on:mouseenter={() => (hoveredRow = i)}
156
+ on:mouseleave={() => (hoveredRow = -1)}
157
+ >
158
+ {#if st === 'linked'}
159
+ <span class="dot" aria-hidden="true"></span>
160
+ {:else if st === 'broken'}
161
+ <svg class="lock" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
162
+ <rect x="3.5" y="7.5" width="9" height="6" rx="1.2"/>
163
+ <path d="M5.5 7.5V5.2a2.5 2.5 0 0 1 4.6-1.4"/>
164
+ </svg>
165
+ {:else}
166
+ <span class="absent" aria-hidden="true"></span>
167
+ {/if}
168
+ </button>
169
+ {/each}
170
+ </div>
171
+ {/if}
172
+ </div>
173
+ </div>
174
+
175
+ <style>
176
+ .chart {
177
+ --linkage-dot: var(--ui-text-tertiary);
178
+ --linkage-broken-fg: #f0a338;
179
+ --linkage-broken-tint: rgba(240, 163, 56, 0.09);
180
+
181
+ flex: 0 0 auto;
182
+ align-self: flex-start;
183
+ display: flex;
184
+ flex-direction: column;
185
+ gap: var(--ui-space-24);
186
+ }
187
+
188
+ .chart-label {
189
+ display: block;
190
+ margin: 0;
191
+ font-size: var(--ui-font-size-md);
192
+ font-weight: 500;
193
+ color: var(--ui-text-secondary);
194
+ }
195
+
196
+ /* Gridlines via 1px gap exposing the container bg; cells fill themselves to hide it. */
197
+ .grid {
198
+ display: grid;
199
+ gap: 1px;
200
+ background: var(--ui-border-faint);
201
+ border: 1px solid var(--ui-border-faint);
202
+ border-radius: var(--ui-radius-sm);
203
+ overflow: hidden;
204
+ }
205
+ .grid-2d { grid-template-columns: auto repeat(var(--cols, 1), minmax(64px, 1fr)); }
206
+ .grid-1d { grid-template-columns: auto 40px; }
207
+
208
+ .grid > * {
209
+ background: var(--ui-surface-lowest);
210
+ padding: var(--ui-space-4) var(--ui-space-10);
211
+ font-size: var(--ui-font-size-sm);
212
+ color: var(--ui-text-tertiary);
213
+ line-height: 1;
214
+ display: flex;
215
+ align-items: center;
216
+ }
217
+ .grid .col-h {
218
+ background: var(--ui-gray-200);
219
+ justify-content: center;
220
+ }
221
+ .grid .cell { justify-content: center; }
222
+
223
+ /* Avoid `font: inherit` — the shorthand resets font-size to body and oversizes row labels. */
224
+ button.row-target {
225
+ border: 0;
226
+ margin: 0;
227
+ font-family: inherit;
228
+ font-weight: inherit;
229
+ text-align: left;
230
+ cursor: pointer;
231
+ }
232
+ button.cell.row-target {
233
+ text-align: center;
234
+ }
235
+ button.row-target:focus-visible {
236
+ outline: 1px solid var(--ui-border-default, var(--ui-gray-700));
237
+ outline-offset: -2px;
238
+ }
239
+
240
+ .row-target.hovered {
241
+ background: var(--ui-hover);
242
+ }
243
+ .grid .row-h.row-target.hovered {
244
+ background: var(--ui-hover-high, var(--ui-hover));
245
+ color: var(--ui-text-secondary);
246
+ }
247
+ .cell.broken.row-target.hovered {
248
+ background: var(--linkage-broken-tint);
249
+ filter: brightness(1.15);
250
+ }
251
+
252
+ /* Selected row — matches the variant tab's active treatment so the visual
253
+ relationship between the focused tab above and the chart row reading the
254
+ same context is clear. The selected cell (variant×state intersection) gets
255
+ an extra accent ring to mark it as the live read-out. */
256
+ .grid .row-h.row-target.selected {
257
+ background: var(--ui-surface-high);
258
+ color: var(--ui-text-primary);
259
+ box-shadow: inset 0 0 0 1px var(--ui-border-default);
260
+ z-index: 1;
261
+ }
262
+ .grid .cell.row-target.in-selected-row,
263
+ .grid .cell.row-target.selected {
264
+ background: var(--ui-surface-high);
265
+ }
266
+ .grid .cell.row-target.selected {
267
+ box-shadow: inset 0 0 0 1px var(--ui-border-default);
268
+ z-index: 1;
269
+ }
270
+ .grid .cell.broken.row-target.in-selected-row,
271
+ .grid .cell.broken.row-target.selected {
272
+ background: color-mix(in srgb, var(--linkage-broken-tint) 60%, var(--ui-surface-high));
273
+ }
274
+
275
+ .dot {
276
+ width: 7px;
277
+ height: 7px;
278
+ border-radius: 50%;
279
+ background: var(--linkage-dot);
280
+ }
281
+
282
+ .cell.broken {
283
+ color: var(--linkage-broken-fg);
284
+ background: var(--linkage-broken-tint);
285
+ }
286
+ .lock {
287
+ width: 13px;
288
+ height: 13px;
289
+ }
290
+
291
+ .absent {
292
+ width: 5px;
293
+ height: 1px;
294
+ background: var(--ui-border-subtle);
295
+ opacity: 0.6;
296
+ }
297
+ </style>