@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,72 @@
1
+ <!--
2
+ Custom-styled radio that matches the editor's selection language: a quiet ring
3
+ in the unselected state (--ui-border-strong stroke, soft black inner fill) and
4
+ the highlight amber when selected (ring + dot, transparent inside).
5
+
6
+ Usage:
7
+ <UIRadio bind:group={selected} value="alpha" />
8
+ <UIRadio bind:group={selected} value="beta" disabled />
9
+ -->
10
+ <script lang="ts">
11
+ /** Value this radio represents within its group. */
12
+ export let value: string;
13
+ /** Two-way bound group selection. The radio is checked when `group === value`. */
14
+ export let group: string;
15
+ /** Optional native name; omit to let Svelte's `bind:group` wire it automatically. */
16
+ export let name: string = '';
17
+ export let disabled: boolean = false;
18
+ </script>
19
+
20
+ <input
21
+ type="radio"
22
+ class="ui-radio"
23
+ {value}
24
+ {name}
25
+ {disabled}
26
+ bind:group
27
+ on:change
28
+ />
29
+
30
+ <style>
31
+ .ui-radio {
32
+ appearance: none;
33
+ -webkit-appearance: none;
34
+ margin: 0;
35
+ flex-shrink: 0;
36
+ width: 14px;
37
+ height: 14px;
38
+ border: 1.5px solid var(--ui-border-strong);
39
+ border-radius: 50%;
40
+ background: rgba(0, 0, 0, 0.3);
41
+ cursor: pointer;
42
+ display: grid;
43
+ place-items: center;
44
+ transition:
45
+ border-color 140ms cubic-bezier(0.4, 0, 0.2, 1),
46
+ background-color 140ms cubic-bezier(0.4, 0, 0.2, 1);
47
+ }
48
+ .ui-radio::before {
49
+ content: "";
50
+ width: 8px;
51
+ height: 8px;
52
+ border-radius: 50%;
53
+ background: var(--ui-highlight);
54
+ transform: scale(0);
55
+ transition: transform 140ms cubic-bezier(0.5, 1.6, 0.5, 1);
56
+ }
57
+ .ui-radio:checked {
58
+ border-color: var(--ui-highlight);
59
+ background: transparent;
60
+ }
61
+ .ui-radio:checked::before {
62
+ transform: scale(1);
63
+ }
64
+ .ui-radio:focus-visible {
65
+ outline: 2px solid var(--ui-highlight);
66
+ outline-offset: 1px;
67
+ }
68
+ .ui-radio:disabled {
69
+ cursor: not-allowed;
70
+ opacity: 0.4;
71
+ }
72
+ </style>
@@ -0,0 +1,59 @@
1
+ <script lang="ts">
2
+ import { createEventDispatcher } from 'svelte';
3
+
4
+ export let value: string;
5
+ export let options: ReadonlyArray<{ value: string; label: string }>;
6
+ export let name: string;
7
+
8
+ const dispatch = createEventDispatcher<{ change: string }>();
9
+
10
+ function select(v: string) {
11
+ if (v === value) return;
12
+ value = v;
13
+ dispatch('change', v);
14
+ }
15
+ </script>
16
+
17
+ <div class="ui-radio-group" role="radiogroup">
18
+ {#each options as opt (opt.value)}
19
+ <label class="ui-radio" class:checked={value === opt.value}>
20
+ <input
21
+ type="radio"
22
+ {name}
23
+ value={opt.value}
24
+ checked={value === opt.value}
25
+ on:change={() => select(opt.value)}
26
+ />
27
+ <span>{opt.label}</span>
28
+ </label>
29
+ {/each}
30
+ </div>
31
+
32
+ <style>
33
+ .ui-radio-group {
34
+ display: inline-flex;
35
+ gap: var(--ui-space-20);
36
+ align-items: center;
37
+ }
38
+ .ui-radio {
39
+ display: inline-flex;
40
+ align-items: center;
41
+ gap: var(--ui-space-4);
42
+ cursor: pointer;
43
+ font-size: var(--ui-font-size-sm);
44
+ color: var(--ui-text-tertiary);
45
+ user-select: none;
46
+ transition: color var(--ui-transition-fast);
47
+ }
48
+ .ui-radio.checked {
49
+ color: var(--ui-text-primary);
50
+ }
51
+ .ui-radio input {
52
+ margin: 0;
53
+ cursor: pointer;
54
+ accent-color: currentColor;
55
+ }
56
+ .ui-radio:not(.checked) input {
57
+ opacity: 0.5;
58
+ }
59
+ </style>
@@ -0,0 +1,235 @@
1
+ <script lang="ts">
2
+ import { createEventDispatcher, onMount, onDestroy } from 'svelte';
3
+ import UIRadio from './UIRadio.svelte';
4
+ import { keepInViewport } from './keepInViewport';
5
+
6
+ type Candidate = { variable: string; alias: string };
7
+
8
+ export let candidates: Candidate[];
9
+ /** Variable whose lock was clicked — its alias is the default selection. */
10
+ export let initialVariable: string;
11
+ /** Component prefix to strip when rendering source labels. */
12
+ export let prefixToStrip: string = '';
13
+
14
+ const dispatch = createEventDispatcher<{ confirm: { alias: string }; cancel: void }>();
15
+
16
+ type Option = { alias: string; sources: string[] };
17
+
18
+ function distinctOptions(list: Candidate[], initial: string): Option[] {
19
+ const ordered = [...list].sort((a, b) =>
20
+ a.variable === initial ? -1 : b.variable === initial ? 1 : 0,
21
+ );
22
+ const seen = new Map<string, Option>();
23
+ for (const c of ordered) {
24
+ const label = prefixToStrip && c.variable.startsWith(prefixToStrip)
25
+ ? c.variable.slice(prefixToStrip.length)
26
+ : c.variable;
27
+ const existing = seen.get(c.alias);
28
+ if (existing) existing.sources.push(label);
29
+ else seen.set(c.alias, { alias: c.alias, sources: [label] });
30
+ }
31
+ return [...seen.values()];
32
+ }
33
+
34
+ $: options = distinctOptions(candidates, initialVariable);
35
+ let selected = '';
36
+ $: if (selected === '' && options.length > 0) selected = options[0].alias;
37
+
38
+ function handleConfirm() {
39
+ if (!selected) return;
40
+ dispatch('confirm', { alias: selected });
41
+ }
42
+
43
+ function handleCancel() {
44
+ dispatch('cancel');
45
+ }
46
+
47
+ function handleKeydown(e: KeyboardEvent) {
48
+ if (e.key === 'Escape') {
49
+ e.preventDefault();
50
+ e.stopPropagation();
51
+ handleCancel();
52
+ } else if (e.key === 'Enter' && (e.target as HTMLElement)?.tagName !== 'BUTTON') {
53
+ e.preventDefault();
54
+ handleConfirm();
55
+ }
56
+ }
57
+
58
+ let popoverEl: HTMLDivElement;
59
+
60
+ onMount(() => {
61
+ popoverEl?.focus();
62
+ document.addEventListener('keydown', handleKeydown, true);
63
+ });
64
+
65
+ onDestroy(() => {
66
+ document.removeEventListener('keydown', handleKeydown, true);
67
+ });
68
+ </script>
69
+
70
+ <div
71
+ class="ui-relink-popover"
72
+ role="dialog"
73
+ aria-label="Confirm link"
74
+ tabindex="-1"
75
+ bind:this={popoverEl}
76
+ use:keepInViewport
77
+ on:click|stopPropagation
78
+ >
79
+ <div class="ui-relink-header">
80
+ {#if options.length > 1}
81
+ <span class="ui-relink-title">{candidates.length} variants disagree — pick one to broadcast</span>
82
+ {:else}
83
+ <span class="ui-relink-title">Link this property across {candidates.length} variants?</span>
84
+ {/if}
85
+ </div>
86
+
87
+ <div class="ui-relink-body">
88
+ {#each options as opt}
89
+ <label class="ui-relink-row">
90
+ <UIRadio bind:group={selected} value={opt.alias} />
91
+ <div class="ui-relink-row-info">
92
+ <code class="ui-relink-alias">{opt.alias}</code>
93
+ <span class="ui-relink-sources">
94
+ from {opt.sources.join(', ')}
95
+ </span>
96
+ </div>
97
+ </label>
98
+ {/each}
99
+ </div>
100
+
101
+ <div class="ui-relink-footer">
102
+ <button type="button" class="ui-relink-btn ui-relink-btn-cancel" on:click={handleCancel}>Cancel</button>
103
+ <button type="button" class="ui-relink-btn ui-relink-btn-confirm" on:click={handleConfirm}>Link</button>
104
+ </div>
105
+ </div>
106
+
107
+ <style>
108
+ .ui-relink-popover {
109
+ position: absolute;
110
+ top: calc(100% + var(--ui-space-4));
111
+ right: 0;
112
+ background: var(--ui-surface-higher);
113
+ border: 1px solid var(--ui-border-medium);
114
+ border-radius: var(--ui-radius-md);
115
+ box-shadow: var(--ui-shadow-lg);
116
+ z-index: 20;
117
+ min-width: 18rem;
118
+ max-width: 24rem;
119
+ padding: var(--ui-space-8);
120
+ display: flex;
121
+ flex-direction: column;
122
+ gap: var(--ui-space-8);
123
+ animation: uiRelinkPopoverIn 120ms ease-out;
124
+ }
125
+
126
+ .ui-relink-popover:focus {
127
+ outline: none;
128
+ }
129
+
130
+ .ui-relink-header {
131
+ border-bottom: 1px solid var(--ui-border-faint);
132
+ padding-bottom: var(--ui-space-6);
133
+ }
134
+
135
+ .ui-relink-title {
136
+ font-size: var(--ui-font-size-xs);
137
+ color: var(--ui-text-secondary);
138
+ font-weight: var(--ui-font-weight-medium);
139
+ }
140
+
141
+ .ui-relink-body {
142
+ display: flex;
143
+ flex-direction: column;
144
+ gap: var(--ui-space-4);
145
+ }
146
+
147
+ .ui-relink-row {
148
+ display: flex;
149
+ align-items: flex-start;
150
+ gap: var(--ui-space-8);
151
+ padding: var(--ui-space-4);
152
+ border-radius: var(--ui-radius-sm);
153
+ cursor: pointer;
154
+ transition: background var(--ui-transition-fast);
155
+ }
156
+
157
+ .ui-relink-row:hover {
158
+ background: var(--ui-hover);
159
+ }
160
+
161
+ /* Lift the radio slightly so it visually aligns with the first line of the
162
+ two-line row label. Selection styling lives in UIRadio. */
163
+ .ui-relink-row :global(.ui-radio) {
164
+ margin-top: 0.2rem;
165
+ }
166
+
167
+ .ui-relink-row-info {
168
+ display: flex;
169
+ flex-direction: column;
170
+ gap: 1px;
171
+ min-width: 0;
172
+ flex: 1;
173
+ }
174
+
175
+ .ui-relink-alias {
176
+ font-family: var(--ui-font-mono);
177
+ font-size: var(--ui-font-size-xs);
178
+ color: var(--ui-text-primary);
179
+ overflow: hidden;
180
+ text-overflow: ellipsis;
181
+ white-space: nowrap;
182
+ }
183
+
184
+ .ui-relink-sources {
185
+ font-family: var(--ui-font-mono);
186
+ font-size: var(--ui-font-size-xs);
187
+ color: var(--ui-text-tertiary);
188
+ overflow: hidden;
189
+ text-overflow: ellipsis;
190
+ white-space: nowrap;
191
+ }
192
+
193
+ .ui-relink-footer {
194
+ display: flex;
195
+ justify-content: flex-end;
196
+ gap: var(--ui-space-6);
197
+ padding-top: var(--ui-space-4);
198
+ border-top: 1px solid var(--ui-border-faint);
199
+ }
200
+
201
+ .ui-relink-btn {
202
+ padding: var(--ui-space-4) var(--ui-space-12);
203
+ font-size: var(--ui-font-size-xs);
204
+ font-weight: var(--ui-font-weight-medium);
205
+ border-radius: var(--ui-radius-sm);
206
+ cursor: pointer;
207
+ transition: all var(--ui-transition-fast);
208
+ }
209
+
210
+ .ui-relink-btn-cancel {
211
+ background: transparent;
212
+ border: 1px solid var(--ui-border-default);
213
+ color: var(--ui-text-secondary);
214
+ }
215
+
216
+ .ui-relink-btn-cancel:hover {
217
+ background: var(--ui-hover);
218
+ color: var(--ui-text-primary);
219
+ }
220
+
221
+ .ui-relink-btn-confirm {
222
+ background: var(--ui-text-accent);
223
+ border: 1px solid var(--ui-text-accent);
224
+ color: var(--ui-surface-lowest);
225
+ }
226
+
227
+ .ui-relink-btn-confirm:hover {
228
+ filter: brightness(1.1);
229
+ }
230
+
231
+ @keyframes uiRelinkPopoverIn {
232
+ from { opacity: 0; transform: translateY(-2px); }
233
+ to { opacity: 1; transform: translateY(0); }
234
+ }
235
+ </style>