efficient-web-builder 2.1.0 → 4.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 (37) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +7 -0
  3. package/dist/components/ChartSection.js +1 -1
  4. package/dist/components/ContactLocations.js +1 -1
  5. package/dist/components/Footprint.js +1 -1
  6. package/dist/components/HeroPoster.js +1 -1
  7. package/dist/components/PartInkControl.js +1 -1
  8. package/dist/components/Placeholder.js +1 -1
  9. package/dist/components/PostCard.js +1 -1
  10. package/dist/components/Reel.js +1 -1
  11. package/dist/components/SectionEditor.js +1 -1
  12. package/dist/components/Split.js +1 -1
  13. package/dist/components/StylesPanel.js +1 -1
  14. package/dist/components/SwitchToBoxFooter.js +1 -1
  15. package/dist/components/TextStyleRow.js +1 -1
  16. package/dist/components/TextStylesField.js +1 -1
  17. package/dist/components/WebsiteScreenParts.js +1 -1
  18. package/dist/components/WebsiteSettingsPanel.d.ts +5 -9
  19. package/dist/components/WebsiteSettingsPanel.js +1 -1
  20. package/dist/components/storefront-editor.css +242 -335
  21. package/dist/lib/content/card-image-background.d.ts +1 -0
  22. package/dist/lib/content/card-image-background.js +1 -1
  23. package/dist/lib/content/section-background.d.ts +1 -0
  24. package/dist/lib/content/section-background.js +1 -1
  25. package/dist/lib/puck/ColourControl.d.ts +5 -0
  26. package/dist/lib/puck/ColourControl.js +1 -1
  27. package/dist/lib/puck/controls.d.ts +0 -10
  28. package/dist/lib/puck/controls.js +1 -1
  29. package/dist/lib/sections/section-number-style.js +1 -1
  30. package/dist/lib/source-rules/label-vocabulary.js +4 -4
  31. package/dist/lib/source-rules/one-colour-control.js +2 -2
  32. package/dist/lib/source-rules/site-square-by-default.js +3 -3
  33. package/dist/lib/source-rules/support/label-extraction.js +5 -5
  34. package/dist/lib/theme.js +1 -1
  35. package/package.json +5 -5
  36. package/dist/lib/puck/slider-typing.d.ts +0 -9
  37. package/dist/lib/puck/slider-typing.js +0 -1
@@ -14,11 +14,24 @@
14
14
  * left/right panels, device frame, inspector).
15
15
  *
16
16
  * Everything is scoped under `.sf-editor` so it can never leak into the public
17
- * storefront. Colour is driven entirely by the `--sf-*` tokens below so the
18
- * chrome themes in ONE place. The editor is deliberately light-only — it does
19
- * NOT follow the admin portal's active theme. The admin still bridges its theme
20
- * into the iframe, but lib/editor-theme.ts pins the editor to the light base
21
- * regardless (see that file), so there is no dark block.
17
+ * storefront. Colour is driven entirely by tokens so the chrome themes in ONE
18
+ * place — and that place is efficient-shell (harness UI-24,
19
+ * Efficient-Pty-Ltd/efficient-easel#199). Every chrome rule reads a `--sf-*`
20
+ * (aliased by efficient-easel's `screen.css` onto `--es-*`, which easel aliases
21
+ * onto the shell's tokens), an `--es-*`, or a shell token directly
22
+ * (`--line-strong`, `--status-*`, `--radius-*`), so the chrome FOLLOWS THE
23
+ * SHELL'S THEME, dark included, with no dark block of its own: the shell swaps
24
+ * its tokens under `<html data-theme="dark">`. The theme reaches that attribute
25
+ * through efficient-easel's `chrome-theme` (re-exported as lib/editor-theme.ts),
26
+ * which pinned the editor light up to easel 0.106.0 and stamps the bridged
27
+ * theme from easel #200 on. Hosts load `efficient-shell/ui.css` before this
28
+ * sheet, or the shell's tokens resolve to nothing.
29
+ *
30
+ * NO COLOUR LITERAL AND NO LITERAL RADIUS IN A CHROME RULE
31
+ * (`scripts/test-editor-css-tokens.ts`). Two regions are not chrome and are
32
+ * marked `@tokens canvas-begin/end` and `@tokens output-begin/end`: rules that
33
+ * paint inside the canvas frame (the website being edited, where no token is
34
+ * defined), and the section covers' palette (a miniature of a section, output).
22
35
  *
23
36
  * WHERE THE VALUES LIVE (card 66034). They no longer live here. Every `--sf-*`
24
37
  * colour, radius, shadow and font below is now an ALIAS onto the `--es-*` shell
@@ -62,28 +75,10 @@
62
75
  }
63
76
 
64
77
  /* ── Top bar ─────────────────────────────────────────────────────────────
65
- The bar, its clusters, the icon buttons, the divider, the device switch and
66
- the ghost / primary buttons are editor-shell's (efficient-easel/chrome.css,
67
- `.es-topbar` and friends), lifted from this sheet and shared with the
68
- campaign editor (redesign PR 2a). Only the website's own additions follow. */
69
-
70
- /* Reuse-component buttons in the top bar inherit the ghost look */
71
- .sf-actions-slot > button {
72
- display: flex;
73
- align-items: center;
74
- gap: 6px;
75
- padding: 7px 12px;
76
- border: 1px solid var(--sf-btn-border);
77
- background: var(--sf-panel);
78
- border-radius: 8px;
79
- cursor: pointer;
80
- font-size: 13px;
81
- font-weight: 500;
82
- color: var(--sf-btn-text);
83
- }
84
- .sf-actions-slot > button:hover {
85
- background: var(--sf-hover);
86
- }
78
+ The bar and its clusters are efficient-easel's (chrome.css, `.es-topbar` and
79
+ friends), shared with the campaign editor (redesign PR 2a); its buttons and
80
+ device switch are efficient-shell's since easel 1.0 (UI-24).
81
+ Only the website's own additions follow. */
87
82
 
88
83
  /* ── Body / floating panels ───────────────────────────────────────────── */
89
84
  /* The panel's title and, beside it, WHICH SITE it is styling (card 66167).
@@ -102,6 +97,7 @@
102
97
  wrapping, because a two-line head would move every row in the panel below it;
103
98
  the whole name is on the `title`, along with where to change it. */
104
99
  .sf-panel-site {
100
+ display: block;
105
101
  margin: 0;
106
102
  min-width: 0;
107
103
  overflow: hidden;
@@ -111,6 +107,22 @@
111
107
  white-space: nowrap;
112
108
  text-overflow: ellipsis;
113
109
  }
