@motion-proto/live-tokens 0.6.2 → 0.8.0

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 (232) hide show
  1. package/README.md +14 -13
  2. package/dist-plugin/index.cjs +854 -226
  3. package/dist-plugin/index.d.cts +2 -1
  4. package/dist-plugin/index.d.ts +2 -1
  5. package/dist-plugin/index.js +852 -225
  6. package/package.json +26 -40
  7. package/src/{styles → app}/site.css +1 -1
  8. package/src/{component-editor → editor/component-editor}/BadgeEditor.svelte +8 -82
  9. package/src/{component-editor → editor/component-editor}/CalloutEditor.svelte +4 -4
  10. package/src/{component-editor → editor/component-editor}/CardEditor.svelte +28 -76
  11. package/src/{component-editor → editor/component-editor}/CollapsibleSectionEditor.svelte +37 -30
  12. package/src/{component-editor → editor/component-editor}/CornerBadgeEditor.svelte +31 -93
  13. package/src/{component-editor → editor/component-editor}/DialogEditor.svelte +60 -57
  14. package/src/editor/component-editor/ImageEditor.svelte +30 -0
  15. package/src/{component-editor → editor/component-editor}/InlineEditActionsEditor.svelte +6 -4
  16. package/src/editor/component-editor/MenuSelectEditor.svelte +160 -0
  17. package/src/{component-editor → editor/component-editor}/NotificationEditor.svelte +67 -38
  18. package/src/{component-editor → editor/component-editor}/ProgressBarEditor.svelte +5 -4
  19. package/src/{component-editor → editor/component-editor}/RadioButtonEditor.svelte +3 -3
  20. package/src/editor/component-editor/SectionDividerEditor.svelte +565 -0
  21. package/src/{component-editor → editor/component-editor}/SegmentedControlEditor.svelte +2 -2
  22. package/src/{component-editor → editor/component-editor}/StandardButtonsEditor.svelte +29 -21
  23. package/src/{component-editor → editor/component-editor}/TabBarEditor.svelte +9 -14
  24. package/src/{component-editor → editor/component-editor}/TableEditor.svelte +9 -18
  25. package/src/{component-editor → editor/component-editor}/TooltipEditor.svelte +11 -47
  26. package/src/editor/component-editor/editors.d.ts +10 -0
  27. package/src/{component-editor → editor/component-editor}/registry.ts +28 -18
  28. package/src/{component-editor → editor/component-editor}/scaffolding/AngleDial.svelte +54 -15
  29. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentEditorBase.svelte +3 -51
  30. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileManager.svelte +151 -424
  31. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileMenu.svelte +18 -170
  32. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentsTab.svelte +2 -2
  33. package/src/{component-editor → editor/component-editor}/scaffolding/CopyFromMenu.svelte +44 -4
  34. package/src/{component-editor → editor/component-editor}/scaffolding/FieldsetWrapper.svelte +1 -1
  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 -12
  37. package/src/editor/component-editor/scaffolding/NonStylableConfig.svelte +38 -0
  38. package/src/editor/component-editor/scaffolding/RadialShapePad.svelte +483 -0
  39. package/src/{component-editor → editor/component-editor}/scaffolding/SaveAsDialog.svelte +66 -12
  40. package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +85 -0
  41. package/src/editor/component-editor/scaffolding/ShadowBackdropControls.svelte +132 -0
  42. package/src/editor/component-editor/scaffolding/StateBlock.svelte +345 -0
  43. package/src/{component-editor → editor/component-editor}/scaffolding/TokenLayout.svelte +17 -12
  44. package/src/{component-editor → editor/component-editor}/scaffolding/TypeEditor.svelte +13 -1
  45. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +858 -0
  46. package/src/{component-editor → editor/component-editor}/scaffolding/buildTypeGroupTokens.ts +1 -0
  47. package/src/{component-editor → editor/component-editor}/scaffolding/editorContext.ts +19 -9
  48. package/src/{component-editor → editor/component-editor}/scaffolding/linkedBlock.ts +2 -2
  49. package/src/{component-editor → editor/component-editor}/scaffolding/types.ts +25 -0
  50. package/src/{lib → editor/core/components}/componentConfigKeys.ts +8 -0
  51. package/src/{lib → editor/core/components}/componentConfigService.ts +3 -3
  52. package/src/{lib → editor/core/components}/componentPersist.ts +11 -9
  53. package/src/editor/core/flashStatus.ts +30 -0
  54. package/src/{lib → editor/core/fonts}/fontLoader.ts +2 -2
  55. package/src/{lib → editor/core/fonts}/fontMigration.ts +4 -4
  56. package/src/{lib → editor/core/fonts}/fontParse.ts +1 -1
  57. package/src/editor/core/manifests/manifestService.ts +171 -0
  58. package/src/editor/core/palettes/familySwap.ts +99 -0
  59. package/src/{lib → editor/core/palettes}/paletteDerivation.ts +71 -2
  60. package/src/{lib → editor/core/palettes}/tokenRegistry.ts +9 -6
  61. package/src/editor/core/productionPulse.ts +37 -0
  62. package/src/{lib → editor/core/routing}/router.ts +1 -1
  63. package/src/{lib/files/versionedFileResource.ts → editor/core/storage/files/versionedFileResourceClient.ts} +8 -1
  64. package/src/{lib → editor/core/store}/editorCore.ts +24 -8
  65. package/src/{lib → editor/core/store}/editorPersistence.ts +3 -3
  66. package/src/{lib → editor/core/store}/editorRenderer.ts +2 -2
  67. package/src/{lib → editor/core/store}/editorStore.ts +222 -28
  68. package/src/{lib → editor/core/store}/editorTypes.ts +56 -13
  69. package/src/editor/core/store/gradientSource.ts +192 -0
  70. package/src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts +28 -0
  71. package/src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts +35 -0
  72. package/src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts +82 -0
  73. package/src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts +24 -0
  74. package/src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts +81 -0
  75. package/src/{lib → editor/core/themes}/migrations/index.ts +10 -0
  76. package/src/{lib → editor/core/themes}/slices/columns.ts +2 -2
  77. package/src/{lib → editor/core/themes}/slices/components.ts +20 -6
  78. package/src/{lib → editor/core/themes}/slices/fonts.ts +1 -1
  79. package/src/{lib → editor/core/themes}/slices/gradients.ts +89 -14
  80. package/src/{lib → editor/core/themes}/slices/overlays.ts +1 -1
  81. package/src/{lib → editor/core/themes}/slices/palettes.ts +1 -1
  82. package/src/{lib → editor/core/themes}/slices/shadows.ts +3 -3
  83. package/src/{lib → editor/core/themes}/themeInit.ts +8 -8
  84. package/src/{lib → editor/core/themes}/themeService.ts +6 -6
  85. package/src/{lib → editor/core/themes}/themeTypes.ts +67 -8
  86. package/src/editor/index.ts +69 -0
  87. package/src/{lib → editor/overlay}/ColumnsOverlay.svelte +0 -1
  88. package/src/{lib → editor/overlay}/LiveEditorOverlay.svelte +80 -129
  89. package/src/{lib → editor/overlay}/columnsOverlay.ts +2 -2
  90. package/src/{pages → editor/pages}/ComponentEditorPage.svelte +12 -12
  91. package/src/{pages → editor/pages}/Editor.svelte +4 -4
  92. package/src/{pages → editor/pages}/EditorShell.svelte +18 -36
  93. package/src/{styles → editor/styles}/ui-editor.css +43 -22
  94. package/src/{styles → editor/styles}/ui-form-controls.css +23 -24
  95. package/src/{ui → editor/ui}/BezierCurveEditor.svelte +119 -68
  96. package/src/{ui → editor/ui}/ColorEditPanel.svelte +13 -13
  97. package/src/{ui → editor/ui}/EditorViewSwitcher.svelte +7 -6
  98. package/src/editor/ui/FileLoadList.svelte +367 -0
  99. package/src/editor/ui/FilePill.svelte +80 -0
  100. package/src/editor/ui/FontStackEditor.svelte +499 -0
  101. package/src/editor/ui/GradientEditor.svelte +690 -0
  102. package/src/{ui → editor/ui}/GradientStopPicker.svelte +12 -4
  103. package/src/editor/ui/ManifestFileManager.svelte +438 -0
  104. package/src/{ui → editor/ui}/PaletteEditor.svelte +180 -673
  105. package/src/editor/ui/ProjectFontsSection.svelte +638 -0
  106. package/src/{ui → editor/ui}/SurfacesTab.svelte +3 -3
  107. package/src/{ui → editor/ui}/TextTab.svelte +3 -3
  108. package/src/editor/ui/ThemeFileManager.svelte +783 -0
  109. package/src/{ui → editor/ui}/UICopyPopover.svelte +4 -4
  110. package/src/{ui → editor/ui}/UIFontFamilySelector.svelte +6 -7
  111. package/src/{ui → editor/ui}/UIFontSizeSelector.svelte +4 -1
  112. package/src/editor/ui/UIInfoPopover.svelte +243 -0
  113. package/src/editor/ui/UILetterSpacingSelector.svelte +65 -0
  114. package/src/{ui → editor/ui}/UILineHeightSelector.svelte +5 -5
  115. package/src/{ui → editor/ui}/UILinkToggle.svelte +2 -2
  116. package/src/{ui → editor/ui}/UIPaddingSelector.svelte +6 -6
  117. package/src/{ui → editor/ui}/UIPaletteSelector.svelte +57 -30
  118. package/src/editor/ui/UIPillButton.svelte +168 -0
  119. package/src/{ui → editor/ui}/UIRadio.svelte +2 -2
  120. package/src/{ui → editor/ui}/UIRelinkConfirmPopover.svelte +4 -4
  121. package/src/editor/ui/UISegmentedControl.svelte +114 -0
  122. package/src/editor/ui/UISquareButton.svelte +172 -0
  123. package/src/{ui → editor/ui}/UITokenSelector.svelte +14 -11
  124. package/src/{ui → editor/ui}/UIVariantSelector.svelte +1 -1
  125. package/src/{ui → editor/ui}/VariablesTab.svelte +46 -17
  126. package/src/{ui → editor/ui}/palette/GradientStopEditor.svelte +13 -13
  127. package/src/{ui → editor/ui}/palette/OverridesPanel.svelte +24 -47
  128. package/src/{ui → editor/ui}/palette/PaletteBase.svelte +11 -8
  129. package/src/{ui → editor/ui}/palette/paletteEditorState.ts +1 -1
  130. package/src/editor/ui/palette/paletteMath.ts +275 -0
  131. package/src/{ui → editor/ui}/sections/ColumnsSection.svelte +137 -18
  132. package/src/{ui → editor/ui}/sections/GradientsSection.svelte +8 -8
  133. package/src/{ui → editor/ui}/sections/OverlaysSection.svelte +18 -18
  134. package/src/{ui → editor/ui}/sections/ShadowsSection.svelte +23 -23
  135. package/src/{ui → editor/ui}/sections/TokenScaleTable.svelte +3 -3
  136. package/src/{components → system/components}/Badge.svelte +0 -36
  137. package/src/{components → system/components}/Button.svelte +2 -2
  138. package/src/{components → system/components}/Card.svelte +34 -60
  139. package/src/{components → system/components}/CollapsibleSection.svelte +25 -2
  140. package/src/{components → system/components}/CornerBadge.svelte +8 -24
  141. package/src/{components → system/components}/Dialog.svelte +1 -1
  142. package/src/system/components/FloatingTokenTags.css +275 -0
  143. package/src/system/components/FloatingTokenTags.svelte +543 -0
  144. package/src/{components → system/components}/InlineEditActions.svelte +6 -4
  145. package/src/system/components/MenuSelect.svelte +229 -0
  146. package/src/{components → system/components}/Notification.svelte +8 -1
  147. package/src/{components → system/components}/ProgressBar.svelte +29 -11
  148. package/src/system/components/SectionDivider.svelte +560 -0
  149. package/src/{components → system/components}/SegmentedControl.svelte +49 -43
  150. package/src/{components → system/components}/TabBar.svelte +81 -65
  151. package/src/{components → system/components}/Table.svelte +17 -3
  152. package/src/{components → system/components}/Tooltip.svelte +6 -4
  153. package/src/system/styles/CONVENTIONS.md +178 -0
  154. package/src/system/styles/fonts.css +20 -0
  155. package/src/system/styles/tokens.css +601 -0
  156. package/src/system/styles/tokens.generated.css +544 -0
  157. package/src/component-editor/ImageEditor.svelte +0 -74
  158. package/src/component-editor/SectionDividerEditor.svelte +0 -265
  159. package/src/component-editor/scaffolding/DividerEditor.svelte +0 -94
  160. package/src/component-editor/scaffolding/GradientCard.svelte +0 -296
  161. package/src/component-editor/scaffolding/NonStylableConfig.svelte +0 -62
  162. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +0 -37
  163. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +0 -61
  164. package/src/component-editor/scaffolding/StateBlock.svelte +0 -132
  165. package/src/component-editor/scaffolding/VariantGroup.svelte +0 -310
  166. package/src/components/SectionDivider.svelte +0 -483
  167. package/src/data/google-fonts.json +0 -75
  168. package/src/lib/index.ts +0 -68
  169. package/src/lib/presetService.ts +0 -214
  170. package/src/lib/productionPulse.ts +0 -32
  171. package/src/styles/fonts.css +0 -30
  172. package/src/styles/tokens.css +0 -1324
  173. package/src/ui/FontStackEditor.svelte +0 -361
  174. package/src/ui/GradientEditor.svelte +0 -470
  175. package/src/ui/PresetFileManager.svelte +0 -1116
  176. package/src/ui/ProjectFontsSection.svelte +0 -645
  177. package/src/ui/ThemeFileManager.svelte +0 -1020
  178. package/src/ui/UnsavedComponentsDialog.svelte +0 -315
  179. /package/src/{component-editor → editor/component-editor}/index.ts +0 -0
  180. /package/src/{component-editor → editor/component-editor}/scaffolding/DemoHeader.svelte +0 -0
  181. /package/src/{component-editor → editor/component-editor}/scaffolding/componentSectionType.ts +0 -0
  182. /package/src/{component-editor → editor/component-editor}/scaffolding/componentSources.ts +0 -0
  183. /package/src/{component-editor → editor/component-editor}/scaffolding/defaultSections.ts +0 -0
  184. /package/src/{component-editor → editor/component-editor}/scaffolding/siblings.ts +0 -0
  185. /package/src/{lib → editor/core}/cssVarSync.ts +0 -0
  186. /package/src/{lib → editor/core/palettes}/oklch.ts +0 -0
  187. /package/src/{lib → editor/core/routing}/navLinkTypes.ts +0 -0
  188. /package/src/{lib → editor/core/routing}/parentRouteStore.ts +0 -0
  189. /package/src/{lib → editor/core/storage}/storage.ts +0 -0
  190. /package/src/{lib → editor/core/store}/editorConfig.ts +0 -0
  191. /package/src/{lib → editor/core/store}/editorConfigStore.ts +0 -0
  192. /package/src/{lib → editor/core/store}/editorKeybindings.ts +0 -0
  193. /package/src/{lib → editor/core/store}/editorViewStore.ts +0 -0
  194. /package/src/{lib → editor/core/themes}/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +0 -0
  195. /package/src/{lib → editor/core/themes}/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +0 -0
  196. /package/src/{lib → editor/core/themes}/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +0 -0
  197. /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +0 -0
  198. /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +0 -0
  199. /package/src/{lib → editor/core/themes}/migrations/2026-05-10-sectiondivider-gradient-stops.ts +0 -0
  200. /package/src/{lib → editor/core/themes}/migrations/2026-05-13-primary-to-brand.ts +0 -0
  201. /package/src/{lib → editor/core/themes}/parsers/globalRootBlock.ts +0 -0
  202. /package/src/{lib → editor/core/themes}/slices/domainVars.ts +0 -0
  203. /package/src/{lib → editor/overlay}/overlayState.ts +0 -0
  204. /package/src/{pages → editor/pages}/ComponentEditorPage.svelte.d.ts +0 -0
  205. /package/src/{pages → editor/pages}/Editor.svelte.d.ts +0 -0
  206. /package/src/{ui → editor/ui}/Toggle.svelte +0 -0
  207. /package/src/{ui → editor/ui}/UIDialog.svelte +0 -0
  208. /package/src/{ui → editor/ui}/UIFontWeightSelector.svelte +0 -0
  209. /package/src/{ui → editor/ui}/UIOptionItem.svelte +0 -0
  210. /package/src/{ui → editor/ui}/UIOptionList.svelte +0 -0
  211. /package/src/{ui → editor/ui}/UIRadioGroup.svelte +0 -0
  212. /package/src/{lib → editor/ui}/copyPopover.ts +0 -0
  213. /package/src/{ui → editor/ui}/curveEngine.ts +0 -0
  214. /package/src/{ui → editor/ui}/index.ts +0 -0
  215. /package/src/{ui → editor/ui}/keepInViewport.ts +0 -0
  216. /package/src/{ui → editor/ui}/palette/ScaleCurveEditor.svelte +0 -0
  217. /package/src/{lib → editor/ui}/scrollSection.ts +0 -0
  218. /package/src/{ui → editor/ui}/sections/tokenScales.ts +0 -0
  219. /package/src/{ui → editor/ui}/variantScales.ts +0 -0
  220. /package/src/{assets → system/assets}/newspaper.webp +0 -0
  221. /package/src/{assets → system/assets}/offering.webp +0 -0
  222. /package/src/{components → system/components}/Callout.svelte +0 -0
  223. /package/src/{components → system/components}/Image.svelte +0 -0
  224. /package/src/{components → system/components}/RadioButton.svelte +0 -0
  225. /package/src/{components → system/components}/types.ts +0 -0
  226. /package/src/{styles → system/styles}/_padding.scss +0 -0
  227. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
  228. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
  229. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
  230. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
  231. /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
  232. /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin.woff2 +0 -0
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import ColorEditPanel from '../ColorEditPanel.svelte';
3
3
  import Toggle from '../Toggle.svelte';
