smoodly 0.0.12 → 0.0.13
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.
- package/README.md +219 -25
- package/dist/admin/editor/CanvasOverlay.d.ts +6 -2
- package/dist/admin/editor/CanvasOverlay.js +9 -11
- package/dist/admin/editor/EditorView.js +130 -25
- package/dist/admin/editor/FloatingToolbar.d.ts +16 -0
- package/dist/admin/editor/FloatingToolbar.js +14 -0
- package/dist/admin/editor/InlineRichtext.d.ts +9 -0
- package/dist/admin/editor/InlineRichtext.js +50 -0
- package/dist/admin/editor/Outline.d.ts +16 -10
- package/dist/admin/editor/Outline.js +13 -10
- package/dist/admin/editor/inline-dom.d.ts +27 -0
- package/dist/admin/editor/inline-dom.js +43 -0
- package/dist/admin/editor/inline-session.d.ts +30 -0
- package/dist/admin/editor/inline-session.js +19 -0
- package/dist/admin/editor/protocol.d.ts +22 -1
- package/dist/admin/editor/useCanvasBridge.d.ts +8 -4
- package/dist/admin/editor/useCanvasBridge.js +12 -7
- package/dist/admin/editor/useInlineSession.d.ts +46 -0
- package/dist/admin/editor/useInlineSession.js +244 -0
- package/dist/admin/field-paths.d.ts +13 -0
- package/dist/admin/field-paths.js +49 -0
- package/dist/admin/forms/FieldWidget.d.ts +7 -2
- package/dist/admin/forms/FieldWidget.js +12 -40
- package/dist/admin/forms/ListField.d.ts +10 -0
- package/dist/admin/forms/ListField.js +42 -0
- package/dist/admin/forms/MediaWidget.js +10 -3
- package/dist/admin/forms/RichtextElementCard.d.ts +3 -0
- package/dist/admin/forms/RichtextElementCard.js +37 -0
- package/dist/admin/forms/RichtextImageCard.d.ts +3 -0
- package/dist/admin/forms/RichtextImageCard.js +42 -0
- package/dist/admin/forms/RichtextInsertMenu.d.ts +6 -0
- package/dist/admin/forms/RichtextInsertMenu.js +6 -0
- package/dist/admin/forms/RichtextPopovers.d.ts +7 -0
- package/dist/admin/forms/RichtextPopovers.js +25 -0
- package/dist/admin/forms/RichtextToolbar.d.ts +4 -2
- package/dist/admin/forms/RichtextToolbar.js +4 -2
- package/dist/admin/forms/RichtextWidget.d.ts +4 -1
- package/dist/admin/forms/RichtextWidget.js +23 -120
- package/dist/admin/forms/elements-context.d.ts +7 -0
- package/dist/admin/forms/elements-context.js +13 -0
- package/dist/admin/forms/reveal.d.ts +5 -0
- package/dist/admin/forms/reveal.js +47 -0
- package/dist/admin/forms/richtext-extensions.d.ts +8 -0
- package/dist/admin/forms/richtext-extensions.js +11 -0
- package/dist/admin/forms/richtext-form-context.d.ts +16 -0
- package/dist/admin/forms/richtext-form-context.js +18 -0
- package/dist/admin/forms/richtext-insert.d.ts +38 -0
- package/dist/admin/forms/richtext-insert.js +37 -0
- package/dist/admin/forms/richtext-nodes.d.ts +37 -0
- package/dist/admin/forms/richtext-nodes.js +85 -0
- package/dist/admin/forms/richtext-paste.js +5 -0
- package/dist/admin/forms/tabs.d.ts +3 -0
- package/dist/admin/forms/tabs.js +6 -0
- package/dist/admin/forms/useRichtextEditor.d.ts +51 -0
- package/dist/admin/forms/useRichtextEditor.js +281 -0
- package/dist/admin/next/bridge.js +51 -20
- package/dist/admin/ops-impl.js +13 -8
- package/dist/admin/richtext-doc.d.ts +3 -0
- package/dist/admin/richtext-doc.js +12 -0
- package/dist/admin/serialize.d.ts +7 -0
- package/dist/admin/serialize.js +16 -1
- package/dist/admin/shell/AdminApp.js +2 -1
- package/dist/admin/shell/EntriesList.js +34 -12
- package/dist/admin/shell/EntryForm.js +22 -15
- package/dist/admin/shell/IconRail.js +6 -5
- package/dist/admin/shell/ListView.d.ts +9 -2
- package/dist/admin/shell/ListView.js +7 -6
- package/dist/admin/shell/LoginView.js +2 -2
- package/dist/admin/shell/PagesList.js +53 -24
- package/dist/admin/shell/SharedForm.js +17 -11
- package/dist/admin/shell/SharedList.js +5 -3
- package/dist/admin/shell/entries-list.d.ts +4 -0
- package/dist/admin/shell/entries-list.js +6 -0
- package/dist/admin/shell/pages-tree.d.ts +24 -0
- package/dist/admin/shell/pages-tree.js +59 -1
- package/dist/admin/tree-ops.d.ts +9 -1
- package/dist/admin/tree-ops.js +27 -0
- package/dist/admin/ui/LocaleSwitcher.d.ts +10 -0
- package/dist/admin/ui/LocaleSwitcher.js +28 -8
- package/dist/admin/ui/Modal.js +14 -2
- package/dist/admin/ui/ResizeHandle.d.ts +1 -0
- package/dist/admin/ui/ResizeHandle.js +127 -0
- package/dist/admin/ui/primitives.d.ts +29 -4
- package/dist/admin/ui/primitives.js +29 -10
- package/dist/admin/ui/resize.d.ts +16 -0
- package/dist/admin/ui/resize.js +23 -0
- package/dist/admin/ui/sortable.d.ts +23 -0
- package/dist/admin/ui/sortable.js +57 -0
- package/dist/admin/ui/theme.d.ts +3 -1
- package/dist/admin/ui/theme.js +512 -165
- package/dist/admin/ui/useSortable.d.ts +35 -0
- package/dist/admin/ui/useSortable.js +220 -0
- package/dist/admin/validate.d.ts +6 -1
- package/dist/admin/validate.js +28 -9
- package/dist/config.d.ts +1 -0
- package/dist/config.js +36 -0
- package/dist/entry-store.d.ts +5 -2
- package/dist/entry-store.js +4 -3
- package/dist/fields.d.ts +4 -0
- package/dist/fields.js +2 -2
- package/dist/image/SmoodlyImage.d.ts +4 -1
- package/dist/image/SmoodlyImage.js +2 -2
- package/dist/index.d.ts +8 -1
- package/dist/index.js +5 -1
- package/dist/marks.d.ts +53 -0
- package/dist/marks.js +43 -0
- package/dist/media.d.ts +3 -2
- package/dist/media.js +48 -6
- package/dist/refs.d.ts +2 -2
- package/dist/refs.js +33 -12
- package/dist/render.js +2 -1
- package/dist/resolve.d.ts +8 -2
- package/dist/resolve.js +8 -7
- package/dist/richtext/index.d.ts +12 -0
- package/dist/richtext/index.js +9 -0
- package/dist/richtext-render.d.ts +22 -2
- package/dist/richtext-render.js +40 -13
- package/dist/richtext-walk.d.ts +44 -0
- package/dist/richtext-walk.js +46 -0
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +13 -1
- package/dist/section-wrapper.js +2 -1
- package/dist/site.d.ts +2 -0
- package/dist/site.js +7 -4
- package/dist/store.d.ts +3 -1
- package/dist/store.js +4 -4
- package/dist/supabase-entry-store.d.ts +1 -0
- package/dist/supabase-entry-store.js +2 -1
- package/dist/supabase-store.js +1 -1
- package/dist/toolset.d.ts +7 -1
- package/dist/toolset.js +13 -4
- package/package.json +6 -1
package/dist/admin/ui/theme.js
CHANGED
|
@@ -7,10 +7,114 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
7
7
|
// is scoped under `.sm-admin` — never `:root` — so the host's own custom
|
|
8
8
|
// properties and class names can't collide with ours.
|
|
9
9
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// The values come from design_handoff_smoodly_warm/tokens/*.css (the warm
|
|
11
|
+
// look: Spruce accent, cream ground, cards instead of hairlines, pills).
|
|
12
|
+
// Every rule below reads its colours, radii, sizes and letter case from
|
|
13
|
+
// tokens, so the previous look survives as a token block alone — see the
|
|
14
|
+
// TEMPORARY `technical` block further down. Hover/focus/disabled live here
|
|
15
|
+
// rather than in inline styles, which is the whole reason for the stylesheet.
|
|
16
|
+
import { INSPECTOR_W_KEY, MIN_INSPECTOR_W } from "./resize.js";
|
|
13
17
|
const TOKENS_LIGHT = `
|
|
18
|
+
--accent:#1C6E5B; --accent-hover:#175C4C; --accent-soft:#DDEBE4; --accent-line:#9CC9B8; --on-accent:#FFFFFF;
|
|
19
|
+
--green-700:#1F7A46; --green-50:#E3F3EA; --green-300:#6FD39A; --green-500:#2E9E5B;
|
|
20
|
+
--amber-700:#8A5A00; --amber-50:#FBF1DC; --amber-300:#E8B85A;
|
|
21
|
+
--red-700:#B42318; --red-50:#FDECEC; --red-300:#F5A5A0;
|
|
22
|
+
|
|
23
|
+
--bg:#F4F1EB; --canvas:#ECE8DF; --surface:#FFFFFF; --surface-form:#FDFCFA; --surface-inset:#F4F1EB;
|
|
24
|
+
--input-bg:#FFFFFF; --input-hover-bg:#FFFFFF; --input-focus-bg:#FFFFFF; --input-border:var(--line);
|
|
25
|
+
--line:#E8E3DA; --line-dashed:#D8D1C4; --line-soft:#EFEBE3;
|
|
26
|
+
--text:#1F1D1A; --text-secondary:#4E4942; --text-muted:#7A746A; --text-subtle:#A39C90; --text-disabled:#C4BDB1;
|
|
27
|
+
--selection:var(--accent); --nav-active-bg:var(--accent-soft); --nav-active-fg:var(--accent);
|
|
28
|
+
--hover:rgba(31,29,26,.05); --press:rgba(31,29,26,.09); --control-hover:#F8F6F1;
|
|
29
|
+
--btn-secondary-bg:var(--surface); --btn-secondary-hover:#F8F6F1; --tile-hover:var(--surface);
|
|
30
|
+
--bar-bg:transparent; --bar-border:0; --menu-border:0; --card-divider:0;
|
|
31
|
+
--card-title-size:var(--text-md); --card-title-color:var(--text);
|
|
32
|
+
--tabs-bg:var(--surface-inset); --tab-active-bg:var(--surface); --tab-active-fg:var(--text); --tab-active-shadow:var(--shadow-seg);
|
|
33
|
+
--seg-bg:var(--canvas);
|
|
34
|
+
--toolbar-bg:#1F1D1A; --toolbar-fg:#F4F1EB;
|
|
35
|
+
/* The "+" rides the canvas page, which stays light in both themes — so
|
|
36
|
+
literals, opaque, not the theme's accent-soft (a translucent tint in
|
|
37
|
+
dark mode that washed out over the white page, 2026-09-10). */
|
|
38
|
+
--plus-bg:#DDEBE4; --plus-hover:#D0E3D9; --plus-fg:#1C6E5B;
|
|
39
|
+
--plus-icon-bg:#1C6E5B; --plus-icon-fg:#FFFFFF; --plus-shadow:none;
|
|
40
|
+
--logo-color:var(--accent);
|
|
41
|
+
|
|
42
|
+
--status-published-fg:var(--green-700); --status-published-bg:var(--green-50);
|
|
43
|
+
--status-draft-fg:var(--amber-700); --status-draft-bg:var(--amber-50);
|
|
44
|
+
--status-scheduled-fg:var(--accent); --status-scheduled-bg:var(--accent-soft);
|
|
45
|
+
--status-saved-dot:var(--green-500);
|
|
46
|
+
--warn:var(--amber-700); --warn-soft:var(--amber-50);
|
|
47
|
+
--danger:var(--red-700); --danger-soft:var(--red-50);
|
|
48
|
+
|
|
49
|
+
/* The edited page inside the canvas stays light in both themes. */
|
|
50
|
+
--page-bg:#FFFFFF; --page-text:#1F1D1A;
|
|
51
|
+
--shadow-page:0 1px 2px rgba(0,0,0,.06), 0 12px 32px rgba(0,0,0,.1);
|
|
52
|
+
--shadow-float:0 2px 8px rgba(0,0,0,.2);
|
|
53
|
+
--shadow-seg:0 1px 2px rgba(40,30,10,.08);
|
|
54
|
+
--focus-ring:0 0 0 .5px var(--accent);
|
|
55
|
+
--shadow-pop:0 4px 20px rgba(0,0,0,.14);
|
|
56
|
+
--logo-filter:none;
|
|
57
|
+
|
|
58
|
+
/* Which half of the theme toggle is visible. A token, so the icon can never
|
|
59
|
+
disagree with the colors — both follow the one cascade below. */
|
|
60
|
+
--when-light:inline-flex; --when-dark:none;
|
|
61
|
+
`;
|
|
62
|
+
const TOKENS_DARK = `
|
|
63
|
+
--accent:#6CC4A6; --accent-hover:#82D2B8; --accent-soft:rgba(108,196,166,.18); --accent-line:#6CC4A6; --on-accent:#0B1F18;
|
|
64
|
+
--bg:#1C1A17; --canvas:#141210; --surface:#27241F; --surface-form:#27241F; --surface-inset:#1C1A17;
|
|
65
|
+
--input-bg:#211E1A; --input-hover-bg:#211E1A; --input-focus-bg:#211E1A;
|
|
66
|
+
--line:#3A3630; --line-dashed:#4A453D; --line-soft:#3A3630;
|
|
67
|
+
--text:#F1EDE6; --text-secondary:#C9C2B7; --text-muted:#9A9388; --text-subtle:#7C7568; --text-disabled:#5A5449;
|
|
68
|
+
--hover:rgba(241,237,230,.05); --press:rgba(241,237,230,.09); --control-hover:#2E2A25;
|
|
69
|
+
--btn-secondary-bg:var(--surface); --btn-secondary-hover:#2E2A25;
|
|
70
|
+
--toolbar-bg:#0F0E0C; --toolbar-fg:#F1EDE6;
|
|
71
|
+
|
|
72
|
+
--status-published-fg:var(--green-300); --status-published-bg:rgba(111,211,154,.14);
|
|
73
|
+
--status-draft-fg:var(--amber-300); --status-draft-bg:rgba(232,184,90,.14);
|
|
74
|
+
--warn:var(--amber-300); --warn-soft:rgba(232,184,90,.14);
|
|
75
|
+
--danger:var(--red-300); --danger-soft:rgba(244,102,92,.14);
|
|
76
|
+
|
|
77
|
+
--shadow-page:0 1px 2px rgba(0,0,0,.4), 0 12px 32px rgba(0,0,0,.35);
|
|
78
|
+
--shadow-pop:0 4px 20px rgba(0,0,0,.5);
|
|
79
|
+
--when-light:none; --when-dark:inline-flex;
|
|
80
|
+
`;
|
|
81
|
+
const SCALE = `
|
|
82
|
+
--font-sans:'Public Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
|
|
83
|
+
--font-serif:'Source Serif 4',Georgia,'Times New Roman',serif;
|
|
84
|
+
--font-mono:ui-monospace,Menlo,Consolas,monospace;
|
|
85
|
+
--text-2xs:10px; --text-xs:11px; --text-sm:12px; --text-md:14px;
|
|
86
|
+
--text-lg:15px; --text-xl:16px; --text-2xl:20px; --text-3xl:22px; --text-4xl:30px;
|
|
87
|
+
--tracking-tight:-0.02em; --tracking-label:0.1em; --tracking-tag:0.08em;
|
|
88
|
+
/* Sentence case everywhere; the technical look flips these to caps. */
|
|
89
|
+
--caps-transform:none; --caps-tracking:0;
|
|
90
|
+
--label-size:12px; --label-weight:500; --label-transform:none; --label-tracking:0;
|
|
91
|
+
--meta-font:var(--font-sans); --meta-size:13px;
|
|
92
|
+
--title-font:var(--font-sans); --title-size:18px; --title-weight:600; --title-tracking:-0.01em;
|
|
93
|
+
--doc-title-size:30px;
|
|
94
|
+
--blocktag-font:var(--font-sans); --blocktag-size:11px; --blocktag-transform:none; --blocktag-tracking:0;
|
|
95
|
+
--blocktag-radius:var(--radius-round); --blocktag-shift:translate(16px,-50%);
|
|
96
|
+
--badge-h:24px; --badge-dot:inline-block;
|
|
97
|
+
|
|
98
|
+
--radius-xs:2px; --radius-sm:8px; --radius-md:10px; --radius-lg:12px;
|
|
99
|
+
--radius-card:14px; --radius-card-lg:16px; --radius-btn:999px; --radius-round:999px;
|
|
100
|
+
--page-radius:4px 4px 0 0; --selection-radius:4px;
|
|
101
|
+
--control-h:40px; --control-h-sm:34px; --control-h-lg:48px; --button-h:36px; --row-h:48px; --topbar-h:64px;
|
|
102
|
+
--outline-row-h:36px; --seg-pad-y:7px; --tabs-pad:3px;
|
|
103
|
+
--plus-h:32px; --plus-pad:0 14px 0 6px; --plus-label:inline;
|
|
104
|
+
--nav-w:72px; --inspector-w:320px; --gutter:20px; --frame-pad:24px;
|
|
105
|
+
--rail-pad:22px 6px 16px; --rail-logo:none; --topbar-pad:0; --back-size:32px; --back-bg:var(--surface);
|
|
106
|
+
--table-pad:8px 12px; --table-top:80px; --canvas-pad:24px 40px 0; --card-pad:16px 18px; --card-gap:12px; --form-pad:32px 40px;
|
|
107
|
+
--border:1px solid var(--line);
|
|
108
|
+
--outline-selection:2px solid var(--selection);
|
|
109
|
+
`;
|
|
110
|
+
/* ── TEMPORARY: the original look, kept for side-by-side comparison while
|
|
111
|
+
the warm restyle lands. Frozen copies of the three strings above as they
|
|
112
|
+
were at tag `look-technical`; applied under `.sm-admin[data-look="technical"]`.
|
|
113
|
+
Switch from the console: localStorage.setItem("smoodly-look","technical")
|
|
114
|
+
and reload; removeItem to go back. Delete this block, the TECHNICAL_SHAPE /
|
|
115
|
+
_EXTRA strings after it, `cascade`'s second call and the boot script's look
|
|
116
|
+
branch once the look is decided. */
|
|
117
|
+
const TECHNICAL_LIGHT = `
|
|
14
118
|
--brand-600:#0038B1; --brand-500:#2554D6; --brand-300:#6E96FF;
|
|
15
119
|
--brand-200:#A9C0FF; --brand-100:#DCE4F9; --brand-50:#E3EAFA;
|
|
16
120
|
--gray-0:#FFFFFF; --gray-50:#F1F2F6; --gray-100:#E1E4EC; --gray-300:#C9D0E2;
|
|
@@ -46,7 +150,7 @@ const TOKENS_LIGHT = `
|
|
|
46
150
|
disagree with the colors — both follow the one cascade below. */
|
|
47
151
|
--when-light:inline-flex; --when-dark:none;
|
|
48
152
|
`;
|
|
49
|
-
const
|
|
153
|
+
const TECHNICAL_DARK = `
|
|
50
154
|
--bg:#0D0F14; --surface:#15181F; --surface-inset:#0D0F14; --input-bg:#1B1F28;
|
|
51
155
|
--line:#2A2F3B; --line-dashed:#2A2F3B;
|
|
52
156
|
--text:#EEF0F5; --text-muted:#8C94A8; --text-subtle:#6B7386;
|
|
@@ -65,7 +169,7 @@ const TOKENS_DARK = `
|
|
|
65
169
|
--logo-filter:brightness(0) invert(1);
|
|
66
170
|
--when-light:none; --when-dark:inline-flex;
|
|
67
171
|
`;
|
|
68
|
-
const
|
|
172
|
+
const TECHNICAL_SCALE = `
|
|
69
173
|
--font-sans:'Public Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
|
|
70
174
|
--font-mono:ui-monospace,Menlo,Consolas,monospace;
|
|
71
175
|
--text-2xs:9px; --text-xs:10px; --text-sm:11px; --text-md:12px;
|
|
@@ -78,17 +182,63 @@ const SCALE = `
|
|
|
78
182
|
--border:1px solid var(--line);
|
|
79
183
|
--outline-selection:1.5px solid var(--selection);
|
|
80
184
|
`;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
185
|
+
/* The tokens the warm restyle added, with the values the technical look
|
|
186
|
+
implied, so the frozen block above renders the old shapes too. */
|
|
187
|
+
const TECHNICAL_SHAPE = `
|
|
188
|
+
--font-serif:var(--font-sans);
|
|
189
|
+
--caps-transform:uppercase; --caps-tracking:.06em;
|
|
190
|
+
--label-size:var(--text-2xs); --label-weight:600; --label-transform:uppercase; --label-tracking:var(--tracking-label);
|
|
191
|
+
--meta-font:var(--font-mono); --meta-size:var(--text-2xs);
|
|
192
|
+
--title-font:var(--font-sans); --title-size:var(--text-xl); --title-weight:600; --title-tracking:0;
|
|
193
|
+
--doc-title-size:var(--text-2xl);
|
|
194
|
+
--blocktag-font:var(--font-mono); --blocktag-size:var(--text-2xs); --blocktag-transform:uppercase; --blocktag-tracking:var(--tracking-tag);
|
|
195
|
+
--blocktag-radius:var(--radius-sm) 0 var(--radius-sm) 0; --blocktag-shift:none;
|
|
196
|
+
--badge-h:20px; --badge-dot:none;
|
|
197
|
+
--radius-lg:var(--radius-md); --radius-card:var(--radius-md); --radius-card-lg:var(--radius-md); --radius-btn:var(--radius-md);
|
|
198
|
+
--page-radius:var(--radius-md); --selection-radius:var(--radius-sm);
|
|
199
|
+
--control-h-sm:24px; --button-h:var(--control-h);
|
|
200
|
+
--outline-row-h:var(--control-h); --seg-pad-y:3px; --tabs-pad:0 14px;
|
|
201
|
+
--plus-h:24px; --plus-pad:0; --plus-label:none;
|
|
202
|
+
--gutter:0px; --frame-pad:0px;
|
|
203
|
+
--rail-pad:14px 6px 12px; --rail-logo:block; --topbar-pad:0 16px; --back-size:auto; --back-bg:transparent;
|
|
204
|
+
--table-pad:0 16px 16px; --table-top:0px; --canvas-pad:0 20px 20px; --card-pad:14px; --card-gap:0px; --form-pad:24px 32px;
|
|
205
|
+
`;
|
|
206
|
+
const TECHNICAL_LIGHT_EXTRA = `
|
|
207
|
+
--accent-hover:var(--brand-500); --accent-line:var(--brand-200); --canvas:var(--bg); --surface-form:var(--surface);
|
|
208
|
+
--input-bg:var(--surface-inset); --input-hover-bg:var(--control-hover); --input-focus-bg:var(--gray-0); --input-border:transparent;
|
|
209
|
+
--line-soft:var(--line); --text-secondary:var(--gray-700); --text-disabled:var(--gray-300);
|
|
210
|
+
--btn-secondary-bg:var(--surface-inset); --btn-secondary-hover:var(--control-hover); --tile-hover:var(--surface-inset);
|
|
211
|
+
--bar-bg:var(--surface); --bar-border:var(--border); --menu-border:var(--border); --card-divider:var(--border);
|
|
212
|
+
--card-title-size:var(--label-size); --card-title-color:var(--text-muted);
|
|
213
|
+
--tabs-bg:transparent; --tab-active-bg:transparent; --tab-active-fg:var(--accent); --tab-active-shadow:inset 0 -2px 0 var(--accent);
|
|
214
|
+
--seg-bg:var(--surface-inset);
|
|
215
|
+
--toolbar-bg:#15181F; --toolbar-fg:#EEF0F5;
|
|
216
|
+
--plus-bg:var(--selection); --plus-hover:var(--brand-500); --plus-fg:#fff;
|
|
217
|
+
--plus-icon-bg:transparent; --plus-icon-fg:#fff; --plus-shadow:0 2px 6px rgba(0,56,177,.35);
|
|
218
|
+
--logo-color:#0038B1;
|
|
219
|
+
`;
|
|
220
|
+
const TECHNICAL_DARK_EXTRA = `
|
|
221
|
+
--input-focus-bg:#1B1F28; --text-secondary:#B8BFCF; --text-disabled:#4A5165;
|
|
222
|
+
`;
|
|
223
|
+
/** The light/dark cascade for one root selector. Order matters: the last
|
|
224
|
+
* rule has the same specificity as the host-attribute rule, so an explicit
|
|
225
|
+
* choice from the theme toggle wins over a dark <html> and over the OS.
|
|
226
|
+
* Each look's root carries one more attribute than the default's, so a
|
|
227
|
+
* look's rules beat the default's at every step of the same cascade. */
|
|
228
|
+
function cascade(root, scale, light, dark) {
|
|
229
|
+
return `
|
|
230
|
+
${root}{${scale}${light}}
|
|
231
|
+
html[data-theme="dark"] ${root},${root}[data-theme="dark"]{${dark}}
|
|
86
232
|
@media (prefers-color-scheme:dark){
|
|
87
|
-
html:not([data-theme="light"])
|
|
233
|
+
html:not([data-theme="light"]) ${root}:not([data-theme="light"]){${dark}}
|
|
88
234
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
235
|
+
${root}[data-theme="light"]{${light}}`;
|
|
236
|
+
}
|
|
237
|
+
export const ADMIN_CSS = `
|
|
238
|
+
@import url("https://fonts.googleapis.com/css2?family=Public+Sans:wght@400;500;600;700&family=Source+Serif+4:opsz,wght@8..60,500;8..60,600&display=swap");
|
|
239
|
+
|
|
240
|
+
${cascade(".sm-admin", SCALE, TOKENS_LIGHT, TOKENS_DARK)}
|
|
241
|
+
${cascade('.sm-admin[data-look="technical"]', TECHNICAL_SCALE + TECHNICAL_SHAPE, TECHNICAL_LIGHT + TECHNICAL_LIGHT_EXTRA, TECHNICAL_DARK + TECHNICAL_DARK_EXTRA)}
|
|
92
242
|
|
|
93
243
|
/* The admin owns the viewport; a host <body> margin would push it into a
|
|
94
244
|
page scrollbar. Scoped by :has, so only a page holding the admin is touched. */
|
|
@@ -96,7 +246,7 @@ body:has(.sm-admin){margin:0}
|
|
|
96
246
|
.sm-admin,.sm-admin *,.sm-admin *::before,.sm-admin *::after{box-sizing:border-box}
|
|
97
247
|
.sm-admin{
|
|
98
248
|
font-family:var(--font-sans);font-size:var(--text-md);line-height:1.4;
|
|
99
|
-
color:var(--text);background:var(--
|
|
249
|
+
color:var(--text);background:var(--bg);
|
|
100
250
|
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
|
|
101
251
|
}
|
|
102
252
|
.sm-admin h1,.sm-admin h2,.sm-admin h3,.sm-admin p,.sm-admin ul{margin:0}
|
|
@@ -104,40 +254,47 @@ body:has(.sm-admin){margin:0}
|
|
|
104
254
|
component class on it (.sm-nav-item, .sm-btn, .sm-back) decides its own
|
|
105
255
|
colour. Without this the element selector silently beat every one of them. */
|
|
106
256
|
:where(.sm-admin a){color:var(--accent);text-decoration:none}
|
|
107
|
-
:where(.sm-admin a:hover){color:var(--
|
|
257
|
+
:where(.sm-admin a:hover){color:var(--accent-hover)}
|
|
108
258
|
.sm-admin button,.sm-admin input,.sm-admin select,.sm-admin textarea{font-family:inherit}
|
|
109
259
|
.sm-admin ::placeholder{color:var(--text-subtle)}
|
|
110
260
|
.sm-admin ::selection{background:var(--accent-soft);color:var(--text)}
|
|
111
261
|
.sm-mono{font-family:var(--font-mono)}
|
|
112
262
|
|
|
113
263
|
/* ── shell ─────────────────────────────────────────────────────────── */
|
|
114
|
-
|
|
264
|
+
/* Rail | main, with the warm look's gutter and frame padding (both 0 in
|
|
265
|
+
the technical look, whose columns touch). The main column stacks the
|
|
266
|
+
top bar over one card-shaped region: list, form or editor. */
|
|
267
|
+
.sm-shell{
|
|
268
|
+
display:grid;grid-template-columns:var(--nav-w) 1fr;column-gap:var(--gutter);
|
|
269
|
+
padding:0 var(--frame-pad) var(--frame-pad) 0;height:100vh;height:100dvh;overflow:hidden;background:var(--bg);
|
|
270
|
+
}
|
|
115
271
|
.sm-shell>.sm-main{min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden}
|
|
116
|
-
.sm-wordmark{height:18px;width:auto;filter:var(--logo-filter);flex:none}
|
|
117
|
-
/* The
|
|
118
|
-
|
|
119
|
-
|
|
272
|
+
.sm-wordmark{height:18px;width:auto;color:var(--logo-color);filter:var(--logo-filter);flex:none}
|
|
273
|
+
/* The IconRail (design_handoff_smoodly_warm/components/IconRail.html): a
|
|
274
|
+
72px rail with 18px Lucide icons over a 10px label and a 42×34 active
|
|
275
|
+
tile, sitting directly on the ground. The technical look gives it a
|
|
276
|
+
surface, a hairline and the app icon on top — all tokens. */
|
|
120
277
|
.sm-rail{
|
|
121
|
-
width:var(--nav-w);height:100%;display:flex;flex-direction:column;align-items:center;gap:
|
|
122
|
-
padding:
|
|
278
|
+
width:var(--nav-w);height:100%;display:flex;flex-direction:column;align-items:center;gap:18px;
|
|
279
|
+
padding:var(--rail-pad);background:var(--bar-bg);border-right:var(--bar-border);color:var(--text);
|
|
123
280
|
font:500 10px/1 var(--font-sans);position:relative;
|
|
124
281
|
}
|
|
125
|
-
.sm-rail__logo{width:28px;height:28px;display:
|
|
126
|
-
.sm-rail__list{display:flex;flex-direction:column;gap:
|
|
282
|
+
.sm-rail__logo{width:28px;height:28px;display:var(--rail-logo);flex:none}
|
|
283
|
+
.sm-rail__list{display:flex;flex-direction:column;gap:8px;width:100%;margin:0;padding:0;list-style:none}
|
|
127
284
|
.sm-rail__item{position:relative}
|
|
128
285
|
.sm-rail__btn{
|
|
129
286
|
appearance:none;background:none;border:0;margin:0;padding:2px 0;width:100%;display:flex;flex-direction:column;
|
|
130
|
-
align-items:center;gap:
|
|
287
|
+
align-items:center;gap:6px;color:inherit;font:inherit;cursor:pointer;border-radius:var(--radius-md);text-decoration:none;
|
|
131
288
|
}
|
|
132
289
|
.sm-rail__btn:hover{color:inherit}
|
|
133
290
|
.sm-rail__btn:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;box-shadow:none}
|
|
134
|
-
.sm-rail__tile{position:relative;width:
|
|
135
|
-
.sm-rail__btn:hover .sm-rail__tile{background:var(--
|
|
291
|
+
.sm-rail__tile{position:relative;width:42px;height:34px;border-radius:var(--radius-md);display:grid;place-items:center;transition:background .12s}
|
|
292
|
+
.sm-rail__btn:hover .sm-rail__tile{background:var(--tile-hover)}
|
|
136
293
|
.sm-rail__btn[aria-current="page"],.sm-rail__btn[aria-expanded="true"]{color:var(--nav-active-fg);font-weight:600}
|
|
137
294
|
.sm-rail__btn[aria-current="page"]:hover,.sm-rail__btn[aria-expanded="true"]:hover{color:var(--nav-active-fg)}
|
|
138
295
|
.sm-rail__btn[aria-current="page"] .sm-rail__tile,.sm-rail__btn[aria-expanded="true"] .sm-rail__tile{background:var(--nav-active-bg)}
|
|
139
296
|
.sm-rail__tile svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
|
|
140
|
-
.sm-rail__chev{position:absolute;right:
|
|
297
|
+
.sm-rail__chev{position:absolute;right:4px;bottom:3px;width:8px;height:8px}
|
|
141
298
|
.sm-rail__chev svg{width:8px;height:8px;stroke-width:3}
|
|
142
299
|
.sm-rail__label{letter-spacing:.01em;white-space:nowrap}
|
|
143
300
|
/* Not greyed: the reference renders every inactive item at --text and marks
|
|
@@ -146,22 +303,22 @@ body:has(.sm-admin){margin:0}
|
|
|
146
303
|
.sm-rail__btn[aria-disabled="true"]:hover .sm-rail__tile{background:transparent}
|
|
147
304
|
.sm-rail__foot{margin-top:auto;display:flex;flex-direction:column;align-items:center}
|
|
148
305
|
.sm-rail__user{
|
|
149
|
-
width:
|
|
150
|
-
display:grid;place-items:center;font-size:var(--text-
|
|
306
|
+
width:28px;height:28px;border-radius:var(--radius-round);background:var(--accent-soft);color:var(--accent);
|
|
307
|
+
display:grid;place-items:center;font-size:var(--text-xs);font-weight:600;border:0;cursor:pointer;padding:0;
|
|
151
308
|
}
|
|
152
309
|
.sm-rail__user:focus-visible{outline:2px solid var(--accent);outline-offset:1px;box-shadow:none}
|
|
153
310
|
/* Flyout: 6px right of the rail, aligned with its item (the user menu aligns to the bottom). */
|
|
154
311
|
.sm-rail__menu{
|
|
155
312
|
position:absolute;left:calc(100% + 6px);top:0;z-index:20;width:168px;padding:6px;margin:0;list-style:none;
|
|
156
|
-
background:var(--surface);border:var(--border);border-radius:var(--radius-md);box-shadow:
|
|
313
|
+
background:var(--surface);border:var(--menu-border);border-radius:var(--radius-md);box-shadow:var(--shadow-pop);
|
|
157
314
|
display:none;flex-direction:column;gap:1px;font-size:var(--text-md);font-weight:500;color:var(--text);
|
|
158
315
|
}
|
|
159
316
|
.sm-rail__menu[data-open="true"]{display:flex}
|
|
160
317
|
.sm-rail__menu--up{top:auto;bottom:0}
|
|
161
|
-
.sm-rail__menu-title{font-size:
|
|
318
|
+
.sm-rail__menu-title{font-size:9px;font-weight:600;letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-muted);padding:6px 8px 4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
162
319
|
.sm-rail__menu-item{
|
|
163
320
|
appearance:none;background:none;border:0;width:100%;display:flex;align-items:center;justify-content:space-between;
|
|
164
|
-
padding:
|
|
321
|
+
padding:7px 10px;border-radius:var(--radius-sm);color:inherit;font:inherit;cursor:pointer;text-align:left;text-decoration:none;
|
|
165
322
|
}
|
|
166
323
|
.sm-rail__menu-item:hover,.sm-rail__menu-item:focus-visible{background:var(--surface-inset);color:inherit;outline:0;box-shadow:none}
|
|
167
324
|
.sm-rail__menu-item[aria-current="page"],.sm-rail__menu-item[aria-current="page"]:hover{background:var(--nav-active-bg);color:var(--nav-active-fg);font-weight:600}
|
|
@@ -169,7 +326,7 @@ body:has(.sm-admin){margin:0}
|
|
|
169
326
|
.sm-when-dark{display:var(--when-dark);align-items:center;gap:8px}
|
|
170
327
|
/* .sm-nav-item survives as the inspector's link style (EditorView). */
|
|
171
328
|
.sm-nav-item{
|
|
172
|
-
display:block;padding:
|
|
329
|
+
display:block;padding:8px 12px;border-radius:var(--radius-sm);line-height:1.3;
|
|
173
330
|
color:var(--text);font-weight:500;text-decoration:none;cursor:pointer;
|
|
174
331
|
background:transparent;border:0;width:100%;text-align:left;font-size:var(--text-md);
|
|
175
332
|
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
|
|
@@ -179,35 +336,43 @@ body:has(.sm-admin){margin:0}
|
|
|
179
336
|
/* ── top bar ───────────────────────────────────────────────────────── */
|
|
180
337
|
.sm-topbar{
|
|
181
338
|
height:var(--topbar-h);flex:none;display:flex;align-items:center;justify-content:space-between;
|
|
182
|
-
gap:16px;padding:
|
|
339
|
+
gap:16px;padding:var(--topbar-pad);border-bottom:var(--bar-border);background:var(--bar-bg);
|
|
183
340
|
}
|
|
184
341
|
.sm-topbar__left{display:flex;align-items:center;gap:10px;min-width:0}
|
|
185
|
-
.sm-topbar__right{display:flex;align-items:center;gap:
|
|
186
|
-
.sm-crumbs{display:flex;align-items:center;gap:
|
|
342
|
+
.sm-topbar__right{display:flex;align-items:center;gap:10px;flex:none}
|
|
343
|
+
.sm-crumbs{display:flex;align-items:center;gap:10px;color:var(--text-muted);min-width:0}
|
|
187
344
|
.sm-crumbs__sep{opacity:.5}
|
|
188
|
-
.sm-crumbs__here{color:var(--text);font-weight:
|
|
189
|
-
.sm-back{
|
|
345
|
+
.sm-crumbs__here{color:var(--text);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
346
|
+
.sm-back{
|
|
347
|
+
width:var(--back-size);height:var(--back-size);flex:none;display:grid;place-items:center;
|
|
348
|
+
border:0;border-radius:var(--radius-round);background:var(--back-bg);padding:0;
|
|
349
|
+
color:var(--text);font:inherit;cursor:pointer;line-height:1;
|
|
350
|
+
}
|
|
190
351
|
.sm-back:hover{color:var(--accent)}
|
|
191
|
-
|
|
192
|
-
.
|
|
352
|
+
/* The view title (Pages, Articles…): Public Sans 18px (2026-09-09; the
|
|
353
|
+
serif stays for the document title and richtext headings). Inside a
|
|
354
|
+
card head or a modal it is a smaller sans heading. */
|
|
355
|
+
.sm-title{font:var(--title-weight) var(--title-size)/1.2 var(--title-font);letter-spacing:var(--title-tracking)}
|
|
356
|
+
.sm-inspector__head .sm-title,.sm-modal__head .sm-title{font:600 var(--text-lg)/1.3 var(--font-sans);letter-spacing:0}
|
|
357
|
+
.sm-count{color:var(--text-muted);font-size:var(--text-md)}
|
|
193
358
|
|
|
194
359
|
/* ── buttons ───────────────────────────────────────────────────────── */
|
|
195
360
|
.sm-btn{
|
|
196
361
|
display:inline-flex;align-items:center;justify-content:center;gap:6px;
|
|
197
|
-
height:var(--
|
|
362
|
+
height:var(--button-h);padding:0 16px;border-radius:var(--radius-btn);border:0;
|
|
198
363
|
font-size:var(--text-md);font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;
|
|
199
364
|
text-decoration:none;
|
|
200
365
|
}
|
|
201
|
-
.sm-btn--lg{height:var(--control-h-lg);padding:0
|
|
202
|
-
.sm-btn--primary{background:var(--accent);color:var(--on-accent);font-weight:600;padding:0
|
|
203
|
-
.sm-btn--primary:hover{background:var(--
|
|
204
|
-
.sm-btn--secondary{background:var(--
|
|
205
|
-
.sm-btn--secondary:hover{background:var(--
|
|
206
|
-
.sm-btn--ghost{background:transparent;color:var(--accent);font-weight:600;padding:0
|
|
366
|
+
.sm-btn--lg{height:var(--control-h-lg);padding:0 20px}
|
|
367
|
+
.sm-btn--primary{background:var(--accent);color:var(--on-accent);font-weight:600;padding:0 18px}
|
|
368
|
+
.sm-btn--primary:hover{background:var(--accent-hover);color:var(--on-accent)}
|
|
369
|
+
.sm-btn--secondary{background:var(--btn-secondary-bg);color:var(--text)}
|
|
370
|
+
.sm-btn--secondary:hover{background:var(--btn-secondary-hover);color:var(--text)}
|
|
371
|
+
.sm-btn--ghost{background:transparent;color:var(--accent);font-weight:600;padding:0 10px}
|
|
207
372
|
.sm-btn--ghost:hover{background:var(--accent-soft);color:var(--accent)}
|
|
208
|
-
.sm-btn--danger{background:var(--
|
|
373
|
+
.sm-btn--danger{background:var(--btn-secondary-bg);color:var(--danger)}
|
|
209
374
|
.sm-btn--danger:hover{background:var(--danger-soft);color:var(--danger)}
|
|
210
|
-
.sm-btn--ok{background:var(--status-published-bg);color:var(--status-published-fg);font-weight:600;padding:0
|
|
375
|
+
.sm-btn--ok{background:var(--status-published-bg);color:var(--status-published-fg);font-weight:600;padding:0 18px}
|
|
211
376
|
.sm-btn:disabled,.sm-btn[aria-disabled="true"]{opacity:.5;cursor:default;pointer-events:none}
|
|
212
377
|
.sm-btn:focus-visible,.sm-iconbtn:focus-visible,.sm-nav-item:focus-visible,
|
|
213
378
|
.sm-tab:focus-visible,.sm-seg__opt:focus-visible,.sm-row:focus-visible{
|
|
@@ -220,227 +385,389 @@ body:has(.sm-admin){margin:0}
|
|
|
220
385
|
font-size:12px;line-height:1;cursor:pointer;
|
|
221
386
|
}
|
|
222
387
|
.sm-iconbtn:hover{background:var(--hover);color:var(--text)}
|
|
223
|
-
.sm-iconbtn--inverse{color
|
|
388
|
+
.sm-iconbtn--inverse{color:var(--toolbar-fg)}
|
|
224
389
|
.sm-iconbtn--inverse:hover{background:rgba(255,255,255,.14);color:#fff}
|
|
225
390
|
.sm-iconbtn:disabled{opacity:.3;cursor:default}
|
|
226
391
|
.sm-iconbtn:disabled:hover{background:transparent}
|
|
227
392
|
|
|
228
393
|
/* ── fields ────────────────────────────────────────────────────────── */
|
|
229
|
-
.sm-field{display:flex;flex-direction:column;gap:
|
|
394
|
+
.sm-field{display:flex;flex-direction:column;gap:8px;min-width:0}
|
|
230
395
|
.sm-field__head{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
|
|
231
396
|
.sm-label{
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
397
|
+
display:inline-flex;align-items:center;gap:5px;
|
|
398
|
+
font-size:var(--label-size);font-weight:var(--label-weight);letter-spacing:var(--label-tracking);
|
|
399
|
+
text-transform:var(--label-transform);color:var(--text-muted);
|
|
400
|
+
}
|
|
401
|
+
/* The "same in every language" mark beside a field name that is not
|
|
402
|
+
.localized() (a Lucide globe-off), instead of grouping fields by locale. */
|
|
403
|
+
.sm-label__mark{display:inline-flex;color:var(--text-subtle);cursor:help}
|
|
404
|
+
.sm-label__mark svg{width:13px;height:13px}
|
|
405
|
+
.sm-counter{font-size:var(--text-sm);color:var(--text-subtle)}
|
|
406
|
+
.sm-hint{font-size:var(--text-sm);color:var(--text-muted)}
|
|
236
407
|
.sm-input,.sm-textarea,.sm-select{
|
|
237
|
-
width:100%;min-width:0;border:
|
|
238
|
-
background:var(--
|
|
408
|
+
width:100%;min-width:0;border:1px solid var(--input-border);border-radius:var(--radius-md);
|
|
409
|
+
background:var(--input-bg);color:var(--text);font-size:var(--text-md);
|
|
239
410
|
outline:0;box-shadow:none;
|
|
240
411
|
}
|
|
241
|
-
.sm-input,.sm-select{height:var(--control-h);padding:0
|
|
242
|
-
.sm-textarea{padding:
|
|
243
|
-
|
|
412
|
+
.sm-input,.sm-select{height:var(--control-h);padding:0 14px}
|
|
413
|
+
.sm-textarea{padding:11px 14px;line-height:1.55;resize:vertical;min-height:72px}
|
|
414
|
+
/* The document title: serif at the doc-title size (sans and small in the technical look). */
|
|
415
|
+
.sm-input--lg{
|
|
416
|
+
height:var(--control-h-lg);font:600 var(--doc-title-size)/1.2 var(--font-serif);letter-spacing:var(--title-tracking);
|
|
417
|
+
}
|
|
244
418
|
.sm-input--mono{font-family:var(--font-mono);font-size:var(--text-sm)}
|
|
245
|
-
.sm-input:hover,.sm-textarea:hover,.sm-select:hover{background:var(--
|
|
419
|
+
.sm-input:hover,.sm-textarea:hover,.sm-select:hover{background:var(--input-hover-bg)}
|
|
246
420
|
.sm-input:focus,.sm-textarea:focus,.sm-select:focus,
|
|
247
421
|
.sm-inputwrap:focus-within{
|
|
248
|
-
background:var(--input-bg);border-color:var(--selection);box-shadow:var(--focus-ring);
|
|
422
|
+
background:var(--input-focus-bg);border-color:var(--selection);box-shadow:var(--focus-ring);
|
|
249
423
|
}
|
|
250
424
|
.sm-input:disabled,.sm-textarea:disabled,.sm-select:disabled{opacity:.6;cursor:default}
|
|
251
425
|
.sm-select{
|
|
252
|
-
appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:
|
|
426
|
+
appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:30px;font-weight:500;
|
|
253
427
|
background-image:linear-gradient(45deg,transparent 50%,var(--text-muted) 50%),
|
|
254
428
|
linear-gradient(135deg,var(--text-muted) 50%,transparent 50%);
|
|
255
|
-
background-position:calc(100% -
|
|
429
|
+
background-position:calc(100% - 16px) calc(50% - 1px),calc(100% - 12px) calc(50% - 1px);
|
|
256
430
|
background-size:4px 4px,4px 4px;background-repeat:no-repeat;
|
|
257
431
|
}
|
|
258
432
|
.sm-inputwrap{
|
|
259
|
-
display:flex;align-items:center;gap:0;height:var(--control-h);padding:0
|
|
260
|
-
border:
|
|
433
|
+
display:flex;align-items:center;gap:0;height:var(--control-h);padding:0 14px;
|
|
434
|
+
border:1px solid var(--input-border);border-radius:var(--radius-md);background:var(--input-bg);
|
|
261
435
|
}
|
|
262
436
|
.sm-inputwrap>.sm-input{height:auto;padding:0;background:transparent;border:0;box-shadow:none}
|
|
263
437
|
.sm-inputwrap>.sm-input:hover,.sm-inputwrap>.sm-input:focus{background:transparent;box-shadow:none}
|
|
264
438
|
.sm-prefix{color:var(--text-muted);font-family:var(--font-mono);font-size:var(--text-sm);flex:none}
|
|
265
439
|
.sm-error{color:var(--danger);font-size:var(--text-sm)}
|
|
266
440
|
/* ── richtext ──────────────────────────────────────────────────────── */
|
|
267
|
-
.sm-richtext{display:flex;flex-direction:column;gap:
|
|
441
|
+
.sm-richtext{display:flex;flex-direction:column;gap:8px;min-width:0}
|
|
268
442
|
.sm-richtext__bar{display:flex;flex-wrap:wrap;align-items:center;gap:2px}
|
|
269
443
|
.sm-richtext__sep{width:1px;height:16px;margin:0 4px;background:var(--line)}
|
|
270
444
|
.sm-richtext__bar .sm-iconbtn[aria-pressed="true"]{background:var(--press);color:var(--text)}
|
|
271
445
|
.sm-richtext__link{display:flex;align-items:center;gap:6px}
|
|
272
446
|
.sm-richtext__content{
|
|
273
|
-
min-height:
|
|
274
|
-
background:var(--
|
|
275
|
-
}
|
|
276
|
-
.sm-richtext__content:hover{background:var(--
|
|
277
|
-
.sm-richtext__content:focus{background:var(--input-bg);border-color:var(--selection);box-shadow:var(--focus-ring)}
|
|
278
|
-
.sm-
|
|
279
|
-
.sm-
|
|
280
|
-
.sm-richtext__content
|
|
281
|
-
.
|
|
447
|
+
min-height:140px;padding:12px 14px;border:1px solid var(--input-border);border-radius:var(--radius-md);
|
|
448
|
+
background:var(--input-bg);color:var(--text);font-size:var(--text-lg);line-height:1.6;outline:0;
|
|
449
|
+
}
|
|
450
|
+
.sm-richtext__content:hover{background:var(--input-hover-bg)}
|
|
451
|
+
.sm-richtext__content:focus{background:var(--input-focus-bg);border-color:var(--selection);box-shadow:var(--focus-ring)}
|
|
452
|
+
/* Block spacing: the sibling rules carry the .sm-admin prefix so they
|
|
453
|
+
outrank the admin-wide .sm-admin p{margin:0} reset (a bare
|
|
454
|
+
.sm-richtext__content>*+* lost to it and left the paragraphs
|
|
455
|
+
touching). Paragraphs get .9em, a heading 1.5em above. */
|
|
456
|
+
.sm-richtext__content :where(p,h1,h2,h3,h4,h5,h6,ul,ol,blockquote){margin:0}
|
|
457
|
+
.sm-admin .sm-richtext__content>*+*{margin-top:.9em}
|
|
458
|
+
.sm-admin .sm-richtext__content>*+:is(h1,h2,h3,h4,h5,h6){margin-top:1.5em}
|
|
459
|
+
/* Block-node cards (TipTap wraps each node view in .react-renderer) get
|
|
460
|
+
room above and below; the document's first and last keep the edges. */
|
|
461
|
+
.sm-richtext__content>.react-renderer{margin:18px 0}
|
|
462
|
+
.sm-richtext__content>.react-renderer:first-child{margin-top:0}
|
|
463
|
+
.sm-richtext__content>.react-renderer:last-child{margin-bottom:0}
|
|
464
|
+
/* Headings inside content are editorial: serif in the warm look. */
|
|
282
465
|
.sm-richtext__content h1,.sm-richtext__content h2,.sm-richtext__content h3,
|
|
283
|
-
.sm-richtext__content h4,.sm-richtext__content h5,.sm-richtext__content h6{
|
|
466
|
+
.sm-richtext__content h4,.sm-richtext__content h5,.sm-richtext__content h6{
|
|
467
|
+
font-family:var(--font-serif);font-weight:600;line-height:1.3;letter-spacing:var(--title-tracking);
|
|
468
|
+
}
|
|
284
469
|
.sm-richtext__content h1{font-size:var(--text-3xl)}
|
|
285
470
|
.sm-richtext__content h2{font-size:var(--text-2xl)}
|
|
286
471
|
.sm-richtext__content h3{font-size:var(--text-xl)}
|
|
287
472
|
.sm-richtext__content h4,.sm-richtext__content h5,.sm-richtext__content h6{font-size:var(--text-lg)}
|
|
288
|
-
.sm-richtext__content ul,.sm-richtext__content ol{padding-left:
|
|
473
|
+
.sm-richtext__content ul,.sm-richtext__content ol{padding-left:20px}
|
|
289
474
|
.sm-richtext__content li+li{margin-top:.25em}
|
|
290
|
-
.sm-
|
|
291
|
-
|
|
475
|
+
.sm-richtext__body{position:relative}
|
|
476
|
+
/* The "+" menu floats under the toolbar's right end (the "+" is its last
|
|
477
|
+
button) instead of pushing the content down; the picker inside drops
|
|
478
|
+
its own chrome. The slash menu floats under the caret the same way. */
|
|
479
|
+
.sm-richtext__head{position:relative}
|
|
480
|
+
.sm-richtext__menu{
|
|
481
|
+
position:absolute;top:calc(100% + 6px);right:0;z-index:65;width:300px;max-width:100%;
|
|
482
|
+
display:flex;flex-direction:column;gap:6px;padding:6px;
|
|
483
|
+
background:var(--surface);border:var(--menu-border);border-radius:var(--radius-md);box-shadow:var(--shadow-pop);
|
|
484
|
+
}
|
|
485
|
+
.sm-richtext__menu .sm-picker{width:100%;padding:0;border:0;box-shadow:none;background:transparent}
|
|
486
|
+
.sm-richtext__slash .sm-picker{width:100%;max-width:300px}
|
|
487
|
+
.sm-richtext__slash{position:absolute;left:0;z-index:65}
|
|
488
|
+
.sm-richtext__insert-empty{padding:8px;color:var(--text-muted);font-size:var(--text-sm)}
|
|
489
|
+
.sm-picker__item--active,.sm-picker__item[aria-selected="true"]{background:var(--nav-active-bg)}
|
|
490
|
+
/* block-node cards */
|
|
491
|
+
.sm-rtcard{border:1px solid var(--line);border-radius:var(--radius-md);background:var(--surface);min-width:0}
|
|
492
|
+
.sm-richtext__content .ProseMirror-selectednode .sm-rtcard,.sm-richtext__content .sm-rtcard.ProseMirror-selectednode{outline:2px solid var(--accent);outline-offset:1px}
|
|
493
|
+
.sm-rtcard__head{display:flex;align-items:center;gap:6px;height:var(--control-h-sm);padding:0 6px 0 10px;cursor:grab;user-select:none}
|
|
494
|
+
.sm-rtcard__icon{width:18px;height:18px;flex:none;border-radius:var(--radius-xs);background:var(--accent-soft);color:var(--accent);display:grid;place-items:center;font-size:11px}
|
|
495
|
+
.sm-rtcard__title{flex:1;min-width:0;font-weight:600;font-size:var(--text-sm);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
496
|
+
.sm-rtcard__body{display:flex;flex-direction:column;gap:10px;padding:10px 12px 12px;border-top:1px solid var(--line)}
|
|
497
|
+
.sm-rtcard__thumb{display:block;width:100%;max-height:160px;object-fit:cover;border-radius:var(--radius-sm);background:var(--surface-inset)}
|
|
498
|
+
.sm-rtcard__file{font-size:var(--text-sm);color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
499
|
+
.sm-richtext__content blockquote{padding-left:12px;border-left:2px solid var(--line);color:var(--text-muted)}
|
|
500
|
+
.sm-richtext__content a{color:var(--accent);text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--accent-line)}
|
|
501
|
+
|
|
502
|
+
/* Inline editing in the canvas (spec 2026-09-10). The outlines are drawn in
|
|
503
|
+
the overlay from the bridge's field rects; the toolbar floats above the
|
|
504
|
+
selection. */
|
|
505
|
+
.sm-fieldhover{outline:1px solid color-mix(in srgb,var(--selection) 55%,transparent);outline-offset:2px;border-radius:2px;pointer-events:none}
|
|
506
|
+
.sm-fieldedit{outline:1.5px solid var(--selection);outline-offset:3px;border-radius:2px;pointer-events:none}
|
|
507
|
+
.sm-floatbar{
|
|
508
|
+
position:absolute;z-index:60;display:flex;flex-direction:column;gap:6px;padding:4px;
|
|
509
|
+
background:var(--surface);border-radius:var(--radius-md);box-shadow:var(--shadow-pop);pointer-events:auto;
|
|
510
|
+
}
|
|
511
|
+
.sm-floatbar .sm-richtext__link{padding:0 4px 4px}
|
|
512
|
+
.sm-floatbar .sm-richtext__menu{position:static;width:300px}
|
|
513
|
+
/* The canvas editor root: ProseMirror's base rules (TipTap injects its
|
|
514
|
+
stylesheet into the admin document, never the iframe) and nothing of the
|
|
515
|
+
widget's typography — the site's CSS styles the content. */
|
|
516
|
+
.sm-inline-richtext{position:relative;outline:none;word-wrap:break-word;white-space:pre-wrap;white-space:break-spaces;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;font-feature-settings:"liga" 0}
|
|
517
|
+
.sm-inline-richtext:focus{outline:none}
|
|
518
|
+
.sm-inline-richtext [contenteditable="false"]{white-space:normal}
|
|
519
|
+
.sm-inline-richtext [contenteditable="false"] [contenteditable="true"]{white-space:pre-wrap}
|
|
520
|
+
.sm-inline-richtext .ProseMirror-selectednode .sm-rtcard,.sm-inline-richtext .sm-rtcard.ProseMirror-selectednode{outline:2px solid var(--accent);outline-offset:1px}
|
|
521
|
+
/* The inspector while a richtext field is edited in the canvas. */
|
|
522
|
+
.sm-inline-note{
|
|
523
|
+
display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:var(--control-h);padding:0 6px 0 14px;
|
|
524
|
+
border-radius:var(--radius-md);background:var(--surface-inset);color:var(--text-muted);font-size:var(--text-sm);
|
|
525
|
+
}
|
|
526
|
+
/* A field revealed from a canvas click: one pulse of the accent, then nothing. */
|
|
527
|
+
.sm-field--reveal{animation:sm-reveal .9s ease-out;border-radius:var(--radius-sm)}
|
|
528
|
+
@keyframes sm-reveal{0%{outline:2px solid var(--selection);outline-offset:4px}100%{outline:2px solid transparent;outline-offset:4px}}
|
|
292
529
|
|
|
293
|
-
.sm-group{display:flex;flex-direction:column;gap:10px;padding:2px 0 0
|
|
294
|
-
.sm-list{display:flex;flex-direction:column;gap:
|
|
295
|
-
.sm-listrow{border:1px solid var(--line);border-radius:var(--radius-md);min-width:0}
|
|
296
|
-
.sm-listrow__head{display:flex;align-items:center;gap:2px;height:var(--control-h);padding:0
|
|
530
|
+
.sm-group{display:flex;flex-direction:column;gap:10px;padding:2px 0 0 12px;border-left:2px solid var(--line)}
|
|
531
|
+
.sm-list{display:flex;flex-direction:column;gap:8px;align-items:stretch}
|
|
532
|
+
.sm-listrow{border:1px solid var(--line);border-radius:var(--radius-md);background:var(--surface);min-width:0}
|
|
533
|
+
.sm-listrow__head{display:flex;align-items:center;gap:2px;height:var(--control-h-sm);padding:0 6px 0 6px}
|
|
297
534
|
.sm-listrow__toggle{
|
|
298
|
-
flex:1;min-width:0;display:flex;align-items:center;gap:6px;height:100%;padding:0
|
|
535
|
+
flex:1;min-width:0;display:flex;align-items:center;gap:6px;height:100%;padding:0 6px;
|
|
299
536
|
border:0;background:transparent;color:var(--text);font:inherit;font-size:var(--text-md);font-weight:500;
|
|
300
537
|
text-align:left;cursor:pointer;
|
|
301
538
|
}
|
|
302
539
|
.sm-listrow__toggle:hover{color:var(--accent)}
|
|
303
540
|
.sm-listrow__summary{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
|
|
304
|
-
.sm-listrow__body{display:flex;flex-direction:column;gap:10px;padding:
|
|
541
|
+
.sm-listrow__body{display:flex;flex-direction:column;gap:10px;padding:10px 12px 12px;border-top:1px solid var(--line)}
|
|
305
542
|
|
|
306
543
|
/* ── data ──────────────────────────────────────────────────────────── */
|
|
307
|
-
|
|
544
|
+
/* The list card: the scrolling region under the top bar (ListView). */
|
|
545
|
+
.sm-listwrap{flex:1;min-height:0;overflow:auto;background:var(--surface-form);border-radius:var(--radius-card-lg)}
|
|
546
|
+
/* The rows sit in a centred column of at most 1200px inside the card,
|
|
547
|
+
under --table-top of air reserved for the coming search and filters. */
|
|
548
|
+
.sm-table{display:flex;flex-direction:column;padding:var(--table-pad);padding-top:var(--table-top);max-width:1200px;margin:0 auto}
|
|
308
549
|
.sm-table__head,.sm-row{display:grid;gap:12px;align-items:center;padding:0 8px}
|
|
309
550
|
.sm-table__head{
|
|
310
|
-
height:
|
|
311
|
-
font-size:var(--
|
|
312
|
-
text-transform:
|
|
551
|
+
height:40px;border-bottom:1px solid var(--line);font-family:var(--meta-font);font-weight:500;
|
|
552
|
+
font-size:var(--meta-size);letter-spacing:var(--caps-tracking);color:var(--text-muted);
|
|
553
|
+
text-transform:var(--caps-transform);position:sticky;top:0;background:var(--surface-form);z-index:1;
|
|
313
554
|
}
|
|
314
|
-
|
|
555
|
+
/* Rows are ruled: a hairline under the header and under every row
|
|
556
|
+
(2026-09-09); the hover fill is square so it meets the rules. */
|
|
557
|
+
.sm-table__body{display:flex;flex-direction:column}
|
|
315
558
|
.sm-row{
|
|
316
|
-
height:var(--row-h);border-radius:
|
|
317
|
-
border:0;font:inherit;color:inherit;text-align:left;width:100%;
|
|
559
|
+
height:var(--row-h);border-radius:0;background:transparent;
|
|
560
|
+
border:0;border-bottom:1px solid var(--line-soft);font:inherit;color:inherit;text-align:left;width:100%;
|
|
318
561
|
}
|
|
319
562
|
.sm-row--clickable{cursor:pointer}
|
|
320
563
|
.sm-row--clickable:hover{background:var(--surface-inset)}
|
|
321
564
|
.sm-cell{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
|
|
322
|
-
.sm-cell--muted{color:var(--text-muted)}
|
|
565
|
+
.sm-cell--muted{color:var(--text-muted);font-size:var(--meta-size)}
|
|
323
566
|
.sm-cell--mono{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--text-muted)}
|
|
324
567
|
.sm-cell--title{font-weight:500}
|
|
568
|
+
.sm-cell--grip{overflow:visible;display:flex;align-items:center;margin-left:-4px}
|
|
325
569
|
.sm-empty{padding:28px 8px;color:var(--text-muted)}
|
|
570
|
+
/* ── drag and drop (spec 2026-09-09 §7) ─────────────────────────────── */
|
|
571
|
+
/* The grip is faint until its row is hovered or it has focus. */
|
|
572
|
+
.sm-grip{
|
|
573
|
+
display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex:none;
|
|
574
|
+
border:0;background:transparent;color:var(--text-muted);border-radius:var(--radius-xs);
|
|
575
|
+
cursor:grab;touch-action:none;opacity:0;transition:opacity 120ms ease;padding:0;
|
|
576
|
+
}
|
|
577
|
+
.sm-row:hover .sm-grip,.sm-listrow__head:hover .sm-grip,.sm-outline-row:hover .sm-grip,.sm-grip:focus-visible{opacity:1}
|
|
578
|
+
.sm-grip:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
|
|
579
|
+
/* The lifted row follows the pointer; siblings slide (transition set inline by the hook). */
|
|
580
|
+
.sm-drag--lifted{position:relative;z-index:2;box-shadow:var(--shadow-pop);background:var(--surface);cursor:grabbing}
|
|
581
|
+
.sm-drag--lifted .sm-grip{opacity:1;cursor:grabbing}
|
|
582
|
+
.sm-drag--invalid{opacity:.5}
|
|
326
583
|
.sm-chevron{
|
|
327
584
|
width:12px;flex:none;border:0;background:none;padding:0;font:inherit;font-size:10px;
|
|
328
585
|
color:var(--text-muted);cursor:pointer;line-height:1;
|
|
329
586
|
}
|
|
330
587
|
.sm-chevron:hover{color:var(--text)}
|
|
331
|
-
.sm-cell--tree{display:flex;align-items:center;gap:
|
|
588
|
+
.sm-cell--tree{display:flex;align-items:center;gap:8px;font-weight:500}
|
|
332
589
|
.sm-cell--tree.sm-cell--parent{font-weight:600}
|
|
333
590
|
.sm-rowmenu{
|
|
334
591
|
border:0;background:none;padding:0 6px;font:inherit;color:var(--text-muted);cursor:pointer;
|
|
335
|
-
border-radius:var(--radius-
|
|
592
|
+
border-radius:var(--radius-sm);line-height:1;height:24px;
|
|
336
593
|
}
|
|
337
594
|
.sm-rowmenu:hover{background:var(--surface-inset);color:var(--text)}
|
|
338
595
|
|
|
596
|
+
/* Status pill: a dot before the word in the warm look (none in the technical). */
|
|
339
597
|
.sm-badge{
|
|
340
|
-
display:inline-flex;align-items:center;height:
|
|
341
|
-
font-size:var(--text-
|
|
598
|
+
display:inline-flex;align-items:center;gap:6px;height:var(--badge-h);padding:0 10px;border-radius:var(--radius-btn);
|
|
599
|
+
font-size:var(--text-sm);font-weight:600;letter-spacing:var(--caps-tracking);white-space:nowrap;
|
|
342
600
|
}
|
|
601
|
+
.sm-badge::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;display:var(--badge-dot);flex:none}
|
|
343
602
|
.sm-savestate{
|
|
344
|
-
display:inline-flex;align-items:center;gap:
|
|
345
|
-
font-size:var(--text-
|
|
603
|
+
display:inline-flex;align-items:center;gap:7px;padding:0 8px;
|
|
604
|
+
font-size:var(--text-sm);font-weight:500;letter-spacing:var(--caps-tracking);text-transform:var(--caps-transform);
|
|
346
605
|
}
|
|
347
|
-
.sm-dot{width:
|
|
606
|
+
.sm-dot{width:6px;height:6px;border-radius:var(--radius-round);flex:none}
|
|
348
607
|
|
|
349
608
|
/* ── navigation bits ───────────────────────────────────────────────── */
|
|
350
|
-
|
|
609
|
+
/* Tabs read as a segmented pill in the warm look and as underlined tabs in
|
|
610
|
+
the technical one; the difference is the track background and the
|
|
611
|
+
active option's shadow (an inset 2px line draws the underline). */
|
|
612
|
+
.sm-tabs{
|
|
613
|
+
display:flex;gap:2px;padding:var(--tabs-pad);background:var(--tabs-bg);border-radius:var(--radius-btn);
|
|
614
|
+
border-bottom:var(--card-divider);flex:none;
|
|
615
|
+
}
|
|
351
616
|
.sm-tab{
|
|
352
|
-
display:flex;align-items:center;border:0;background:transparent;
|
|
353
|
-
|
|
617
|
+
flex:1;display:flex;align-items:center;justify-content:center;border:0;background:transparent;
|
|
618
|
+
padding:var(--seg-pad-y) 10px;border-radius:var(--radius-btn);font:inherit;font-weight:500;
|
|
619
|
+
cursor:pointer;color:var(--text-muted);white-space:nowrap;
|
|
354
620
|
}
|
|
355
621
|
.sm-tab:hover{color:var(--text)}
|
|
356
|
-
.sm-tab[aria-selected="true"]{color:var(--
|
|
357
|
-
|
|
622
|
+
.sm-tab[aria-selected="true"]{background:var(--tab-active-bg);color:var(--tab-active-fg);font-weight:600;box-shadow:var(--tab-active-shadow)}
|
|
623
|
+
/* The segmented control's track is --seg-bg (the canvas tone), one step
|
|
624
|
+
below the inset so it reads on the cream ground of the top bar and the
|
|
625
|
+
canvas meta row as well as on a white card. */
|
|
626
|
+
.sm-seg{display:flex;gap:2px;padding:3px;background:var(--seg-bg);border-radius:var(--radius-btn)}
|
|
627
|
+
/* A locale switch: each option wide enough to read as a tab, not a chip. */
|
|
628
|
+
.sm-seg--locale .sm-seg__opt{min-width:64px}
|
|
358
629
|
.sm-seg--stretch{width:100%}
|
|
359
630
|
.sm-seg--disabled{opacity:.6}
|
|
360
631
|
.sm-seg__opt:disabled{cursor:default}
|
|
361
632
|
.sm-seg__opt{
|
|
362
|
-
flex:1;padding:
|
|
363
|
-
color:var(--text-muted);font:inherit;cursor:pointer;white-space:nowrap;
|
|
633
|
+
flex:1;padding:var(--seg-pad-y) 10px;border:0;border-radius:var(--radius-btn);background:transparent;
|
|
634
|
+
color:var(--text-muted);font:inherit;font-weight:500;cursor:pointer;white-space:nowrap;
|
|
364
635
|
}
|
|
365
636
|
.sm-seg__opt:hover{color:var(--text)}
|
|
366
637
|
.sm-seg__opt[aria-pressed="true"]{background:var(--surface);color:var(--text);font-weight:600;box-shadow:var(--shadow-seg)}
|
|
638
|
+
/* A locale the record does not have yet: subtle, still a button (it opens the add pane). */
|
|
639
|
+
.sm-seg__opt--absent{color:var(--text-subtle)}
|
|
367
640
|
.sm-divider{height:1px;background:var(--line);flex:none}
|
|
368
641
|
.sm-sectionlabel{display:flex;align-items:center;justify-content:space-between;gap:8px}
|
|
369
642
|
.sm-sectionlabel--mono>.sm-label{
|
|
370
643
|
font-family:var(--font-mono);font-weight:400;letter-spacing:var(--tracking-tag);
|
|
371
644
|
}
|
|
372
645
|
.sm-banner{
|
|
373
|
-
display:flex;gap:14px;align-items:flex-start;padding:
|
|
646
|
+
display:flex;gap:14px;align-items:flex-start;padding:12px 16px;border-radius:var(--radius-md);
|
|
374
647
|
font-size:var(--text-md);
|
|
375
648
|
}
|
|
376
649
|
.sm-banner--error{background:var(--danger-soft);color:var(--danger)}
|
|
377
650
|
.sm-banner--ok{background:var(--status-published-bg);color:var(--status-published-fg)}
|
|
378
651
|
.sm-banner--warn{background:var(--warn-soft);color:var(--warn)}
|
|
379
652
|
|
|
653
|
+
/* ── cards ─────────────────────────────────────────────────────────── */
|
|
654
|
+
/* The inspector column (editor, entry and shared forms) is a stack of
|
|
655
|
+
cards; the technical look draws them flush with a hairline between. */
|
|
656
|
+
.sm-inspector{
|
|
657
|
+
display:flex;flex-direction:column;gap:var(--card-gap);min-height:0;overflow:auto;
|
|
658
|
+
background:var(--bar-bg);border-left:var(--bar-border);
|
|
659
|
+
}
|
|
660
|
+
.sm-card{
|
|
661
|
+
display:flex;flex-direction:column;gap:12px;padding:var(--card-pad);flex:none;
|
|
662
|
+
background:var(--surface);border-radius:var(--radius-card);
|
|
663
|
+
}
|
|
664
|
+
.sm-card+.sm-card{border-top:var(--card-divider)}
|
|
665
|
+
/* A card's first section label is its title. */
|
|
666
|
+
.sm-card>.sm-sectionlabel:first-child>.sm-label,.sm-card>.sm-inspector__head>.sm-label{
|
|
667
|
+
font-size:var(--card-title-size);font-weight:600;color:var(--card-title-color);
|
|
668
|
+
}
|
|
669
|
+
.sm-inspector__head{display:flex;align-items:center;justify-content:space-between;gap:8px;flex:none}
|
|
670
|
+
.sm-inspector__body{display:flex;flex-direction:column;gap:14px}
|
|
671
|
+
/* The form card: the main column of the entry and shared forms. Every
|
|
672
|
+
field (and the banner) is a centred 680px column — a reading width —
|
|
673
|
+
while the card itself still fills the main area. */
|
|
674
|
+
.sm-form{
|
|
675
|
+
display:flex;flex-direction:column;gap:18px;padding:var(--form-pad);min-width:0;overflow:auto;
|
|
676
|
+
background:var(--surface-form);border-radius:var(--radius-card-lg);
|
|
677
|
+
}
|
|
678
|
+
.sm-form>*{width:100%;max-width:680px;align-self:center}
|
|
679
|
+
|
|
380
680
|
/* ── editor ────────────────────────────────────────────────────────── */
|
|
381
|
-
.
|
|
382
|
-
.
|
|
383
|
-
.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
681
|
+
/* canvas · handle · inspector. The handle column is the gutter (8px in the
|
|
682
|
+
technical look, whose gutter is 0). The 50% is the half-row maximum the
|
|
683
|
+
drag maths (ui/resize.ts) also applies, so a window that shrinks after a
|
|
684
|
+
drag never leaves the canvas squeezed. */
|
|
685
|
+
.sm-editor{flex:1;min-height:0;display:grid;grid-template-columns:1fr max(var(--gutter),8px) min(var(--inspector-w),50%)}
|
|
686
|
+
/* The drag-to-resize handle (spec 2026-09-10 §3): fills its column, draws a
|
|
687
|
+
2px line down its centre on hover and while dragging — a shade off the
|
|
688
|
+
ground, since the col-resize cursor already says it drags (2026-09-10);
|
|
689
|
+
keyboard focus alone gets the accent, a focus ring must be seen. */
|
|
690
|
+
.sm-resize{position:relative;cursor:col-resize;touch-action:none;outline:none;align-self:stretch}
|
|
691
|
+
.sm-resize::after{content:"";position:absolute;top:0;bottom:0;left:50%;width:2px;margin-left:-1px;border-radius:1px;background:transparent;transition:background .12s}
|
|
692
|
+
.sm-resize:hover::after,.sm-admin--resizing .sm-resize::after{background:var(--line-dashed)}
|
|
693
|
+
.sm-resize:focus-visible::after{background:var(--accent)}
|
|
694
|
+
/* While a drag is live: the resize cursor everywhere, no text selection, and
|
|
695
|
+
the canvas iframe must not swallow the pointer when it crosses it. */
|
|
696
|
+
.sm-admin--resizing,.sm-admin--resizing *{cursor:col-resize!important;user-select:none}
|
|
697
|
+
.sm-admin--resizing iframe{pointer-events:none}
|
|
698
|
+
.sm-canvas{
|
|
699
|
+
display:flex;flex-direction:column;background:var(--canvas);border-radius:var(--radius-card-lg);
|
|
700
|
+
min-width:0;min-height:0;overflow:hidden;
|
|
701
|
+
}
|
|
702
|
+
.sm-canvas__scroll{flex:1;min-height:0;overflow:auto;padding:var(--canvas-pad)}
|
|
388
703
|
.sm-page{
|
|
389
|
-
position:relative;background:var(--page-bg);border-radius:var(--radius
|
|
704
|
+
position:relative;background:var(--page-bg);border-radius:var(--page-radius);
|
|
390
705
|
box-shadow:var(--shadow-page);min-height:100%;
|
|
391
706
|
}
|
|
392
|
-
.sm-
|
|
393
|
-
display:
|
|
394
|
-
|
|
707
|
+
.sm-canvas__loading{
|
|
708
|
+
height:240px;display:grid;place-items:center;color:var(--text-subtle);font-family:var(--meta-font);
|
|
709
|
+
font-size:var(--meta-size);letter-spacing:var(--caps-tracking);text-transform:var(--caps-transform);
|
|
395
710
|
}
|
|
396
|
-
.sm-inspector__head{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 14px 10px;flex:none}
|
|
397
|
-
.sm-inspector__body{display:flex;flex-direction:column;gap:14px;padding:14px;overflow:auto}
|
|
398
711
|
.sm-blockglyph{width:14px;height:10px;border:1.5px solid var(--text-muted);border-radius:var(--radius-xs);flex:none}
|
|
712
|
+
/* The selected block's label: a pill riding the outline in the warm look,
|
|
713
|
+
a mono tag tucked in the corner in the technical one. */
|
|
399
714
|
.sm-blocktag{
|
|
400
|
-
position:absolute;top:0;left:0;background:var(--selection);color
|
|
401
|
-
font-family:var(--font
|
|
402
|
-
letter-spacing:var(--tracking
|
|
403
|
-
border-radius:var(--
|
|
715
|
+
position:absolute;top:0;left:0;transform:var(--blocktag-shift);background:var(--selection);color:var(--on-accent);
|
|
716
|
+
font-family:var(--blocktag-font);font-size:var(--blocktag-size);font-weight:600;line-height:1.3;
|
|
717
|
+
letter-spacing:var(--blocktag-tracking);text-transform:var(--blocktag-transform);padding:3px 10px;
|
|
718
|
+
border-radius:var(--blocktag-radius);white-space:nowrap;
|
|
404
719
|
}
|
|
405
720
|
.sm-blocktoolbar{
|
|
406
|
-
display:flex;gap:2px;padding:
|
|
721
|
+
display:flex;gap:2px;padding:3px;background:var(--toolbar-bg);border-radius:var(--radius-btn);
|
|
407
722
|
box-shadow:var(--shadow-float);
|
|
408
723
|
}
|
|
724
|
+
.sm-blocktoolbar__note{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--toolbar-fg);opacity:.7;padding:4px 8px}
|
|
725
|
+
/* The insert affordance between blocks: a labelled pill (the label is
|
|
726
|
+
hidden in the technical look, leaving the 24px circle). */
|
|
409
727
|
.sm-plus{
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
box-shadow:
|
|
413
|
-
|
|
414
|
-
|
|
728
|
+
display:inline-flex;align-items:center;gap:8px;height:var(--plus-h);min-width:var(--plus-h);padding:var(--plus-pad);
|
|
729
|
+
border-radius:var(--radius-round);border:0;background:var(--plus-bg);color:var(--plus-fg);
|
|
730
|
+
font:500 var(--text-lg)/1 var(--font-sans);cursor:pointer;box-shadow:var(--plus-shadow);white-space:nowrap;
|
|
731
|
+
transition:background .12s,transform .12s;
|
|
732
|
+
}
|
|
733
|
+
/* Hover is a tiny scale-up, nothing that moves the pill (the tooltip that
|
|
734
|
+
used to appear under it grew the wrapper and shifted it, 2026-09-10). */
|
|
735
|
+
.sm-plus:hover{background:var(--plus-hover);transform:scale(1.05)}
|
|
736
|
+
.sm-plus__icon{
|
|
737
|
+
width:20px;height:20px;flex:none;border-radius:50%;background:var(--plus-icon-bg);color:var(--plus-icon-fg);
|
|
738
|
+
display:grid;place-items:center;font-size:15px;line-height:1;
|
|
739
|
+
}
|
|
740
|
+
.sm-plus__label{display:var(--plus-label);font-size:var(--text-sm)}
|
|
415
741
|
.sm-guide{height:1px;background:color-mix(in srgb,var(--selection) 35%,transparent)}
|
|
416
|
-
.sm-tooltip{
|
|
417
|
-
background:#15181F;color:#EEF0F5;font-size:var(--text-sm);padding:4px 8px;
|
|
418
|
-
border-radius:var(--radius-sm);white-space:nowrap;
|
|
419
|
-
}
|
|
420
742
|
.sm-outline-row{
|
|
421
743
|
display:flex;align-items:center;justify-content:space-between;gap:4px;
|
|
422
|
-
height:var(--
|
|
744
|
+
height:var(--outline-row-h);border-radius:var(--radius-md);padding:0 6px 0 12px;
|
|
423
745
|
color:var(--text);font-weight:500;background:transparent;
|
|
424
746
|
border:1px solid var(--line);
|
|
425
747
|
}
|
|
426
748
|
.sm-outline-row--clickable{cursor:pointer}
|
|
427
749
|
.sm-outline-row--clickable:hover{background:var(--surface-inset)}
|
|
428
750
|
/* Selected and locked rows are read by their fill, so they drop the hairline —
|
|
429
|
-
border-color, not border, so every row keeps the same
|
|
751
|
+
border-color, not border, so every row keeps the same box. */
|
|
430
752
|
.sm-outline-row--selected,.sm-outline-row--selected:hover{
|
|
431
753
|
background:var(--nav-active-bg);color:var(--nav-active-fg);font-weight:600;border-color:transparent;
|
|
432
754
|
}
|
|
433
|
-
.sm-outline-row--empty{border:1px dashed var(--line-dashed);color:var(--text-muted);padding:0
|
|
434
|
-
.sm-outline-row--locked{background:var(--surface-inset);color:var(--text-muted);padding:0
|
|
755
|
+
.sm-outline-row--empty{border:1px dashed var(--line-dashed);color:var(--text-muted);padding:0 12px}
|
|
756
|
+
.sm-outline-row--locked{background:var(--surface-inset);color:var(--text-muted);padding:0 12px;border-color:transparent}
|
|
435
757
|
.sm-outline-row__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
|
|
758
|
+
.sm-outline-row__note{font-size:var(--text-sm);font-weight:500;flex:none;letter-spacing:var(--caps-tracking);text-transform:var(--caps-transform)}
|
|
759
|
+
.sm-outline-row__add{color:var(--accent);font-weight:500;flex:none}
|
|
760
|
+
/* A row with a grip: the grip takes the left padding's place and the label follows it. */
|
|
761
|
+
.sm-outline-row--grip{padding-left:2px}
|
|
762
|
+
.sm-outline-row--grip .sm-outline-row__label{flex:1}
|
|
436
763
|
|
|
437
764
|
.sm-picker{
|
|
438
|
-
width:300px;background:var(--surface);border:var(--border);border-radius:var(--radius-md);
|
|
765
|
+
width:300px;background:var(--surface);border:var(--menu-border);border-radius:var(--radius-md);
|
|
439
766
|
padding:6px;box-shadow:var(--shadow-pop);
|
|
440
767
|
}
|
|
441
768
|
.sm-picker__item{
|
|
442
769
|
display:flex;gap:10px;align-items:center;width:100%;text-align:left;background:transparent;
|
|
443
|
-
border:0;border-radius:var(--radius-
|
|
770
|
+
border:0;border-radius:var(--radius-sm);padding:8px 10px;cursor:pointer;color:var(--text);font:inherit;
|
|
444
771
|
}
|
|
445
772
|
.sm-picker__item:hover{background:var(--nav-active-bg)}
|
|
446
773
|
.sm-picker__icon{
|
|
@@ -448,26 +775,27 @@ body:has(.sm-admin){margin:0}
|
|
|
448
775
|
color:var(--accent);display:grid;place-items:center;font-size:13px;
|
|
449
776
|
}
|
|
450
777
|
.sm-dashed{
|
|
451
|
-
border:1px dashed var(--line-dashed);border-radius:var(--radius-
|
|
452
|
-
display:flex;align-items:center;justify-content:center;gap:8px;color:var(--text-
|
|
778
|
+
border:1px dashed var(--line-dashed);border-radius:var(--radius-lg);
|
|
779
|
+
display:flex;align-items:center;justify-content:center;gap:8px;color:var(--text-subtle);
|
|
780
|
+
font-family:var(--meta-font);font-size:var(--text-sm);letter-spacing:var(--caps-tracking);text-transform:var(--caps-transform);
|
|
453
781
|
}
|
|
454
782
|
|
|
455
783
|
/* ── media ─────────────────────────────────────────────────────────── */
|
|
456
784
|
.sm-modal{position:fixed;inset:0;z-index:70;background:rgba(0,0,0,.45);display:grid;place-items:center;padding:24px}
|
|
457
785
|
.sm-modal__panel{
|
|
458
786
|
max-width:100%;max-height:100%;display:flex;flex-direction:column;background:var(--surface);
|
|
459
|
-
border:var(--border);border-radius:var(--radius-
|
|
787
|
+
border:var(--menu-border);border-radius:var(--radius-card);box-shadow:var(--shadow-pop);overflow:hidden;
|
|
460
788
|
}
|
|
461
|
-
.sm-modal__head{display:flex;align-items:center;justify-content:space-between;padding:10px
|
|
462
|
-
.sm-modal__body{padding:12px;overflow:auto;display:flex;flex-direction:column;gap:10px;min-height:0}
|
|
463
|
-
.sm-modal__foot{display:flex;justify-content:flex-end;gap:8px;padding:
|
|
789
|
+
.sm-modal__head{display:flex;align-items:center;justify-content:space-between;padding:14px 16px 10px;border-bottom:var(--card-divider)}
|
|
790
|
+
.sm-modal__body{padding:12px 16px;overflow:auto;display:flex;flex-direction:column;gap:10px;min-height:0}
|
|
791
|
+
.sm-modal__foot{display:flex;justify-content:flex-end;gap:8px;padding:12px 16px 14px;border-top:var(--card-divider)}
|
|
464
792
|
.sm-picker-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
465
793
|
.sm-dropzone{
|
|
466
|
-
border:1px dashed var(--line-dashed);border-radius:var(--radius-
|
|
467
|
-
display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:
|
|
794
|
+
border:1px dashed var(--line-dashed);border-radius:var(--radius-lg);background:var(--input-bg);color:var(--text-muted);
|
|
795
|
+
display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:18px;text-align:center;
|
|
468
796
|
}
|
|
469
|
-
.sm-dropzone--bar{padding:
|
|
470
|
-
.sm-mediagrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(
|
|
797
|
+
.sm-dropzone--bar{padding:10px;font-size:var(--text-sm)}
|
|
798
|
+
.sm-mediagrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px}
|
|
471
799
|
.sm-mediacard{
|
|
472
800
|
display:flex;flex-direction:column;gap:4px;padding:6px;background:transparent;border:1.5px solid transparent;
|
|
473
801
|
border-radius:var(--radius-md);cursor:pointer;text-align:left;color:var(--text);font:inherit;min-width:0;
|
|
@@ -480,11 +808,19 @@ body:has(.sm-admin){margin:0}
|
|
|
480
808
|
.sm-mediacard__name{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
481
809
|
.sm-mediacard__meta{font-size:var(--text-sm);color:var(--text-muted)}
|
|
482
810
|
.sm-media{display:flex;flex-direction:column;gap:6px}
|
|
483
|
-
|
|
811
|
+
/* The filled image field: a canvas (inset ground, up to 300px tall) with
|
|
812
|
+
the cropped frame contained inside it — the frame keeps its aspect and
|
|
813
|
+
is sized by the widget as min(300px tall, full width). */
|
|
814
|
+
.sm-media__canvas{
|
|
815
|
+
display:flex;align-items:center;justify-content:center;max-height:300px;overflow:hidden;
|
|
816
|
+
border-radius:var(--radius-md);background:var(--surface-inset);
|
|
817
|
+
}
|
|
818
|
+
.sm-media__thumb{position:relative;overflow:hidden;max-width:100%;max-height:300px;background:var(--surface-inset)}
|
|
484
819
|
.sm-media__thumb>img,.sm-media__thumb>video{position:absolute;max-width:none;display:block}
|
|
485
820
|
.sm-media__alt{font-size:var(--text-sm);color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
821
|
+
.sm-media>.sm-media__alt{text-align:center}
|
|
486
822
|
.sm-media__actions{display:flex;gap:6px}
|
|
487
|
-
.sm-media__chip{display:flex;align-items:center;gap:8px;padding:6px
|
|
823
|
+
.sm-media__chip{display:flex;align-items:center;gap:8px;padding:6px 12px;background:var(--surface-inset);border-radius:var(--radius-btn)}
|
|
488
824
|
.sm-crop{display:grid;grid-template-columns:1fr 240px;gap:14px;min-height:0}
|
|
489
825
|
.sm-crop__stage{position:relative;user-select:none;touch-action:none;background:var(--surface-inset);border-radius:var(--radius-md);overflow:hidden}
|
|
490
826
|
.sm-crop__stage>img{display:block;width:100%;height:auto;pointer-events:none}
|
|
@@ -493,25 +829,36 @@ body:has(.sm-admin){margin:0}
|
|
|
493
829
|
.sm-crop__handle{position:absolute;width:12px;height:12px;background:#fff;border:1px solid rgba(0,0,0,.4);border-radius:2px}
|
|
494
830
|
.sm-crop__handle--nw{left:-6px;top:-6px;cursor:nwse-resize}.sm-crop__handle--ne{right:-6px;top:-6px;cursor:nesw-resize}
|
|
495
831
|
.sm-crop__handle--sw{left:-6px;bottom:-6px;cursor:nesw-resize}.sm-crop__handle--se{right:-6px;bottom:-6px;cursor:nwse-resize}
|
|
496
|
-
.sm-crop__hotspot{position:absolute;width:22px;height:22px;margin:-11px 0 0 -11px;border-radius:50%;border:2px solid #fff;background:
|
|
832
|
+
.sm-crop__hotspot{position:absolute;width:22px;height:22px;margin:-11px 0 0 -11px;border-radius:50%;border:2px solid #fff;background:color-mix(in srgb,var(--accent) 55%,transparent);cursor:grab;box-shadow:0 0 0 1px rgba(0,0,0,.4)}
|
|
497
833
|
.sm-crop__side{display:flex;flex-direction:column;gap:10px}
|
|
498
834
|
.sm-crop__preview{position:relative;overflow:hidden;border-radius:var(--radius-md);background:var(--surface-inset)}
|
|
499
835
|
.sm-crop__preview>img{position:absolute;max-width:none;display:block}
|
|
500
|
-
.sm-mediascreen{display:grid;grid-template-columns:1fr 300px;flex:1;min-height:0}
|
|
501
|
-
.sm-mediascreen__grid{padding:
|
|
502
|
-
.sm-mediascreen__inspector{
|
|
836
|
+
.sm-mediascreen{display:grid;grid-template-columns:1fr 300px;column-gap:var(--gutter);flex:1;min-height:0}
|
|
837
|
+
.sm-mediascreen__grid{padding:var(--table-pad);overflow:auto;background:var(--surface-form);border-radius:var(--radius-card-lg)}
|
|
838
|
+
.sm-mediascreen__inspector{
|
|
839
|
+
border-left:var(--bar-border);padding:var(--card-pad);overflow:auto;display:flex;flex-direction:column;gap:10px;
|
|
840
|
+
background:var(--surface);border-radius:var(--radius-card);
|
|
841
|
+
}
|
|
503
842
|
.sm-facts{display:grid;grid-template-columns:auto 1fr;gap:4px 10px;font-size:var(--text-sm);color:var(--text-muted)}
|
|
504
843
|
.sm-usage{display:flex;flex-direction:column;gap:4px}
|
|
505
844
|
`;
|
|
506
845
|
/** Where the theme toggle's choice is remembered, browser-side only. */
|
|
507
846
|
export const THEME_KEY = "smoodly-theme";
|
|
847
|
+
/** TEMPORARY, see the technical block: which look the developer is comparing. */
|
|
848
|
+
export const LOOK_KEY = "smoodly-look";
|
|
508
849
|
/** Applies a remembered choice before first paint, so a dark-mode editor never
|
|
509
|
-
* gets a white flash
|
|
510
|
-
* `currentScript.parentElement` is that
|
|
511
|
-
* document's <html> is left alone.
|
|
850
|
+
* gets a white flash, and the inspector never jumps to a dragged width. It
|
|
851
|
+
* runs INSIDE the admin wrapper, so `currentScript.parentElement` is that
|
|
852
|
+
* element — no id lookup, and the host document's <html> is left alone. The
|
|
853
|
+
* width test repeats parseStoredWidth (ui/resize.ts) inline: an integer
|
|
854
|
+
* string at or above the minimum, else ignored. */
|
|
512
855
|
const THEME_BOOT = `(function(){try{var e=document.currentScript.parentElement,` +
|
|
513
|
-
`t=localStorage.getItem(${JSON.stringify(THEME_KEY)})
|
|
514
|
-
`
|
|
856
|
+
`t=localStorage.getItem(${JSON.stringify(THEME_KEY)}),` +
|
|
857
|
+
`l=localStorage.getItem(${JSON.stringify(LOOK_KEY)}),` +
|
|
858
|
+
`w=localStorage.getItem(${JSON.stringify(INSPECTOR_W_KEY)});` +
|
|
859
|
+
`if(t==="dark"||t==="light")e.setAttribute("data-theme",t);` +
|
|
860
|
+
`if(l==="technical")e.setAttribute("data-look",l);` +
|
|
861
|
+
`if(w&&/^\\d+$/.test(w)&&+w>=${MIN_INSPECTOR_W})e.style.setProperty("--inspector-w",w+"px")}catch(e){}})()`;
|
|
515
862
|
/** One <style> element and the theme boot, rendered once by AdminLayout. */
|
|
516
863
|
export function AdminStyles() {
|
|
517
864
|
return (_jsxs(_Fragment, { children: [_jsx("style", { "data-smoodly-admin-styles": true, dangerouslySetInnerHTML: { __html: ADMIN_CSS } }), _jsx("script", { dangerouslySetInnerHTML: { __html: THEME_BOOT } })] }));
|