efficient-web-builder 1.0.0 → 2.0.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 (340) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +2 -1
  3. package/dist/components/AddBlockRow.d.ts +1 -7
  4. package/dist/components/AddBlockRow.js +1 -1
  5. package/dist/components/AddChildRow.d.ts +1 -6
  6. package/dist/components/AddChildRow.js +1 -1
  7. package/dist/components/AddSidePanel.d.ts +2 -39
  8. package/dist/components/AddSidePanel.js +1 -1
  9. package/dist/components/BlockGapField.js +1 -1
  10. package/dist/components/BlogPostSource.js +1 -1
  11. package/dist/components/CardShadowField.js +1 -1
  12. package/dist/components/ChatSettingsPanel.js +1 -1
  13. package/dist/components/CornersField.d.ts +0 -1
  14. package/dist/components/CornersField.js +1 -1
  15. package/dist/components/DuplicateToPageMenu.js +1 -1
  16. package/dist/components/EditorScreenMount.d.ts +1 -0
  17. package/dist/components/EditorScreenMount.js +1 -0
  18. package/dist/components/EditorStoreProvider.d.ts +1 -0
  19. package/dist/components/EditorStoreProvider.js +1 -0
  20. package/dist/components/HeroImageField.js +1 -1
  21. package/dist/components/HeroSection.d.ts +2 -6
  22. package/dist/components/HeroSection.js +4 -4
  23. package/dist/components/HoverEffectField.js +1 -1
  24. package/dist/components/ImageFocusRow.js +1 -1
  25. package/dist/components/KeepHint.d.ts +5 -0
  26. package/dist/components/KeepHint.js +1 -0
  27. package/dist/components/LocationsGroupedField.js +1 -1
  28. package/dist/components/MediaSidePanel.d.ts +1 -6
  29. package/dist/components/MediaSidePanel.js +1 -1
  30. package/dist/components/MediaUploadField.js +1 -1
  31. package/dist/components/MultiSelectField.d.ts +4 -1
  32. package/dist/components/MultiSelectField.js +1 -1
  33. package/dist/components/NodeContextMenu.d.ts +2 -96
  34. package/dist/components/NodeContextMenu.js +1 -1
  35. package/dist/components/PageEditGuardNotices.d.ts +1 -1
  36. package/dist/components/PageEditGuardNotices.js +1 -1
  37. package/dist/components/PanelToggleIcon.d.ts +1 -3
  38. package/dist/components/PanelToggleIcon.js +1 -1
  39. package/dist/components/PartSettingsPanel.d.ts +5 -0
  40. package/dist/components/PartSettingsPanel.js +1 -1
  41. package/dist/components/PhotographyField.js +1 -1
  42. package/dist/components/PreviewDeviceContext.d.ts +2 -4
  43. package/dist/components/PreviewDeviceContext.js +1 -1
  44. package/dist/components/PreviewPartsContext.d.ts +1 -3
  45. package/dist/components/PreviewPartsContext.js +1 -1
  46. package/dist/components/SearchSelectField.d.ts +3 -1
  47. package/dist/components/SearchSelectField.js +1 -1
  48. package/dist/components/SectionEditor.d.ts +2 -5
  49. package/dist/components/SectionEditor.js +1 -1
  50. package/dist/components/SectionEditorShell.d.ts +1 -1
  51. package/dist/components/SectionEditorShell.js +1 -1
  52. package/dist/components/SectionThemePicker.d.ts +3 -1
  53. package/dist/components/SectionThemePicker.js +1 -1
  54. package/dist/components/ShadowColourField.js +1 -1
  55. package/dist/components/SidePanelHead.d.ts +1 -23
  56. package/dist/components/SidePanelHead.js +1 -1
  57. package/dist/components/SideSpaceField.d.ts +0 -1
  58. package/dist/components/SideSpaceField.js +1 -1
  59. package/dist/components/SiteEditorProvider.d.ts +3 -10
  60. package/dist/components/SiteEditorProvider.js +1 -1
  61. package/dist/components/SiteWidthField.d.ts +0 -1
  62. package/dist/components/SiteWidthField.js +1 -1
  63. package/dist/components/SlotChildActionsContext.d.ts +2 -13
  64. package/dist/components/SlotChildActionsContext.js +1 -1
  65. package/dist/components/SocialLinksPanel.js +1 -1
  66. package/dist/components/SourceStatus.js +1 -1
  67. package/dist/components/StandaloneSectionEditor.d.ts +1 -0
  68. package/dist/components/StandaloneSectionEditor.js +1 -1
  69. package/dist/components/StorefrontDocumentContext.d.ts +2 -67
  70. package/dist/components/StorefrontDocumentContext.js +1 -1
  71. package/dist/components/StorefrontEditor.d.ts +1 -0
  72. package/dist/components/StorefrontEditor.js +1 -1
  73. package/dist/components/StorefrontEditorChrome.d.ts +1 -1
  74. package/dist/components/StorefrontEditorChrome.js +1 -1
  75. package/dist/components/StorefrontLinkField.d.ts +9 -0
  76. package/dist/components/StorefrontLinkField.js +1 -1
  77. package/dist/components/ThemeField.js +1 -1
  78. package/dist/components/TickerSettingsPanel.js +1 -1
  79. package/dist/components/UiIcon.d.ts +2 -10
  80. package/dist/components/UiIcon.js +1 -1
  81. package/dist/components/WebsiteScreenParts.d.ts +2 -0
  82. package/dist/components/WebsiteScreenParts.js +1 -0
  83. package/dist/components/WidthFollowField.js +1 -1
  84. package/dist/components/panel-widths.d.ts +2 -12
  85. package/dist/components/panel-widths.js +1 -1
  86. package/dist/components/storefront-editor.css +125 -986
  87. package/dist/components/useFooterFocus.d.ts +2 -0
  88. package/dist/components/useFooterFocus.js +1 -0
  89. package/dist/components/useLocationsTree.d.ts +6 -0
  90. package/dist/components/useLocationsTree.js +1 -0
  91. package/dist/components/usePartBridge.d.ts +1 -9
  92. package/dist/components/usePartBridge.js +1 -1
  93. package/dist/components/usePinnedChromeSeed.d.ts +2 -0
  94. package/dist/components/usePinnedChromeSeed.js +1 -0
  95. package/dist/components/useSocialSettings.js +1 -1
  96. package/dist/components/useStorefrontBlogPosts.js +1 -1
  97. package/dist/lib/client-only.d.ts +1 -0
  98. package/dist/lib/client-only.js +1 -0
  99. package/dist/lib/content/view-tiers.d.ts +2 -6
  100. package/dist/lib/content/view-tiers.js +1 -1
  101. package/dist/lib/editor-admin-bridge.d.ts +2 -29
  102. package/dist/lib/editor-admin-bridge.js +1 -1
  103. package/dist/lib/editor-backend-error.d.ts +2 -0
  104. package/dist/lib/editor-backend-error.js +1 -0
  105. package/dist/lib/editor-blocks.d.ts +2 -2
  106. package/dist/lib/editor-chrome.d.ts +2 -52
  107. package/dist/lib/editor-chrome.js +1 -1
  108. package/dist/lib/editor-document-adapter.d.ts +3 -51
  109. package/dist/lib/editor-document-adapter.js +1 -1
  110. package/dist/lib/editor-document-addressing.d.ts +2 -0
  111. package/dist/lib/editor-document-addressing.js +1 -0
  112. package/dist/lib/editor-document-contract.d.ts +1 -0
  113. package/dist/lib/editor-document-contract.js +0 -0
  114. package/dist/lib/editor-document-hooks.d.ts +1 -15
  115. package/dist/lib/editor-document-switch.d.ts +2 -0
  116. package/dist/lib/editor-document-switch.js +1 -0
  117. package/dist/lib/editor-failure.d.ts +1 -4
  118. package/dist/lib/editor-failure.js +1 -1
  119. package/dist/lib/editor-host-inbound.d.ts +1 -1
  120. package/dist/lib/editor-host-inbound.js +1 -1
  121. package/dist/lib/editor-host.d.ts +2 -135
  122. package/dist/lib/editor-host.js +1 -1
  123. package/dist/lib/editor-key-scope.d.ts +1 -3
  124. package/dist/lib/editor-key-scope.js +1 -1
  125. package/dist/lib/editor-load-error.d.ts +1 -4
  126. package/dist/lib/editor-load-error.js +1 -1
  127. package/dist/lib/editor-media-panel.d.ts +2 -23
  128. package/dist/lib/editor-media-panel.js +1 -1
  129. package/dist/lib/editor-media-picker.d.ts +2 -12
  130. package/dist/lib/editor-media-picker.js +1 -1
  131. package/dist/lib/editor-page-lock.d.ts +1 -1
  132. package/dist/lib/editor-page-lock.js +1 -1
  133. package/dist/lib/editor-screen.d.ts +2 -0
  134. package/dist/lib/editor-screen.js +1 -0
  135. package/dist/lib/editor-section-templates.d.ts +1 -2
  136. package/dist/lib/editor-section-templates.js +1 -1
  137. package/dist/lib/editor-session-context.d.ts +1 -7
  138. package/dist/lib/editor-session-context.js +1 -1
  139. package/dist/lib/editor-session.d.ts +2 -45
  140. package/dist/lib/editor-session.js +1 -1
  141. package/dist/lib/editor-site-slug.js +1 -1
  142. package/dist/lib/editor-theme.d.ts +1 -1
  143. package/dist/lib/editor-theme.js +1 -1
  144. package/dist/lib/hero-arrows.d.ts +1 -1
  145. package/dist/lib/links/link-filters.d.ts +1 -0
  146. package/dist/lib/links/link-filters.js +0 -0
  147. package/dist/lib/links/link-picker-setup.d.ts +29 -0
  148. package/dist/lib/links/link-picker-setup.js +1 -0
  149. package/dist/lib/puck/ColourControl.d.ts +4 -1
  150. package/dist/lib/puck/ColourControl.js +1 -1
  151. package/dist/lib/puck/add-palette.d.ts +3 -9
  152. package/dist/lib/puck/add-palette.js +1 -1
  153. package/dist/lib/puck/add-target-types.d.ts +1 -0
  154. package/dist/lib/puck/add-target-types.js +0 -0
  155. package/dist/lib/puck/add-target.d.ts +2 -9
  156. package/dist/lib/puck/block-choice.d.ts +2 -0
  157. package/dist/lib/puck/block-choice.js +1 -0
  158. package/dist/lib/puck/block-offer.js +1 -1
  159. package/dist/lib/puck/block-types-in.d.ts +1 -1
  160. package/dist/lib/puck/block-types-in.js +1 -1
  161. package/dist/lib/puck/blocks/general/index.d.ts +2 -2
  162. package/dist/lib/puck/content-tree.d.ts +2 -43
  163. package/dist/lib/puck/content-tree.js +1 -1
  164. package/dist/lib/puck/controls.d.ts +11 -22
  165. package/dist/lib/puck/controls.js +1 -1
  166. package/dist/lib/puck/device-fields.d.ts +2 -24
  167. package/dist/lib/puck/device-fields.js +1 -1
  168. package/dist/lib/puck/field-buckets.d.ts +2 -0
  169. package/dist/lib/puck/field-buckets.js +1 -0
  170. package/dist/lib/puck/field-groups.d.ts +3 -3
  171. package/dist/lib/puck/field-groups.js +1 -1
  172. package/dist/lib/puck/field-markers.d.ts +2 -16
  173. package/dist/lib/puck/field-markers.js +1 -1
  174. package/dist/lib/puck/footer-block-row-name.d.ts +4 -0
  175. package/dist/lib/puck/footer-block-row-name.js +1 -0
  176. package/dist/lib/puck/footer-blocks.d.ts +2 -10
  177. package/dist/lib/puck/footer-blocks.js +1 -1
  178. package/dist/lib/puck/hidable.d.ts +2 -9
  179. package/dist/lib/puck/hidable.js +1 -1
  180. package/dist/lib/puck/palette-sections.d.ts +2 -0
  181. package/dist/lib/puck/palette-sections.js +1 -0
  182. package/dist/lib/puck/panel-fields.d.ts +2 -12
  183. package/dist/lib/puck/panel-fields.js +1 -1
  184. package/dist/lib/puck/panel-no-control-mark.d.ts +2 -7
  185. package/dist/lib/puck/panel-no-control-mark.js +1 -1
  186. package/dist/lib/puck/part-id.d.ts +1 -0
  187. package/dist/lib/puck/part-id.js +1 -0
  188. package/dist/lib/puck/pinned-seed-gate.d.ts +2 -12
  189. package/dist/lib/puck/pinned-seed-gate.js +1 -1
  190. package/dist/lib/puck/preview-click.d.ts +1 -2
  191. package/dist/lib/puck/preview-click.js +1 -1
  192. package/dist/lib/puck/preview-dom.d.ts +1 -6
  193. package/dist/lib/puck/preview-dom.js +1 -1
  194. package/dist/lib/puck/preview-events.d.ts +2 -0
  195. package/dist/lib/puck/preview-events.js +1 -0
  196. package/dist/lib/puck/preview-selection-context.d.ts +2 -19
  197. package/dist/lib/puck/preview-selection-context.js +1 -1
  198. package/dist/lib/puck/section-doc.d.ts +1 -5
  199. package/dist/lib/puck/section-doc.js +1 -1
  200. package/dist/lib/puck/section-groups.d.ts +1 -1
  201. package/dist/lib/puck/slot-child-name.d.ts +2 -8
  202. package/dist/lib/puck/slot-child-name.js +1 -1
  203. package/dist/lib/puck/slot-heal.d.ts +1 -2
  204. package/dist/lib/puck/slot-heal.js +1 -1
  205. package/dist/lib/puck/slot-section-spec.d.ts +1 -0
  206. package/dist/lib/puck/slot-section-spec.js +0 -0
  207. package/dist/lib/puck/slot-specs.d.ts +2 -13
  208. package/dist/lib/puck/style-clipboard.d.ts +1 -19
  209. package/dist/lib/puck/style-clipboard.js +1 -1
  210. package/dist/lib/puck/text-control-kinds.d.ts +2 -13
  211. package/dist/lib/puck/text-control-kinds.js +1 -1
  212. package/dist/lib/puck/text-parts.d.ts +2 -5
  213. package/dist/lib/puck/text-parts.js +1 -1
  214. package/dist/lib/puck/tree-reveal.d.ts +1 -11
  215. package/dist/lib/puck/tree-reveal.js +1 -1
  216. package/dist/lib/puck/use-section-ops.d.ts +2 -25
  217. package/dist/lib/puck/use-section-ops.js +1 -1
  218. package/dist/lib/reel.d.ts +1 -1
  219. package/dist/lib/section-template-types.d.ts +1 -21
  220. package/dist/lib/sections/new-section-node.d.ts +2 -0
  221. package/dist/lib/sections/new-section-node.js +1 -0
  222. package/dist/lib/source-rules/accent-token-name.d.ts +20 -0
  223. package/dist/lib/source-rules/accent-token-name.js +4 -0
  224. package/dist/lib/source-rules/button-corners.d.ts +13 -0
  225. package/dist/lib/source-rules/button-corners.js +2 -0
  226. package/dist/lib/source-rules/editor-chrome-note.d.ts +16 -0
  227. package/dist/lib/source-rules/editor-chrome-note.js +13 -0
  228. package/dist/lib/source-rules/editor-context-menu.d.ts +5 -0
  229. package/dist/lib/source-rules/editor-context-menu.js +4 -0
  230. package/dist/lib/source-rules/editor-puck-drag-off.d.ts +8 -0
  231. package/dist/lib/source-rules/editor-puck-drag-off.js +4 -0
  232. package/dist/lib/source-rules/efficient-easel-version.d.ts +9 -0
  233. package/dist/lib/source-rules/efficient-easel-version.js +2 -0
  234. package/dist/lib/source-rules/every-button-follows-the-button-colour.d.ts +12 -0
  235. package/dist/lib/source-rules/every-button-follows-the-button-colour.js +7 -0
  236. package/dist/lib/source-rules/flat-theme-palette.d.ts +10 -0
  237. package/dist/lib/source-rules/flat-theme-palette.js +8 -0
  238. package/dist/lib/source-rules/full-width-means-full.d.ts +8 -0
  239. package/dist/lib/source-rules/full-width-means-full.js +2 -0
  240. package/dist/lib/source-rules/heading-ceiling-sweep.d.ts +11 -0
  241. package/dist/lib/source-rules/heading-ceiling-sweep.js +8 -0
  242. package/dist/lib/source-rules/label-hints.d.ts +7 -0
  243. package/dist/lib/source-rules/label-hints.js +5 -0
  244. package/dist/lib/source-rules/label-vocabulary.d.ts +14 -0
  245. package/dist/lib/source-rules/label-vocabulary.js +5 -0
  246. package/dist/lib/source-rules/mirrored-rows-agree.d.ts +19 -0
  247. package/dist/lib/source-rules/mirrored-rows-agree.js +10 -0
  248. package/dist/lib/source-rules/no-comment-in-jsx.d.ts +9 -0
  249. package/dist/lib/source-rules/no-comment-in-jsx.js +7 -0
  250. package/dist/lib/source-rules/no-glyph-rows.d.ts +15 -0
  251. package/dist/lib/source-rules/no-glyph-rows.js +4 -0
  252. package/dist/lib/source-rules/one-colour-control.d.ts +7 -0
  253. package/dist/lib/source-rules/one-colour-control.js +2 -0
  254. package/dist/lib/source-rules/one-dropdown.d.ts +10 -0
  255. package/dist/lib/source-rules/one-dropdown.js +4 -0
  256. package/dist/lib/source-rules/one-editable-list.d.ts +16 -0
  257. package/dist/lib/source-rules/one-editable-list.js +6 -0
  258. package/dist/lib/source-rules/one-editor-list.d.ts +7 -0
  259. package/dist/lib/source-rules/one-editor-list.js +3 -0
  260. package/dist/lib/source-rules/one-right-click.d.ts +10 -0
  261. package/dist/lib/source-rules/one-right-click.js +2 -0
  262. package/dist/lib/source-rules/one-switch.d.ts +9 -0
  263. package/dist/lib/source-rules/one-switch.js +7 -0
  264. package/dist/lib/source-rules/one-up-level-link.d.ts +16 -0
  265. package/dist/lib/source-rules/one-up-level-link.js +18 -0
  266. package/dist/lib/source-rules/panel-colour-tokens.d.ts +48 -0
  267. package/dist/lib/source-rules/panel-colour-tokens.js +20 -0
  268. package/dist/lib/source-rules/panel-no-divider-lines.d.ts +14 -0
  269. package/dist/lib/source-rules/panel-no-divider-lines.js +10 -0
  270. package/dist/lib/source-rules/panel-one-arrow.d.ts +21 -0
  271. package/dist/lib/source-rules/panel-one-arrow.js +1 -0
  272. package/dist/lib/source-rules/panel-one-hover.d.ts +8 -0
  273. package/dist/lib/source-rules/panel-one-hover.js +2 -0
  274. package/dist/lib/source-rules/panel-rows-use-the-shared-row.d.ts +23 -0
  275. package/dist/lib/source-rules/panel-rows-use-the-shared-row.js +22 -0
  276. package/dist/lib/source-rules/part-slider-fills-row.d.ts +11 -0
  277. package/dist/lib/source-rules/part-slider-fills-row.js +29 -0
  278. package/dist/lib/source-rules/part-style-naming.d.ts +10 -0
  279. package/dist/lib/source-rules/part-style-naming.js +2 -0
  280. package/dist/lib/source-rules/puck-document-surfaces.d.ts +16 -0
  281. package/dist/lib/source-rules/puck-document-surfaces.js +8 -0
  282. package/dist/lib/source-rules/reduced-motion.d.ts +26 -0
  283. package/dist/lib/source-rules/reduced-motion.js +9 -0
  284. package/dist/lib/source-rules/route-content-width.d.ts +22 -0
  285. package/dist/lib/source-rules/route-content-width.js +5 -0
  286. package/dist/lib/source-rules/rule.d.ts +21 -0
  287. package/dist/lib/source-rules/rule.js +1 -0
  288. package/dist/lib/source-rules/section-theme-preview.d.ts +9 -0
  289. package/dist/lib/source-rules/section-theme-preview.js +8 -0
  290. package/dist/lib/source-rules/site-gutter.d.ts +6 -0
  291. package/dist/lib/source-rules/site-gutter.js +4 -0
  292. package/dist/lib/source-rules/site-square-by-default.d.ts +17 -0
  293. package/dist/lib/source-rules/site-square-by-default.js +3 -0
  294. package/dist/lib/source-rules/site-width.d.ts +11 -0
  295. package/dist/lib/source-rules/site-width.js +7 -0
  296. package/dist/lib/source-rules/size-token-paints.d.ts +8 -0
  297. package/dist/lib/source-rules/size-token-paints.js +11 -0
  298. package/dist/lib/source-rules/social-icons-import.d.ts +6 -0
  299. package/dist/lib/source-rules/social-icons-import.js +6 -0
  300. package/dist/lib/source-rules/source-status-is-shared.d.ts +7 -0
  301. package/dist/lib/source-rules/source-status-is-shared.js +1 -0
  302. package/dist/lib/source-rules/style-face-matches-size.d.ts +10 -0
  303. package/dist/lib/source-rules/style-face-matches-size.js +4 -0
  304. package/dist/lib/source-rules/support/accent-rename-bytes.d.ts +5 -0
  305. package/dist/lib/source-rules/support/accent-rename-bytes.js +1 -0
  306. package/dist/lib/source-rules/support/css-box-model.d.ts +5 -0
  307. package/dist/lib/source-rules/support/css-box-model.js +1 -0
  308. package/dist/lib/source-rules/support/css-length.d.ts +2 -0
  309. package/dist/lib/source-rules/support/css-length.js +1 -0
  310. package/dist/lib/source-rules/support/css-rules.d.ts +12 -0
  311. package/dist/lib/source-rules/support/css-rules.js +1 -0
  312. package/dist/lib/source-rules/support/css-source.d.ts +2 -0
  313. package/dist/lib/source-rules/support/css-source.js +3 -0
  314. package/dist/lib/source-rules/support/label-extraction.d.ts +14 -0
  315. package/dist/lib/source-rules/support/label-extraction.js +5 -0
  316. package/dist/lib/source-rules/support/panel-select-cascade.d.ts +72 -0
  317. package/dist/lib/source-rules/support/panel-select-cascade.js +2 -0
  318. package/dist/lib/source-rules/support/part-slider-call-sites.d.ts +9 -0
  319. package/dist/lib/source-rules/support/part-slider-call-sites.js +17 -0
  320. package/dist/lib/source-rules/support/registry-source.d.ts +14 -0
  321. package/dist/lib/source-rules/support/registry-source.js +3 -0
  322. package/dist/lib/source-rules/support/ts-source.d.ts +2 -0
  323. package/dist/lib/source-rules/support/ts-source.js +3 -0
  324. package/dist/lib/source-rules/theme-mode-controls-gone.d.ts +10 -0
  325. package/dist/lib/source-rules/theme-mode-controls-gone.js +5 -0
  326. package/dist/lib/source-rules/upload-intake-guard.d.ts +11 -0
  327. package/dist/lib/source-rules/upload-intake-guard.js +6 -0
  328. package/dist/lib/source-rules/word-styles.d.ts +8 -0
  329. package/dist/lib/source-rules/word-styles.js +4 -0
  330. package/dist/lib/theme-row-persist.js +1 -1
  331. package/dist/lib/theme-save-message.js +1 -1
  332. package/dist/lib/web-backend.d.ts +4 -59
  333. package/dist/lib/web-backend.js +1 -1
  334. package/dist/lib/website-document-addressing.d.ts +2 -0
  335. package/dist/lib/website-document-addressing.js +1 -0
  336. package/dist/lib/website-host-inbound.d.ts +1 -0
  337. package/dist/lib/website-host-inbound.js +1 -0
  338. package/dist/lib/website-session.d.ts +5 -0
  339. package/dist/lib/website-session.js +1 -0
  340. package/package.json +15 -5
