@motion-proto/live-tokens 0.6.2 → 0.7.1

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 (212) hide show
  1. package/README.md +14 -13
  2. package/dist-plugin/index.cjs +147 -136
  3. package/dist-plugin/index.d.cts +1 -1
  4. package/dist-plugin/index.d.ts +1 -1
  5. package/dist-plugin/index.js +145 -135
  6. package/package.json +25 -40
  7. package/src/{component-editor → editor/component-editor}/BadgeEditor.svelte +8 -82
  8. package/src/{component-editor → editor/component-editor}/CalloutEditor.svelte +4 -4
  9. package/src/{component-editor → editor/component-editor}/CardEditor.svelte +28 -76
  10. package/src/{component-editor → editor/component-editor}/CollapsibleSectionEditor.svelte +3 -3
  11. package/src/{component-editor → editor/component-editor}/CornerBadgeEditor.svelte +31 -93
  12. package/src/{component-editor → editor/component-editor}/DialogEditor.svelte +60 -57
  13. package/src/editor/component-editor/ImageEditor.svelte +30 -0
  14. package/src/{component-editor → editor/component-editor}/InlineEditActionsEditor.svelte +6 -4
  15. package/src/editor/component-editor/MenuSelectEditor.svelte +160 -0
  16. package/src/{component-editor → editor/component-editor}/NotificationEditor.svelte +64 -37
  17. package/src/{component-editor → editor/component-editor}/ProgressBarEditor.svelte +5 -4
  18. package/src/{component-editor → editor/component-editor}/RadioButtonEditor.svelte +3 -3
  19. package/src/{component-editor → editor/component-editor}/SectionDividerEditor.svelte +57 -84
  20. package/src/{component-editor → editor/component-editor}/SegmentedControlEditor.svelte +2 -2
  21. package/src/{component-editor → editor/component-editor}/StandardButtonsEditor.svelte +16 -20
  22. package/src/{component-editor → editor/component-editor}/TabBarEditor.svelte +9 -14
  23. package/src/{component-editor → editor/component-editor}/TableEditor.svelte +9 -18
  24. package/src/{component-editor → editor/component-editor}/TooltipEditor.svelte +11 -47
  25. package/src/{component-editor → editor/component-editor}/registry.ts +28 -18
  26. package/src/{component-editor → editor/component-editor}/scaffolding/AngleDial.svelte +2 -2
  27. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentEditorBase.svelte +3 -51
  28. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileManager.svelte +144 -416
  29. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileMenu.svelte +18 -170
  30. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentsTab.svelte +2 -2
  31. package/src/{component-editor → editor/component-editor}/scaffolding/CopyFromMenu.svelte +44 -4
  32. package/src/{component-editor → editor/component-editor}/scaffolding/DividerEditor.svelte +1 -1
  33. package/src/{component-editor → editor/component-editor}/scaffolding/FieldsetWrapper.svelte +1 -1
  34. package/src/{component-editor → editor/component-editor}/scaffolding/GradientCard.svelte +6 -6
  35. package/src/{component-editor → editor/component-editor}/scaffolding/LinkageChart.svelte +6 -6
  36. package/src/{component-editor → editor/component-editor}/scaffolding/LinkedBlock.svelte +6 -11
  37. package/src/editor/component-editor/scaffolding/NonStylableConfig.svelte +38 -0
  38. package/src/{component-editor → editor/component-editor}/scaffolding/SaveAsDialog.svelte +66 -12
  39. package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +72 -0
  40. package/src/editor/component-editor/scaffolding/ShadowBackdropControls.svelte +132 -0
  41. package/src/editor/component-editor/scaffolding/StateBlock.svelte +257 -0
  42. package/src/{component-editor → editor/component-editor}/scaffolding/TokenLayout.svelte +9 -7
  43. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +644 -0
  44. package/src/{component-editor → editor/component-editor}/scaffolding/editorContext.ts +19 -9
  45. package/src/{component-editor → editor/component-editor}/scaffolding/linkedBlock.ts +2 -2
  46. package/src/{component-editor → editor/component-editor}/scaffolding/types.ts +14 -0
  47. package/src/{lib → editor/core/components}/componentConfigService.ts +2 -2
  48. package/src/{lib → editor/core/components}/componentPersist.ts +5 -5
  49. package/src/editor/core/flashStatus.ts +30 -0
  50. package/src/{lib → editor/core/fonts}/fontLoader.ts +2 -2
  51. package/src/{lib → editor/core/fonts}/fontMigration.ts +4 -4
  52. package/src/{lib → editor/core/fonts}/fontParse.ts +1 -1
  53. package/src/editor/core/manifests/manifestService.ts +116 -0
  54. package/src/{lib → editor/core/palettes}/paletteDerivation.ts +2 -2
  55. package/src/{lib → editor/core/palettes}/tokenRegistry.ts +5 -5
  56. package/src/editor/core/productionPulse.ts +37 -0
  57. package/src/{lib → editor/core/routing}/router.ts +1 -1
  58. package/src/{lib/files/versionedFileResource.ts → editor/core/storage/files/versionedFileResourceClient.ts} +8 -1
  59. package/src/{lib → editor/core/store}/editorCore.ts +24 -8
  60. package/src/{lib → editor/core/store}/editorPersistence.ts +3 -3
  61. package/src/{lib → editor/core/store}/editorRenderer.ts +2 -2
  62. package/src/{lib → editor/core/store}/editorStore.ts +17 -17
  63. package/src/{lib → editor/core/store}/editorTypes.ts +1 -1
  64. package/src/{lib → editor/core/themes}/slices/columns.ts +2 -2
  65. package/src/{lib → editor/core/themes}/slices/components.ts +2 -2
  66. package/src/{lib → editor/core/themes}/slices/fonts.ts +1 -1
  67. package/src/{lib → editor/core/themes}/slices/gradients.ts +2 -2
  68. package/src/{lib → editor/core/themes}/slices/overlays.ts +1 -1
  69. package/src/{lib → editor/core/themes}/slices/palettes.ts +1 -1
  70. package/src/{lib → editor/core/themes}/slices/shadows.ts +3 -3
  71. package/src/{lib → editor/core/themes}/themeInit.ts +6 -6
  72. package/src/{lib → editor/core/themes}/themeService.ts +6 -6
  73. package/src/{lib → editor/core/themes}/themeTypes.ts +11 -7
  74. package/src/editor/index.ts +69 -0
  75. package/src/{lib → editor/overlay}/LiveEditorOverlay.svelte +79 -125
  76. package/src/{lib → editor/overlay}/columnsOverlay.ts +2 -2
  77. package/src/{pages → editor/pages}/ComponentEditorPage.svelte +12 -12
  78. package/src/{pages → editor/pages}/Editor.svelte +4 -4
  79. package/src/{pages → editor/pages}/EditorShell.svelte +18 -36
  80. package/src/{styles → editor/styles}/ui-editor.css +41 -21
  81. package/src/{styles → editor/styles}/ui-form-controls.css +8 -8
  82. package/src/{ui → editor/ui}/BezierCurveEditor.svelte +8 -8
  83. package/src/{ui → editor/ui}/ColorEditPanel.svelte +13 -13
  84. package/src/{ui → editor/ui}/EditorViewSwitcher.svelte +8 -6
  85. package/src/editor/ui/FileLoadList.svelte +350 -0
  86. package/src/editor/ui/FilePill.svelte +80 -0
  87. package/src/{ui → editor/ui}/FontStackEditor.svelte +7 -7
  88. package/src/{ui → editor/ui}/GradientEditor.svelte +11 -11
  89. package/src/{ui → editor/ui}/GradientStopPicker.svelte +1 -1
  90. package/src/editor/ui/ManifestFileManager.svelte +371 -0
  91. package/src/{ui → editor/ui}/PaletteEditor.svelte +132 -598
  92. package/src/{ui → editor/ui}/ProjectFontsSection.svelte +102 -144
  93. package/src/{ui → editor/ui}/SurfacesTab.svelte +3 -3
  94. package/src/{ui → editor/ui}/TextTab.svelte +3 -3
  95. package/src/{ui → editor/ui}/ThemeFileManager.svelte +286 -519
  96. package/src/{ui → editor/ui}/UICopyPopover.svelte +4 -4
  97. package/src/{ui → editor/ui}/UIFontFamilySelector.svelte +6 -6
  98. package/src/{ui → editor/ui}/UIFontSizeSelector.svelte +1 -1
  99. package/src/editor/ui/UIInfoPopover.svelte +244 -0
  100. package/src/{ui → editor/ui}/UILineHeightSelector.svelte +5 -5
  101. package/src/{ui → editor/ui}/UILinkToggle.svelte +2 -2
  102. package/src/{ui → editor/ui}/UIPaddingSelector.svelte +6 -6
  103. package/src/{ui → editor/ui}/UIPaletteSelector.svelte +26 -26
  104. package/src/editor/ui/UIPillButton.svelte +138 -0
  105. package/src/{ui → editor/ui}/UIRadio.svelte +2 -2
  106. package/src/{ui → editor/ui}/UIRelinkConfirmPopover.svelte +4 -4
  107. package/src/editor/ui/UISquareButton.svelte +172 -0
  108. package/src/{ui → editor/ui}/UITokenSelector.svelte +10 -10
  109. package/src/{ui → editor/ui}/UIVariantSelector.svelte +1 -1
  110. package/src/{ui → editor/ui}/VariablesTab.svelte +31 -8
  111. package/src/{ui → editor/ui}/palette/GradientStopEditor.svelte +13 -13
  112. package/src/{ui → editor/ui}/palette/OverridesPanel.svelte +13 -13
  113. package/src/{ui → editor/ui}/palette/PaletteBase.svelte +8 -5
  114. package/src/{ui → editor/ui}/palette/paletteEditorState.ts +1 -1
  115. package/src/editor/ui/palette/paletteMath.ts +275 -0
  116. package/src/{ui → editor/ui}/sections/ColumnsSection.svelte +137 -17
  117. package/src/{ui → editor/ui}/sections/GradientsSection.svelte +7 -7
  118. package/src/{ui → editor/ui}/sections/OverlaysSection.svelte +17 -17
  119. package/src/{ui → editor/ui}/sections/ShadowsSection.svelte +22 -22
  120. package/src/{ui → editor/ui}/sections/TokenScaleTable.svelte +3 -3
  121. package/src/{components → system/components}/Badge.svelte +0 -36
  122. package/src/{components → system/components}/Card.svelte +8 -62
  123. package/src/{components → system/components}/CornerBadge.svelte +8 -24
  124. package/src/{components → system/components}/Dialog.svelte +1 -1
  125. package/src/system/components/FloatingTokenTags.css +256 -0
  126. package/src/system/components/FloatingTokenTags.svelte +592 -0
  127. package/src/{components → system/components}/InlineEditActions.svelte +6 -4
  128. package/src/system/components/MenuSelect.svelte +229 -0
  129. package/src/{components → system/components}/ProgressBar.svelte +29 -11
  130. package/src/{components → system/components}/SegmentedControl.svelte +49 -43
  131. package/src/{components → system/components}/TabBar.svelte +81 -65
  132. package/src/{components → system/components}/Table.svelte +17 -3
  133. package/src/{components → system/components}/Tooltip.svelte +6 -4
  134. package/src/system/styles/CONVENTIONS.md +178 -0
  135. package/src/{styles → system/styles}/fonts.css +6 -3
  136. package/src/{styles → system/styles}/tokens.css +149 -29
  137. package/src/component-editor/ImageEditor.svelte +0 -74
  138. package/src/component-editor/scaffolding/NonStylableConfig.svelte +0 -62
  139. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +0 -37
  140. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +0 -61
  141. package/src/component-editor/scaffolding/StateBlock.svelte +0 -132
  142. package/src/component-editor/scaffolding/VariantGroup.svelte +0 -310
  143. package/src/data/google-fonts.json +0 -75
  144. package/src/lib/index.ts +0 -68
  145. package/src/lib/presetService.ts +0 -214
  146. package/src/lib/productionPulse.ts +0 -32
  147. package/src/ui/PresetFileManager.svelte +0 -1116
  148. package/src/ui/UnsavedComponentsDialog.svelte +0 -315
  149. /package/src/{styles → app}/site.css +0 -0
  150. /package/src/{component-editor → editor/component-editor}/index.ts +0 -0
  151. /package/src/{component-editor → editor/component-editor}/scaffolding/DemoHeader.svelte +0 -0
  152. /package/src/{component-editor → editor/component-editor}/scaffolding/TypeEditor.svelte +0 -0
  153. /package/src/{component-editor → editor/component-editor}/scaffolding/buildTypeGroupTokens.ts +0 -0
  154. /package/src/{component-editor → editor/component-editor}/scaffolding/componentSectionType.ts +0 -0
  155. /package/src/{component-editor → editor/component-editor}/scaffolding/componentSources.ts +0 -0
  156. /package/src/{component-editor → editor/component-editor}/scaffolding/defaultSections.ts +0 -0
  157. /package/src/{component-editor → editor/component-editor}/scaffolding/siblings.ts +0 -0
  158. /package/src/{lib → editor/core/components}/componentConfigKeys.ts +0 -0
  159. /package/src/{lib → editor/core}/cssVarSync.ts +0 -0
  160. /package/src/{lib → editor/core/palettes}/oklch.ts +0 -0
  161. /package/src/{lib → editor/core/routing}/navLinkTypes.ts +0 -0
  162. /package/src/{lib → editor/core/routing}/parentRouteStore.ts +0 -0
  163. /package/src/{lib → editor/core/storage}/storage.ts +0 -0
  164. /package/src/{lib → editor/core/store}/editorConfig.ts +0 -0
  165. /package/src/{lib → editor/core/store}/editorConfigStore.ts +0 -0
  166. /package/src/{lib → editor/core/store}/editorKeybindings.ts +0 -0
  167. /package/src/{lib → editor/core/store}/editorViewStore.ts +0 -0
  168. /package/src/{lib → editor/core/themes}/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +0 -0
  169. /package/src/{lib → editor/core/themes}/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +0 -0
  170. /package/src/{lib → editor/core/themes}/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +0 -0
  171. /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +0 -0
  172. /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +0 -0
  173. /package/src/{lib → editor/core/themes}/migrations/2026-05-10-sectiondivider-gradient-stops.ts +0 -0
  174. /package/src/{lib → editor/core/themes}/migrations/2026-05-13-primary-to-brand.ts +0 -0
  175. /package/src/{lib → editor/core/themes}/migrations/index.ts +0 -0
  176. /package/src/{lib → editor/core/themes}/parsers/globalRootBlock.ts +0 -0
  177. /package/src/{lib → editor/core/themes}/slices/domainVars.ts +0 -0
  178. /package/src/{lib → editor/overlay}/ColumnsOverlay.svelte +0 -0
  179. /package/src/{lib → editor/overlay}/overlayState.ts +0 -0
  180. /package/src/{pages → editor/pages}/ComponentEditorPage.svelte.d.ts +0 -0
  181. /package/src/{pages → editor/pages}/Editor.svelte.d.ts +0 -0
  182. /package/src/{ui → editor/ui}/Toggle.svelte +0 -0
  183. /package/src/{ui → editor/ui}/UIDialog.svelte +0 -0
  184. /package/src/{ui → editor/ui}/UIFontWeightSelector.svelte +0 -0
  185. /package/src/{ui → editor/ui}/UIOptionItem.svelte +0 -0
  186. /package/src/{ui → editor/ui}/UIOptionList.svelte +0 -0
  187. /package/src/{ui → editor/ui}/UIRadioGroup.svelte +0 -0
  188. /package/src/{lib → editor/ui}/copyPopover.ts +0 -0
  189. /package/src/{ui → editor/ui}/curveEngine.ts +0 -0
  190. /package/src/{ui → editor/ui}/index.ts +0 -0
  191. /package/src/{ui → editor/ui}/keepInViewport.ts +0 -0
  192. /package/src/{ui → editor/ui}/palette/ScaleCurveEditor.svelte +0 -0
  193. /package/src/{lib → editor/ui}/scrollSection.ts +0 -0
  194. /package/src/{ui → editor/ui}/sections/tokenScales.ts +0 -0
  195. /package/src/{ui → editor/ui}/variantScales.ts +0 -0
  196. /package/src/{assets → system/assets}/newspaper.webp +0 -0
  197. /package/src/{assets → system/assets}/offering.webp +0 -0
  198. /package/src/{components → system/components}/Button.svelte +0 -0
  199. /package/src/{components → system/components}/Callout.svelte +0 -0
  200. /package/src/{components → system/components}/CollapsibleSection.svelte +0 -0
  201. /package/src/{components → system/components}/Image.svelte +0 -0
  202. /package/src/{components → system/components}/Notification.svelte +0 -0
  203. /package/src/{components → system/components}/RadioButton.svelte +0 -0
  204. /package/src/{components → system/components}/SectionDivider.svelte +0 -0
  205. /package/src/{components → system/components}/types.ts +0 -0
  206. /package/src/{styles → system/styles}/_padding.scss +0 -0
  207. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
  208. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
  209. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
  210. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
  211. /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
  212. /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin.woff2 +0 -0