4
- import { beginSliderGesture } from '../../lib/editorStore';
4
+ import { beginSliderGesture } from '../../core/store/editorStore';
5
5
 
6
6
 
7
7
 
@@ -137,42 +137,45 @@
137
137
  width: 4rem;
138
138
  height: 4rem;
139
139
  border-radius: var(--ui-radius-md);
140
- border: 2px solid var(--ui-border-default);
140
+ border: 2px solid var(--ui-border);
141
141
  flex-shrink: 0;
142
142
  cursor: pointer;
143
143
  }
144
144
 
145
145
  .header-swatch:hover {
146
- border-color: var(--ui-border-strong);
146
+ border-color: var(--ui-border-higher);
147
147
  }
148
148
 
149
149
  .header-swatch.active {
150
- border-color: var(--ui-border-strong);
151
- outline: 2px solid var(--ui-border-medium);
150
+ border-color: var(--ui-border-higher);
151
+ outline: 2px solid var(--ui-border-high);
152
152
  outline-offset: 1px;
153
153
  }
154
154
 
155
155
  .editor-label {
156
- font-size: var(--ui-font-size-lg);
156
+ font-size: var(--ui-font-size-xl);
157
157
  font-weight: var(--ui-font-weight-semibold);
158
158
  color: var(--ui-text-primary);
159
159
  }