@@ -48,192 +48,6 @@
48
48
  height: 100%;
49
49
  }
50
50
 
51
- .sf-editor {
52
- /* ── Accent (efficient-shell blue) ───────────────────────────────────── */
53
- --sf-accent: var(--es-accent);
54
- --sf-accent-tint: var(--es-accent-tint);
55
- --sf-accent-tint-strong: var(--es-accent-tint-strong);
56
- --sf-accent-text: var(--es-accent-text);
57
- --sf-accent-ring: var(--es-accent-ring);
58
- --sf-accent-shadow: var(--es-accent-shadow);
59
- --sf-on-accent: var(--es-on-accent);
60
-
61
- /* ── Surfaces (cool gray ramp) ──────────────────────────────────────── */
62
- --sf-app-bg: var(--es-app-bg);
63
- --sf-preview-bg: var(--es-preview-bg);
64
- --sf-panel: var(--es-panel);
65
- --sf-raised: var(--es-raised);
66
- --sf-frame-bg: var(--es-frame-bg);
67
- --sf-hover: var(--es-hover);
68
- --sf-hatch: var(--es-hatch);
69
- --sf-addcard-veil: var(--es-addcard-veil);
70
-
71
- /* ── Fields ─────────────────────────────────────────────────────────── */
72
- --sf-field-bg: var(--es-field-bg);
73
- --sf-track-bg: var(--es-track-bg);
74
- --sf-input-border: var(--es-input-border);
75
- --sf-field-text: var(--es-field-text);
76
- --sf-field-placeholder: var(--es-field-placeholder);
77
- --sf-knob: var(--es-knob);
78
-
79
- /* ── Text ───────────────────────────────────────────────────────────── */
80
- --sf-text: var(--es-text);
81
- --sf-text-strong: var(--es-text-strong);
82
- --sf-text-secondary: var(--es-text-secondary);
83
- --sf-muted: var(--es-muted);
84
- --sf-icon: var(--es-icon);
85
- --sf-disabled: var(--es-disabled);
86
-
87
- /* ── Lines / chips / buttons ────────────────────────────────────────── */
88
- --sf-divider: var(--es-divider);
89
- --sf-line: var(--es-line);
90
- --sf-btn-border: var(--es-btn-border);
91
- --sf-btn-text: var(--es-btn-text);
92
- --sf-chip-bg: var(--es-chip-bg);
93
- --sf-chip-fg: var(--es-chip-fg);
94
-
95
- /* ── Named chrome literals ──────────────────────────────────────────── */
96
- --sf-device-border: var(--es-device-border);
97
- --sf-toast-bg: var(--es-toast-bg);
98
- --sf-scrollbar: var(--es-scrollbar);
99
- --sf-scrollbar-hover: var(--es-scrollbar-hover);
100
-
101
- /* ── Danger / warning / success (shell red / amber / green) ─────────── */
102
- --sf-danger: var(--es-danger);
103
- --sf-danger-strong: var(--es-danger-strong);
104
- --sf-danger-tint: var(--es-danger-tint);
105
- --sf-warning: var(--es-warning);
106
- --sf-preview-tint: var(--es-preview-tint);
107
-
108
- /* ── Radii / shape (tighter, shell-like) ────────────────────────────── */
109
- /*
110
- * ┌─ FLAT CHROME (card 66161) — these three do NOT alias the shell. ─────────
111
- * │
112
- * │ The panels used to be floating cards: rounded, drop-shadowed, sitting on
113
- * │ the grey app background with a 10px gap between each pair and a 10px frame
114
- * │ padding around the lot. The owner asked for lines instead. On a 1280px
115
- * │ laptop that gave the website preview 50px back — 576px to 626px — because
116
- * │ gaps, corners and shadows hold nothing. No panel got narrower and no
117
- * │ vertical measurement changed.
118
- * │
119
- * │ WHY THESE STOPPED ALIASING, AND EXACTLY WHAT ENDS IT
120
- * │
121
- * │ The `--sf-*` block exists exactly so the shop can pick its own values off
122
- * │ the shared `--es-*` layer. Flat is the SHOP's decision, not the shell's.
123
- * │
124
- * │ Note the ORIGINAL reason is already gone, so do not go looking for it:
125
- * │ when this was written, card 66160 was mid-release on editor-shell and two
126
- * │ windows bumping one package version would have collided. That released as
127
- * │ `editor-shell@0.13.0` the same day, and the shop still declares `^0.12.0`.
128
- * │ The values stayed local anyway, for a reason that has nothing to do with
129
- * │ release timing:
130
- * │
131
- * │ THE OWNER DECIDED FLAT FOR THE STOREFRONT EDITOR ONLY.
132
- * │
133
- * │ Putting these in the shell's defaults would make the campaign editor flat
134
- * │ too, which nobody has asked for. The campaign editor is also still pinned
135
- * │ to `editor-shell@0.2.0` and cannot receive shell changes at all until it
136
- * │ comes off that pin.
137
- * │
138
- * │ So this is NOT a half-finished alias block, and it is NOT drift. Do not
139
- * │ "fix" these back into `var(--es-…)`.
140
- * │
141
- * │ IT ENDS WHEN BOTH ARE TRUE:
142
- * │ 1. the campaign editor comes off its `editor-shell@0.2.0` pin, AND
143
- * │ 2. the owner decides the campaign editor should go flat as well.
144
- * │ Then promote the three values into the shell defaults, delete these three
145
- * │ lines, and drop the matching waiver in `scripts/test-inspector-inherit.tsx`
146
- * │ in the same change. Either one alone is not enough.
147
- * │
148
- * │ `scripts/test-editor-flat-chrome.ts` fails if they are re-aliased.
149
- * └──────────────────────────────────────────────────────────────────────────
150
- */
151
- --sf-panel-radius: 0;
152
- --sf-row-radius: var(--es-row-radius);
153
- --sf-field-radius: var(--es-field-radius);
154
- /* The editor "frame" gap: the space between the panels and the preview, and
155
- the padding around the whole framed area (top/bottom + outer left/right).
156
- One token so the frame tightens in ONE place — .sf-body drives it, and the
157
- Add-section picker + section-editor top strip track it.
158
- Flat since 66161 (see the note above). It MUST stay a length rather than a
159
- bare `0`: it is spent inside calc() below and in the picker's width, and
160
- `calc(0 + 46px)` is invalid CSS — the whole declaration would be dropped and
161
- the left grip would land at the frame's edge instead of on its seam. */
162
- --sf-panel-gap: 0px;
163
- /* Side-panel widths ride in as editor-shell's --es-left-w / --es-right-w, set
164
- on the editor ROOT by BOTH editors through components/panel-widths.ts (the
165
- page chrome per drag; the standalone section editor at the fixed defaults).
166
- The literal widths deliberately do NOT live here — see that module. */
167
- /* Top-bar height. ONE source for both the chrome that draws it AND the
168
- working-area overlay (the Add-section picker) that must clear
169
- it to sit inside the frame, not cover it.
170
- Storefront-LOCAL geometry: the top bar is this editor's own chrome
171
- dimension, not part of the shared token layer. */
172
- --sf-topbar-h: 52px;
173
- /* There is no `--sf-rail-w`. Card 66198 moved the icon rail into the top bar,
174
- where editor-shell's row variant is `width: auto` — the rail is as wide as
175
- its buttons, so no element has a width for that token to name. It was NOT
176
- set to 0: a 0 would leave every calc() below arithmetically correct while
177
- keeping a token still aimed at the content column, so restoring a
178
- non-zero value would move it. Deleting it means the
179
- next person has to write the term back on purpose.
180
-
181
- Where the content column BEGINS. Now the frame padding and nothing else:
182
- the left panel is `.sf-body`'s first in-flow child, so its box starts at the
183
- padding edge. Everything drawn against that box — the left resize grip — and
184
- every overlay framed in the working area reads this one name.
185
-
186
- Card 66149 is why the name exists: the left grip spent
187
- `--sf-panel-gap + --es-left-w` while a rail really was in front of the
188
- panel, and landed 56px inside it where no merchant could reach it. This
189
- card is the mirror image — the danger now is a pin that keeps PAYING for a
190
- rail nobody renders — and the guard is the same, because
191
- `scripts/test-editor-rail-in-topbar.ts` evaluates this at probe values with
192
- no `--sf-rail-w` in the table at all: a restored rail term throws by name
193
- rather than quietly reserving 46px of website.
194
-
195
- Still written as `var(--sf-panel-gap)` and not a bare `0`, for the reason
196
- given at that token above: it is spent inside calc() and `calc(0 + 288px)`
197
- is invalid CSS — the whole declaration would be dropped and the left grip
198
- would land at the frame's edge instead of on its seam. */
199
- --sf-content-x: var(--sf-panel-gap);
200
- /* Flat since 66161 — see the note at --sf-panel-radius above. */
201
- --sf-panel-shadow: none;
202
- --sf-font: var(--es-font);
203
-
204
- /* No `--puck-*` names here. Puck read its `--puck-color-azure-*` ramp and
205
- `--puck-font-family` from editor-shell's shell.css on this same root, and
206
- they were deliberately never re-declared in this file — one blue is the
207
- point. Puck and those names left with blueprint 6.1/6.3; the blue is the
208
- `--es-*` set in efficient-easel/shell.css. */
209
-
210
- /*
211
- * Fill the iframe viewport. `100dvh` resolves against the viewport directly,
212
- * so the editor always fills the embedding iframe with no flex/min-height
213
- * dependency (percentage heights don't resolve against the app shell's
214
- * min-height, which otherwise left a gap below the editor). Mounted inside
215
- * another app's window it fills that window instead — `.sf-embedded`, below.
216
- */
217
- width: 100%;
218
- height: 100vh;
219
- height: 100dvh;
220
- display: flex;
221
- flex-direction: column;
222
- overflow: hidden;
223
- position: relative; /* positioning context for the floating add-section modal + toast */
224
- background: var(--sf-app-bg);
225
- color: var(--sf-text);
226
- font-family: var(--sf-font);
227
- font-size: 14px;
228
- -webkit-font-smoothing: antialiased;
229
- }
230
-
231
- .sf-editor *,
232
- .sf-editor *::before,
233
- .sf-editor *::after {
234
- box-sizing: border-box;
235
- }
236
-
237
51
  /* Visually-hidden, screen-reader-only (e.g. the live search-result count). */