@@ -1,31 +1,21 @@
1
1
  <script lang="ts">
2
- import type { FontSource } from '../lib/themeTypes';
3
- import { editorState, setFontSources, transaction } from '../lib/editorStore';
4
- import { applyFontSources, applyFontStacks } from '../lib/fontLoader';
2
+ import type { FontSource } from '../core/themes/themeTypes';
3
+ import { editorState, setFontSources, transaction } from '../core/store/editorStore';
4
+ import { applyFontSources, applyFontStacks } from '../core/fonts/fontLoader';
5
5
  import {
6
6
  buildSourceFromFontFaceText,
7
7
  buildSourceFromUrl,
8
8
  discoverFamiliesFromUrl,
9
9
  parseFontFaceText,
10
10
  type ParsedFamily,
11
- } from '../lib/fontParse';
12
- import googleFontsData from '../data/google-fonts.json';
11
+ } from '../core/fonts/fontParse';
12
+ import UIPillButton from './UIPillButton.svelte';
13
13
 
14
- interface GoogleFontEntry { family: string; category: string; variants: number[] }
15
- const GOOGLE_FONTS: GoogleFontEntry[] = (googleFontsData as any).fonts;
14
+ type AddMode = 'closed' | 'url' | 'fontface';
15
+ interface Props { addMode?: AddMode }
16
+ let { addMode = $bindable('closed') }: Props = $props();
16
17
 