160
160
 
161
161
  .base-hex {
162
- font-size: var(--ui-font-size-xs);
162
+ font-size: var(--ui-font-size-md);
163
163
  color: var(--ui-text-secondary);
164
164
  font-family: var(--ui-font-mono);
165
165
  }
166
166
 
167
167
  .clickable-hex {
168
+ align-self: flex-start;
168
169
  background: none;
169
170
  border: none;
170
171
  cursor: pointer;
171
172
  padding: var(--ui-space-2) var(--ui-space-4);
173
+ margin-left: calc(-1 * var(--ui-space-4));
172
174
  border-radius: var(--ui-radius-sm);
173
- font-size: var(--ui-font-size-xs);
175
+ font-size: var(--ui-font-size-md);
174
176
  color: var(--ui-text-secondary);
175
177
  font-family: var(--ui-font-mono);
178
+ text-align: left;
176
179
  }
177
180
 
178
181
  .clickable-hex:hover {
@@ -30,7 +30,7 @@
30
30
  * edits don't open a panel.
31
31
  */
32
32
 
33
- import type { Scope } from '../../lib/editorStore';
33
+ import type { Scope } from '../../core/store/editorStore';
34
34
 
35
35
  /** Sentinel key for the base swatch (used as `editingKey === BASE_KEY`). */
36
36
  export const BASE_KEY = '__base__';
@@ -0,0 +1,275 @@
1
+ import { hexToOklch, oklchToHex, gamutClamp } from '../../core/palettes/oklch';
2
+ import { type CurveAnchor, makeAnchor, sampleCurve } from '../curveEngine';
3
+
4
+ export const GRAY_FALLBACK = '#808080';
5
+ export const DEFAULT_TINT_CHROMA = 0.04;
6
+
7
+ export interface Step {
8
+ name: string;
9
+ position: number;
10
+ lightness?: number;
11
+ saturation?: number;
12
+ }
13
+
14
+ export interface Scale {
15
+ title: string;
16
+ isText: boolean;
17
+ steps: Step[];
18
+ }
19
+
20
+ export interface GrayStep {
21
+ label: string;
22
+ hue: number;
23
+ saturation: number;
24
+ lightness: number;
25
+ }
26
+
27
+ export interface PaletteStepDef {
28
+ label: string;
29
+ lightness: number;
30
+ }
31
+
32
+ export type CurveOffset = Record<string, number>;
33
+ export type ScaleCurves = Record<string, { lightness: CurveAnchor[]; saturation: CurveAnchor[] }>;
34
+
35
+ export const DEFAULT_PALETTE_LIGHTNESS = (): CurveAnchor[] => [makeAnchor(0, 95, 5), makeAnchor(100, 8, 5)];
36
+ export const DEFAULT_PALETTE_SATURATION = (): CurveAnchor[] => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)];
37
+ export const DEFAULT_GRAY_LIGHTNESS = (): CurveAnchor[] => [makeAnchor(0, 92, 5), makeAnchor(100, 3, 5)];
38
+ export const DEFAULT_GRAY_SATURATION = (): CurveAnchor[] => [makeAnchor(0, 20, 30), makeAnchor(100, 20, 30)];
39
+
40
+ export const defaultScaleCurves: Record<string, { lightness: () => CurveAnchor[]; saturation: () => CurveAnchor[] }> = {
41
+ Surfaces: {
42
+ lightness: () => [makeAnchor(0, 15, 5), makeAnchor(100, 47, 5)],
43
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)],
44
+ },
45
+ Borders: {
46
+ lightness: () => [makeAnchor(0, 25, 5), makeAnchor(100, 80, 5)],
47
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)],
48
+ },
49
+ Text: {
50
+ lightness: () => [makeAnchor(0, 120, 30), makeAnchor(100, 55, 30)],
51
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 15, 30)],
52
+ },
53
+ };
54
+
55
+ export function defaultScaleCurvesObject(): ScaleCurves {
56
+ return {
57
+ Surfaces: { lightness: defaultScaleCurves.Surfaces.lightness(), saturation: defaultScaleCurves.Surfaces.saturation() },
58
+ Borders: { lightness: defaultScaleCurves.Borders.lightness(), saturation: defaultScaleCurves.Borders.saturation() },
59
+ Text: { lightness: defaultScaleCurves.Text.lightness(), saturation: defaultScaleCurves.Text.saturation() },
60
+ };
61
+ }
62
+
63
+ export const paletteStepLightness: PaletteStepDef[] = [
64
+ { label: '100', lightness: 95 },
65
+ { label: '200', lightness: 88 },
66
+ { label: '300', lightness: 78 },
67
+ { label: '400', lightness: 68 },
68
+ { label: '500', lightness: 57 },
69
+ { label: '600', lightness: 49 },
70
+ { label: '700', lightness: 41 },
71
+ { label: '800', lightness: 32 },
72
+ { label: '850', lightness: 25 },
73
+ { label: '900', lightness: 17 },
74
+ { label: '950', lightness: 8 },
75
+ ];
76
+
77
+ export const graySteps: GrayStep[] = [
78
+ { label: '100', hue: 240, saturation: 5, lightness: 92 },
79
+ { label: '200', hue: 220, saturation: 13, lightness: 84 },
80
+ { label: '300', hue: 216, saturation: 12, lightness: 72 },
81
+ { label: '400', hue: 240, saturation: 5, lightness: 61 },
82
+ { label: '500', hue: 240, saturation: 5, lightness: 50 },
83
+ { label: '600', hue: 240, saturation: 5, lightness: 42 },
84
+ { label: '700', hue: 240, saturation: 5, lightness: 34 },
85
+ { label: '800', hue: 240, saturation: 10, lightness: 25 },
86
+ { label: '850', hue: 229, saturation: 20, lightness: 18 },
87
+ { label: '900', hue: 240, saturation: 30, lightness: 10 },
88
+ { label: '950', hue: 229, saturation: 34, lightness: 3 },
89
+ ];
90
+
91
+ export const scales: Scale[] = [
92
+ {
93
+ title: 'Surfaces',
94
+ isText: false,
95
+ steps: [
96
+ { name: 'lowest', position: -1 },
97
+ { name: 'lower', position: -2/3 },
98
+ { name: 'low', position: -1/3 },
99
+ { name: 'default', position: 0 },
100
+ { name: 'high', position: 1/3 },
101
+ { name: 'higher', position: 2/3 },
102
+ { name: 'highest', position: 1 },
103
+ ]
104
+ },
105
+ {
106
+ title: 'Borders',
107
+ isText: false,
108
+ steps: [
109
+ { name: 'faint', position: -1 },
110
+ { name: 'subtle', position: -0.5 },
111
+ { name: 'default', position: 0 },
112
+ { name: 'medium', position: 0.5 },
113
+ { name: 'strong', position: 1 },
114
+ ]
115
+ },
116
+ {
117
+ title: 'Text',
118
+ isText: true,
119
+ steps: [
120
+ { name: 'primary', position: 0 },
121
+ { name: 'secondary', position: 0 },
122
+ { name: 'tertiary', position: 0 },
123
+ { name: 'muted', position: 0 },
124
+ { name: 'disabled', position: 0 },
125
+ ]
126
+ }
127
+ ];
128
+
129
+ export const paletteStepKey = (label: string) => `Palette-${label}`;
130
+ export const grayStepKey = (label: string) => `gray-${label}`;
131
+ export const stepKey = (scaleTitle: string, stepName: string) => `${scaleTitle}-${stepName}`;
132
+ export const scaleCurveKey = (scaleTitle: string, channel: 'lightness' | 'saturation') => `${scaleTitle}-${channel}`;
133
+
134
+ export function stepIndexToX(index: number): number {
135
+ return (index / (paletteStepLightness.length - 1)) * 100;
136
+ }
137
+
138
+ export function grayStepToX(index: number): number {
139
+ return graySteps.length > 1 ? (index / (graySteps.length - 1)) * 100 : 50;
140
+ }
141
+
142
+ export function scaleStepToX(step: Step, scale: Scale): number {
143
+ const idx = scale.steps.indexOf(step);
144
+ return scale.steps.length > 1 ? (idx / (scale.steps.length - 1)) * 100 : 50;
145
+ }
146
+
147
+ export function injectLockedAnchor(curve: CurveAnchor[], x: number, y: number): { curve: CurveAnchor[]; idx: number; injected: boolean } {
148
+ const existing = curve.findIndex(a => Math.abs(a.x - x) < 0.5);
149
+ if (existing >= 0) {
150
+ if (curve[existing].x === x && Math.abs(curve[existing].y - y) < 0.01) return { curve, idx: existing, injected: false };
151
+ return { curve: curve.map((a, i) => i === existing ? { ...a, x, y } : a), idx: existing, injected: false };
152
+ }
153
+ let insertAt = curve.findIndex(a => a.x > x);
154
+ if (insertAt < 0) insertAt = curve.length;
155
+ return { curve: [...curve.slice(0, insertAt), makeAnchor(x, y, 15), ...curve.slice(insertAt)], idx: insertAt, injected: true };
156
+ }
157
+
158
+ export function removeLockedAnchor(curve: CurveAnchor[], idx: number | null): CurveAnchor[] {
159
+ if (idx === null || idx === 0 || idx === curve.length - 1) return curve;
160
+ return curve.filter((_, i) => i !== idx);
161
+ }
162
+
163
+ export function computeGrayColor(
164
+ index: number,
165
+ hue: number,
166
+ chroma: number,
167
+ lightnessCurve: CurveAnchor[],
168
+ saturationCurve: CurveAnchor[],
169
+ curveOffset: CurveOffset
170
+ ): string {
171
+ const xPos = grayStepToX(index);
172
+ const lOff = curveOffset['gray-lightness'] ?? 0;
173
+ const sOff = curveOffset['gray-saturation'] ?? 0;
174
+
175
+ const targetL = Math.max(0, Math.min(100, sampleCurve(lightnessCurve, xPos) + lOff)) / 100;
176
+ const satMul = Math.max(0, Math.min(2, (sampleCurve(saturationCurve, xPos) + sOff) / 100));
177
+ const targetC = chroma * satMul;
178
+
179
+ const clamped = gamutClamp(targetL, targetC, hue);
180
+ return oklchToHex(clamped.l, clamped.c, clamped.h);
181
+ }
182
+
183
+ export function computePaletteColor(
184
+ index: number,
185
+ base: string,
186
+ lightnessCurve: CurveAnchor[],
187
+ saturationCurve: CurveAnchor[],
188
+ curveOffset: CurveOffset
189
+ ): string {
190
+ const { c: baseC, h } = hexToOklch(base);
191
+ const xPos = stepIndexToX(index);
192
+
193
+ const targetL = Math.max(0, Math.min(100, sampleCurve(lightnessCurve, xPos) + (curveOffset['lightness'] ?? 0))) / 100;
194
+ const satMul = Math.max(0, Math.min(2, (sampleCurve(saturationCurve, xPos) + (curveOffset['saturation'] ?? 0)) / 100));
195
+ const targetC = baseC * satMul;
196
+
197
+ const clamped = gamutClamp(targetL, targetC, h);
198
+ return oklchToHex(clamped.l, clamped.c, clamped.h);
199
+ }
200
+
201
+ export function computeDerivedColor(
202
+ step: Step,
203
+ base: string,
204
+ scaleTitle: string,
205
+ scaleCurves: ScaleCurves,
206
+ curveOffset: CurveOffset
207
+ ): string {
208
+ const { l: baseL, c: baseC, h: baseH } = hexToOklch(base);
209
+ const scale = scales.find(s => s.title === scaleTitle)!;
210
+ const xPos = scaleStepToX(step, scale);
211
+
212
+ const lCurve = scaleCurves[scaleTitle]?.lightness ?? [];
213
+ const sCurve = scaleCurves[scaleTitle]?.saturation ?? [];
214
+ const lOff = curveOffset[scaleCurveKey(scaleTitle, 'lightness')] ?? 0;
215
+ const sOff = curveOffset[scaleCurveKey(scaleTitle, 'saturation')] ?? 0;
216
+
217
+ let targetL: number;
218
+ if (scale.isText) {
219
+ // Text: lightness curve is a multiplier (100 = 1x base lightness)
220
+ const lMul = Math.max(0, Math.min(2, (sampleCurve(lCurve, xPos) + lOff) / 100));
221
+ targetL = Math.max(0, Math.min(1, baseL * lMul));
222
+ } else {
223
+ targetL = Math.max(0, Math.min(100, sampleCurve(lCurve, xPos) + lOff)) / 100;
224
+ }
225
+
226
+ const satMul = Math.max(0, Math.min(2, (sampleCurve(sCurve, xPos) + sOff) / 100));
227
+ const targetC = baseC * satMul;
228
+
229
+ const clamped = gamutClamp(targetL, targetC, baseH);
230
+ return oklchToHex(clamped.l, clamped.c, clamped.h);
231
+ }
232
+
233
+ interface PaletteComputed {
234
+ hex: string;
235
+ }
236
+
237
+ // Pick the contiguous window of palette steps (dark-first) whose lightness
238
+ // curve best matches this scale's derived lightness curve.
239
+ export function snapScaleToPalette(
240
+ scale: Scale,
241
+ baseColor: string,
242
+ scaleCurves: ScaleCurves,
243
+ curveOffset: CurveOffset,
244
+ paletteComputed: ReadonlyArray<PaletteComputed>
245
+ ): Record<string, string> {
246
+ const n = scale.steps.length;
247
+
248
+ const stepL = scale.steps.map(step => {
249
+ const derived = computeDerivedColor(step, baseColor, scale.title, scaleCurves, curveOffset);
250
+ return hexToOklch(derived).l;
251
+ });
252
+
253
+ const palDarkFirst = [...paletteComputed].reverse();
254
+ const palLDarkFirst = palDarkFirst.map(ps => hexToOklch(ps.hex).l);
255
+
256
+ let bestStart = 0;
257
+ let bestCost = Infinity;
258
+ for (let start = 0; start <= palDarkFirst.length - n; start++) {
259
+ let cost = 0;
260
+ for (let i = 0; i < n; i++) {
261
+ const d = stepL[i] - palLDarkFirst[start + i];
262
+ cost += d * d;
263
+ }
264
+ if (cost < bestCost) {
265
+ bestCost = cost;
266
+ bestStart = start;
267
+ }
268
+ }
269
+
270
+ const assigned: Record<string, string> = {};
271
+ for (let i = 0; i < n; i++) {
272
+ assigned[stepKey(scale.title, scale.steps[i].name)] = palDarkFirst[bestStart + i].hex;
273
+ }
274
+ return assigned;
275
+ }
@@ -1,14 +1,22 @@
1
1
  <script lang="ts">