110
+ /* The site's name sits in the shell's Tooltip (harness UI-24), which carries
111
+ the whole name and where to change it. Its wrapper is block-level and gives
112
+ way like the name did, so the name still ellipsises inside it rather than
113
+ the wrapper's inline box ending the ellipsis. */
114
+ .sf-name-tip {
115
+ position: relative;
116
+ display: block;
117
+ min-width: 0;
118
+ max-width: 100%;
119
+ }
120
+ .sf-name-text {
121
+ display: block;
122
+ overflow: hidden;
123
+ white-space: nowrap;
124
+ text-overflow: ellipsis;
125
+ }
114
126
  .sf-panel-site::before {
115
127
  content: "·";
116
128
  margin-right: 6px;
@@ -120,7 +132,7 @@
120
132
  height: 24px;
121
133
  border: none;
122
134
  background: transparent;
123
- border-radius: 6px;
135
+ border-radius: var(--radius-md);
124
136
  cursor: pointer;
125
137
  color: var(--sf-muted);
126
138
  display: flex;
@@ -238,7 +250,7 @@
238
250
  top: 50%;
239
251
  height: 2px;
240
252
  transform: translateY(-50%);
241
- border-radius: 2px;
253
+ border-radius: calc(var(--radius-sm) / 2);
242
254
  background: var(--sf-accent);
243
255
  opacity: 0;
244
256
  transition: opacity 0.12s;
@@ -252,7 +264,7 @@
252
264
  height: 18px;
253
265
  border-radius: 50%;
254
266
  background: var(--sf-accent);
255
- color: #fff;
267
+ color: var(--sf-on-accent);
256
268
  display: flex;
257
269
  align-items: center;
258
270
  justify-content: center;
@@ -322,7 +334,7 @@
322
334
  margin-top: 16px;
323
335
  padding: 10px;
324
336
  border: 1px solid var(--sf-divider);
325
- border-radius: 10px;
337
+ border-radius: var(--radius-xl);
326
338
  }
327
339
  .sf-addside-sitewide-glyph {
328
340
  flex: none;
@@ -330,7 +342,7 @@
330
342
  place-items: center;
331
343
  width: 28px;
332
344
  height: 28px;
333
- border-radius: 7px;
345
+ border-radius: var(--radius-lg);
334
346
  background: var(--sf-hover);
335
347
  color: var(--sf-muted);
336
348
  }
@@ -369,7 +381,7 @@
369
381
  margin: 18px 0 6px;
370
382
  padding: 12px;
371
383
  border: 1px solid var(--sf-divider);
372
- border-radius: 10px;
384
+ border-radius: var(--radius-xl);
373
385
  }