238
52
  .sf-sr-only {
239
53
  position: absolute;
@@ -247,25 +61,6 @@
247
61
  white-space: nowrap;
248
62
  }
249
63
 
250
- /* Scrollbars inside the editor panels */
251
- .sf-scroll::-webkit-scrollbar {
252
- width: 11px;
253
- height: 11px;
254
- }
255
- .sf-scroll::-webkit-scrollbar-thumb {
256
- background: var(--sf-scrollbar);
257
- border-radius: 8px;
258
- border: 3px solid transparent;
259
- background-clip: content-box;
260
- }
261
- .sf-scroll::-webkit-scrollbar-thumb:hover {
262
- background: var(--sf-scrollbar-hover);
263
- background-clip: content-box;
264
- }
265
- .sf-scroll::-webkit-scrollbar-track {
266
- background: transparent;
267
- }
268
-
269
64
  /* ── Top bar ─────────────────────────────────────────────────────────────
270
65
  The bar, its clusters, the icon buttons, the divider, the device switch and
271
66
  the ghost / primary buttons are editor-shell's (efficient-easel/chrome.css,
@@ -290,69 +85,7 @@
290
85
  background: var(--sf-hover);
291
86
  }
292
87
 
293
- /* Standalone section editor — a slim top strip carrying the "Preview mode"
294
- switch (left) and the autosave pill (right), above the reused sf-body
295
- (canvas + inspector). */
296
- .sf-section-bar {
297
- flex: none;
298
- display: flex;
299
- align-items: center;
300
- justify-content: space-between;
301
- gap: 16px;
302
- /* PINNED at 10px by card 66161, which took `--sf-panel-gap` to 0 to flatten
303
- the PAGE chrome. This strip belongs to the standalone SECTION editor — a
304
- different surface — and the 10px here is real padding holding the
305
- "Preview mode" switch and the autosave pill off the window edge, not a gap
306
- that existed so a card could float. Following the token to 0 would have
307
- changed a surface this card was never about, so it is spelled out instead.
308
- Deliberately its own literal rather than a shared "inset" token: one token
309
- quietly deciding the padding of a dialog AND a different editor's strip is
310
- the coupling that made this a question at all. Whether this strip should go
311
- flat too is its own decision, on its own card. */
312
- padding: 8px 10px;
313
- }
314
-
315
- /* The save pill (dot, ring, words, the autosave switch around it) is
316
- editor-shell's `.es-savestate` (efficient-easel/chrome.css), lifted from this
317
- sheet with its card-66103 quiet state and the countdown ring (redesign 2a). */
318
-
319
88
  /* ── Body / floating panels ───────────────────────────────────────────── */