17
- type AddMode = 'closed' | 'google' | 'url' | 'fontface';
18
- let addMode: AddMode = $state('closed');
19
-
20
- // Google search
21
- let googleQuery = $state('');
22
- let googleMatches = $derived(googleQuery.trim().length >= 1
23
- ? GOOGLE_FONTS
24
- .filter((f) => f.family.toLowerCase().includes(googleQuery.toLowerCase()))
25
- .slice(0, 20)
26
- : GOOGLE_FONTS.slice(0, 10));
27
-
28
- // URL paste
18
+ // URL paste accepts a bare URL, a `<link>` tag, or an `@import url(...)` block.
29
19
  let urlInput = $state('');
30
20
  let urlError = $state('');
31
21
  let urlDiscovering = $state(false);
@@ -40,7 +30,6 @@
40
30
 
41
31
  function reset() {
42
32
  addMode = 'closed';
43
- googleQuery = '';
44
33
  urlInput = '';
45
34
  urlError = '';
46
35
  urlDiscovering = false;
@@ -52,6 +41,21 @@
52
41
  fontFaceParsed = [];
53
42
  }
54
43
 
44
+ // Pull a fonts URL out of whatever the user pastes: bare URL, link tag,
45
+ // @import url(...), or a full style-tag wrapper around an @import.
46
+ function extractFontsUrl(raw: string): string | null {
47
+ const text = raw.trim();
48
+ if (!text) return null;
49
+ const href = text.match(/href\s*=\s*["']([^"']+)["']/i);
50
+ if (href) return href[1];
51
+ const importUrl = text.match(/@import\s+url\(\s*['"]?([^'")]+)['"]?\s*\)/i);
52
+ if (importUrl) return importUrl[1];
53
+ const importBare = text.match(/@import\s+['"]([^'"]+)['"]/i);
54
+ if (importBare) return importBare[1];
55
+ if (/^https?:\/\//i.test(text)) return text;
56
+ return null;
57
+ }
58
+
55
59
  let fontSourcesList = $derived($editorState.fonts.sources);
56
60
  let fontStacksList = $derived($editorState.fonts.stacks);
57
61
 
@@ -61,23 +65,15 @@
61
65
  applyFontStacks(fontStacksList, next);
62
66
  }