374
386
  .sf-box-footer-switch-text {
375
387
  margin: 0;
@@ -387,6 +399,12 @@
387
399
  * colour literal lives in the .tsx (doc/no-hardcoding.md R3); the admin mirror
388
400
  * defines the same block in src/index.css. Light-only: the picker + the console
389
401
  * catalog both sit on a light surface. */
402
+ /* @tokens output-begin — the section COVERS' palette. A cover is a miniature
403
+ picture of a kind of SECTION (output), drawn the same in every tenant and in
404
+ the admin's catalog; it is not chrome and does not follow the shell theme,
405
+ exactly as the canvas paper stays white (UI-24 leaves rendered output its own
406
+ look). The card around a cover is easel's `.es-add-*` chrome, on shell tokens.
407
+ `scripts/test-editor-css-tokens.ts` skips this region. */
390
408
  .sf-thumb {
391
409
  --sf-thumb-card: #ffffff;
392
410
  --sf-thumb-thumb-bg: #fcfdff;
@@ -448,6 +466,7 @@
448
466
  colour here rather than an `rgba()` sitting in the component. */
449
467
  --sf-thumb-scrim: rgba(0, 0, 0, 0.55);
450
468
  }
469
+ /* @tokens output-end */
451
470
  /* Drives the Ticker cover's scrolling strip. */
452
471
  @keyframes sf-thumb-marquee {
453
472
  from {
@@ -480,8 +499,8 @@
480
499
  align-items: center;
481
500
  gap: 6px;
482
501
  background: var(--sf-accent);
483
- color: #fff;
484
- border-radius: 9px;
502
+ color: var(--sf-on-accent);
503
+ border-radius: var(--radius-lg);
485
504
  padding: 8px 14px;
486
505
  font-size: 12.5px;
487
506
  font-weight: 600;
@@ -566,6 +585,13 @@
566
585
  src>`) — see components/EditorPreviewSurface. No editor-side frame CSS is
567
586
  needed; the ribbon is styled inline in that component. */
568
587
 
588
+ /* @tokens canvas-begin — the rules from here to `@tokens canvas-end` paint
589
+ INSIDE the canvas frame, on the website being edited: that document has no
590
+ `.es-editor` root, so no shell or `--es-*` token is defined there, and each
591
+ colour carries its own fallback (see the note at B below). Harness UI-24
592
+ leaves the canvas to the page; `scripts/test-editor-css-tokens.ts` skips
593
+ this region and counts everything else. */
594
+
569
595
  /* ── One dashed outline on hover, not a field of them (card 66395) ─────────
570
596
  The owner, 2026-09-01: hovering a section shows too many dashed lines. He
571
597
  wants to find the hover target directly, and ONE is enough.
@@ -843,6 +869,8 @@
843
869
  outline: none;
844
870
  }
845
871
 
872
+ /* @tokens canvas-end */
873
+
846
874
  /* ── Canvas "Add section" seams (overlay between preview sections) ──────────
847
875
  Absolutely positioned over .sf-preview-host (the iframe's box), one band per
848
876
  seam between top-level sections, placed at the boundary Y measured from the
@@ -1269,10 +1297,11 @@
1269
1297
  flex: none;
1270
1298
  display: flex;
1271
1299
  overflow: hidden;
1272
- border-radius: 4px;
1300
+ border-radius: var(--radius-sm);
1273
1301
  /* A hairline of the merchant's own ink would vanish on a theme whose paper is
1274
- that ink. A translucent black keeps the chip's edge on every palette. */
1275
- border: 1px solid rgba(0, 0, 0, 0.14);
1302
+ that ink. The shell's strong line keeps the chip's edge on every palette,
1303
+ against the panel it sits on in either theme. */
1304
+ border: 1px solid var(--line-strong);
1276
1305
  }
1277
1306
  .sf-secttheme-chip i {
1278
1307
  display: block;
@@ -1384,7 +1413,7 @@
1384
1413
  .sf-secttheme-done:focus-visible {
1385
1414
  outline: 2px solid var(--sf-accent);
1386
1415
  outline-offset: -2px;
1387
- border-radius: 4px;
1416
+ border-radius: var(--radius-sm);
1388
1417
  }
1389
1418
  .sf-secttheme-sep {
1390
1419
  height: 1px;
@@ -1503,7 +1532,7 @@
1503
1532
  margin: 0 12px 8px;
1504
1533
  padding: 7px 10px;
1505
1534
  background: var(--sf-track-bg);
1506
- border-radius: 8px;
1535
+ border-radius: var(--radius-lg);
1507
1536
  color: var(--sf-muted);
1508
1537
  }
1509
1538
  .sf-pages-search-input {
@@ -1604,8 +1633,9 @@
1604
1633
  background: var(--sf-accent-tint);
1605
1634
  }
1606
1635
  .sf-badge-lightbox {
1607
- color: #047857; /* emerald-700 — matches the Console's Lightbox pill */
1608
- background: #ecfdf5; /* emerald-50 */
1636
+ /* The shell's success wash — the green the Console's Lightbox pill wears. */
1637
+ color: var(--status-success-soft-ink);
1638
+ background: var(--status-success-soft);
1609
1639
  }
1610
1640
  .sf-page-edit {
1611
1641
  flex: none;
@@ -1613,7 +1643,7 @@
1613
1643
  height: 24px;
1614
1644
  border: none;
1615
1645
  background: transparent;
1616
- border-radius: 6px;
1646
+ border-radius: var(--radius-md);
1617
1647
  color: var(--sf-muted);
1618
1648
  display: none;
1619
1649
  align-items: center;
@@ -1687,7 +1717,7 @@
1687
1717
  height: 22px;
1688
1718
  border: none;
1689
1719
  background: transparent;
1690
- border-radius: 5px;
1720
+ border-radius: var(--radius-md);
1691
1721
  cursor: pointer;
1692
1722
  color: var(--sf-danger);
1693
1723
  display: flex;
@@ -2147,7 +2177,7 @@
2147
2177
  height: 22px;
2148
2178
  border: none;
2149
2179
  background: transparent;
2150
- border-radius: 5px;
2180
+ border-radius: var(--radius-md);
2151
2181
  cursor: pointer;
2152
2182
  color: var(--sf-muted);
2153
2183
  display: flex;
@@ -2244,35 +2274,12 @@
2244
2274
  line-height: 1;
2245
2275
  white-space: nowrap;
2246
2276
  }
2277
+ /* A mark is the shell's IconButton since efficient-easel 1.0 (UI-24): its
2278
+ ground, ink, hover, press, pressed (`aria-pressed`) and disabled looks are
2279
+ the shell's. Only its height is this row's: the bar is 22px tall. */
2247
2280
  .sf-copybox .es-copy-mark,
2248
2281
  .es-list-above .es-copy-mark {
2249
2282
  height: 22px;
2250
- border: none;
2251
- background: transparent;
2252
- border-radius: 5px;
2253
- cursor: pointer;
2254
- color: var(--sf-icon);
2255
- display: flex;
2256
- align-items: center;
2257
- justify-content: center;
2258
- opacity: 0.75;
2259
- transition: background 0.12s, color 0.12s, opacity 0.12s;
2260
- }
2261
- .sf-copybox .es-copy-mark:hover:not(:disabled),
2262
- .es-list-above .es-copy-mark:hover:not(:disabled) {
2263
- background: var(--sf-hover);
2264
- color: var(--sf-text-secondary);
2265
- opacity: 1;
2266
- }
2267
- .sf-copybox .es-copy-mark:active:not(:disabled),
2268
- .es-list-above .es-copy-mark:active:not(:disabled) {
2269
- background: var(--sf-accent-tint);
2270
- color: var(--sf-accent-text);
2271
- }
2272
- .sf-copybox .es-copy-mark:disabled,
2273
- .es-list-above .es-copy-mark:disabled {
2274
- color: var(--sf-disabled);
2275
- cursor: default;
2276
2283
  }
2277
2284
  /* The fifth button — clear formatting (card 8809) — pushed away from the four.
2278
2285
  The four ADD a mark to a selection; this one TAKES every mark off the whole
@@ -2367,16 +2374,6 @@
2367
2374
  .sf-copybox:not(:focus-within) > .es-copy-bar {
2368
2375
  display: none;
2369
2376
  }
2370
- /* PRESSED: the selection already wears this mark, so a press takes it off. The
2371
- same tint as the :active press above, held — under the pointer too, which is
2372
- where it is right after the press (the hover rule would otherwise win). */
2373
- .sf-copybox .es-copy-mark.is-active,
2374
- .sf-copybox .es-copy-mark.is-active:hover:not(:disabled),
2375
- .es-list-above .es-copy-mark.is-active,
2376
- .es-list-above .es-copy-mark.is-active:hover:not(:disabled) {
2377
- background: var(--sf-accent-tint);
2378
- color: var(--sf-accent-text);
2379
- }
2380
2377
  /* The input gives up its own frame to the wrapper. The `.sf-insp-body` +
2381
2378
  attribute selectors are not decoration: the base control rule near the top of
2382
2379
  this file is `.sf-insp-body input[type="text"]`, which ties on specificity
@@ -2412,11 +2409,11 @@
2412
2409
  .sf-swatch {
2413
2410
  width: 26px;
2414
2411
  height: 26px;
2415
- border-radius: 7px;
2412
+ border-radius: var(--radius-lg);
2416
2413
  border: none;
2417
2414
  cursor: pointer;
2418
2415
  padding: 0;
2419
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
2416
+ box-shadow: inset 0 0 0 1px var(--line-strong);
2420
2417
  }
2421
2418
  .sf-swatch.is-active {
2422
2419
  box-shadow: 0 0 0 2px var(--sf-panel), 0 0 0 4px var(--sf-accent);
@@ -2428,69 +2425,59 @@
2428
2425
  margin-left: 2px;
2429
2426
  }
2430
2427
 
2431
- /* ── THE colour control — efficient-easel's `ColourPicker` (blueprint 4.8) ──
2432
- One swatch, one typeable hex, and — pressing the swatch — the package's own
2433
- window under the row: the site's theme colours, a saturation square, a hue
2434
- strip and the hex. Its look is `efficient-easel/pick.css`; what is here is
2435
- only how the shop's rows hold it. There used to be two colour controls in
2436
- this file's rows, then one on `<input type="color">`, whose window was the
2437
- operating system's. See lib/puck/ColourControl.tsx.
2428
+ /* ── THE colour control — efficient-shell's `ColorPicker` (harness UI-24) ──
2429
+ One swatch, one typeable hex (the shell's `HexInput`), and — pressing the
2430
+ swatch — the shell's picker in a popover: the site's theme colours as its
2431
+ presets, a saturation square, a hue strip and the hex. Its look is the
2432
+ shell's; what is here is only how the shop's rows hold it. Before UI-24 it
2433
+ was efficient-easel's `ColourPicker` (blueprint 4.8), and before that
2434
+ `<input type="color">`, whose window was the operating system's. See
2435
+ lib/puck/ColourControl.tsx.
2438
2436
 
2439
2437
  THE ROW HOLDS THE PICKER IN ITS LABEL LINE — `SettingsField`'s `action`
2440
- slot (`colorInput()` too, since [MERGE] One Settings Row And Hint) — so the picker's own box steps aside
2441
- (`display: contents`) and its two halves become items of that line: the
2442
- swatch and hex stay at the end of the label line (`margin-left: auto`, which
2443
- the shell gives `.es-field-value` and nothing else), and the window wraps
2444
- onto a line of its own at the row's FULL width. Left inside the picker's box
2445
- it would open in the few pixels the action slot has. */
2446
- .es-field-head:has(> .es-pick-colour) {
2447
- flex-wrap: wrap;
2448
- }
2449
- .es-field-head > .es-pick-colour {
2450
- display: contents;
2438
+ slot — and the swatch and hex sit at the end of that line (`margin-left:
2439
+ auto`, which the shell gives `.es-field-value` and nothing else). The window
2440
+ is a popover now, so the line no longer wraps to make room for it. */
2441
+ .sf-colour {
2442
+ display: inline-flex;
2443
+ align-items: center;
2444
+ gap: 6px;
2445
+ min-width: 0;
2451
2446
  }
2452
- .es-field-head > .es-pick-colour > .es-pick-colour-row {
2447
+ .es-field-head > .sf-colour {
2453
2448
  margin-left: auto;
2454
2449
  }
2455
- .es-field-head > .es-pick-colour > .es-pick-window {
2456
- flex: 1 0 100%;
2457
- min-width: 0;
2458
- /* LAST on the line, whatever follows it in the markup: the row's Default /
2459
- Reset part (easel's `SettingsDefaultReset`, owner 2026-10-06) comes after
2460
- the picker, and without this an open window pushed Reset onto a line of
2461
- its own UNDER the window, away from the swatch it belongs beside. */
2462
- order: 1;
2463
- }
2464
-
2465
- /* ⚠️ THE HEX BOX MUST OUT-SPECIFY THE SHARED INSPECTOR INPUT. `.sf-insp-body
2466
- input[type="text"]` (0,2,1) is `width: 100%`, `padding: 8px 11px`,
2467
- `font-size: 13px` — a full-width form field — and it beats the package's
2468
- one-class rule. Inherited here it would eat the row and shove the swatch out
2469
- of it, and at 13px `#DDDDDD` rendered `#DDDDD`, one digit short, on a control
2470
- whose whole job is to show a hex exactly (the 2026-09-04 drawing). So EVERY
2471
- property the shared rule sets is restated, at the package's own values, on
2472
- a selector that wins on specificity (0,3,1) and not on source order. */
2473
- .sf-insp-body input[type="text"].es-pick-hex {
2474
- width: var(--es-pick-readout-w);
2475
- border: 1px solid transparent;
2476
- background: transparent;
2477
- border-radius: 6px;
2478
- padding: 4px 6px;
2479
- font-size: 12px;
2480
- color: var(--es-text);
2481
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
2450
+ /* Seven monospaced characters and the box's padding — no wider, so a two-word
2451
+ label keeps its line beside the swatch. */
2452
+ .sf-colour-hexwrap {
2482
2453
  flex: none;
2454
+ width: 4.75rem;
2483
2455
  }
2484
- .sf-insp-body input[type="text"].es-pick-hex:hover {
2485
- border-color: var(--es-input-border);
2486
- }
2487
- .sf-insp-body input[type="text"].es-pick-hex:focus {
2488
- outline: none;
2489
- border-color: var(--es-accent);
2490
- box-shadow: none;
2491
- background: var(--es-panel);
2456
+ .sf-colour-caption {
2457
+ font-size: 12px;
2458
+ color: var(--sf-muted);
2459
+ white-space: nowrap;
2492
2460
  }
2493
2461
 
2462
+ /* ⚠️ THE SHELL'S FIELDS MUST NOT WEAR THE INSPECTOR'S OLD INPUT RULE.
2463
+ `.sf-insp-body input[type="text"]` (0,2,1, below the shell in no layer) is
2464
+ `width: 100%`, `padding: 8px 11px`, `font-size: 13px` — the box Puck's native
2465
+ fields were given — and an unlayered rule beats every shell utility whatever
2466
+ its specificity. Inside the shell's own controls it is rolled back to the
2467
+ shell's layer, so the hex box and the slider's number look as the shell
2468
+ draws them everywhere else. */
2469
+ .sf-editor .sf-insp-body :is(.sf-slider, .sf-colour) input[type="text"],
2470
+ .sf-editor .sf-insp-body :is(.sf-slider, .sf-colour) input[type="text"]:focus,
2471
+ .sf-editor .sf-insp-body :is(.sf-slider, .sf-colour) input::placeholder {
2472
+ all: revert-layer;
2473
+ }
2474
+ /* The colour a row FOLLOWS, shown in its box in grey (option E): the grey is
2475
+ what says the setting has no colour of its own. After the roll-back above,
2476
+ and more specific than it, so the roll-back does not take the grey away. */
2477
+ .sf-editor .sf-colour input.sf-colour-hex.is-inherited,
2478
+ .sf-editor .sf-insp-body .sf-colour input[type="text"].sf-colour-hex.is-inherited {
2479
+ color: var(--sf-muted);
2480
+ }
2494
2481
 
2495
2482
  /* ── Site styles' own controls (card 66148) ───────────────────────────────────
2496
2483
  These three shapes -- a dropdown, a strip of choice rungs, and the small text
@@ -2570,7 +2557,7 @@
2570
2557
  border: 1px solid var(--sf-divider);
2571
2558
  border-radius: var(--sf-field-radius);
2572
2559
  background: var(--sf-panel);
2573
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
2560
+ box-shadow: var(--es-menu-shadow);
2574
2561
  }
2575
2562
  /* The font menu is long enough to need its own ceiling; the theme menu is not. */
2576
2563
  .sf-chooser-menu--tall {
@@ -2759,7 +2746,7 @@
2759
2746
  ON THE TAB PANEL'S FIRST CHILD, whatever that child is. A rule per tab would
2760
2747
  be three statements of one fact, and would go stale the first time a tab's
2761
2748
  opening control changes — which is precisely how these three drifted apart. */
2762
- #sf-site-styles-tabpanel > :first-child {
2749
+ .sf-site-styles-tabpanel > :first-child {
2763
2750
  margin-top: var(--es-rhythm-group-first);
2764
2751
  }
2765
2752
 
@@ -2826,6 +2813,14 @@
2826
2813
  text-overflow: ellipsis;
2827
2814
  white-space: nowrap;
2828
2815
  }
2816
+ /* The sample in the shell's Tooltip (UI-24): the wrapper takes the sample's
2817
+ place at the end of the line and gives way, and the sample ellipsises in it. */
2818
+ .sf-style-sample-tip {
2819
+ position: relative;
2820
+ display: flex;
2821
+ min-width: 0;
2822
+ margin-left: auto;
2823
+ }
2829
2824
  /* Where Done used to sit. The editor autosaves, so the thing to say here is
2830
2825
  "stored", and it says it once and goes quiet again. */
2831
2826
  .sf-style-slot {
@@ -2895,6 +2890,35 @@
2895
2890
  .sf-rung--glyph:disabled:hover {
2896
2891
  background: var(--sf-field-bg);
2897
2892
  }
2893
+ /* The B and the I each sit in the shell's Tooltip (harness UI-24), whose
2894
+ wrapper is the strip's flex item now: it takes the glyph's 34px and the
2895
+ rung fills it. */
2896
+ .sf-rung-tip {
2897
+ position: relative;
2898
+ display: inline-flex;
2899
+ flex: 0 0 34px;
2900
+ }
2901
+ .sf-rung-tip .sf-rung--glyph {
2902
+ flex: 1;
2903
+ }
2904
+ /* A DISABLED BUTTON GETS NO HOVER AND NO FOCUS, so a reason written on it is
2905
+ never shown. The reason sits on a focusable wrapper instead, and the button
2906
+ lets the pointer through to it. Used wherever a disabled control explains
2907
+ itself through the shell's Tooltip. */
2908
+ .sf-tip-disabled {
2909
+ display: inline-flex;
2910
+ }
2911
+ .sf-rung-tip > .sf-tip-disabled {
2912
+ flex: 1;
2913
+ }
2914
+ .sf-tip-disabled > button:disabled {
2915
+ pointer-events: none;
2916
+ }
2917
+ .sf-tip-disabled:focus-visible {
2918
+ outline: 2px solid var(--sf-accent);
2919
+ outline-offset: 2px;
2920
+ border-radius: var(--radius-sm);
2921
+ }
2898
2922
  /* One theme's swatch in the preset dropdown, and one colour row's chip. */
2899
2923
  /* ── The theme list: one card per theme, each a small page in its own palette ──
2900
2924
  Card 66304. Sized against the RIGHT panel's real widths — 320px default and
@@ -2922,7 +2946,7 @@
2922
2946
  .sf-theme-card,
2923
2947
  .sf-secttheme-btn {
2924
2948
  border: 1px solid var(--sf-input-border);
2925
- border-radius: 9px;
2949
+ border-radius: var(--radius-lg);
2926
2950
  overflow: hidden;
2927
2951
  background: var(--sf-panel);
2928
2952
  }
@@ -2991,7 +3015,7 @@
2991
3015
  font-weight: 700;
2992
3016
  letter-spacing: 0.02em;
2993
3017
  padding: 5px 11px;
2994
- border-radius: 4px;
3018
+ border-radius: var(--radius-sm);
2995
3019
  white-space: nowrap;
2996
3020
  flex: none;
2997
3021
  }
@@ -2999,7 +3023,7 @@
2999
3023
  flex: 1;
3000
3024
  min-width: 0;
3001
3025
  height: 22px;
3002
- border-radius: 3px;
3026
+ border-radius: var(--radius-sm);
3003
3027
  border: 1px solid;
3004
3028
  display: flex;
3005
3029
  align-items: center;
@@ -3036,7 +3060,7 @@
3036
3060
  margin-left: auto;
3037
3061
  font-size: 10px;
3038
3062
  font-weight: 700;
3039
- color: #b45309;
3063
+ color: var(--status-warning-soft-ink);
3040
3064
  white-space: nowrap;
3041
3065
  }
3042
3066
  .sf-theme-warn + .sf-theme-edit { margin-left: 8px; }
@@ -3220,8 +3244,8 @@
3220
3244
  width: 9px;
3221
3245
  height: 9px;
3222
3246
  flex: none;
3223
- border-radius: 2px;
3224
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
3247
+ border-radius: calc(var(--radius-sm) / 2);
3248
+ box-shadow: inset 0 0 0 1px var(--line-strong);
3225
3249
  }
3226
3250
 
3227
3251
  /* The nine-square grid moved into `efficient-easel/panel` as `SettingsPlacement`
@@ -3271,68 +3295,14 @@
3271
3295
  flex: 1;
3272
3296
  min-width: 0;
3273
3297
  }
3274
- /* The range was the one control still drawn entirely by the browser — a native
3275
- track and thumb tinted with `accent-color`, sitting beside a panel of bespoke
3276
- toggles, segmenteds and swatches. It read as an unstyled leftover at every OS,
3277
- and each OS drew it differently. Drawn explicitly here instead, off the same
3278
- tokens as its neighbours: a 4px rail on the field track colour, and a white
3279
- thumb ringed in the accent (the shell's control shape — cf. `.es-switch`).
3280
-
3281
- `accent-color` is deliberately dropped: with an explicit thumb + track it only
3282
- fights the rules below. The two vendor thumb selectors CANNOT be combined into
3283
- one rule — a selector list is discarded wholesale by any browser that doesn't
3284
- recognise one member, which would leave the thumb unstyled. */
3285
- .sf-slider input[type="range"] {
3298
+ /* The track and the typed number are efficient-shell's `Slider` (harness
3299
+ UI-24); until it had one, this sheet drew a 4px rail and a ringed thumb on a
3300
+ native range here, and a readout that was pressed to type into (card
3301
+ 66275). The shell's control does both, so those rules went with them. Its
3302
+ box fills `.sf-slider` like the input did. */
3303
+ .sf-slider > .sf-slider-track {
3286
3304
  flex: 1;
3287
3305
  min-width: 0;
3288
- height: 18px;
3289
- margin: 0;
3290
- padding: 0;
3291
- background: transparent;
3292
- cursor: pointer;
3293
- -webkit-appearance: none;
3294
- appearance: none;
3295
- }
3296
- .sf-slider input[type="range"]::-webkit-slider-runnable-track {
3297
- height: 4px;
3298
- border-radius: 999px;
3299
- background: var(--sf-track-bg);
3300
- box-shadow: inset 0 0 0 1px var(--sf-input-border);
3301
- }
3302
- .sf-slider input[type="range"]::-moz-range-track {
3303
- height: 4px;
3304
- border-radius: 999px;
3305
- background: var(--sf-track-bg);
3306
- box-shadow: inset 0 0 0 1px var(--sf-input-border);
3307
- }
3308
- .sf-slider input[type="range"]::-webkit-slider-thumb {
3309
- -webkit-appearance: none;
3310
- appearance: none;
3311
- width: 14px;
3312
- height: 14px;
3313
- /* Centre the thumb on a 4px track: (4 - 14) / 2. Webkit lays the thumb out
3314
- from the track's top edge, so without this it hangs below the rail. */
3315
- margin-top: -5px;
3316
- border-radius: 50%;
3317
- background: var(--sf-knob);
3318
- border: 2px solid var(--sf-accent);
3319
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
3320
- transition: transform 0.12s;
3321
- }
3322
- .sf-slider input[type="range"]::-moz-range-thumb {
3323
- width: 14px;
3324
- height: 14px;
3325
- border-radius: 50%;
3326
- background: var(--sf-knob);
3327
- border: 2px solid var(--sf-accent);
3328
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
3329
- transition: transform 0.12s;
3330
- }
3331
- .sf-slider input[type="range"]:hover::-webkit-slider-thumb {
3332
- transform: scale(1.12);
3333
- }
3334
- .sf-slider input[type="range"]:hover::-moz-range-thumb {
3335
- transform: scale(1.12);
3336
3306
  }
3337
3307
  /* THE NOTCH — where the style is, on a track that overrides it (card 66116).
3338
3308
  Drag away from it to override; land on it and the override is cleared, so the
@@ -3353,57 +3323,11 @@
3353
3323
  width: 2px;
3354
3324
  height: 10px;
3355
3325
  margin-top: -5px;
3356
- border-radius: 1px;
3326
+ border-radius: calc(var(--radius-sm) / 2);
3357
3327
  background: var(--sf-input-border);
3358
3328
  pointer-events: none;
3359
3329
  }
3360
3330
 
3361
- /* THE NUMBER, AND IT IS A BUTTON (card 66275). A track that runs 200–900 in
3362
- tens has seventy stops on it, and 380 is one of them — reachable by dragging
3363
- only if the merchant lands the thumb on exactly the right pixel. So the
3364
- readout is pressed to type into, which means it is a real <button> and needs
3365
- the browser's own button drawing taken off it: everything below the first
3366
- five declarations is undoing an appearance, not adding one. It must measure
3367
- exactly what the <span> measured, because `.es-field-value` and this box sit
3368
- in the same 42px column and a merchant reads down it. */
3369
- .sf-slider-val {
3370
- font-size: 12px;
3371
- color: var(--sf-icon);
3372
- font-variant-numeric: tabular-nums;
3373
- min-width: 42px;
3374
- text-align: right;
3375
- padding: 0;
3376
- border: none;
3377
- background: none;
3378
- font-family: inherit;
3379
- line-height: inherit;
3380
- }
3381
- button.sf-slider-val {
3382
- cursor: text;
3383
- border-radius: 4px;
3384
- }
3385
- button.sf-slider-val:hover {
3386
- color: var(--sf-text);
3387
- box-shadow: inset 0 0 0 1px var(--sf-input-border);
3388
- }
3389
- /* The same box, being typed into. It keeps the readout's own width and
3390
- alignment so the row does not shift under the merchant's caret the moment
3391
- they click it — a number that jumps sideways as it becomes editable reads as
3392
- two different controls. */
3393
- input.sf-slider-typed {
3394
- width: 42px;
3395
- color: var(--sf-text);
3396
- box-shadow: inset 0 0 0 1px var(--sf-accent);
3397
- border-radius: 4px;
3398
- padding: 1px 3px;
3399
- /* iOS zooms a focused input under 16px unless the page says otherwise; the
3400
- editor is desktop-first but the panel is reachable on a tablet. */
3401
- touch-action: manipulation;
3402
- }
3403
- input.sf-slider-typed:focus {
3404
- outline: none;
3405
- }
3406
-
3407
3331
  /* Pinned editor-only toggle bar — sits BETWEEN the inspector head and the
3408
3332
  scrolling body (SectionEditor), so an aid like "Preview hover state" stays
3409
3333
  put at the top while the fields below it scroll. `flex: none` keeps it from
@@ -3434,34 +3358,14 @@ input.sf-slider-typed:focus {
3434
3358
  }
3435
3359
 
3436
3360
  /* Columns-per-line stepper — a compact − N + shown for the view the footer's
3437
- "Columns per line" control is currently editing (the top-bar device). */
3361
+ "Columns per line" control is currently editing (the top-bar device). The −
3362
+ and + are the shell's `IconButton` (harness UI-24); this only lines the three
3363
+ parts up and sets the number. */
3438
3364
  .sf-colstep {
3439
3365
  display: flex;
3440
3366
  align-items: center;
3441
3367
  gap: 6px;
3442
3368
  }
3443
- .sf-colstep-btn {
3444
- width: 22px;
3445
- height: 22px;
3446
- padding: 0;
3447
- border: 1px solid var(--sf-line);
3448
- border-radius: 6px;
3449
- background: transparent;
3450
- color: var(--sf-text);
3451
- font-size: 15px;
3452
- line-height: 1;
3453
- cursor: pointer;
3454
- display: flex;
3455
- align-items: center;
3456
- justify-content: center;
3457
- }
3458
- .sf-colstep-btn:hover:not(:disabled) {
3459
- border-color: var(--sf-accent);
3460
- }
3461
- .sf-colstep-btn:disabled {
3462
- opacity: 0.4;
3463
- cursor: default;
3464
- }
3465
3369
  .sf-colstep-value {
3466
3370
  min-width: 14px;
3467
3371
  text-align: center;
@@ -3494,13 +3398,13 @@ input.sf-slider-typed:focus {
3494
3398
 
3495
3399
  `:focus-visible`, not `:focus`, so a mouse click never paints a ring — the
3496
3400
  reason the outline was dropped in the first place. Same 2px accent ring as
3497
- the top bar's `.es-btn-ghost` (editor-shell) / `.sf-addcard`, so focus reads identically across the whole
3498
- editor rather than per-control. */
3401
+ `.sf-addcard`, so focus reads identically across the whole editor rather
3402
+ than per-control. (The top bar's buttons are the shell's `Button` since
3403
+ efficient-easel 1.0 and ring themselves.) */
3499
3404
  .sf-seg2 button:focus-visible,
3500
3405
  .sf-readability-suggestion:focus-visible,
3501
3406
  .sf-swatch:focus-visible,
3502
3407
  .sf-field-eye:focus-visible,
3503
- .sf-slider input[type="range"]:focus-visible,
3504
3408
  .sf-insp-body select:focus-visible {
3505
3409
  outline: 2px solid var(--sf-accent);
3506
3410
  outline-offset: 2px;
@@ -3520,14 +3424,14 @@ input.sf-slider-typed:focus {
3520
3424
  gap: 3px;
3521
3425
  background: var(--sf-track-bg);
3522
3426
  border: 1px solid var(--sf-input-border);
3523
- border-radius: 9px;
3427
+ border-radius: var(--radius-lg);
3524
3428
  padding: 3px;
3525
3429
  }
3526
3430
  .sf-seg2 button {
3527
3431
  flex: 1;
3528
3432
  border: none;
3529
3433
  background: transparent;
3530
- border-radius: 6px;
3434
+ border-radius: var(--radius-md);
3531
3435
  padding: 6px 8px;
3532
3436
  font-size: 12px;
3533
3437
  font-weight: 500;
@@ -3621,7 +3525,7 @@ input.sf-slider-typed:focus {
3621
3525
  color: var(--sf-text-strong);
3622
3526
  /* Softer and shorter than the old flat 0.14 drop: the active segment should
3623
3527
  look lifted off the track, not outlined against it. */
3624
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.04);
3528
+ box-shadow: var(--es-raised-shadow);
3625
3529
  }
3626
3530
  /* ─── A control the panel has taken out of force (card 66216) ─────────────
3627
3531
  The setting still exists and still shows the merchant's saved answer; another
@@ -3630,11 +3534,9 @@ input.sf-slider-typed:focus {
3630
3534
  Background. DIMMED, NEVER HIDDEN: a control that disappears reads as a feature
3631
3535
  that was removed, and leaves the merchant no way to see what to change.
3632
3536
 
3633
- `--sf-disabled` is the panel's existing token for exactly this — the same dim
3634
- the top bar's icon and ghost buttons wear (editor-shell's `.es-iconbtn` /
3635
- `.es-btn-ghost`, lifted from this sheet); this is the same state on
3636
- the control that had no rule for it (the switch is efficient-easel's
3637
- `.es-switch`, which dims itself). The track keeps its border and the
3537
+ `--sf-disabled` is the panel's existing token for exactly this; this is the
3538
+ same state on the control that had no rule for it (the switch is the
3539
+ shell's `Switch` since efficient-easel 1.0, which dims itself). The track keeps its border and the
3638
3540
  pressed segment keeps its lift, so the strip still READS as a strip with an
3639
3541
  answer in it — it is quieter, not broken. */
3640
3542
  .sf-seg2[data-disabled] {
@@ -3704,8 +3606,8 @@ input.sf-list-marking {
3704
3606
  /* The "Open" control inside a source note — the route the sentence names.
3705
3607
  [ADD] Source Note Opens The Record, 2026-09-06.
3706
3608
 
3707
- AN INLINE BUTTON, NOT A BLOCK ONE (`.sf-blogsource-btn` is the block form on
3708
- the product inspector). This one sits INSIDE the sentence, at the end, so it
3609
+ AN INLINE BUTTON, NOT A BLOCK ONE (the shell's `Button` beside the status is
3610
+ the block form, `SourceStatus`). This one sits INSIDE the sentence, at the end, so it
3709
3611
  inherits the caption's 11px and only its colour and underline say it is
3710
3612
  pressable — a 12px pill on the end of an 11px line would be a second control
3711
3613
  grammar for the same act.
@@ -3728,33 +3630,7 @@ input.sf-list-marking {
3728
3630
  .sf-source-open:focus-visible {
3729
3631
  outline: 2px solid var(--sf-accent);
3730
3632
  outline-offset: 2px;
3731
- border-radius: 2px;
3732
- }
3733
-
3734
- /* ⏳ DRAWN BY NO FILE OF THIS REPOSITORY'S. `SourceStatus` takes the shell's
3735
- `Button` (harness UI-24); this rule is kept for the panels
3736
- `efficient-storefront-blocks` still draws by hand (CollectionPicker,
3737
- EditProductLink, FormPicker), and is deleted when they move
3738
- (Efficient-Pty-Ltd/efficient-easel#199). */
3739
- .sf-blogsource-btn {
3740
- align-self: flex-start;
3741
- padding: 7px 14px;
3742
- border: 1px solid var(--sf-input-border);
3743
- border-radius: 8px;
3744
- background: transparent;
3745
- color: var(--sf-text-secondary);
3746
- font-size: 12px;
3747
- font-weight: 500;
3748
- cursor: pointer;
3749
- transition: border-color 0.12s, color 0.12s, background 0.12s;
3750
- }
3751
- .sf-blogsource-btn:hover:not(:disabled) {
3752
- border-color: var(--sf-accent);
3753
- color: var(--sf-accent);
3754
- }
3755
- .sf-blogsource-btn:disabled {
3756
- opacity: 0.55;
3757
- cursor: default;
3633
+ border-radius: calc(var(--radius-sm) / 2);
3758
3634
  }
3759
3635
 
3760
3636
  /* Form picker — the "which form does this section show" control. Reuses the
@@ -3800,7 +3676,7 @@ input.sf-list-marking {
3800
3676
  border: 1px solid var(--sf-btn-border);
3801
3677
  background: var(--sf-panel);
3802
3678
  color: var(--sf-btn-text);
3803
- border-radius: 6px;
3679
+ border-radius: var(--radius-md);
3804
3680
  padding: 4px 10px;
3805
3681
  font-size: 12px;
3806
3682
  font-weight: 500;
@@ -3842,7 +3718,7 @@ ul.sf-image-status {
3842
3718
  because of its old name, `.sf-media-note` (card 66121). */
3843
3719
  .sf-image-slot-inert {
3844
3720
  border: 1.5px dashed var(--sf-input-border);
3845
- border-radius: 9px;
3721
+ border-radius: var(--radius-lg);
3846
3722
  padding: 12px 14px;
3847
3723
  font-size: 12px;
3848
3724
  line-height: 1.5;
@@ -3879,7 +3755,7 @@ ul.sf-image-status {
3879
3755
  min-height: 150px;
3880
3756
  padding: 0;
3881
3757
  border: 1px solid var(--sf-line);
3882
- border-radius: 6px;
3758
+ border-radius: var(--radius-md);
3883
3759
  background: var(--sf-preview-bg);
3884
3760
  cursor: crosshair;
3885
3761
  touch-action: none;
@@ -3909,7 +3785,7 @@ ul.sf-image-status {
3909
3785
  }
3910
3786
  .sf-focus-cross {
3911
3787
  position: absolute;
3912
- background: rgb(255 255 255 / 45%);
3788
+ background: color-mix(in srgb, var(--status-on-solid) 45%, transparent);
3913
3789
  pointer-events: none;
3914
3790
  }
3915
3791
  .sf-focus-cross--h {
@@ -3924,14 +3800,16 @@ ul.sf-image-status {
3924
3800
  }
3925
3801
  /* Drawn in white with a dark ring rather than in a panel token: it sits on a
3926
3802
  merchant's own photograph, which can be any colour, and a token that read
3927
- correctly against the panel would vanish against half of them. */
3803
+ correctly against the panel would vanish against half of them. White and the
3804
+ ring are the shell's own on-media pair (`--status-on-solid`, the media
3805
+ scrim), which do not change with the theme for the same reason. */
3928
3806
  .sf-focus-marker {
3929
3807
  position: absolute;
3930
3808
  width: 18px;
3931
3809
  height: 18px;
3932
- border: 2px solid #fff;
3810
+ border: 2px solid var(--status-on-solid);
3933
3811
  border-radius: 50%;
3934
- box-shadow: 0 0 0 1.5px rgb(0 0 0 / 55%), 0 1px 5px rgb(0 0 0 / 50%);
3812
+ box-shadow: 0 0 0 1.5px var(--rosh-media-scrim-button), 0 1px 5px var(--rosh-media-scrim-button);
3935
3813
  transform: translate(-50%, -50%);
3936
3814
  pointer-events: none;
3937
3815
  }
@@ -4011,7 +3889,7 @@ ul.sf-image-status {
4011
3889
  .sf-note--error {
4012
3890
  color: var(--sf-danger);
4013
3891
  background: var(--sf-danger-tint);
4014
- border-radius: 6px;
3892
+ border-radius: var(--radius-md);
4015
3893
  }
4016
3894
  /* Where this section's words come from, when they are not the merchant's to
4017
3895
  type (card 66089, owner ruling 7). A MODIFIER rather than a second note
@@ -4044,7 +3922,7 @@ ul.sf-image-status {
4044
3922
  margin: 0 0 4px;
4045
3923
  padding: 11px 13px;
4046
3924
  border: 1px solid var(--sf-divider);
4047
- border-radius: 12px;
3925
+ border-radius: var(--radius-xl);
4048
3926
  background: var(--sf-track-bg);
4049
3927
  }
4050
3928
  /* Marked only once something has actually been overridden, so the card is quiet
@@ -4063,7 +3941,7 @@ ul.sf-image-status {
4063
3941
  /* Rounds ITSELF against the card's left corners, so the card no longer needs
4064
3942
  `overflow: hidden` to hide the square ends. Left radii only — the right side
4065
3943
  is a straight edge into the card. */
4066
- border-radius: 12px 0 0 12px;
3944
+ border-radius: var(--radius-xl) 0 0 var(--radius-xl);
4067
3945
  }
4068
3946
  /* The card's own caption — the panel's small-label voice, so it reads as a
4069
3947
  heading for the name below rather than as another name. */
@@ -4144,7 +4022,7 @@ ul.sf-image-status {
4144
4022
  .sf-part-style-trigger:focus-visible {
4145
4023
  outline: 2px solid var(--sf-accent);
4146
4024
  outline-offset: 2px;
4147
- border-radius: 3px;
4025
+ border-radius: var(--radius-sm);
4148
4026
  }
4149
4027
  /* Sits over the card's own content rather than pushing it down: the card is a
4150
4028
  summary and a menu that grew it would move the controls under it while a
@@ -4154,7 +4032,7 @@ ul.sf-image-status {
4154
4032
  z-index: 30;
4155
4033
  left: 0;
4156
4034
  right: 0;
4157
- box-shadow: 0 8px 24px rgb(0 0 0 / 0.18);
4035
+ box-shadow: var(--es-menu-shadow);
4158
4036
  }
4159
4037
  .sf-part-style-option {
4160
4038
  display: flex;
@@ -4321,8 +4199,7 @@ ul.sf-image-status {
4321
4199
  slot now holds — without it the row keeps drawing `style` at full strength
4322
4200
  and the one visual difference between "set" and "following the style"
4323
4201
  disappears. */
4324
- .sf-part-field.is-style-value > .es-field-head > .es-field-value,
4325
- .sf-part-field.is-style-value > .es-field-head > .es-field-value > .sf-slider-val {
4202
+ .sf-part-field.is-style-value > .es-field-head > .es-field-value {
4326
4203
  color: var(--sf-muted);
4327
4204
  }
4328
4205
 
@@ -4352,10 +4229,29 @@ ul.sf-image-status {
4352
4229
  gap: 8px;
4353
4230
  min-width: 0;
4354
4231
  }
4355
- /* In this column the picker keeps its own box: the window opens under the
4356
- dropdown at the column's width, and the swatch and hex sit at its end. */
4357
- .sf-part-ink > .es-pick-colour > .es-pick-colour-row {
4358
- align-self: flex-end;
4232
+ /* The part panel's Color row: its name and what it holds on one line, the
4233
+ theme's swatches and Any color under it — the shell's swatches and picker. */
4234
+ .sf-part-ink-top {
4235
+ display: flex;
4236
+ align-items: baseline;
4237
+ gap: 8px;
4238
+ }
4239
+ .sf-part-ink-label {
4240
+ font-size: 11px;
4241
+ font-weight: 600;
4242
+ color: var(--sf-muted);
4243
+ }
4244
+ .sf-part-ink-read {
4245
+ margin-left: auto;
4246
+ font-size: 12px;
4247
+ color: var(--sf-text-secondary);
4248
+ font-variant-numeric: tabular-nums;
4249
+ }
4250
+ .sf-part-ink-swatches {
4251
+ display: flex;
4252
+ flex-wrap: wrap;
4253
+ align-items: center;
4254
+ gap: 6px;
4359
4255
  }
4360
4256
 
4361
4257
  /* The override mark, half two — and it IS the reset button, which is why it is
@@ -4586,10 +4482,21 @@ ul.sf-image-status {
4586
4482
  flex: 1 1 auto;
4587
4483
  min-width: 0;
4588
4484
  }
4485
+ /* Each tile sits in the shell's Tooltip (harness UI-24); its wrapper is the
4486
+ grid item now, and the tile fills it. */
4487
+ .sf-tile-tip {
4488
+ position: relative;
4489
+ display: flex;
4490
+ min-width: 0;
4491
+ }
4492
+ .sf-tile-tip > button {
4493
+ flex: 1;
4494
+ min-width: 0;
4495
+ }
4589
4496
  .sf-gallery-layouts button {
4590
4497
  border: 1px solid var(--sf-input-border);
4591
4498
  background: var(--sf-field-bg);
4592
- border-radius: 7px;
4499
+ border-radius: var(--radius-lg);
4593
4500
  padding: 5px;
4594
4501
  cursor: pointer;
4595
4502
  transition: border-color 0.12s, box-shadow 0.12s, background 0.12s;
@@ -4615,7 +4522,7 @@ ul.sf-image-status {
4615
4522
  .sf-gallery-pic i {
4616
4523
  display: block;
4617
4524
  background: var(--sf-track-bg);
4618
- border-radius: 1.5px;
4525
+ border-radius: calc(var(--radius-sm) / 2);
4619
4526
  }
4620
4527
  .sf-gallery-layouts button[aria-pressed="true"] .sf-gallery-pic i {
4621
4528
  background: var(--sf-accent);