320
- .sf-body {
321
- flex: 1;
322
- display: flex;
323
- gap: var(--sf-panel-gap);
324
- padding: var(--sf-panel-gap);
325
- min-height: 0;
326
- /* Positioning context for the absolutely-placed resize grips (editor-shell's .es-resizer),
327
- which the chrome pins over each panel↔preview seam. */
328
- position: relative;
329
- }
330
- /* THE SIDE PANELS AND THEIR GRIPS ARE editor-shell's (efficient-easel/chrome.css):
331
- `.es-sidepanel` — flush, a hairline on the SEAM side only (card 66161: draw the
332
- seams, leave the outer edges alone), the size-container context every
333
- `@container` rule in this sheet asks (card 66212) — and `.es-resizer`, pinned
334
- over each seam from `--es-left-w` / `--es-right-w`, with the drag's
335
- `body.es-col-resizing`. Lifted from this sheet (redesign 2a). The panels keep
336
- `.sf-panel` / `.sf-panel--left|right` as well, which is what this sheet's own
337
- descendant rules (`.sf-panel--right .sf-insp-body`, …) hang on. */
338
- .sf-panel-head {
339
- display: flex;
340
- align-items: center;
341
- justify-content: space-between;
342
- padding: 13px 14px 11px;
343
- flex: none;
344
- }
345
- /* A panel's own name. It is an `h2` in the views that own their title
346
- (StylesPanel), so the rule states the three properties a heading element
347
- would otherwise inherit from the UA sheet — `margin` above all, which is
348
- `0.83em 0` on an h2 and would push the whole head open. The `--btn` variant
349
- below re-states its own margin and wins by source order. */
350
- .sf-panel-title {
351
- font-size: 13px;
352
- font-weight: 600;
353
- color: var(--sf-text);
354
- margin: 0;
355
- }
356
89
  /* The panel's title and, beside it, WHICH SITE it is styling (card 66167).
357
90
  `min-width: 0` on both so the name — which is a merchant's own words and can
358
91
  be any length — is what gives way when the panel is dragged narrow, rather
@@ -382,31 +115,6 @@
382
115
  content: "·";
383
116
  margin-right: 6px;
384
117
  }
385
- /* In the standalone section editor the title doubles as the SELECT-ROOT control
386
- (clicking the section name selects the section node → its section-level
387
- fields), so it renders as a <button>. Reset the UA button chrome back to the
388
- heading it replaces, then add row-style hover / selected affordance so it
389
- reads as interactive and shows when the root is the active selection. */
390
- .sf-panel-title--btn {
391
- appearance: none;
392
- border: 0;
393
- background: transparent;
394
- font-family: inherit;
395
- cursor: pointer;
396
- text-align: left;
397
- padding: 5px 8px;
398
- margin: -5px -8px;
399
- border-radius: var(--sf-row-radius);
400
- transition: background 0.12s;
401
- }
402
- .sf-panel-title--btn:hover {
403
- background: var(--sf-hover);
404
- }
405
- .sf-panel-title--btn.is-selected {
406
- color: var(--sf-accent-text);
407
- background: var(--sf-accent-tint);
408
- box-shadow: inset 2px 0 0 var(--sf-accent);
409
- }
410
118
  .sf-x {
411
119
  width: 24px;
412
120
  height: 24px;
@@ -425,51 +133,6 @@
425
133
  }
426
134
 
427
135
  /* ── Left panel: section tree (wraps Puck.Outline) ────────────────────── */
428
- .sf-tree {
429
- flex: 1;
430
- overflow-y: auto;
431
- /* THE TWO SIDES PAY FOR DIFFERENT THINGS, and they always did.
432
- LEFT 8 — the inset a rounded row needs. The reason WAS "a rounded bar
433
- cannot bleed to a panel edge"; the bars are gone (One Ladder, 2026-09-04)
434
- and the reason survives them unchanged, because every row in the tree is
435
- still a rounded control and an inset control is simply a control.
436
- RIGHT 11 — this element also carries `.sf-scroll`, and
437
- `.sf-scroll::-webkit-scrollbar` is `width: 11px` of REAL, space-taking
438
- gutter, not an overlay. This tree scrolls on almost every page. What used
439
- to live at the row's right end was the caret; it is the count pill now,
440
- and a count sitting under a scrollbar thumb is the same defect wearing a
441
- different glyph.
442
- Everything inside still starts on the same 11px text column, which is what
443
- keeps the words aligned down the panel. */
444
- padding: 0 11px 10px 8px;
445
-
446
- /* ── THE TREE'S RHYTHM — the shell's names, the tree's own density ─────────
447
- `efficient-easel` 0.19.0 stopped hiding its spacing inside literals and gave
448
- each rhythm a name (card 66228, `efficient-easel/panel.css`). The tree reads
449
- those names. It does NOT read the panel's VALUES and does not compute them:
450
-
451
- · Copying 28/7 in would be a second source of truth for numbers the shell
452
- is already the source of — the one rule that sits above a green suite.
453
- · A scale FACTOR off them would be a lie. Lewis picked the tree's two
454
- numbers by eye on 2026-08-31 (`mockups/layers-panel-v9-left-only-and-drag.html`
455
- and `editor-add-and-context-v1.html`): 10 between bars, 6 between rows.
456
- Against the panel that is 10/36 = 0.28 and 6/28 = 0.21 — TWO factors,
457
- not one, so there is no single number to scale by. `panel.css` already
458
- refuses this shape for the same reason, in its own words: 28 was
459
- measured, it is not "10 plus 18".
460
-
461
- So what is shared is the VOCABULARY and the RULE, not the values: `-group`
462
- means "a heading, from what is above it" in both panels and `-between`
463
- means "one row, from the next" in both, each stated once at its own
464
- density. A tree at the panel's 28px a row would scroll forever.
465
-
466
- Declared HERE rather than on `.sf-editor` deliberately — the settings panel
467
- is a sibling reading the same names from the shell, and an override at the
468
- editor root would re-rhythm IT too. `scripts/test-tree-rhythm-tokens.ts` is
469
- the gate. */
470
- --es-rhythm-group: 10px;
471
- --es-rhythm-between: 6px;
472
- }
473
136
 
474
137
  /* EVERY SEAM THE TREE STACKS, and no bare number among them.
475
138
  The pairs are spelled out rather than written `> * + *` because the tree
@@ -530,36 +193,6 @@
530
193
  color: var(--sf-accent-text);
531
194
  font-weight: 600;
532
195
  }
533
- .sf-chip {
534
- width: 18px;
535
- height: 18px;
536
- border-radius: 5px;
537
- display: flex;
538
- align-items: center;
539
- justify-content: center;
540
- font-size: 12px;
541
- flex: none;
542
- /* NO GROUND AND NO RULE. Every row carries a glyph now, so a filled tile on
543
- each one is 40 tiles down a page — the chip was a way of picking the icon
544
- row out of a list that mostly had none, and there is no such list any more.
545
- The glyph itself is the mark; `--sf-icon` is the same grey the top bar's
546
- icons wear. */
547
- background: transparent;
548
- color: var(--sf-icon);
549
- }
550
- .sf-row-name {
551
- flex: 1;
552
- /* One size at every depth — the tree's three (11 / 10.5 / 11.5) were a second
553
- way of saying the indent already says. 12px/500 is `.es-group-head`'s size
554
- at a row's weight, so the tree and the inspector's headings agree on how big
555
- a name in this editor is. */
556
- font-size: 12px;
557
- font-weight: 500;
558
- color: var(--sf-text);
559
- white-space: nowrap;
560
- overflow: hidden;
561
- text-overflow: ellipsis;
562
- }
563
196
  /* `.sf-add-section` WAS HERE, and it is gone on purpose (card 66228). Lewis
564
197
  ruled on 2026-08-31 that ONE `+` in the top bar replaces every other add door
565
198
  — the drawing is `editor-add-and-context-v1.html` in the SHARED `mockups/`
@@ -672,119 +305,7 @@
672
305
  gap: var(--es-rhythm-between);
673
306
  }
674
307
 
675
- /* THE TWO BAR TIERS ARE GONE (One Ladder, 2026-09-04).
676
-
677
- `.sf-row--bar` (a 1px outline, 11px/600) and `.sf-row--bar-nested` (a
678
- `color-mix` ground one shade off the panel, 10.5px/600) were how this tree
679
- said "a level". Both are deleted, and with them the whole question of which
680
- tier a row belongs to.
681
-
682
- THE NESTED BAR IS THE ONE WORTH RECORDING. Its own note said it: at ~2% off
683
- white the fill alone disappears on a cheap panel, so it needed a hairline
684
- beside the fill to survive. A difference that has to be said twice to be seen
685
- once is not carrying its weight — and the indent and the subtree's guide line
686
- were already saying the same thing, legibly, for free.
687
-
688
- What replaced them is `.sf-subtree` below: an indent and a 1px rule. Nothing
689
- in this tree is told apart by a fill any more except the SELECTED row, which
690
- is the one place a fill is not competing with anything. */
691
- .sf-add-card {
692
- display: flex;
693
- align-items: center;
694
- gap: 8px;
695
- width: 100%;
696
- padding: 6px 9px;
697
- border: none;
698
- background: transparent;
699
- border-radius: 8px;
700
- cursor: pointer;
701
- color: var(--sf-accent);
702
- font-size: 12px;
703
- font-weight: 500;
704
- }
705
- .sf-add-card:hover {
706
- background: var(--sf-accent-tint);
707
- }
708
- .sf-add-card .sf-plus {
709
- width: 18px;
710
- height: 18px;
711
- border-radius: 5px;
712
- display: flex;
713
- align-items: center;
714
- justify-content: center;
715
- font-size: 13px;
716
- flex: none;
717
- background: var(--sf-accent-tint);
718
- }
719
-
720
308
  /* ── Footer "Add block" menu — heterogeneous block-type picker ──────────── */