2
2
  import { onMount } from 'svelte';
3
- import { editorState, mutate, beginSliderGesture } from '../../lib/editorStore';
4
- import type { ColumnsState } from '../../lib/editorTypes';
3
+ import { editorState, mutate, beginSliderGesture } from '../../core/store/editorStore';
4
+ import type { ColumnsState } from '../../core/store/editorTypes';
5
+
6
+ const STANDARD_COLS = 12;
7
+ const COLS_MIN = 1;
8
+ const COLS_MAX = 24;
9
+ // Pointer-events needed to break free of 12 once the drag arrives there.
10
+ // The slider is bound to state, so returning early during these trips
11
+ // keeps the thumb visually pinned at 12 even as the pointer wanders.
12
+ const DETENT_RESISTANCE = 4;
5
13
 
6
14
  function clampNum(v: number, lo: number, hi: number): number {
7
15
  return Math.max(lo, Math.min(hi, Math.round(v)));
8
16
  }
9
17
 
10
18
  function setColumnsCount(n: number) {
11
- mutate('set columns count', (s) => { s.columns.count = clampNum(n, 1, 24); });
19
+ mutate('set columns count', (s) => { s.columns.count = clampNum(n, COLS_MIN, COLS_MAX); });
12
20
  }
13
21
  function setColumnsMaxWidth(px: number) {
14
22
  mutate('set columns max-width', (s) => { s.columns.maxWidth = clampNum(px, 320, 2560); });
@@ -20,6 +28,44 @@
20
28
  mutate('set columns margin', (s) => { s.columns.margin = clampNum(px, 0, 400); });
21
29
  }