63
67
 
64
- function addGoogleFont(entry: GoogleFontEntry) {
65
- const weightList = entry.variants.length > 0 ? entry.variants : [400];
66
- const weightSpec = weightList.length > 1
67
- ? `wght@${weightList.join(';')}`
68
- : `wght@${weightList[0]}`;
69
- const url = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(entry.family).replace(/%20/g, '+')}:${weightSpec}&display=swap`;
70
- const source = buildSourceFromUrl(url, [{ name: entry.family, weights: weightList }]);
71
- commitSources([...fontSourcesList, source]);
72
- reset();
73
- }
74
-
75
68
  async function discoverUrl() {
76
69
  urlError = '';
77
70
  urlParsed = null;
78
71
  urlNeedsManualFamilies = false;
79
- const url = urlInput.trim();
80
- if (!url) return;
72
+ const url = extractFontsUrl(urlInput);
73
+ if (!url) {
74
+ urlError = "Couldn't find a fonts URL in that paste";
75
+ return;
76
+ }
81
77
  urlDiscovering = true;
82
78
  try {
83
79
  const found = await discoverFamiliesFromUrl(url);
@@ -95,8 +91,11 @@
95
91
  }
96
92
 
97
93
  function addUrlSource() {
98
- const url = urlInput.trim();
99
- if (!url) return;
94
+ const url = extractFontsUrl(urlInput);
95
+ if (!url) {
96
+ urlError = "Couldn't find a fonts URL in that paste";
97
+ return;
98
+ }
100
99
  let families: ParsedFamily[] = [];
101
100
  if (urlParsed) {
102
101
  families = urlParsed.filter((f) => urlPickedNames.has(f.name));
@@ -239,46 +238,33 @@
239
238
  </div>
240
239
 
241
240
  {#if addMode === 'closed'}
242
- <button type="button" class="pf-add-toggle" onclick={() => (addMode = 'google')}>+ add font</button>
241
+ <div class="pf-add-toggle-row">
242
+ <UIPillButton icon="fa-plus" onclick={() => (addMode = 'url')}>Add Font</UIPillButton>
243
+ </div>
243
244
  {:else}
244
245
  <div class="pf-add-panel">
245
246
  <div class="pf-add-tabs">
246
- <button type="button" class:active={addMode === 'google'} onclick={() => (addMode = 'google')}>Google search</button>
247
- <button type="button" class:active={addMode === 'url'} onclick={() => (addMode = 'url')}>Paste URL</button>
247
+ <button type="button" class:active={addMode === 'url'} onclick={() => (addMode = 'url')}>Paste URL or embed</button>
248
248
  <button type="button" class:active={addMode === 'fontface'} onclick={() => (addMode = 'fontface')}>@font-face</button>
249
249
  <button type="button" class="pf-add-close" onclick={reset} aria-label="Cancel">×</button>
250
250
  </div>
251
251
 
252
- {#if addMode === 'google'}
253
- <input
254
- type="text"
255
- class="ui-form-input"
256
- placeholder="Search Google Fonts (e.g. Inter)"
257
- bind:value={googleQuery}
258
- />
259
- <ul class="pf-results">
260
- {#each googleMatches as m (m.family)}
261
- <li class="pf-result">
262
- <span class="pf-result-preview" style="font-family: '{m.family}', {m.category};">{m.family}</span>
263
- <span class="pf-result-meta">{m.category} · {m.variants.length}w</span>
264
- <button type="button" class="pf-result-add" onclick={() => addGoogleFont(m)}>add</button>
265
- </li>
266
- {/each}
267
- {#if googleMatches.length === 0}
268
- <li class="pf-no-results">No matches</li>
269
- {/if}
270
- </ul>
271
- {:else if addMode === 'url'}
272
- <input
273
- type="text"
274
- class="ui-form-input"
275
- placeholder="https://fonts.googleapis.com/css2?family=... or Typekit URL"
252
+ {#if addMode === 'url'}
253
+ <p class="pf-hint">
254
+ Pick fonts on
255
+ <a href="https://fonts.google.com/selection/embed" target="_blank" rel="noopener noreferrer">Google Fonts <i class="fas fa-arrow-up-right-from-square" aria-hidden="true"></i></a>,
256
+ copy either the <code>&lt;link&gt;</code> tag or the <code>@import</code> block, and paste it below. Any CSS URL (Typekit, custom host) also works.
257
+ </p>
258
+ <textarea
259
+ class="ui-form-input pf-textarea pf-url-input"
260
+ placeholder={'<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">\n\nor\n\n@import url(\'https://fonts.googleapis.com/css2?...\');\n\nor just the URL'}
261
+ rows="4"
276
262
  bind:value={urlInput}
277
- />
263
+ ></textarea>
278
264
  <div class="pf-row">
279
- <button type="button" class="pf-btn" onclick={discoverUrl} disabled={!urlInput.trim() || urlDiscovering}>
265
+ <UIPillButton variant="secondary" onclick={discoverUrl} disabled={!urlInput.trim() || urlDiscovering}>
280
266
  {urlDiscovering ? 'Checking…' : 'Detect families'}
281
- </button>
267
+ </UIPillButton>
282
268
  </div>
283
269
  {#if urlError}<div class="pf-error">{urlError}</div>{/if}
284
270
  {#if urlParsed}
@@ -305,7 +291,7 @@
305
291
  </li>
306
292
  {/each}
307
293
  </ul>
308
- <button type="button" class="pf-btn primary" onclick={addUrlSource}>Add {urlPickedNames.size} selected</button>
294
+ <UIPillButton variant="primary" onclick={addUrlSource}>Add {urlPickedNames.size} selected</UIPillButton>
309
295
  {:else if urlNeedsManualFamilies}
310
296
  <div class="pf-detected">Couldn't auto-detect families (CORS or no metadata). Name them:</div>
311
297
  <input
@@ -314,7 +300,7 @@
314
300
  placeholder="Comma-separated family names"
315
301
  bind:value={urlManualFamilies}
316
302
  />
317
- <button type="button" class="pf-btn primary" onclick={addUrlSource} disabled={!urlManualFamilies.trim()}>Add</button>
303
+ <UIPillButton variant="primary" onclick={addUrlSource} disabled={!urlManualFamilies.trim()}>Add</UIPillButton>
318
304
  {/if}
319
305
  {:else if addMode === 'fontface'}
320
306
  <textarea
@@ -327,7 +313,7 @@
327
313
  {#if fontFaceParsed.length > 0}
328
314
  <div class="pf-detected">Detected: {fontFaceParsed.map((f) => f.name).join(', ')}</div>
329
315
  {/if}
330
- <button type="button" class="pf-btn primary" onclick={addFontFaceSource} disabled={fontFaceParsed.length === 0}>Add</button>
316
+ <UIPillButton variant="primary" onclick={addFontFaceSource} disabled={fontFaceParsed.length === 0}>Add</UIPillButton>
331
317
  {/if}
332
318
  </div>
333
319
  {/if}
@@ -338,6 +324,7 @@
338
324
  display: flex;
339
325
  flex-direction: column;
340
326
  gap: var(--ui-space-8);
327
+ max-width: 56rem;
341
328
  }
342
329
 
343
330
  .pf-header {
@@ -350,7 +337,8 @@
350
337
  .group-title {
351
338
  margin: 0;
352
339
  font-size: var(--ui-font-size-lg);
353
- color: var(--ui-text-primary);
340
+ font-weight: var(--ui-font-weight-semibold);
341
+ color: var(--ui-text-secondary);
354
342
  }
355
343
 
356
344
  .pf-empty {
@@ -367,7 +355,7 @@
367
355
  }
368
356
 
369
357
  .pf-source {
370
- border: 1px solid var(--ui-border-faint);
358
+ border: 1px solid var(--ui-border-low);
371
359
  border-radius: var(--ui-radius-md);
372
360
  display: flex;
373
361
  flex-direction: column;
@@ -378,7 +366,7 @@
378
366
  align-items: center;
379
367
  gap: var(--ui-space-8);
380
368
  padding: var(--ui-space-8) var(--ui-space-12);
381
- border-bottom: 1px solid var(--ui-border-faint);
369
+ border-bottom: 1px solid var(--ui-border-low);
382
370
  background: var(--ui-surface-subtle, rgba(255,255,255,0.02));
383
371
  border-radius: var(--ui-radius-md) var(--ui-radius-md) 0 0;
384
372
  }
@@ -386,7 +374,7 @@
386
374
  .pf-kind-badge {
387
375
  font-size: var(--ui-font-size-xs);
388
376
  color: var(--ui-text-tertiary);
389
- border: 1px solid var(--ui-border-faint);
377
+ border: 1px solid var(--ui-border-low);
390
378
  padding: 0 var(--ui-space-4);
391
379
  border-radius: var(--ui-radius-sm);
392
380
  font-family: var(--ui-font-mono);
@@ -395,13 +383,13 @@
395
383
  .pf-source-label {
396
384
  font-size: var(--ui-font-size-lg);
397
385
  color: var(--ui-text-primary);
398
- font-weight: 500;
386
+ font-weight: var(--ui-font-weight-medium);
399
387
  }
400
388
 
401
389
  .pf-source-url {
402
390
  font-family: var(--ui-font-mono);
403
391
  font-size: var(--ui-font-size-xs);
404
- color: var(--ui-text-tertiary);
392
+ color: var(--ui-text-secondary);
405
393
  overflow: hidden;
406
394
  text-overflow: ellipsis;
407
395
  white-space: nowrap;
@@ -459,7 +447,7 @@
459
447
  background: var(--ui-surface-hover, rgba(255,255,255,0.06));
460
448
  }
461
449
  .pf-family-disclosure i {
462
- transition: transform 0.12s ease;
450
+ transition: transform var(--ui-transition-fast);
463
451
  }
464
452
  .pf-family-disclosure.open i { transform: rotate(90deg); }
465
453
  .pf-family-disclosure-placeholder {
@@ -510,19 +498,8 @@
510
498
  }
511
499
  .pf-meta-weights { word-break: break-word; }
512
500
 
513
- .pf-add-toggle {
514
- align-self: flex-start;
515
- background: none;
516
- border: 1px dashed var(--ui-border-faint);
517
- color: var(--ui-text-muted);
518
- font-size: var(--ui-font-size-sm);
519
- padding: var(--ui-space-4) var(--ui-space-8);
520
- border-radius: var(--ui-radius-sm);
521
- cursor: pointer;
522
- }
523
- .pf-add-toggle:hover {
524
- color: var(--ui-text-primary);
525
- border-color: var(--ui-border);
501
+ .pf-add-toggle-row {
502
+ display: flex;
526
503
  }
527
504
 
528
505
  .pf-add-panel {
@@ -530,7 +507,7 @@
530
507
  flex-direction: column;
531
508
  gap: var(--ui-space-8);
532
509
  padding: var(--ui-space-8);
533
- border: 1px solid var(--ui-border-faint);
510
+ border: 1px solid var(--ui-border-low);
534
511
  border-radius: var(--ui-radius-sm);
535
512
  }
536
513
 
@@ -540,16 +517,21 @@
540
517
  }
541
518
  .pf-add-tabs button {
542
519
  background: none;
543
- border: 1px solid var(--ui-border-faint);
544
- color: var(--ui-text-muted);
520
+ border: 1px solid var(--ui-border-low);
521
+ color: var(--ui-text-secondary);
545
522
  font-size: var(--ui-font-size-sm);
546
523
  padding: var(--ui-space-4) var(--ui-space-8);
547
524
  border-radius: var(--ui-radius-sm);
548
525
  cursor: pointer;
549
526
  }
527
+ .pf-add-tabs button:hover {
528
+ color: var(--ui-text-primary);
529
+ border-color: var(--ui-border-high);
530
+ }
550
531
  .pf-add-tabs button.active {
551
532
  color: var(--ui-text-primary);
552
- border-color: var(--ui-border);
533
+ background: var(--ui-surface-high);
534
+ border-color: var(--ui-border-higher);
553
535
  }
554
536
  .pf-add-tabs .pf-add-close {
555
537
  margin-left: auto;
@@ -561,26 +543,9 @@
561
543
  align-items: center;
562
544
  }
563
545
 
564
- .pf-btn {
565
- background: none;
566
- border: 1px solid var(--ui-border-faint);
567
- color: var(--ui-text-primary);
568
- font-size: var(--ui-font-size-sm);
569
- padding: var(--ui-space-4) var(--ui-space-8);
570
- border-radius: var(--ui-radius-sm);
571
- cursor: pointer;
572
- }
573
- .pf-btn:hover:not(:disabled) { border-color: var(--ui-border); }
574
- .pf-btn:disabled { opacity: 0.4; cursor: not-allowed; }
575
- .pf-btn.primary {
576
- background: var(--ui-focus, #5eb2ff);
577
- border-color: var(--ui-focus, #5eb2ff);
578
- color: #000;
579
- }
580
-
581
546
  .pf-error { color: var(--ui-text-danger, #ff6b6b); font-size: var(--ui-font-size-sm); }
582
547
 
583
- .pf-detected { color: var(--ui-text-tertiary); font-size: var(--ui-font-size-sm); }
548
+ .pf-detected { color: var(--ui-text-secondary); font-size: var(--ui-font-size-sm); }
584
549
 
585
550
  .pf-checklist {
586
551
  list-style: none;
@@ -600,46 +565,39 @@
600
565
  .pf-check-name { color: var(--ui-text-primary); }
601
566
  .pf-check-meta { color: var(--ui-text-tertiary); font-family: var(--ui-font-mono); font-size: var(--ui-font-size-xs); }
602
567
 
603
- .pf-results {
604
- list-style: none;
605
- margin: 0;
606
- padding: 0;
607
- display: flex;
608
- flex-direction: column;
609
- gap: var(--ui-space-2);
610
- max-height: 18rem;
611
- overflow-y: auto;
568
+ .pf-textarea {
569
+ font-family: var(--ui-font-mono);
570
+ font-size: var(--ui-font-size-xs);
571
+ resize: vertical;
572
+ color: var(--ui-text-primary);
612
573
  }
574
+ .pf-textarea::placeholder { color: var(--ui-text-muted); opacity: 1; }
613
575
 
614
- .pf-result {
615
- display: grid;
616
- grid-template-columns: 1fr auto auto;
617
- align-items: center;
618
- gap: var(--ui-space-8);
619
- padding: var(--ui-space-4);
620
- border: 1px solid transparent;
621
- border-radius: var(--ui-radius-sm);
576
+ .pf-url-input {
577
+ white-space: pre;
578
+ overflow-x: auto;
622
579
  }
623
- .pf-result:hover { border-color: var(--ui-border-faint); }
624
580
 
625
- .pf-result-preview { font-size: var(--ui-font-size-lg); color: var(--ui-text-primary); }
626
- .pf-result-meta { font-size: var(--ui-font-size-xs); color: var(--ui-text-tertiary); font-family: var(--ui-font-mono); }
627
- .pf-result-add {
628
- background: none;
629
- border: 1px solid var(--ui-border-faint);
630
- color: var(--ui-text-muted);
581
+ .pf-hint {
582
+ margin: 0;
583
+ color: var(--ui-text-tertiary);
631
584
  font-size: var(--ui-font-size-sm);
632
- padding: 2px var(--ui-space-6);
633
- border-radius: var(--ui-radius-sm);
634
- cursor: pointer;
585
+ line-height: 1.4;
635
586
  }
636
- .pf-result-add:hover { color: var(--ui-text-primary); border-color: var(--ui-border); }
637
-
638
- .pf-no-results { color: var(--ui-text-muted); font-size: var(--ui-font-size-sm); padding: var(--ui-space-4); }
639
-
640
- .pf-textarea {
587
+ .pf-hint a {
588
+ color: var(--ui-text-primary);
589
+ text-decoration: underline;
590
+ text-underline-offset: 2px;
591
+ text-decoration-thickness: 1px;
592
+ white-space: nowrap;
593
+ }
594
+ .pf-hint a:hover { text-decoration-thickness: 2px; }
595
+ .pf-hint a i { font-size: 0.75em; margin-left: var(--ui-space-2); }
596
+ .pf-hint code {
641
597
  font-family: var(--ui-font-mono);
642
- font-size: var(--ui-font-size-xs);
643
- resize: vertical;
598
+ font-size: 0.92em;
599
+ padding: 0 var(--ui-space-2);
600
+ background: var(--ui-surface-hover, rgba(255,255,255,0.06));
601
+ border-radius: var(--ui-radius-sm);
644
602
  }
645
603
  </style>
@@ -272,12 +272,12 @@
272
272
  }
273
273
 
274
274
  .section-title {
275
- font-size: var(--ui-font-size-lg);
275
+ font-size: var(--ui-font-size-2xl);
276
276
  font-weight: var(--ui-font-weight-semibold);
277
277
  color: var(--ui-text-primary);
278
278
  margin: 0;
279
279
  padding-bottom: var(--ui-space-8);
280
- border-bottom: 1px solid var(--ui-border-subtle);
280
+ border-bottom: 2px solid var(--ui-border-high);
281
281
  }
282
282
 
283
283
  .swatch-groups-grid {
@@ -294,7 +294,7 @@
294
294
  }
295
295
 
296
296
  .group-title {
297
- font-size: var(--ui-font-size-sm);
297
+ font-size: var(--ui-font-size-lg);
298
298
  font-weight: var(--ui-font-weight-semibold);
299
299
  color: var(--ui-text-secondary);
300
300
  margin: 0;
@@ -125,12 +125,12 @@
125
125
  }
126
126
 
127
127
  .group-title {
128
- font-size: var(--ui-font-size-sm);
128
+ font-size: var(--ui-font-size-lg);
129
129
  font-weight: var(--ui-font-weight-semibold);
130
130
  color: var(--ui-text-secondary);
131
131
  margin: 0;
132
132
  padding-bottom: var(--ui-space-4);
133
- border-bottom: 1px solid var(--ui-border-faint);
133
+ border-bottom: 1px solid var(--ui-border-low);
134
134
  }
135
135
 
136
136
  .text-colors-grid {
@@ -141,7 +141,7 @@
141
141
 
142
142
  .text-color-card {
143
143
  background: var(--ui-surface-low);
144
- border: 1px solid var(--ui-border-subtle);
144
+ border: 1px solid var(--ui-border-low);
145
145
  border-radius: var(--ui-radius-md);
146
146
  padding: var(--ui-space-12);
147
147
  display: flex;