721
- .sf-blockmenu {
722
- display: flex;
723
- flex-direction: column;
724
- gap: 1px;
725
- margin: 2px 0 4px;
726
- padding: 4px;
727
- border: 1px solid var(--sf-line);
728
- border-radius: 8px;
729
- background: var(--sf-panel);
730
- box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
731
- }
732
- .sf-blockmenu-item {
733
- display: flex;
734
- align-items: center;
735
- gap: 8px;
736
- width: 100%;
737
- padding: 7px 9px;
738
- border: none;
739
- background: transparent;
740
- border-radius: 6px;
741
- cursor: pointer;
742
- color: var(--sf-text, var(--sf-text));
743
- font-size: 12.5px;
744
- text-align: left;
745
- }
746
- .sf-blockmenu-item:hover {
747
- background: var(--sf-accent-tint);
748
- color: var(--sf-accent);
749
- }
750
-
751
- /* A group heading inside that menu — drawn only where a choice list carries
752
- groups (a Box's does; the Footer's and the Slide box's do not, and render
753
- exactly as before).
754
-
755
- ⚠️ THE SAME TYPE AS `.sf-addgroup-title` BELOW, and deliberately not a second
756
- look: that is the heading the Add-section panel puts over every one of its
757
- categories, and this menu is the OTHER door a merchant adds something
758
- through. One grammar for "these belong together" (rule zero). It is not the
759
- same CLASS because the two live in different boxes — a 4px-padded floating
760
- menu and a 20px panel column — so only the spacing differs, and it differs
761
- because the container does.
762
-
763
- `role="presentation"` on the row: it is a label, not a menuitem, and a
764
- keyboard user arrowing through the menu must not land on it. */
765
- .sf-menugroup-head {
766
- display: flex;
767
- align-items: baseline;
768
- gap: 8px;
769
- padding: 9px 9px 5px;
770
- }
771
- /* No top padding on the first heading — the menu's own 4px inset already sets
772
- it in, and a second inset would leave the first group sitting lower than the
773
- rows it names. */
774
- .sf-menugroup-head:first-child {
775
- padding-top: 4px;
776
- }
777
- .sf-menugroup-title {
778
- font-size: 11px;
779
- font-weight: 700;
780
- letter-spacing: 0.07em;
781
- text-transform: uppercase;
782
- color: var(--sf-muted);
783
- }
784
- .sf-menugroup-count {
785
- font-size: 11px;
786
- color: var(--sf-field-placeholder);
787
- }
788
309
 
789
310
  /* ── Add — a mode over the left panel (components/AddSidePanel) ────────────
790
311
  Blueprint step 3.7: the floating `.sf-picker` dialog is gone, and Add is the
@@ -792,29 +313,6 @@
792
313
  tiles are efficient-easel/drag's `AddPanel` (drag.css); a section is a CARD
793
314
  with its cover there (`.es-add-grid.is-cards`). What is the website's alone
794
315
  is the panel's inset and the Live chat row under the groups. */
795
- .sf-addside {
796
- flex: 1;
797
- min-height: 0;
798
- overflow-y: auto;
799
- padding: 0 14px 16px;
800
- }
801
- /* The hairline round a section's cover — the one the dialog's cards wore
802
- (`--sf-thumb-thumb-border`'s value). The cover box is a containing block in
803
- the engine itself since efficient-easel 0.80.1: a scene drawn to fill it
804
- painted over the whole panel before. */
805
- .sf-addside .es-add-tile-cover {
806
- border: 1px solid #edeff4;
807
- }
808
- /* The Media view's body — the HOST's library (lib/editor-media-panel), drawn
809
- in whatever the panel leaves under the head. It scrolls itself (its grid
810
- keeps its own toolbar pinned), so this box only hands it the height. */
811
- .sf-media-panel {
812
- flex: 1;
813
- min-height: 0;
814
- display: flex;
815
- flex-direction: column;
816
- overflow: hidden;
817
- }
818
316
  /* The Live chat bubble: site-wide and not a section, so a switch on a row
819
317
  rather than a tile. The name opens its settings; the switch turns it on. */
820
318
  .sf-addside-sitewide {
@@ -1123,90 +621,7 @@
1123
621
  font-size: 12.5px;
1124
622
  }
1125
623
 
1126
- /* Toast — transient confirmation (e.g. after adding a section) */
1127
- .sf-toast {
1128
- position: absolute;
1129
- left: 50%;
1130
- bottom: 34px;
1131
- transform: translateX(-50%);
1132
- z-index: 60;
1133
- display: flex;
1134
- align-items: center;
1135
- gap: 10px;
1136
- padding: 11px 17px;
1137
- border-radius: 11px;
1138
- background: var(--sf-toast-bg);
1139
- color: #fff;
1140
- font-size: 13px;
1141
- box-shadow: 0 12px 30px rgba(15, 23, 42, 0.3);
1142
- }
1143
- .sf-toast-check {
1144
- display: inline-flex;
1145
- align-items: center;
1146
- justify-content: center;
1147
- width: 18px;
1148
- height: 18px;
1149
- border-radius: 50%;
1150
- background: var(--sf-accent);
1151
- color: #fff;
1152
- font-size: 11px;
1153
- flex: none;
1154
- }
1155
- /* Error variant — same dark pill, red mark instead of the green check. */
1156
- .sf-toast--error .sf-toast-check {
1157
- background: var(--sf-danger);
1158
- }
1159
-
1160
624
  /* ── Center: device-framed preview (wraps Puck.Preview) ──────────────── */
1161
- .sf-center {
1162
- flex: 1;
1163
- min-width: 0;
1164
- min-height: 0;
1165
- background: var(--sf-preview-bg);
1166
- border-radius: var(--sf-panel-radius);
1167
- box-shadow: var(--sf-panel-shadow);
1168
- overflow: hidden;
1169
- display: flex;
1170
- /* `safe center`: centre the device sizer when it fits, but fall back to
1171
- flex-start when a zoom makes it larger than the well, so the near edge
1172
- stays reachable while the well scrolls (overflow-x set inline per-zoom). */
1173
- justify-content: safe center;
1174
- align-items: safe center;
1175
- /* No inset: the preview frame fills the well so it flows flush with the panels
1176
- at exactly the --sf-panel-gap frame gap (the flex gap between panel and this
1177
- well). Any padding here would ADD to that gap. In tablet/mobile the fixed-width
1178
- device frame still centres, showing the well's tint down its sides. */
1179
- padding: 0;
1180
- }
1181
- .sf-frame {
1182
- width: 100%;
1183
- height: 100%;
1184
- max-height: 100%;
1185
- background: var(--sf-frame-bg);
1186
- /* SQUARE (owner, 2026-10-07: "the website should not have round corners").
1187
- The desktop frame fills the well edge to edge and meets the toolbar and the
1188
- panels directly, and those have been flat since 66161 (--sf-panel-radius:
1189
- 0) — so a 10px radius here drew one rounded notch, top-left, where the
1190
- page meets the chrome, and clipped that corner of the website itself. The
1191
- tablet and phone frames below are square for the same reason (owner, the
1192
- same day): their 18px radius read as a device's edge, and it clipped all
1193
- four corners of the page inside. They are told apart from the well by their
1194
- width and their outline, not by a corner. */
1195
- border-radius: 0;
1196
- overflow: hidden;
1197
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 12px 36px rgba(0, 0, 0, 0.1);
1198
- transition: width 0.25s ease;
1199
- display: flex;
1200
- flex-direction: column;
1201
- min-height: 0;
1202
- }
1203
- /* Sizer box for the device frame: its layout size is the frame's *painted*
1204
- (scaled) size, so the .sf-center well centres it when it fits and scrolls it
1205
- when a zoom makes it larger. The frame inside is scaled from its top-left. */
1206
- .sf-frame-scaler {
1207
- flex: none;
1208
- position: relative;
1209
- }
1210
625
  .sf-frame--tablet,
1211
626
  .sf-frame--mobile {
1212
627
  /* device frames don't stretch to full width but still fill height */
@@ -1229,44 +644,6 @@
1229
644
  outline: 1px solid var(--sf-device-border);
1230
645
  outline-offset: -1px;
1231
646
  }
1232
- /* The template editor's faux browser bar (dots · page switcher · URL ·
1233
- "Preview mode" toggle) is gone: pages switch from the shared left Pages
1234
- panel, the URL is drawn by the editor WINDOW's title bar (the admin console
1235
- owns that chrome; card 66159), and Preview mode was removed — the canvas
1236
- meets the toolbar directly in both modes. */
1237
- .sf-preview-host {
1238
- flex: 1;
1239
- min-height: 0;
1240
- position: relative;
1241
- }
1242
- /* Puck.Preview fills the frame */
1243
- .sf-preview-host > div,
1244
- .sf-preview-host iframe {
1245
- width: 100% !important;
1246
- height: 100% !important;
1247
- border: 0;
1248
- }
1249
- /* …but `height: 100%` only means anything when the host's OWN height is
1250
- definite, and that depends on which shell mounted it.
1251
-
1252
- The page editor wraps the host in `.sf-frame` — a column flex the chrome
1253
- sizes in pixels (`frameStyle`/`scalerStyle` in StorefrontEditorChrome) — so
1254
- the host's `flex: 1` above resolves against a real number and the rule works.
1255
-
1256
- The SECTION editor has no device switch, so it drops the host straight into
1257
- the `.sf-center` well (SectionEditorShell). That well is a ROW flex with
1258
- `align-items: safe center`: the host is centred on the cross axis instead of
1259
- stretched, so its height stays `auto`. `height: 100%` then has no definite
1260
- containing block, the iframe falls back to its intrinsic 150px, and a
1261
- `100vh`/`h-screen` section inside the frame measures the viewport as 150px —
1262
- which is how a full-bleed Hero came out as a thin band floating mid-canvas.
1263
-
1264
- Stretching the host restores a definite height, so the frame's viewport IS
1265
- the canvas. Scoped to the direct child so the page editor, whose host is a
1266
- child of `.sf-frame`, is untouched. */
1267
- .sf-center > .sf-preview-host {
1268
- align-self: stretch;
1269
- }
1270
647
 
1271
648
  /* The Cart / Checkout surfaces are previewed in-canvas by rendering the real
1272
649
  components inside the Puck preview iframe (same-document, no nested `<iframe
@@ -1557,98 +934,6 @@
1557
934
  interactive; only the slim bands are clickable. On hover a band shows an accent
1558
935
  insertion line + a dark "Add section" pill; clicking opens the picker targeted
1559
936
  at that seam. It sits inside the scaled device frame, so it tracks the zoom. */