22
30
 
31
+ let colsDragging = false;
32
+ let colsDetentTrips = 0;
33
+
34
+ function onColsPointerDown() {
35
+ beginSliderGesture('drag columns count');
36
+ colsDragging = true;
37
+ colsDetentTrips = 0;
38
+ }
39
+ function onColsPointerUp() {
40
+ colsDragging = false;
41
+ colsDetentTrips = 0;
42
+ }
43
+ function handleColsInput(raw: number, target: HTMLInputElement) {
44
+ const current = $editorState.columns.count;
45
+ if (
46
+ colsDragging &&
47
+ current === STANDARD_COLS &&
48
+ Math.abs(raw - STANDARD_COLS) === 1
49
+ ) {
50
+ colsDetentTrips += 1;
51
+ if (colsDetentTrips < DETENT_RESISTANCE) {
52
+ // Force the thumb back. Svelte's controlled value may not re-sync
53
+ // when the underlying number is unchanged, so set the DOM value here.
54
+ target.value = String(STANDARD_COLS);
55
+ return;
56
+ }
57
+ colsDetentTrips = 0;
58
+ }
59
+ if (raw === STANDARD_COLS) colsDetentTrips = 0;
60
+ setColumnsCount(raw);
61
+ }
62
+
63
+ // Tick position on the slider track. Slider runs from COLS_MIN to COLS_MAX,
64
+ // so 12 sits at (12 - min) / (max - min) along the track. Inset the edges by
65
+ // approximately one thumb-radius so the tick aligns with where the thumb
66
+ // sits when value === 12.
67
+ const colsTickPct = ((STANDARD_COLS - COLS_MIN) / (COLS_MAX - COLS_MIN)) * 100;
68
+
23
69
  let initialColumns: ColumnsState | null = null;