1560
- .sf-preview-gaps {
1561
- position: absolute;
1562
- inset: 0;
1563
- overflow: hidden;
1564
- pointer-events: none;
1565
- z-index: 6;
1566
- }
1567
- /* The full-width band only POSITIONS the affordance over a seam — it is itself
1568
- click-through (pointer-events:none) so it never steals canvas clicks / Puck
1569
- selection near a section boundary. Only the centred pill is interactive. */
1570
- .sf-preview-gap {
1571
- position: absolute;
1572
- left: 0;
1573
- right: 0;
1574
- height: 24px;
1575
- transform: translateY(-50%);
1576
- display: flex;
1577
- align-items: center;
1578
- justify-content: center;
1579
- padding: 0;
1580
- border: 0;
1581
- background: transparent;
1582
- pointer-events: none;
1583
- }
1584
- .sf-preview-gap-line {
1585
- position: absolute;
1586
- left: 0;
1587
- right: 0;
1588
- top: 50%;
1589
- height: 2px;
1590
- transform: translateY(-50%);
1591
- background: var(--sf-accent);
1592
- opacity: 0;
1593
- pointer-events: none;
1594
- transition: opacity 0.12s;
1595
- }
1596
- /* The only clickable element: a compact "+" chip that is hidden at rest and
1597
- fades in on hover, expanding to the full "Add section" pill. Keeping it
1598
- invisible until hovered means the canvas carries no persistent affordance,
1599
- while the dead zone stays no larger than this small chip (opacity:0 still
1600
- hit-tests, so the seam remains hoverable). */
1601
- .sf-preview-gap-pill {
1602
- position: relative;
1603
- display: inline-flex;
1604
- align-items: center;
1605
- padding: 4px;
1606
- border-radius: 999px;
1607
- background: var(--sf-toast-bg);
1608
- color: #fff;
1609
- font-family: var(--sf-font);
1610
- font-size: 12px;
1611
- font-weight: 500;
1612
- white-space: nowrap;
1613
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
1614
- opacity: 0;
1615
- cursor: pointer;
1616
- pointer-events: auto;
1617
- transition: opacity 0.12s, padding 0.12s;
1618
- }
1619
- .sf-preview-gap-pill:hover {
1620
- opacity: 1;
1621
- padding: 4px 12px 4px 4px;
1622
- }
1623
- .sf-preview-gap-plus {
1624
- display: inline-flex;
1625
- align-items: center;
1626
- justify-content: center;
1627
- width: 18px;
1628
- height: 18px;
1629
- border-radius: 50%;
1630
- background: var(--sf-accent);
1631
- color: #fff;
1632
- font-size: 13px;
1633
- line-height: 1;
1634
- flex: none;
1635
- }
1636
- /* Label collapsed until hover so the resting chip is just the "+". */
1637
- .sf-preview-gap-label {
1638
- max-width: 0;
1639
- margin-left: 0;
1640
- overflow: hidden;
1641
- opacity: 0;
1642
- transition: max-width 0.14s, margin-left 0.14s, opacity 0.12s;
1643
- }
1644
- .sf-preview-gap-pill:hover .sf-preview-gap-label {
1645
- max-width: 140px;
1646
- margin-left: 6px;
1647
- opacity: 1;
1648
- }
1649
- .sf-preview-gap:has(.sf-preview-gap-pill:hover) .sf-preview-gap-line {
1650
- opacity: 1;
1651
- }
1652
937
 
1653
938
  /* ── Right panel: inspector (wraps Puck.Fields) ──────────────────────── */
1654
939
  /* The head — chip, the panel's name as its h2 (card 66127), the kind line and
@@ -2320,15 +1605,6 @@
2320
1605
  color: var(--sf-text-secondary);
2321
1606
  }
2322
1607
 
2323
- .sf-msg {
2324
- padding: 24px;
2325
- font-size: 13px;
2326
- color: var(--sf-icon);
2327
- }
2328
- .sf-msg--error {
2329
- color: var(--sf-danger);
2330
- }
2331
-
2332
1608
  /* Collapsed-panel state hook (when Puck's UI flags hide a side) */
2333
1609
  .sf-panel--hidden {
2334
1610
  display: none;
@@ -2359,32 +1635,6 @@
2359
1635
  and put that card back. The rail's surface is the bar's.
2360
1636
 
2361
1637
  Everything left below is colour the row variant does not touch. */
2362
- .sf-editor .es-rail {
2363
- --es-rail-fg: var(--sf-muted);
2364
- --es-rail-hover-bg: var(--sf-hover);
2365
- --es-rail-hover-fg: var(--sf-text);
2366
- --es-rail-accent: var(--sf-accent);
2367
- --es-rail-accent-tint: var(--sf-accent-tint);
2368
- }
2369
-
2370
- /* THE RAIL COLUMN (owner, 2026-09-04: "the top control panel and the panel
2371
- below it" must read as one) — the cluster exactly the left panel's width,
2372
- carrying its hairline up through the bar, the buttons spread across it (his
2373
- option A, spread evenly), and the arrow under the open panel's icon — is editor-shell's
2374
- `.es-cluster--rail` (efficient-easel/chrome.css), lifted from this sheet with its
2375
- `flex: none` and its clip-path triangle (redesign 2a). ⚠️ `MIN_PANEL_W` 220 is
2376
- still load-bearing on it: six 34px buttons fill 204 exactly, and a SEVENTH
2377
- rail button does not fit at 220. `scripts/test-editor-rail-in-topbar.ts`
2378
- holds that arithmetic. */
2379
-
2380
- /* The "+" is a plain character in a rail button, the way it was a plain
2381
- character in the toolbar button it replaces — every other "+" affordance in
2382
- this editor is one (`.sf-gap-plus`, `.sf-addcard-plus`, `.sf-plus`). The rail
2383
- sizes SVGs and has nothing to say about text, so its one line is here. */
2384
- .sf-rail-plus {
2385
- font-size: 20px;
2386
- line-height: 1;
2387
- }
2388
1638
 
2389
1639
  /* ── Left panel: Pages view (Wix-style page list) ───────────────────────── */
2390
1640
  .sf-pages {
@@ -2877,17 +2127,6 @@
2877
2127
  margin-top: 0;
2878
2128
  padding-top: var(--es-rhythm-group-first);
2879
2129
  }
2880
- /* A ONE-LINE row — label and control on the same line — needs less air than a
2881
- setting that stacks its control under its label. The shell makes the same
2882
- split with `.es-field.is-inline`; this is that rule, on this panel's own
2883
- class. */
2884
- .sf-field--row {
2885
- display: flex;
2886
- align-items: center;
2887
- justify-content: space-between;
2888
- gap: 12px;
2889
- margin-top: var(--es-rhythm-between-tight);
2890
- }
2891
2130
  /* A HEADING OWNS ITS FIRST SETTING, so that setting sits closer to it than to
2892
2131
  the settings below it. The shell says this as
2893
2132
  `.es-group-body > .es-field:first-child`, which cannot fire here: Puck's
@@ -2915,23 +2154,6 @@
2915
2154
  .sf-field-label--inline {
2916
2155
  margin-bottom: 0;
2917
2156
  }
2918
- /* Small caption under a field — e.g. explaining a read-only/system-set value. */
2919
- .sf-field-hint {
2920
- /* 6px is a RAW NUMBER and it is allow-listed in
2921
- `scripts/test-panel-spacing-tokens.ts` rather than tokenised, because there
2922
- is nothing to read: neither sheet names this gap, and `efficient-easel`'s own
2923
- `.es-field-hint` writes a bare `7px` for it. Inventing an `--es-rhythm-*`
2924
- for it belongs in that package, not here — a token declared in this file
2925
- would be the second source the rest of this block exists to remove. */
2926
- margin-top: 6px;
2927
- /* A `<p>`'s own bottom margin is the UA's, and `.sf-field` has no padding to
2928
- stop it collapsing straight out of the field — so a setting that carries a
2929
- hint stood 11px further from the next one than a setting that does not.
2930
- Measured at 61px against 50px before this line. */
2931
- margin-bottom: 0;
2932
- font-size: 11px;
2933
- color: var(--sf-muted);
2934
- }
2935
2157
  /* A hint that answers a question you only have WHILE TYPING waits until the box
2936
2158
  is in use (card 8802.g). Which sentence is which — and why one waits and the
2937
2159
  other never does — is decided once, in `hintIsWhileTyping` in
@@ -2941,7 +2163,7 @@
2941
2163
  a repaint on focus drops the browser's text selection, and the formatting bar
2942
2164
  above the box exists to act on that selection.
2943
2165
 
2944
- SCOPED TO THE MODIFIER, NEVER TO .sf-field-hint ITSELF. The shared caption
2166
+ SCOPED TO THE MODIFIER, NEVER TO .es-field-hint ITSELF. The shared caption
2945
2167
  class also carries the anchor sentence, which is on every section and is the
2946
2168
  only thing that says what the term of art "Anchor name" means. A rule written
2947
2169
  one class wider would take that explanation off all of them at once. */
@@ -2950,41 +2172,34 @@
2950
2172
  control the Basics tab has had since card 66177 — a section's Style tab was
2951
2173
  carrying two- and three-line explanations on rows a merchant has read once.
2952
2174
 
2953
- ⚠️ `.es-field-hint` ONLY, AND NEVER `.sf-field-hint`. They look identical and
2954
- they are NOT the same sentence:
2955
-
2956
- .es-field-hint editor-shell draws it, from SettingsField's `hint` prop.
2957
- This is a ROW'S EXPLANATION — "Follows Site styles ▸ Basics
2958
- ▸ Corners until you set a number here." These fold.
2959
- .sf-field-hint the SHOP draws it, for what a SettingsField cannot say. Two
2960
- things live here and neither may fold: the "Anchor name"
2961
- sentence, which is the only place that term of art is
2962
- explained, and the source note, which tells a merchant why
2963
- clicking a hydrated word gave them no caret — and now
2964
- carries the control that opens the record.
2965
-
2966
- A rule one class wider takes those off every section at once. The sheet
2967
- already carries this warning at `.sf-field-hint--while-typing`; this is the
2968
- second rule that had to obey it. */
2969
- .sf-panel--right.sf-hints-folded .es-field-hint {
2175
+ ⚠️ IT FOLDS A ROW'S EXPLANATION, NEVER A STATE. Every quiet line is
2176
+ `.es-field-hint` now, and two kinds must stay on screen: the "Anchor name"
2177
+ sentence, the only place that term of art is explained, and the source note,
2178
+ which tells a merchant why clicking a hydrated word gave them no caret. Both
2179
+ are marked `.sf-hint-keep`, and the rule below leaves them alone. */
2180
+ /* ⚠️ AND NEVER A HINT THAT HOLDS `.sf-hint-keep` ([MERGE] One Settings Row And
2181
+ Hint In The Website Editor, 2026-10-06). The shop's own hint classes are
2182
+ gone; every quiet line under a control is `SettingsField`'s `hint`. The few
2183
+ that are a STATE rather than an explanation — loading, empty, why a control
2184
+ is disabled — wrap their words in `components/KeepHint.tsx`, and a line under
2185
+ no row wears `sf-hint-keep` itself; this rule leaves both on screen. `scripts/test-section-hints-fold.ts` holds both. */
2186
+ .sf-panel--right.sf-hints-folded .es-field-hint:not(.sf-hint-keep):not(:has(.sf-hint-keep)) {
2970
2187
  display: none;
2971
2188
  }
2972
2189
 
2973
- .sf-field-hint--while-typing {
2190
+ .es-field-hint:has(.sf-hint-while-typing) {
2974
2191
  display: none;
2975
2192
  }
2976
- .sf-field:focus-within > .sf-field-hint--while-typing {
2193
+ .es-field:focus-within > .es-field-hint:has(.sf-hint-while-typing) {
2977
2194
  display: block;
2978
2195
  }
2979
2196
 
2980
2197
  /* ── Device-aware fields (lib/puck/device-fields.tsx) ─────────────────────────
2981
- A control that belongs to a device the canvas is not showing paints a
2982
- zero-size marker instead of itself, and its row (efficient-easel's public
2983
- `.es-insp-row`, blueprint 4.4) collapses when it holds one, so no gap is left.
2984
- One declarative rule; the row's own "nothing drawn" case is `:empty`. */
2985
- .es-insp-row:has(> [data-sf-device-hidden]) {
2986
- display: none !important;
2987
- }
2198
+ The rule that collapses a row holding the device gate's marker
2199
+ (`[data-sf-device-hidden]`) is efficient-easel/screen.css's since 0.103.0:
2200
+ the screen's own gate paints the marker, so every host that mounts the screen
2201
+ needs the rule, and this sheet goes to one of them. It loads before this
2202
+ sheet, where the rule stood; no rule here meets it on `display !important`. */
2988
2203
  /* ── A field that draws NO CONTROL here (card 66178) ──────────────────────────
2989
2204
  Puck owned the wrapper around every top-level field and ruled the gap between
2990
2205
  two of them, so a field whose render returned nothing still took its
@@ -2995,11 +2210,15 @@
2995
2210
 
2996
2211
  The field says so instead, and the wrapper goes — `display: none`, so the row
2997
2212
  leaves the accessibility tree with it rather than lingering as an unlabelled
2998
- blank a screen reader still walks through. Declarative, like the two rules
2999
- above and below it, so it cannot race the tab pass; and the attribute name is
3000
- stated once in `lib/puck/panel-no-control-mark`, which
3001
- `scripts/test-panel-no-empty-rows.tsx` §4 reads back to prove this rule is
3002
- really here. */
2213
+ blank a screen reader still walks through. Declarative, like the device
2214
+ gate's rule (efficient-easel/screen.css) and the one below, so it cannot race
2215
+ the tab pass; and the attribute name is stated once in
2216
+ `lib/puck/panel-no-control-mark`, which `scripts/test-panel-no-empty-rows.tsx`
2217
+ §4 reads back to prove this rule is really here.
2218
+ The marker is the screen's (efficient-easel paints it), so the rule belongs
2219
+ in efficient-easel/screen.css too, and moves there once that storefront guard
2220
+ reads both sheets (`editorSheet()`); easel's tests/screen-css-closure lists it
2221
+ as open until then. */
3003
2222
  .es-insp-row:has(> [data-sf-no-control]) {
3004
2223
  display: none !important;
3005
2224
  }
@@ -3037,85 +2256,17 @@
3037
2256
  to delete the override rather than leave it lying here — which is exactly what
3038
2257
  happened to the drill one above. */
3039
2258
 
3040
- /* The one line that says WHICH device's settings are on screen. Quiet on
3041
- purpose — it sits above every group, so it earns its space by being read once
3042
- and then ignored. Hidden entirely on desktop, the resting state.
3043
-
3044
- It is a SCOPE banner, not a note (card 66121): it does not explain, it says
3045
- what the panel below it is showing, and it is tinted so it reads as a state.
3046
- Nor is it one of this file's chips — those are all small square glyph holders
3047
- (.sf-chip, .sf-insp-chip) or a colour swatch (.sf-readability-chip); this is
3048
- a full-width strip, so it keeps its own rule. */
3049
- .sf-device-scope {
3050
- margin: 8px 0 2px;
3051
- padding: 7px 10px;
3052
- border-radius: 7px;
3053
- background: var(--sf-chip-bg);
3054
- font-size: 11.5px;
3055
- line-height: 1.35;
3056
- color: var(--sf-muted);
3057
- }
2259
+ /* The header panel's px readouts (Size, Space from the logo, Height) follow
2260
+ option E (Lewis, 2026-10-07): grey while the setting is unchanged — the grey
2261
+ is what says "default" — and the text colour once it is set, beside the ↺. */
2262
+ .sf-header-value[data-changed] { color: var(--sf-text); }
3058
2263
 
3059
- /* ── Inherit / overridden badge (card 66034) ──────────────────────────────────
3060
- The chip at the right of a field's label row saying whether the setting is
3061
- following the page/site value or has been pinned on this section. Two states,
3062
- deliberately different WEIGHTS rather than different hues:
3063
-
3064
- • Inheriting — a quiet grey chip. This is the RESTING state of a tidy page,
3065
- so it must not draw the eye; it answers a question, it doesn't raise one.
3066
- • Overridden — a button, in the accent tint. It is the state that carries an
3067
- action (reset), and the one worth spotting when scanning a panel for "what
3068
- has this section pinned?".
3069
-
3070
- Sized to sit on the label's line without changing the row's height (the label
3071
- is 11px/500; these are 10px), so adding the badge doesn't reflow any panel. */
3072
- .sf-inherit {
3073
- flex: none;
3074
- display: inline-flex;
3075
- align-items: center;
3076
- gap: 4px;
3077
- max-width: 55%;
3078
- padding: 2px 6px;
3079
- border: 1px solid transparent;
3080
- border-radius: 999px;
3081
- font-family: var(--sf-font);
3082
- font-size: 10px;
3083
- font-weight: 500;
3084
- line-height: 1.5;
3085
- letter-spacing: 0.01em;
3086
- white-space: nowrap;
3087
- overflow: hidden;
3088
- text-overflow: ellipsis;
3089
- background: var(--sf-chip-bg);
3090
- color: var(--sf-chip-fg);
3091
- }
3092
- /* Inheriting, but with a way OUT — the type sizes, where the merchant cannot
3093
- retype the previous value because it was a responsive clamp. Stays the quiet
3094
- grey of the resting state (it is still the tidy state); only hover reveals that
3095
- it does something, so a panel full of inheriting fields still reads calm. */
3096
- .sf-inherit--following {
3097
- cursor: pointer;
3098
- transition: background 0.12s, color 0.12s;
3099
- }
3100
- .sf-inherit--following:hover {
3101
- background: var(--sf-hover);
3102
- color: var(--sf-text-secondary);
3103
- }
3104
- /* Overridden: an actual button — pressing it resets the field to inheriting. */
3105
- .sf-inherit--over {
3106
- background: var(--sf-accent-tint);
3107
- border-color: var(--sf-accent-tint-strong);
3108
- color: var(--sf-accent-text);
3109
- cursor: pointer;
3110
- transition: background 0.12s, border-color 0.12s;
3111
- }
3112
- .sf-inherit--over:hover {
3113
- background: var(--sf-accent-tint-strong);
3114
- }
3115
- .sf-inherit-revert {
3116
- font-size: 11px;
3117
- line-height: 1;
3118
- }
2264
+ /* ── Inherit / overridden badge: GONE (owner 2026-10-06) ─────────────────────
2265
+ The `.sf-inherit` chip ("Inherits · Site" / "Overridden ↺") was replaced by
2266
+ easel's `SettingsDefaultReset` — the word "Default", and a "Reset" button —
2267
+ which draws itself from `efficient-easel/panel.css`. One part, both editors;
2268
+ no shop rule styles it. `scripts/test-one-default-reset.ts` fails on a new
2269
+ `.sf-inherit` rule. */
3119
2270
 
3120
2271
  /* Read-only value display — same metrics as an inspector input, but styled as a
3121
2272
  system-set value the panel SHOWS rather than edits (e.g. the Website name,
@@ -3146,10 +2297,6 @@
3146
2297
  label, with a glyph and an eye beside it. */
3147
2298
  margin-bottom: var(--es-rhythm-within);
3148
2299
  }
3149
- .sf-field-type {
3150
- flex: none;
3151
- color: var(--sf-muted);
3152
- }
3153
2300
  .sf-field-head .sf-field-label {
3154
2301
  flex: 1;
3155
2302
  min-width: 0;
@@ -3178,16 +2325,16 @@
3178
2325
  /* Hidden: the element is dropped from the slide, but the input stays so the copy
3179
2326
  is preserved and editable. Strike the label + dim the input + light the eye —
3180
2327
  mirroring the section tree's hidden-row cue. */
3181
- .sf-field.is-hidden .sf-field-label {
2328
+ .es-field.is-hidden .es-field-label {
3182
2329
  color: var(--sf-muted);
3183
2330
  text-decoration: line-through;
3184
2331
  }
3185
- .sf-field.is-hidden .sf-field-eye {
2332
+ .es-field.is-hidden .sf-field-eye {
3186
2333
  opacity: 1;
3187
2334
  color: var(--sf-text-secondary);
3188
2335
  }
3189
- .sf-field.is-hidden input,
3190
- .sf-field.is-hidden textarea {
2336
+ .es-field.is-hidden input,
2337
+ .es-field.is-hidden textarea {
3191
2338
  opacity: 0.5;
3192
2339
  }
3193
2340
 
@@ -3332,7 +2479,7 @@
3332
2479
  }
3333
2480
  /* A hidden element's copy is still editable, so the bar dims with the input
3334
2481
  rather than disappearing — same cue, same reason as the input's 0.5. */
3335
- .sf-field.is-hidden .es-copy-bar {
2482
+ .es-field.is-hidden .es-copy-bar {
3336
2483
  opacity: 0.5;
3337
2484
  }
3338
2485
 
@@ -3455,28 +2602,29 @@
3455
2602
  operating system's. See lib/puck/ColourControl.tsx.
3456
2603
 
3457
2604
  THE ROW HOLDS THE PICKER IN ITS LABEL LINE — `SettingsField`'s `action`
3458
- slot, or a `.sf-field--row` — so the picker's own box steps aside
2605
+ slot (`colorInput()` too, since [MERGE] One Settings Row And Hint) — so the picker's own box steps aside
3459
2606
  (`display: contents`) and its two halves become items of that line: the
3460
2607
  swatch and hex stay at the end of the label line (`margin-left: auto`, which
3461
2608
  the shell gives `.es-field-value` and nothing else), and the window wraps
3462
2609
  onto a line of its own at the row's FULL width. Left inside the picker's box
3463
2610
  it would open in the few pixels the action slot has. */
3464
- .es-field-head:has(> .es-pick-colour),
3465
- .sf-field--row:has(> .es-pick-colour) {
2611
+ .es-field-head:has(> .es-pick-colour) {
3466
2612
  flex-wrap: wrap;
3467
2613
  }
3468
- .es-field-head > .es-pick-colour,
3469
- .sf-field--row > .es-pick-colour {
2614
+ .es-field-head > .es-pick-colour {
3470
2615
  display: contents;
3471
2616
  }
3472
- .es-field-head > .es-pick-colour > .es-pick-colour-row,
3473
- .sf-field--row > .es-pick-colour > .es-pick-colour-row {
2617
+ .es-field-head > .es-pick-colour > .es-pick-colour-row {
3474
2618
  margin-left: auto;
3475
2619
  }
3476
- .es-field-head > .es-pick-colour > .es-pick-window,
3477
- .sf-field--row > .es-pick-colour > .es-pick-window {
2620
+ .es-field-head > .es-pick-colour > .es-pick-window {
3478
2621
  flex: 1 0 100%;
3479
2622
  min-width: 0;
2623
+ /* LAST on the line, whatever follows it in the markup: the row's Default /
2624
+ Reset part (easel's `SettingsDefaultReset`, owner 2026-10-06) comes after
2625
+ the picker, and without this an open window pushed Reset onto a line of
2626
+ its own UNDER the window, away from the swatch it belongs beside. */
2627
+ order: 1;
3480
2628
  }
3481
2629
 
3482
2630
  /* ⚠️ THE HEX BOX MUST OUT-SPECIFY THE SHARED INSPECTOR INPUT. `.sf-insp-body
@@ -3862,7 +3010,7 @@
3862
3010
  scripts/test-inspector-inherit.tsx). Take the token; never invent the value.
3863
3011
 
3864
3012
  So this tick stays muted because of WHERE it is. It sits at the end of a
3865
- settings row, inches from `.sf-part-mark`, which is already an accent-blue
3013
+ settings row, inches from the Reset button, which is already an accent-blue
3866
3014
  mark on the same line; a second coloured mark beside it would read as a
3867
3015
  second thing to act on. The top bar has no such neighbour — its dot is the
3868
3016
  only mark in the corner — which is why the same idea is allowed a colour
@@ -4511,8 +3659,9 @@ input.sf-slider-typed:focus {
4511
3659
  color: var(--sf-text);
4512
3660
  }
4513
3661
 
4514
- /* Checkbox — a literal tick box tinted to the editor accent (label left, box
4515
- right via sf-field--row). The whole row is a <label>, so the text is clickable. */
3662
+ /* Checkbox — a literal tick box tinted to the editor accent. The row is the
3663
+ shell's SettingsField with the box in its `action` slot (label left, box
3664
+ right); the label points at the box, so the text is clickable. */
4516
3665
  .sf-checkbox {
4517
3666
  cursor: pointer;
4518
3667
  }
@@ -4546,8 +3695,6 @@ input.sf-slider-typed:focus {
4546
3695
  .sf-readability-suggestion:focus-visible,
4547
3696
  .sf-swatch:focus-visible,
4548
3697
  .sf-field-eye:focus-visible,
4549
- .sf-inherit--over:focus-visible,
4550
- .sf-inherit--following:focus-visible,
4551
3698
  .sf-slider input[type="range"]:focus-visible,
4552
3699
  .sf-insp-body select:focus-visible,
4553
3700
  .sf-checkbox input[type="checkbox"]:focus-visible {
@@ -4659,10 +3806,6 @@ input.sf-slider-typed:focus {
4659
3806
  and the strip takes the body's width. Scoped to `.sf-panel` because
4660
3807
  `.flex-shrink-0` is a Tailwind utility used in seven other files, and none of
4661
3808
  them is this panel. */
4662
- .sf-panel .flex-shrink-0:has(.es-segs-fit) {
4663
- flex-basis: 100%;
4664
- min-width: 0;
4665
- }
4666
3809
  /* An inactive segment gave no feedback at all before the click, so the strip read
4667
3810
  as static text until you hit it. */
4668
3811
  .sf-seg2 button:hover:not(.is-active) {
@@ -4799,12 +3942,6 @@ input.sf-list-marking {
4799
3942
  opacity: 0.55;
4800
3943
  cursor: default;
4801
3944
  }
4802
- .sf-blogsource-hint {
4803
- margin: 0;
4804
- font-size: 11px;
4805
- line-height: 1.4;
4806
- color: var(--sf-muted);
4807
- }
4808
3945
 
4809
3946
  /* Form picker — the "which form does this section show" control. Reuses the
4810
3947
  blog-source card for its frame, buttons and hint, and adds the read-only
@@ -5075,35 +4212,6 @@ ul.sf-image-status {
5075
4212
  is the panel's quietest thing on purpose; it explains, it does not warn. */
5076
4213
 
5077
4214
  /* ── Part panel: the inspector scoped to ONE clicked control ──────────── */
5078
- /* The way back sits at the very top, before the control, so a merchant can see
5079
- the exit before they have read anything else — nobody is ever stuck inside a
5080
- sub-panel. Full-bleed out of the body's 14px inset so its hit area runs
5081
- the panel's whole width, like the inspector head's own. */
5082
- .sf-part-back {
5083
- display: flex;
5084
- align-items: center;
5085
- gap: 6px;
5086
- width: calc(100% + 28px);
5087
- margin: 0 -14px 10px;
5088
- padding: 9px 14px;
5089
- background: none;
5090
- border: 0;
5091
- font: inherit;
5092
- font-size: 12px;
5093
- color: var(--sf-muted);
5094
- text-align: left;
5095
- cursor: pointer;
5096
- }
5097
- .sf-part-back:hover {
5098
- color: var(--sf-text);
5099
- background: var(--sf-chip-bg);
5100
- }
5101
- .sf-part-back span {
5102
- overflow: hidden;
5103
- white-space: nowrap;
5104
- text-overflow: ellipsis;
5105
- }
5106
-
5107
4215
  /* The style CARD: which site style this part follows, what that style actually
5108
4216
  looks like, and how far this part has been pulled away from it. Sits above
5109
4217
  every control because it is the thing the controls are relative TO — a
@@ -5276,6 +4384,23 @@ ul.sf-image-status {
5276
4384
  text-overflow: ellipsis;
5277
4385
  white-space: nowrap;
5278
4386
  }
4387
+ /* The text region's Style row is easel's FieldSelect (card [MERGE] One Pop-up
4388
+ List For Editor And One For Shoppers). Its "No style" row draws its own note
4389
+ so the NAME keeps its width and the NOTE gives way (owner 2026-09-06) — the
4390
+ reverse of FieldSelect's meta, which is right for a price. */
4391
+ .es-fsel-label.sf-part-style-keep {
4392
+ flex: none;
4393
+ }
4394
+ .sf-part-style-aside {
4395
+ min-width: 0;
4396
+ margin-left: auto;
4397
+ overflow: hidden;
4398
+ text-overflow: ellipsis;
4399
+ white-space: nowrap;
4400
+ font-size: 11px;
4401
+ font-weight: 400;
4402
+ color: var(--es-muted);
4403
+ }
5279
4404
  .sf-part-style-meta {
5280
4405
  margin-top: 1px;
5281
4406
  font-size: 11px;
@@ -5637,22 +4762,14 @@ ul.sf-image-status {
5637
4762
  `.sf-slider` carries the same two lines from card 66247, and the shell
5638
4763
  carries them for `.es-tabs-fit` and `.es-segs-fit`.
5639
4764
 
5640
- ⚠️ AND `.sf-linkstack` JOINED THEM, which is why this is one rule with a
5641
- growing list rather than a fix per control. The storefront link field's
5642
- stacked pickers were an INLINE `display:flex; flex-direction:column` — 291px
5643
- before, 117px inside the slot, both selects with it. An inline style cannot
5644
- be named here, so it got a class in order to join the list. Every consumer
5645
- control that is a flex or grid box written for a block row belongs on this
5646
- selector; the day one is fixed somewhere else instead, the list stops being
5647
- the place to look. */
5648
- .sf-linkstack {
5649
- display: flex;
5650
- flex-direction: column;
5651
- gap: 7px;
5652
- }
4765
+ `.sf-linkstack` was on this list until the link field became the shared
4766
+ picker ([MERGE] One Link Picker For Both Editors): its stack is now the
4767
+ shell's own `.es-flink`, and the shell carries the same two lines for it.
4768
+ Every consumer control that is a flex or grid box written for a block row
4769
+ belongs on this selector; the day one is fixed somewhere else instead, the
4770
+ list stops being the place to look. */
5653
4771
  .es-field-ctl > .sf-gallery-layouts,
5654
- .es-field-ctl > .sf-gallery-filter,
5655
- .es-field-ctl > .sf-linkstack {
4772
+ .es-field-ctl > .sf-gallery-filter {
5656
4773
  flex: 1 1 auto;
5657
4774
  min-width: 0;
5658
4775
  }
@@ -5704,28 +4821,50 @@ ul.sf-image-status {
5704
4821
  own tools from the hide button that ends every head, and a mode's way out
5705
4822
  is a word ("Done", "Cancel") on the engine's ghost button, drawn to the
5706
4823
  28px of the head's icon buttons so the row keeps one height. */
5707
- .sf-head-divider {
5708
- width: 1px;
5709
- height: 16px;
5710
- margin: 0 4px;
5711
- background: var(--sf-line);
5712
- flex: none;
4824
+
4825
+ /* ── The Contact / Locations inspector's level views ────────────────────────
4826
+ LocationsGroupedField shows ONE level at a time (section, group, city, its
4827
+ image or map). Each level used to be wrapped in a bare `.sf-field`, which
4828
+ made the whole view one "row" with rows inside it. The rows are
4829
+ efficient-easel's `SettingsField` now ([MERGE] One Settings Row And Hint In
4830
+ The Website Editor, 2026-10-06); this keeps the view's own top air, from the
4831
+ shell's rhythm token like every row beside it. */
4832
+ .sf-locations-view {
4833
+ margin-top: var(--es-rhythm-between);
5713
4834
  }
5714
- .es-btn-ghost.sf-head-textbtn {
5715
- height: 28px;
5716
- padding: 0 10px;
5717
- font-size: 12.5px;
5718
- border-radius: 7px;
5719
- white-space: nowrap;
4835
+
4836
+ /* ── A quiet line that belongs to no row ────────────────────────────────────
4837
+ [MERGE] One Settings Row And Hint In The Website Editor, 2026-10-06. A line
4838
+ UNDER A CONTROL is `SettingsField`'s own `hint`. A few lines sit under no
4839
+ row — the caption inside a linked-source card, a panel's opening sentence,
4840
+ the empty state of an open focus picker — and they wear the SAME class,
4841
+ `<p class="es-field-hint sf-hint-keep">`: one hint line in the whole editor,
4842
+ not a shop copy of its look. That replaces the shop's `.sf-field-hint` and
4843
+ `.sf-blogsource-hint`, which drew this idea twice, slightly differently.
4844
+
4845
+ Not a NEW class, and not `.sf-note`: `test-editor-chrome-note` holds the
4846
+ chrome to ONE note style, and these are hints, at the hint's size.
4847
+ `sf-hint-keep` on the element keeps the hints switch off them — none is a
4848
+ row's explanation.
4849
+
4850
+ Inside a source card the card's own gap spaces it. */
4851
+ .sf-blogsource > .es-field-hint,
4852
+ .sf-formsummary .es-field-hint {
4853
+ margin: 0;
5720
4854
  }
5721
4855
 
5722
- /* A hidden side panel's strip (components/SidePanelHead `PanelShowStrip`):
5723
- one Show panel button where the panel was. It IS a side panel — the
5724
- engine's `.es-sidepanel--left|right` gives it the panels' ground and the
5725
- hairline on the seam side — only 40px wide, its button level with the
5726
- heads' buttons (the head's 12px top padding, a 28px button). */
5727
- .es-sidepanel.sf-panel-strip {
5728
- width: 40px;
5729
- align-items: center;
5730
- padding-top: 12px;
4856
+ /* The copy box sits in `SettingsField`'s control slot, which is
4857
+ `display: flex` — the trap the Gallery layouts note above describes. Told to
4858
+ fill the slot, or it shrinks to its own words. (The select fields need no
4859
+ rule: easel's `.es-fsel` is `width: 100%` itself.) */
4860
+ .es-field-ctl > .sf-copybox {
4861
+ flex: 1 1 auto;
4862
+ min-width: 0;
4863
+ }
4864
+
4865
+ /* The focal-point picker's row is TextStyleRow's disclosure row, not a
4866
+ SettingsField; this keeps the gap above it that its old bare `.sf-field`
4867
+ wrapper gave, from the same rhythm token. */
4868
+ .sf-focal-row {
4869
+ margin-top: var(--es-rhythm-between);
5731
4870
  }