24
70
 
25
71
  onMount(() => {
@@ -41,16 +87,28 @@
41
87
  </p>
42
88
 
43
89
  <div class="columns-controls">
44
- <div class="global-shadow-row">
90
+ <div class="global-shadow-row cols-row">
45
91
  <span class="shadow-slider-label" title="Number of columns">Cols</span>
46
- <input type="range" min="1" max="24" value={$editorState.columns.count}
47
- onpointerdown={() => beginSliderGesture('drag columns count')}
48
- oninput={(e) => setColumnsCount(+e.currentTarget.value)} />
49
- <input class="shadow-slider-input" type="number" min="1" max="24"
92
+ <div class="cols-slider-wrap">
93
+ <input type="range" min={COLS_MIN} max={COLS_MAX} value={$editorState.columns.count}
94
+ onpointerdown={onColsPointerDown}
95
+ onpointerup={onColsPointerUp}
96
+ onpointercancel={onColsPointerUp}
97
+ oninput={(e) => handleColsInput(+e.currentTarget.value, e.currentTarget)} />
98
+ <span class="cols-tick" style="left: {colsTickPct}%" aria-hidden="true"></span>
99
+ <span class="cols-tick-label" style="left: {colsTickPct}%" aria-hidden="true">12</span>
100
+ </div>
101
+ <input class="shadow-slider-input" type="number" min={COLS_MIN} max={COLS_MAX}
50
102
  value={$editorState.columns.count}
51
103
  onchange={(e) => setColumnsCount(+e.currentTarget.value)} />
52
104
  <span class="shadow-slider-unit"></span>
53
105
  </div>
106
+ {#if $editorState.columns.count !== STANDARD_COLS}
107
+ <p class="cols-consequence" role="note">
108
+ <i class="fas fa-circle-exclamation"></i>
109
+ <span>Most components assume 12 cols. Reset to restore.</span>
110
+ </p>
111
+ {/if}
54
112
  <div class="global-shadow-row">
55
113
  <span class="shadow-slider-label" title="Maximum content width">Max-Width</span>
56
114
  <input type="range" min="480" max="2560" step="10" value={$editorState.columns.maxWidth}
@@ -106,16 +164,16 @@
106
164
  .section {
107
165
  display: flex;
108
166
  flex-direction: column;
109
- gap: var(--ui-space-16);
167
+ gap: var(--ui-space-24);
110
168
  }
111
169
 
112
170
  .section-title {
113
- font-size: var(--ui-font-size-lg);
171
+ font-size: var(--ui-font-size-2xl);
114
172
  font-weight: var(--ui-font-weight-semibold);
115
173
  color: var(--ui-text-primary);
116
174
  margin: 0;
117
175
  padding-bottom: var(--ui-space-8);
118
- border-bottom: 1px solid var(--ui-border-subtle);
176
+ border-bottom: 2px solid var(--ui-border-high);
119
177
  }
120
178
 
121
179
  .columns-intro {
@@ -136,7 +194,7 @@
136
194
  gap: var(--ui-space-8);
137
195
  padding: var(--ui-space-12) var(--ui-space-16);
138
196
  background: var(--ui-surface-low);
139
- border: 1px solid var(--ui-border-faint);
197
+ border: 1px solid var(--ui-border-low);
140
198
  border-radius: var(--ui-radius-md);
141
199
  }
142
200
 
@@ -145,6 +203,67 @@
145
203
  text-align: left;
146
204
  }
147
205
 
206
+ .cols-row {
207
+ /* Slightly more breathing room so the tick label below the slider
208
+ does not collide with the next row. */
209
+ padding-bottom: var(--ui-space-6);
210
+ }
211
+
212
+ .cols-slider-wrap {
213
+ flex: 1;
214
+ position: relative;
215
+ display: flex;
216
+ align-items: center;
217
+ min-width: 4rem;
218
+ }
219
+
220
+ .cols-slider-wrap input[type="range"] {
221
+ flex: 1;
222
+ min-width: 4rem;
223
+ accent-color: var(--ui-text-accent);
224
+ height: 4px;
225
+ cursor: pointer;
226
+ }
227
+
228
+ .cols-tick {
229
+ position: absolute;
230
+ top: 50%;
231
+ width: 2px;
232
+ height: 10px;
233
+ background: var(--ui-text-muted);
234
+ opacity: 0.55;
235
+ transform: translate(-50%, -50%);
236
+ pointer-events: none;
237
+ border-radius: 1px;
238
+ }
239
+
240
+ .cols-tick-label {
241
+ position: absolute;
242
+ top: calc(50% + 9px);
243
+ transform: translateX(-50%);
244
+ font-size: 9px;
245
+ font-family: var(--ui-font-mono);
246
+ color: var(--ui-text-muted);
247
+ pointer-events: none;
248
+ line-height: 1;
249
+ }
250
+
251
+ .cols-consequence {
252
+ display: flex;
253
+ align-items: center;
254
+ gap: var(--ui-space-6);
255
+ margin: calc(var(--ui-space-4) * -1) 0 0;
256
+ padding: var(--ui-space-4) 0 var(--ui-space-4) calc(5rem + var(--ui-space-8));
257
+ font-size: var(--ui-font-size-xs);
258
+ color: var(--ui-link-broken);
259
+ line-height: 1.3;
260
+ }
261
+
262
+ .cols-consequence i {
263
+ font-size: 10px;
264
+ opacity: 0.85;
265
+ }
266
+
148
267
  .columns-input-wide {
149
268
  width: 3.5rem;
150
269
  }
@@ -154,7 +273,7 @@
154
273
  justify-content: flex-end;
155
274
  padding-top: var(--ui-space-8);
156
275
  margin-top: var(--ui-space-4);
157
- border-top: 1px solid var(--ui-border-faint);
276
+ border-top: 1px solid var(--ui-border-low);
158
277
  }
159
278
 
160
279
  .columns-reset {
@@ -163,7 +282,7 @@
163
282
  gap: var(--ui-space-6);
164
283
  padding: var(--ui-space-4) var(--ui-space-10);
165
284
  background: transparent;
166
- border: 1px solid var(--ui-border-subtle);
285
+ border: 1px solid var(--ui-border-low);
167
286
  border-radius: var(--ui-radius-md);
168
287
  color: var(--ui-text-tertiary);
169
288
  font-family: inherit;
@@ -174,7 +293,7 @@
174
293
 
175
294
  .columns-reset:hover {
176
295
  color: var(--ui-text-primary);
177
- border-color: var(--ui-border-medium);
296
+ border-color: var(--ui-border-high);
178
297
  }
179
298
 
180
299
  .columns-reset i {
@@ -183,7 +302,7 @@
183
302
 
184
303
  .columns-preview {
185
304
  background: var(--ui-surface-lowest);
186
- border: 1px solid var(--ui-border-faint);
305
+ border: 1px solid var(--ui-border-low);
187
306
  border-radius: var(--ui-radius-md);
188
307
  padding: var(--ui-space-12) 0;
189
308
  overflow: hidden;
@@ -245,7 +364,7 @@
245
364
  text-align: right;
246
365
  flex-shrink: 0;
247
366
  background: var(--ui-surface-lowest);
248
- border: 1px solid var(--ui-border-subtle);
367
+ border: 1px solid var(--ui-border-low);
249
368
  border-radius: var(--ui-radius-sm);
250
369
  padding: var(--ui-space-2) var(--ui-space-4);
251
370
  -moz-appearance: textfield;
@@ -260,7 +379,7 @@
260
379
 
261
380
  .shadow-slider-input:focus {
262
381
  outline: none;
263
- border-color: var(--ui-border-medium);
382
+ border-color: var(--ui-border-high);
264
383
  }
265
384
 
266
385
  .shadow-slider-unit {
@@ -7,7 +7,7 @@
7
7
  * direction, kind switch) lives in <GradientEditor>; this section is a
8
8
  * thin grid that toggles which gradient is being edited.
9
9
  */
10
- import { editorState } from '../../lib/editorStore';
10
+ import { editorState } from '../../core/store/editorStore';
11
11
  import GradientEditor from '../GradientEditor.svelte';
12
12
 
13
13
  interface Props {
@@ -56,16 +56,16 @@
56
56
  .section {
57
57
  display: flex;
58
58
  flex-direction: column;
59
- gap: var(--ui-space-16);
59
+ gap: var(--ui-space-24);
60
60
  }
61
61
 
62
62
  .section-title {
63
- font-size: var(--ui-font-size-lg);
63
+ font-size: var(--ui-font-size-2xl);
64
64
  font-weight: var(--ui-font-weight-semibold);
65
65
  color: var(--ui-text-primary);
66
66
  margin: 0;
67
67
  padding-bottom: var(--ui-space-8);
68
- border-bottom: 1px solid var(--ui-border-subtle);
68
+ border-bottom: 2px solid var(--ui-border-high);
69
69
  }
70
70
 
71
71
  .editor-intro {
@@ -103,7 +103,7 @@
103
103
  flex-direction: column;
104
104
  gap: var(--ui-space-8);
105
105
  padding: var(--ui-space-12);
106
- border: 1px solid var(--ui-border-faint);
106
+ border: 1px solid var(--ui-border-low);
107
107
  border-radius: var(--ui-radius-lg);
108
108
  background: var(--ui-surface-lowest);
109
109
  min-width: 0;
@@ -124,7 +124,7 @@
124
124
  .gradient-edit-btn {
125
125
  padding: var(--ui-space-2) var(--ui-space-10);
126
126
  background: var(--ui-surface-low);
127
- border: 1px solid var(--ui-border-faint);
127
+ border: 1px solid var(--ui-border-low);
128
128
  border-radius: var(--ui-radius-sm);
129
129
  color: var(--ui-text-secondary);
130
130
  font-size: var(--ui-font-size-xs);
@@ -134,13 +134,13 @@
134
134
 
135
135
  .gradient-edit-btn:hover {
136
136
  color: var(--ui-text-primary);
137
- border-color: var(--ui-border-default);
137
+ border-color: var(--ui-border);
138
138
  }
139
139
 
140
140
  .gradient-editor-host {
141
141
  margin-top: var(--ui-space-8);
142
142
  padding-top: var(--ui-space-12);
143
- border-top: 1px dashed var(--ui-border-faint);
143
+ border-top: 1px dashed var(--ui-border-low);
144
144
  }
145
145
 
146
146
  .gradient-box {