@ohhwells/bridge 0.1.63-next.175 → 0.1.63

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/dist/index.js CHANGED
@@ -96,7 +96,6 @@ function applyTreeToState(state, payload) {
96
96
  const entry = {
97
97
  id: payload.id,
98
98
  label: payload.label ?? "Generated section",
99
- ...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
100
99
  afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
101
100
  ...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
102
101
  ...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
@@ -119,314 +118,6 @@ function deleteSectionFromState(state, sectionId) {
119
118
  return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
120
119
  }
121
120
 
122
- // src/lib/brand-chrome.ts
123
- var BRAND_NAME_KEY = "__ohw_brand_name";
124
- var BRAND_TITLE_KEY = "__ohw_site_title";
125
- var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
126
- var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
127
- BRAND_NAME_KEY,
128
- BRAND_TITLE_KEY,
129
- BRAND_FAVICON_LETTER_KEY
130
- ]);
131
- function upsertMeta(selector, attr, token, value) {
132
- let el = document.head.querySelector(selector);
133
- if (!el) {
134
- el = document.createElement("meta");
135
- el.setAttribute(attr, token);
136
- document.head.appendChild(el);
137
- }
138
- if (el.getAttribute("content") !== value) el.setAttribute("content", value);
139
- }
140
- function escapeXml(value) {
141
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
142
- }
143
- function applyLetterFavicon(letter) {
144
- const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="12" fill="#111827"/><text x="32" y="46" font-family="system-ui,-apple-system,Segoe UI,sans-serif" font-size="40" font-weight="700" text-anchor="middle" fill="#ffffff">${escapeXml(letter)}</text></svg>`;
145
- const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
146
- let link = document.head.querySelector('link[rel="icon"]');
147
- if (!link) {
148
- link = document.createElement("link");
149
- link.rel = "icon";
150
- document.head.appendChild(link);
151
- }
152
- link.type = "image/svg+xml";
153
- if (link.href !== href) link.href = href;
154
- }
155
- function applyBrandChrome(content) {
156
- const name = content[BRAND_NAME_KEY];
157
- if (typeof name === "string" && name.length > 0) {
158
- document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
159
- if (el.textContent !== name) el.textContent = name;
160
- if (el.getAttribute("title") !== name) el.setAttribute("title", name);
161
- });
162
- }
163
- const title = content[BRAND_TITLE_KEY];
164
- if (typeof title === "string" && title.length > 0) {
165
- if (document.title !== title) document.title = title;
166
- upsertMeta('meta[property="og:title"]', "property", "og:title", title);
167
- upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
168
- }
169
- const letter = content[BRAND_FAVICON_LETTER_KEY];
170
- if (typeof letter === "string" && letter.length > 0) {
171
- applyLetterFavicon(letter);
172
- }
173
- }
174
-
175
- // src/lib/brand-kit.ts
176
- var BRAND_KIT_KEY = "__ohw_brand";
177
- var BRAND_VAR_PREFIX = "--ohw-brand-";
178
- var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
179
- (role) => `${BRAND_VAR_PREFIX}${role}`
180
- );
181
- var FONT_VARS = { heading: ["--font-heading", "--font-display"], body: ["--font-body"] };
182
- var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
183
- function brandColorVars(kit) {
184
- const { dark, primary, accent, light } = kit.palette;
185
- const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
186
- return {
187
- [`${BRAND_VAR_PREFIX}primary`]: primary,
188
- [`${BRAND_VAR_PREFIX}accent`]: accent,
189
- [`${BRAND_VAR_PREFIX}light`]: light,
190
- [`${BRAND_VAR_PREFIX}dark`]: dark,
191
- [`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
192
- [`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
193
- [`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
194
- };
195
- }
196
- function parseBrandKit(raw) {
197
- if (!raw) return null;
198
- try {
199
- const parsed = JSON.parse(raw);
200
- const p = parsed?.palette;
201
- const f = parsed?.fonts;
202
- if (!p || !f || typeof p.dark !== "string" || typeof p.primary !== "string" || typeof p.accent !== "string" || typeof p.light !== "string" || typeof f.heading !== "string" || typeof f.body !== "string") {
203
- return null;
204
- }
205
- return {
206
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
207
- fonts: { heading: f.heading, body: f.body }
208
- };
209
- } catch {
210
- return null;
211
- }
212
- }
213
- function familyOf(stack) {
214
- const first = stack.split(",")[0]?.trim() ?? "";
215
- return first.replace(/^['"]|['"]$/g, "");
216
- }
217
- function loadBrandFonts(families) {
218
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
219
- if (unique.length === 0) return;
220
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
221
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
222
- let link = document.getElementById(BRAND_FONT_LINK_ID);
223
- if (!link) {
224
- link = document.createElement("link");
225
- link.id = BRAND_FONT_LINK_ID;
226
- link.rel = "stylesheet";
227
- document.head.appendChild(link);
228
- }
229
- if (link.href !== href) link.href = href;
230
- }
231
- function applyBrandToDom(kit) {
232
- const root = document.documentElement;
233
- if (!kit) {
234
- for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
235
- for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
236
- document.getElementById(BRAND_FONT_LINK_ID)?.remove();
237
- return;
238
- }
239
- for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
240
- for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
241
- for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
242
- loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
243
- }
244
-
245
- // src/lib/section-styles.ts
246
- var STYLE_STORE_KEY = "__ohw_styles";
247
- var STYLE_SHEET_ID = "ohw-section-styles";
248
- function parseStyleStore(raw) {
249
- if (!raw) return null;
250
- try {
251
- const parsed = JSON.parse(raw);
252
- if (parsed?.v !== 1) return null;
253
- return {
254
- v: 1,
255
- sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
256
- nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
257
- };
258
- } catch {
259
- return null;
260
- }
261
- }
262
- var BG_VALUES = {
263
- surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
264
- accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
265
- "accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
266
- };
267
- var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
268
- function styleSheetCss() {
269
- const rules = [];
270
- for (const [tone, value] of Object.entries(BG_VALUES)) {
271
- rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
272
- }
273
- rules.push(
274
- `[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
275
- );
276
- rules.push(
277
- `[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
278
- `[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
279
- );
280
- for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
281
- rules.push(
282
- `[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
283
- );
284
- }
285
- rules.push(
286
- `[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
287
- );
288
- for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
289
- rules.push(
290
- `[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
291
- );
292
- }
293
- const pad = { tight: 40, balanced: 64, airy: 96 };
294
- for (const [spacing, px] of Object.entries(pad)) {
295
- rules.push(
296
- `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
297
- );
298
- }
299
- return rules.join("\n");
300
- }
301
- var STYLE_FONT_LINK_ID = "ohw-style-fonts";
302
- function loadStyleFonts(families) {
303
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
304
- const existing = document.getElementById(STYLE_FONT_LINK_ID);
305
- if (unique.length === 0) {
306
- existing?.remove();
307
- return;
308
- }
309
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
310
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
311
- let link = existing;
312
- if (!link) {
313
- link = document.createElement("link");
314
- link.id = STYLE_FONT_LINK_ID;
315
- link.rel = "stylesheet";
316
- document.head.appendChild(link);
317
- }
318
- if (link.href !== href) link.href = href;
319
- }
320
- var SECTION_ATTRS = {
321
- sectionBackground: "data-ohw-style-bg",
322
- textDistribution: "data-ohw-style-distribution",
323
- headlineScale: "data-ohw-style-headline",
324
- imageAspect: "data-ohw-style-aspect",
325
- spacing: "data-ohw-style-spacing"
326
- };
327
- var NODE_WROTE_ATTR = "data-ohw-style-node";
328
- var NODE_PROPS = ["color", "font-family", "font-size", "background"];
329
- function saveInline(el, prop) {
330
- const attr = `data-ohw-style-prev-${prop}`;
331
- if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
332
- }
333
- function restoreInline(el, prop) {
334
- const attr = `data-ohw-style-prev-${prop}`;
335
- if (!el.hasAttribute(attr)) return;
336
- const prev = el.getAttribute(attr) ?? "";
337
- if (prev) el.style.setProperty(prop, prev);
338
- else el.style.removeProperty(prop);
339
- el.removeAttribute(attr);
340
- }
341
- function ensureStyleSheet() {
342
- let el = document.getElementById(STYLE_SHEET_ID);
343
- if (!el) {
344
- el = document.createElement("style");
345
- el.id = STYLE_SHEET_ID;
346
- document.head.appendChild(el);
347
- }
348
- const css = styleSheetCss();
349
- if (el.textContent !== css) el.textContent = css;
350
- }
351
- function clearSectionAttrs(root) {
352
- for (const attr of Object.values(SECTION_ATTRS)) {
353
- for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
354
- }
355
- for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
356
- restoreInline(el, "background");
357
- el.removeAttribute("data-ohw-style-bgcolor");
358
- }
359
- }
360
- function clearNodeProps(root) {
361
- for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
362
- const h = el;
363
- for (const prop of NODE_PROPS) restoreInline(h, prop);
364
- h.removeAttribute(NODE_WROTE_ATTR);
365
- }
366
- }
367
- function buttonSurfaceOf(el) {
368
- return el.closest("a, button") ?? el;
369
- }
370
- function applyStylesToDom(store) {
371
- ensureStyleSheet();
372
- clearSectionAttrs(document);
373
- clearNodeProps(document);
374
- loadStyleFonts(
375
- store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
376
- );
377
- if (!store) return;
378
- for (const [sectionId, override] of Object.entries(store.sections)) {
379
- const sections = document.querySelectorAll(
380
- `[data-ohw-section="${CSS.escape(sectionId)}"]`
381
- );
382
- for (const section of Array.from(sections)) {
383
- for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
384
- const value = override[prop];
385
- if (value === void 0) continue;
386
- if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
387
- section.setAttribute(attr, String(value).replace(":", "-"));
388
- }
389
- if (override.sectionBackgroundColor !== void 0) {
390
- saveInline(section, "background");
391
- section.style.setProperty("background", override.sectionBackgroundColor, "important");
392
- section.setAttribute("data-ohw-style-bgcolor", "");
393
- }
394
- }
395
- }
396
- for (const [key, override] of Object.entries(store.nodes)) {
397
- const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
398
- for (const el of Array.from(nodes)) {
399
- if (override.color !== void 0) {
400
- saveInline(el, "color");
401
- el.style.setProperty("color", override.color, "important");
402
- el.setAttribute(NODE_WROTE_ATTR, "");
403
- }
404
- if (override.fontFamily !== void 0) {
405
- saveInline(el, "font-family");
406
- el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
407
- el.setAttribute(NODE_WROTE_ATTR, "");
408
- }
409
- if (override.fontSize !== void 0) {
410
- saveInline(el, "font-size");
411
- el.style.setProperty("font-size", `${override.fontSize}px`, "important");
412
- el.setAttribute(NODE_WROTE_ATTR, "");
413
- }
414
- if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
415
- const surface = buttonSurfaceOf(el);
416
- if (override.buttonBackground !== void 0) {
417
- saveInline(surface, "background");
418
- surface.style.setProperty("background", override.buttonBackground, "important");
419
- }
420
- if (override.buttonText !== void 0) {
421
- saveInline(surface, "color");
422
- surface.style.setProperty("color", override.buttonText, "important");
423
- }
424
- surface.setAttribute(NODE_WROTE_ATTR, "");
425
- }
426
- }
427
- }
428
- }
429
-
430
121
  // src/ui/ai-tree/aiSectionsManager.tsx
431
122
  import { flushSync } from "react-dom";
432
123
  import { createRoot } from "react-dom/client";
@@ -441,8 +132,7 @@ function lucideByName(name) {
441
132
  }
442
133
  var typeStyle = (spec, font) => ({
443
134
  fontFamily: font,
444
- // Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
445
- fontSize: spec.size >= 24 ? `clamp(${Math.max(18, Math.round(spec.size * 0.6))}px, ${(spec.size / 9).toFixed(2)}vw, ${spec.size}px)` : spec.size,
135
+ fontSize: spec.size,
446
136
  lineHeight: spec.line,
447
137
  fontWeight: spec.weight
448
138
  });
@@ -469,8 +159,6 @@ var AI_RESPONSIVE_CSS = [
469
159
  " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
470
160
  " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
471
161
  " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
472
- " [data-ai-responsive] { overflow-x: hidden; }",
473
- " [data-ai-responsive] img { max-width: 100%; }",
474
162
  "}"
475
163
  ].join("\n");
476
164
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
@@ -1478,20 +1166,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1478
1166
  const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
1479
1167
  const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
1480
1168
  const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
1481
- const toneBackground = (() => {
1482
- const { dark, primary, light } = resolvedBrand.palette;
1483
- switch (settings.sectionBackground) {
1484
- case "surface":
1485
- return `color-mix(in srgb, ${light} 94%, ${dark})`;
1486
- case "accent":
1487
- return primary;
1488
- case "accent-soft":
1489
- return `color-mix(in srgb, ${primary} 12%, ${light})`;
1490
- default:
1491
- return void 0;
1492
- }
1493
- })();
1494
- const distributed = !isOverlay && settings.textDistribution;
1495
1169
  return /* @__PURE__ */ jsxs(
1496
1170
  "section",
1497
1171
  {
@@ -1501,11 +1175,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1501
1175
  style: {
1502
1176
  position: "relative",
1503
1177
  padding: `${pad}px 0`,
1504
- background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
1178
+ background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
1505
1179
  backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
1506
1180
  backgroundSize: "cover",
1507
- backgroundPosition: "center",
1508
- color: settings.sectionBackground === "accent" ? resolvedBrand.palette.light : void 0
1181
+ backgroundPosition: "center"
1509
1182
  },
1510
1183
  children: [
1511
1184
  /* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
@@ -1529,24 +1202,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1529
1202
  display: "grid",
1530
1203
  gridTemplateColumns: "repeat(12, 1fr)",
1531
1204
  gap: AI_TREE_TOKENS.spacing6,
1532
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1205
+ alignItems: settings.verticalPosition === "top" ? "start" : "center",
1533
1206
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1534
1207
  },
1535
- children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx(
1536
- "div",
1537
- {
1538
- "data-ai-cell": "",
1539
- style: {
1540
- gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1541
- minWidth: 0,
1542
- // space-between: each column becomes a flex column whose content spreads over
1543
- // the full row height instead of clumping at the top.
1544
- ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
1545
- },
1546
- children: renderNode(block, ctx, `r${r2}.b${b}`)
1547
- },
1548
- b
1549
- ))
1208
+ children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx("div", { style: { gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`, minWidth: 0 }, children: renderNode(block, ctx, `r${r2}.b${b}`) }, b))
1550
1209
  },
1551
1210
  r2
1552
1211
  ))
@@ -1562,34 +1221,17 @@ import { jsx as jsx2 } from "react/jsx-runtime";
1562
1221
  var CONTAINER_ATTR = "data-ohw-ai-generated";
1563
1222
  var REPLACED_ATTR = "data-ohw-ai-replaced-by";
1564
1223
  var REMOVED_ATTR = "data-ohw-ai-removed";
1565
- function readRootVar(name) {
1566
- if (typeof document === "undefined") return "";
1567
- return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1568
- }
1569
- function deriveBrandOverride() {
1570
- const dark = readRootVar("--ohw-brand-dark");
1571
- const primary = readRootVar("--ohw-brand-primary");
1572
- const light = readRootVar("--ohw-brand-light");
1573
- if (!dark || !primary || !light) return null;
1574
- const accent = readRootVar("--ohw-brand-accent");
1575
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1576
- const body = readRootVar("--font-body");
1577
- return {
1578
- palette: { dark, primary, accent: accent || dark, light },
1579
- fonts: {
1580
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
1581
- body: body || AI_DEFAULT_BRAND.fonts.body
1582
- }
1583
- };
1584
- }
1585
1224
  function deriveTemplateBrand() {
1586
- const dark = readRootVar("--color-dark");
1587
- const primary = readRootVar("--color-primary");
1588
- const light = readRootVar("--color-light");
1225
+ if (typeof document === "undefined") return null;
1226
+ const cs = getComputedStyle(document.documentElement);
1227
+ const read = (name) => cs.getPropertyValue(name).trim();
1228
+ const dark = read("--color-dark");
1229
+ const primary = read("--color-primary");
1230
+ const light = read("--color-light");
1589
1231
  if (!dark || !primary || !light) return null;
1590
- const accent = readRootVar("--color-accent");
1591
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1592
- const body = readRootVar("--font-body");
1232
+ const accent = read("--color-accent");
1233
+ const heading = read("--font-heading") || read("--font-display");
1234
+ const body = read("--font-body");
1593
1235
  return {
1594
1236
  palette: { dark, primary, accent: accent || dark, light },
1595
1237
  fonts: {
@@ -1681,12 +1323,8 @@ function syncReplacedOriginals(state) {
1681
1323
  }
1682
1324
  function applyAiSectionsToDom(state, options) {
1683
1325
  if (typeof document === "undefined") return;
1684
- const brandOverride = deriveBrandOverride();
1685
1326
  const templateBrand = deriveTemplateBrand();
1686
- const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
1687
- const pagePath = window.location.pathname;
1688
- const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
1689
- const activeIds = new Set(pageSections.map((entry) => entry.id));
1327
+ const activeIds = new Set(state.sections.map((entry) => entry.id));
1690
1328
  for (const [id, section] of mounted) {
1691
1329
  if (!activeIds.has(id)) {
1692
1330
  section.root.unmount();
@@ -1694,8 +1332,8 @@ function applyAiSectionsToDom(state, options) {
1694
1332
  mounted.delete(id);
1695
1333
  }
1696
1334
  }
1697
- for (const entry of pageSections) {
1698
- const serialized = JSON.stringify(entry) + brandKey;
1335
+ for (const entry of state.sections) {
1336
+ const serialized = JSON.stringify(entry);
1699
1337
  const existing = mounted.get(entry.id);
1700
1338
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
1701
1339
  continue;
@@ -1709,7 +1347,6 @@ function applyAiSectionsToDom(state, options) {
1709
1347
  mounted.delete(entry.id);
1710
1348
  }
1711
1349
  container.setAttribute("data-ohw-section", entry.id);
1712
- container.setAttribute("data-ohw-instance", entry.id);
1713
1350
  container.setAttribute("data-ohw-section-label", entry.label);
1714
1351
  placeContainer(container, entry);
1715
1352
  const root = mounted.get(entry.id)?.root ?? createRoot(container);
@@ -1720,7 +1357,7 @@ function applyAiSectionsToDom(state, options) {
1720
1357
  AiTreeRenderer,
1721
1358
  {
1722
1359
  tree: entry.tree,
1723
- brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1360
+ brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1724
1361
  resolveMedia,
1725
1362
  editKeyPrefix: `ai.${entry.id}`
1726
1363
  }
@@ -2337,7 +1974,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2337
1974
  const autoId = useId();
2338
1975
  const insertAfter = insertAfterProp ?? autoId;
2339
1976
  const [schedule, setSchedule] = useState2(null);
2340
- const [loading, setLoading] = useState2(initialScheduleId !== null);
1977
+ const [loading, setLoading] = useState2(true);
2341
1978
  const [inEditor, setInEditor] = useState2(false);
2342
1979
  const [isHovered, setIsHovered] = useState2(false);
2343
1980
  const [modalState, setModalState] = useState2(null);
@@ -2511,10 +2148,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2511
2148
  "*"
2512
2149
  );
2513
2150
  };
2151
+ if (!inEditor && !loading && !schedule) return null;
2514
2152
  const sectionId = `scheduling-${insertAfter}`;
2515
- if (!inEditor && !loading && !schedule) {
2516
- return /* @__PURE__ */ jsx4("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2517
- }
2518
2153
  return /* @__PURE__ */ jsxs3(
2519
2154
  "section",
2520
2155
  {
@@ -7033,12 +6668,8 @@ function parseSectionsFromHtml(html) {
7033
6668
 
7034
6669
  // src/ui/ai-section/AiSectionOverlay.tsx
7035
6670
  import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
7036
- function findSectionElement(instanceId) {
7037
- const escaped = CSS.escape(instanceId);
7038
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7039
- }
7040
- function readRect(instanceId) {
7041
- const el = findSectionElement(instanceId);
6671
+ function readRect(sectionId) {
6672
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7042
6673
  if (!el) return null;
7043
6674
  const r2 = el.getBoundingClientRect();
7044
6675
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7061,7 +6692,7 @@ function useLiveSectionRect(sectionId) {
7061
6692
  const opts = { capture: true, passive: true };
7062
6693
  window.addEventListener("scroll", update, opts);
7063
6694
  window.addEventListener("resize", update);
7064
- const el = findSectionElement(sectionId);
6695
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7065
6696
  const ro = el ? new ResizeObserver(update) : null;
7066
6697
  if (el && ro) ro.observe(el);
7067
6698
  const interval = setInterval(update, 500);
@@ -7074,14 +6705,6 @@ function useLiveSectionRect(sectionId) {
7074
6705
  }, [sectionId]);
7075
6706
  return rect;
7076
6707
  }
7077
- function computeSectionBoundaryFlags(instanceId) {
7078
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7079
- (el) => !el.parentElement?.closest("[data-ohw-section]")
7080
- );
7081
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7082
- if (index === -1) return { isFirst: true, isLast: true };
7083
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7084
- }
7085
6708
  var PRIMARY2 = "#0885FE";
7086
6709
  function edgeAwareRadius(rect) {
7087
6710
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7155,7 +6778,6 @@ function AiSectionOverlay({
7155
6778
  }) {
7156
6779
  const [selectedId, setSelectedId] = useState4(null);
7157
6780
  const [reviewId, setReviewId] = useState4(null);
7158
- const [reviewButtonsHidden, setReviewButtonsHidden] = useState4(false);
7159
6781
  const reviewIdRef = useRef4(null);
7160
6782
  reviewIdRef.current = reviewId;
7161
6783
  const selectedIdRef = useRef4(null);
@@ -7164,7 +6786,7 @@ function AiSectionOverlay({
7164
6786
  (el) => {
7165
6787
  postToParent2({
7166
6788
  type: "ow:section-selected",
7167
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
6789
+ sectionId: el?.dataset.ohwSection ?? null,
7168
6790
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7169
6791
  });
7170
6792
  },
@@ -7173,7 +6795,7 @@ function AiSectionOverlay({
7173
6795
  const selectFromElement = useCallback2(
7174
6796
  (el, options) => {
7175
6797
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7176
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
6798
+ const id = sectionEl?.dataset.ohwSection ?? null;
7177
6799
  if (id === selectedIdRef.current) return;
7178
6800
  setSelectedId(id);
7179
6801
  if (options?.report !== false) report(sectionEl);
@@ -7214,10 +6836,9 @@ function AiSectionOverlay({
7214
6836
  }
7215
6837
  const found = readRect(sectionId) != null;
7216
6838
  setReviewId(found ? sectionId : null);
7217
- setReviewButtonsHidden(e.data.hideButtons === true);
7218
6839
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7219
6840
  if (found) {
7220
- document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
6841
+ document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7221
6842
  }
7222
6843
  }
7223
6844
  };
@@ -7236,7 +6857,7 @@ function AiSectionOverlay({
7236
6857
  return;
7237
6858
  }
7238
6859
  const sec = t.closest("[data-ohw-section]");
7239
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
6860
+ setHoveredId(sec?.dataset.ohwSection ?? null);
7240
6861
  };
7241
6862
  const onLeave = () => setHoveredId(null);
7242
6863
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -7268,29 +6889,9 @@ function AiSectionOverlay({
7268
6889
  },
7269
6890
  [postToParent2]
7270
6891
  );
7271
- const activeSelectionId = reviewId ? null : selectedId;
7272
- const selectionRect = useLiveSectionRect(activeSelectionId);
6892
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
7273
6893
  const reviewRect = useLiveSectionRect(reviewId);
7274
6894
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
7275
- useEffect4(() => {
7276
- if (!activeSelectionId || !selectionRect) {
7277
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
7278
- return;
7279
- }
7280
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
7281
- postToParent2({
7282
- type: "ow:section-rect",
7283
- instanceId: activeSelectionId,
7284
- rect: {
7285
- top: selectionRect.top + window.scrollY,
7286
- left: selectionRect.left + window.scrollX,
7287
- width: selectionRect.width,
7288
- height: selectionRect.height
7289
- },
7290
- isFirst,
7291
- isLast
7292
- });
7293
- }, [activeSelectionId, selectionRect, postToParent2]);
7294
6895
  return /* @__PURE__ */ jsxs8(Fragment5, { children: [
7295
6896
  hoverRect && /* @__PURE__ */ jsx16(
7296
6897
  "div",
@@ -7341,16 +6942,13 @@ function AiSectionOverlay({
7341
6942
  border: `2px solid ${PRIMARY2}`,
7342
6943
  borderRadius: edgeAwareRadius(reviewRect),
7343
6944
  zIndex: 2147483200,
7344
- // The veil itself: swallows clicks so the section stays locked until decided. This
7345
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
7346
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
7347
- // Accept/Discard resolves to the media beneath and opens the file picker.
6945
+ // The veil itself: swallows clicks so the section stays locked until decided.
7348
6946
  background: "rgba(8, 133, 254, 0.04)",
7349
6947
  pointerEvents: "auto",
7350
6948
  cursor: "default"
7351
6949
  },
7352
6950
  onClick: (e) => e.stopPropagation(),
7353
- children: !reviewButtonsHidden && /* @__PURE__ */ jsxs8(
6951
+ children: /* @__PURE__ */ jsxs8(
7354
6952
  "div",
7355
6953
  {
7356
6954
  style: {
@@ -11250,296 +10848,42 @@ function deleteFooterColumn(column) {
11250
10848
  };
11251
10849
  }
11252
10850
 
11253
- // src/lib/logo-identity.ts
11254
- var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
11255
- var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
11256
- var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
11257
- var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
11258
- var LOGO_ALT_KEY = "logo-alt";
11259
- var LOGO_IMAGE_URL_KEY = "nav-logo-image";
11260
- var PLACEHOLDER_BUSINESS_NAME = "Business name";
11261
- function resolveLogoDisplayText(text) {
11262
- const trimmed = (text ?? "").trim();
11263
- return trimmed || PLACEHOLDER_BUSINESS_NAME;
11264
- }
11265
- function isFooterLogoRoot(root) {
11266
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11267
- }
11268
- function imageKeyForRoot(root) {
11269
- return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
11270
- }
11271
- function textKeyForRoot(root) {
11272
- return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
11273
- }
11274
- function ensureLogoHrefKey(root) {
11275
- if (!(root instanceof HTMLAnchorElement)) return;
11276
- if (root.hasAttribute("data-ohw-href-key")) return;
11277
- root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
11278
- }
11279
- function applyLogoIdentity(text, isPlaceholder) {
11280
- const display = resolveLogoDisplayText(text);
11281
- const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
11282
- for (const key of LOGO_TEXT_KEYS) {
11283
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11284
- if (el.textContent !== display) el.textContent = display;
11285
- });
11286
- }
11287
- for (const key of LOGO_IMAGE_KEYS) {
11288
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11289
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
11290
- if (img) img.alt = display;
11291
- });
11292
- }
11293
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
11294
- if (placeholder) el.setAttribute("data-ohw-placeholder", "");
11295
- else el.removeAttribute("data-ohw-placeholder");
11296
- });
11297
- return display;
11298
- }
11299
- function applyLogoImage(url, alt) {
11300
- const displayAlt = resolveLogoDisplayText(alt);
11301
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11302
- ensureLogoHrefKey(root);
11303
- const imageKey = imageKeyForRoot(root);
11304
- const textKey = textKeyForRoot(root);
11305
- let img = root.querySelector(`img[data-ohw-key="${imageKey}"]`) ?? (root.querySelector(`[data-ohw-key="${imageKey}"]`) instanceof HTMLImageElement ? root.querySelector(`[data-ohw-key="${imageKey}"]`) : null) ?? root.querySelector("img");
11306
- let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
11307
- if (url) {
11308
- if (!img) {
11309
- img = document.createElement("img");
11310
- img.setAttribute("data-ohw-editable", "image");
11311
- img.setAttribute("data-ohw-key", imageKey);
11312
- img.alt = displayAlt;
11313
- img.style.height = "";
11314
- img.style.maxHeight = "none";
11315
- img.style.width = "auto";
11316
- img.style.display = "block";
11317
- img.style.objectFit = "contain";
11318
- root.insertBefore(img, root.firstChild);
11319
- } else {
11320
- img.setAttribute("data-ohw-editable", "image");
11321
- img.setAttribute("data-ohw-key", imageKey);
11322
- }
11323
- img.removeAttribute("srcset");
11324
- img.removeAttribute("sizes");
11325
- img.src = url;
11326
- img.alt = displayAlt;
11327
- img.style.display = "block";
11328
- if (textEl) textEl.style.display = "none";
11329
- root.removeAttribute("data-ohw-placeholder");
11330
- return;
11331
- }
11332
- if (img) {
11333
- img.removeAttribute("src");
11334
- img.removeAttribute("srcset");
11335
- img.removeAttribute("sizes");
11336
- img.alt = displayAlt;
11337
- img.style.display = "none";
11338
- }
11339
- if (!textEl) {
11340
- textEl = document.createElement("span");
11341
- textEl.setAttribute("data-ohw-editable", "plain");
11342
- textEl.setAttribute("data-ohw-key", textKey);
11343
- root.appendChild(textEl);
11344
- }
11345
- textEl.style.display = "";
11346
- if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
11347
- if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
11348
- root.setAttribute("data-ohw-placeholder", "");
11349
- } else {
11350
- root.removeAttribute("data-ohw-placeholder");
11351
- }
11352
- });
11353
- }
11354
- function applyLogoHref(href) {
11355
- const target = href.trim() || "/";
11356
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11357
- ensureLogoHrefKey(root);
11358
- if (root instanceof HTMLAnchorElement) {
11359
- root.setAttribute("href", target);
11360
- }
11361
- });
11362
- for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
11363
- }
11364
- function readLogoIdentityFromDom() {
11365
- let imageUrl = null;
11366
- for (const key of LOGO_IMAGE_KEYS) {
11367
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
11368
- const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
11369
- const attrSrc = img?.getAttribute("src")?.trim() ?? "";
11370
- if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
11371
- imageUrl = img.currentSrc || img.src;
11372
- break;
11373
- }
11374
- }
11375
- let text = PLACEHOLDER_BUSINESS_NAME;
11376
- let isPlaceholder = true;
11377
- for (const key of LOGO_TEXT_KEYS) {
11378
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
11379
- if (el?.textContent?.trim()) {
11380
- text = el.textContent.trim();
11381
- const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
11382
- isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
11383
- break;
11384
- }
11385
- }
11386
- if (imageUrl) {
11387
- const logoImg = document.querySelector(
11388
- '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
11389
- );
11390
- const alt = logoImg?.alt?.trim() || text;
11391
- isPlaceholder = false;
11392
- const hrefEl = document.querySelector(
11393
- 'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
11394
- );
11395
- const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
11396
- return { text, isPlaceholder, imageUrl, href: href2, alt };
11397
- }
11398
- const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
11399
- const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
11400
- return { text, isPlaceholder, imageUrl: null, href, alt: text };
11401
- }
11402
- function applyLogoFromContent(content) {
11403
- const hasLogoIdentity = LOGO_PLACEHOLDER_KEY in content || LOGO_TEXT_KEYS.some((key) => key in content) || LOGO_IMAGE_KEYS.some((key) => key in content) || LOGO_ALT_KEY in content || LOGO_HREF_KEYS.some((key) => key in content);
11404
- if (!hasLogoIdentity) return false;
11405
- const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
11406
- const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
11407
- const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
11408
- const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
11409
- const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
11410
- const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
11411
- if (logoImageUrl) {
11412
- applyLogoImage(logoImageUrl, logoAlt);
11413
- } else {
11414
- if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
11415
- applyLogoIdentity(logoText, logoIsPlaceholder);
11416
- }
11417
- const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
11418
- if (typeof logoHref === "string" && logoHref.trim()) {
11419
- applyLogoHref(logoHref);
11420
- }
11421
- return true;
11422
- }
11423
-
11424
- // src/lib/logo-size.ts
11425
- var LOGO_SIZE_DEFAULTS = {
11426
- navbar: 28,
11427
- footer: 32
11428
- };
11429
- var LOGO_SIZE_MIN = 16;
11430
- var LOGO_SIZE_MAX = 80;
11431
- var LOGO_SIZE_DESKTOP_KEYS = {
11432
- navbar: "nav-logo-size",
11433
- footer: "footer-logo-size"
11434
- };
11435
- var LOGO_SIZE_MOBILE_KEYS = {
11436
- navbar: "nav-logo-size-mobile",
11437
- footer: "footer-logo-size-mobile"
11438
- };
11439
- var LOGO_SIZE_KEYS = [
11440
- LOGO_SIZE_DESKTOP_KEYS.navbar,
11441
- LOGO_SIZE_DESKTOP_KEYS.footer,
11442
- LOGO_SIZE_MOBILE_KEYS.navbar,
11443
- LOGO_SIZE_MOBILE_KEYS.footer
11444
- ];
11445
- function isFooterLogoRoot2(root) {
11446
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11447
- }
11448
- function getLogoPlacement(root) {
11449
- return isFooterLogoRoot2(root) ? "footer" : "navbar";
11450
- }
11451
- function parseLogoSizePx(raw, fallback) {
11452
- if (raw == null || raw === "") return fallback;
11453
- const n = Number.parseFloat(raw);
11454
- if (!Number.isFinite(n)) return fallback;
11455
- return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
11456
- }
11457
- function isMobileLogoSizeFollowing(content, placement) {
11458
- const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
11459
- return raw == null || raw.trim() === "";
11460
- }
11461
- function resolveDesktopLogoSize(content, placement) {
11462
- return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
11463
- }
11464
- function resolveMobileLogoSize(content, placement) {
11465
- if (isMobileLogoSizeFollowing(content, placement)) {
11466
- return resolveDesktopLogoSize(content, placement);
11467
- }
11468
- return parseLogoSizePx(
11469
- content[LOGO_SIZE_MOBILE_KEYS[placement]],
11470
- resolveDesktopLogoSize(content, placement)
11471
- );
10851
+ // src/lib/add-footer-column.ts
10852
+ function buildFooterColumnEditContentPatch(result) {
10853
+ return {
10854
+ [result.headingKey]: result.heading,
10855
+ [result.hrefKey]: result.href,
10856
+ [result.labelKey]: result.label,
10857
+ [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
10858
+ };
11472
10859
  }
11473
- function setRootSizeVars(root, desktopPx, mobilePx, following) {
11474
- root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
11475
- if (following) {
11476
- root.style.removeProperty("--ohw-logo-size-mobile");
11477
- } else {
11478
- root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
10860
+ function addFooterColumnWithPersist({
10861
+ postToParent: postToParent2
10862
+ }) {
10863
+ if (!canAddFooterColumn()) {
10864
+ postToParent2({
10865
+ type: "ow:toast",
10866
+ title: `Maximum ${MAX_FOOTER_COLUMNS} columns`,
10867
+ toastType: "error"
10868
+ });
10869
+ return null;
11479
10870
  }
11480
- root.querySelectorAll("img").forEach((img) => {
11481
- img.style.height = "";
11482
- img.style.maxHeight = "none";
11483
- img.style.width = "auto";
11484
- img.style.objectFit = "contain";
11485
- });
11486
- }
11487
- function applyLogoSizes(content) {
11488
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11489
- const placement = getLogoPlacement(root);
11490
- const desktop = resolveDesktopLogoSize(content, placement);
11491
- const following = isMobileLogoSizeFollowing(content, placement);
11492
- const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
11493
- setRootSizeVars(root, desktop, mobile, following);
11494
- });
11495
- }
11496
- function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
11497
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11498
- if (getLogoPlacement(root) !== placement) return;
11499
- setRootSizeVars(root, desktopPx, mobilePx, following);
10871
+ const result = insertFooterColumn();
10872
+ const patch = buildFooterColumnEditContentPatch(result);
10873
+ setStoredLinkHref(result.hrefKey, result.href);
10874
+ postToParent2({
10875
+ type: "ow:change",
10876
+ nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
11500
10877
  });
11501
- }
11502
- function logoHasUploadedImage(logoEl) {
11503
- if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
11504
- const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
11505
- if (!img) return false;
11506
- const src = img.getAttribute("src")?.trim() ?? "";
11507
- if (!src || src.startsWith("data:")) return false;
11508
- if (img.style.display === "none") return false;
11509
- return true;
11510
- }
11511
- function getLogoInteractionRect(logoEl) {
11512
- if (logoHasUploadedImage(logoEl)) {
11513
- const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
11514
- if (img) {
11515
- const r2 = img.getBoundingClientRect();
11516
- if (r2.width > 0 && r2.height > 0) return r2;
11517
- }
11518
- }
11519
- const text = logoEl.querySelector(
11520
- '[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
11521
- );
11522
- if (text) {
11523
- const style = window.getComputedStyle(text);
11524
- if (style.display !== "none" && style.visibility !== "hidden") {
11525
- const r2 = text.getBoundingClientRect();
11526
- if (r2.width > 0 && r2.height > 0) return r2;
11527
- }
11528
- }
11529
- return logoEl.getBoundingClientRect();
11530
- }
11531
- function readLogoSizeState(content, placement) {
11532
- const desktopPx = resolveDesktopLogoSize(content, placement);
11533
- const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
11534
- const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
11535
- return { desktopPx, mobilePx, mobileFollowing };
10878
+ postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
10879
+ enforceLinkHrefs();
10880
+ return result;
11536
10881
  }
11537
10882
 
11538
10883
  // src/lib/site-wide-scope.ts
11539
10884
  function getLogoElement(el) {
11540
10885
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
11541
10886
  if (marked) return marked;
11542
- if (el.closest('[data-ohw-editable="icon"]')) return null;
11543
10887
  const root = el.closest("nav, [data-ohw-nav-root], footer");
11544
10888
  if (!root) return null;
11545
10889
  const anchor = el.closest("a");
@@ -11573,38 +10917,6 @@ function isSiteWideScopeActive(args) {
11573
10917
  return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
11574
10918
  }
11575
10919
 
11576
- // src/lib/add-footer-column.ts
11577
- function buildFooterColumnEditContentPatch(result) {
11578
- return {
11579
- [result.headingKey]: result.heading,
11580
- [result.hrefKey]: result.href,
11581
- [result.labelKey]: result.label,
11582
- [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
11583
- };
11584
- }
11585
- function addFooterColumnWithPersist({
11586
- postToParent: postToParent2
11587
- }) {
11588
- if (!canAddFooterColumn()) {
11589
- postToParent2({
11590
- type: "ow:toast",
11591
- title: `Maximum ${MAX_FOOTER_COLUMNS} columns`,
11592
- toastType: "error"
11593
- });
11594
- return null;
11595
- }
11596
- const result = insertFooterColumn();
11597
- const patch = buildFooterColumnEditContentPatch(result);
11598
- setStoredLinkHref(result.hrefKey, result.href);
11599
- postToParent2({
11600
- type: "ow:change",
11601
- nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
11602
- });
11603
- postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
11604
- enforceLinkHrefs();
11605
- return result;
11606
- }
11607
-
11608
10920
  // src/ui/FloatingPanel.tsx
11609
10921
  import {
11610
10922
  useCallback as useCallback5,
@@ -11794,127 +11106,16 @@ function FloatingPanel({
11794
11106
  );
11795
11107
  }
11796
11108
 
11797
- // src/ui/logo-size-panel.tsx
11798
- import { ArrowUpRight, Link as Link2 } from "lucide-react";
11799
- import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
11800
- function SizeSlider({
11801
- value,
11802
- onChange
11803
- }) {
11804
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
11805
- return /* @__PURE__ */ jsxs17("div", { className: "flex w-full flex-col gap-3", children: [
11806
- /* @__PURE__ */ jsxs17("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
11807
- /* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
11808
- /* @__PURE__ */ jsxs17("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
11809
- value,
11810
- " px"
11811
- ] })
11812
- ] }),
11813
- /* @__PURE__ */ jsxs17("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
11814
- /* @__PURE__ */ jsx27(
11815
- "div",
11816
- {
11817
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
11818
- style: { width: `${pct}%` }
11819
- }
11820
- ),
11821
- /* @__PURE__ */ jsx27(
11822
- "input",
11823
- {
11824
- type: "range",
11825
- min: LOGO_SIZE_MIN,
11826
- max: LOGO_SIZE_MAX,
11827
- step: 1,
11828
- value,
11829
- "aria-label": "Logo size",
11830
- className: cn(
11831
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
11832
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
11833
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
11834
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
11835
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
11836
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
11837
- "[&::-moz-range-thumb]:bg-background"
11838
- ),
11839
- onChange: (e) => onChange(Number(e.target.value))
11840
- }
11841
- )
11842
- ] })
11843
- ] });
11844
- }
11845
- function LogoSizePanel({
11846
- viewport,
11847
- sizePx,
11848
- mobileFollowing = true,
11849
- onSizeChange,
11850
- onCustomizeMobile,
11851
- onResetMobile,
11852
- onUpdateEverywhere,
11853
- className
11854
- }) {
11855
- const showFollowing = viewport === "mobile" && mobileFollowing;
11856
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
11857
- const showDesktopSlider = viewport === "desktop";
11858
- return /* @__PURE__ */ jsxs17("div", { className: cn("flex w-full flex-col gap-4", className), children: [
11859
- showFollowing ? /* @__PURE__ */ jsxs17("div", { className: "flex w-full flex-col gap-2", children: [
11860
- /* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-1", children: [
11861
- /* @__PURE__ */ jsx27(Link2, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
11862
- /* @__PURE__ */ jsx27("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
11863
- ] }),
11864
- /* @__PURE__ */ jsx27("p", { className: "text-sm leading-5 text-muted-foreground", children: "Mobile uses the desktop size until you customize it. Change the desktop size and it follows automatically." }),
11865
- /* @__PURE__ */ jsx27(
11866
- Button,
11867
- {
11868
- type: "button",
11869
- variant: "outline",
11870
- size: "sm",
11871
- className: "h-9 w-full min-w-0 cursor-pointer",
11872
- onClick: onCustomizeMobile,
11873
- children: "Customize for mobile"
11874
- }
11875
- )
11876
- ] }) : null,
11877
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ jsx27(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
11878
- showMobileSlider ? /* @__PURE__ */ jsx27(
11879
- Button,
11880
- {
11881
- type: "button",
11882
- variant: "outline",
11883
- size: "sm",
11884
- className: "h-9 w-full min-w-0 cursor-pointer",
11885
- onClick: onResetMobile,
11886
- children: "Reset to desktop size"
11887
- }
11888
- ) : null,
11889
- /* @__PURE__ */ jsx27("div", { className: "h-px w-full bg-border", role: "separator" }),
11890
- /* @__PURE__ */ jsxs17(
11891
- Button,
11892
- {
11893
- type: "button",
11894
- variant: "outline",
11895
- size: "sm",
11896
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
11897
- onClick: onUpdateEverywhere,
11898
- children: [
11899
- "Update logo everywhere",
11900
- /* @__PURE__ */ jsx27(ArrowUpRight, { size: 16, "aria-hidden": true })
11901
- ]
11902
- }
11903
- ),
11904
- /* @__PURE__ */ jsx27("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
11905
- ] });
11906
- }
11907
-
11908
11109
  // src/ui/socials-display-panel.tsx
11909
- import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
11110
+ import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
11910
11111
  function DisplaySwitch({
11911
11112
  label,
11912
11113
  checked,
11913
11114
  disabled,
11914
11115
  onChange
11915
11116
  }) {
11916
- return /* @__PURE__ */ jsxs18("div", { className: "flex w-full items-center gap-2", children: [
11917
- /* @__PURE__ */ jsx28(
11117
+ return /* @__PURE__ */ jsxs17("div", { className: "flex w-full items-center gap-2", children: [
11118
+ /* @__PURE__ */ jsx27(
11918
11119
  "span",
11919
11120
  {
11920
11121
  className: cn(
@@ -11924,7 +11125,7 @@ function DisplaySwitch({
11924
11125
  children: label
11925
11126
  }
11926
11127
  ),
11927
- /* @__PURE__ */ jsx28(
11128
+ /* @__PURE__ */ jsx27(
11928
11129
  "button",
11929
11130
  {
11930
11131
  type: "button",
@@ -11938,7 +11139,7 @@ function DisplaySwitch({
11938
11139
  checked ? "bg-primary" : "bg-primary-50",
11939
11140
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
11940
11141
  ),
11941
- children: /* @__PURE__ */ jsx28(
11142
+ children: /* @__PURE__ */ jsx27(
11942
11143
  "span",
11943
11144
  {
11944
11145
  className: cn(
@@ -11952,8 +11153,8 @@ function DisplaySwitch({
11952
11153
  ] });
11953
11154
  }
11954
11155
  function SocialsDisplayPanel({ display, onChange, className }) {
11955
- return /* @__PURE__ */ jsxs18("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11956
- /* @__PURE__ */ jsx28(
11156
+ return /* @__PURE__ */ jsxs17("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11157
+ /* @__PURE__ */ jsx27(
11957
11158
  DisplaySwitch,
11958
11159
  {
11959
11160
  label: "Text",
@@ -11962,7 +11163,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
11962
11163
  onChange: (text) => onChange({ ...display, text })
11963
11164
  }
11964
11165
  ),
11965
- /* @__PURE__ */ jsx28(
11166
+ /* @__PURE__ */ jsx27(
11966
11167
  DisplaySwitch,
11967
11168
  {
11968
11169
  label: "Icon",
@@ -12523,7 +11724,7 @@ function useNavItemDrag({
12523
11724
 
12524
11725
  // src/ui/footer-container-chrome.tsx
12525
11726
  import { Plus as Plus2 } from "lucide-react";
12526
- import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
11727
+ import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
12527
11728
  function FooterContainerChrome({
12528
11729
  rect,
12529
11730
  onAdd,
@@ -12531,7 +11732,7 @@ function FooterContainerChrome({
12531
11732
  }) {
12532
11733
  const chromeGap = 6;
12533
11734
  const buttonMargin = 7;
12534
- return /* @__PURE__ */ jsx29(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx29(
11735
+ return /* @__PURE__ */ jsx28(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx28(
12535
11736
  "div",
12536
11737
  {
12537
11738
  "data-ohw-footer-container-chrome": "",
@@ -12543,8 +11744,8 @@ function FooterContainerChrome({
12543
11744
  width: rect.width + chromeGap * 2,
12544
11745
  height: rect.height + chromeGap * 2
12545
11746
  },
12546
- children: /* @__PURE__ */ jsxs19(Tooltip, { children: [
12547
- /* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
11747
+ children: /* @__PURE__ */ jsxs18(Tooltip, { children: [
11748
+ /* @__PURE__ */ jsx28(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(
12548
11749
  "button",
12549
11750
  {
12550
11751
  type: "button",
@@ -12563,10 +11764,10 @@ function FooterContainerChrome({
12563
11764
  if (addDisabled) return;
12564
11765
  onAdd();
12565
11766
  },
12566
- children: /* @__PURE__ */ jsx29(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
11767
+ children: /* @__PURE__ */ jsx28(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12567
11768
  }
12568
11769
  ) }),
12569
- /* @__PURE__ */ jsx29(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
11770
+ /* @__PURE__ */ jsx28(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12570
11771
  ] })
12571
11772
  }
12572
11773
  ) });
@@ -12749,18 +11950,6 @@ function collectEditableNodes(extraContent, root = document) {
12749
11950
  }
12750
11951
  if (extraContent && !isScoped) {
12751
11952
  applyNavFooterDeleteOverrides(byKey, extraContent);
12752
- for (const key of LOGO_IMAGE_KEYS) {
12753
- if (!(key in extraContent)) continue;
12754
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
12755
- }
12756
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
12757
- if (!(key in extraContent)) continue;
12758
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12759
- }
12760
- for (const key of LOGO_SIZE_KEYS) {
12761
- if (!(key in extraContent)) continue;
12762
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12763
- }
12764
11953
  }
12765
11954
  return Array.from(byKey.values());
12766
11955
  }
@@ -13027,13 +12216,13 @@ function deleteSelectedNavFooterItem(deps) {
13027
12216
 
13028
12217
  // src/ui/navbar-container-chrome.tsx
13029
12218
  import { Plus as Plus3 } from "lucide-react";
13030
- import { jsx as jsx30 } from "react/jsx-runtime";
12219
+ import { jsx as jsx29 } from "react/jsx-runtime";
13031
12220
  function NavbarContainerChrome({
13032
12221
  rect,
13033
12222
  onAdd
13034
12223
  }) {
13035
12224
  const chromeGap = 6;
13036
- return /* @__PURE__ */ jsx30(
12225
+ return /* @__PURE__ */ jsx29(
13037
12226
  "div",
13038
12227
  {
13039
12228
  "data-ohw-navbar-container-chrome": "",
@@ -13045,7 +12234,7 @@ function NavbarContainerChrome({
13045
12234
  width: rect.width + chromeGap * 2,
13046
12235
  height: rect.height + chromeGap * 2
13047
12236
  },
13048
- children: /* @__PURE__ */ jsx30(
12237
+ children: /* @__PURE__ */ jsx29(
13049
12238
  "button",
13050
12239
  {
13051
12240
  type: "button",
@@ -13062,7 +12251,7 @@ function NavbarContainerChrome({
13062
12251
  e.stopPropagation();
13063
12252
  onAdd();
13064
12253
  },
13065
- children: /* @__PURE__ */ jsx30(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12254
+ children: /* @__PURE__ */ jsx29(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13066
12255
  }
13067
12256
  )
13068
12257
  }
@@ -13071,7 +12260,7 @@ function NavbarContainerChrome({
13071
12260
 
13072
12261
  // src/ui/drop-indicator.tsx
13073
12262
  import * as React10 from "react";
13074
- import { jsx as jsx31 } from "react/jsx-runtime";
12263
+ import { jsx as jsx30 } from "react/jsx-runtime";
13075
12264
  var dropIndicatorVariants = cva(
13076
12265
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
13077
12266
  {
@@ -13095,7 +12284,7 @@ var dropIndicatorVariants = cva(
13095
12284
  );
13096
12285
  var DropIndicator = React10.forwardRef(
13097
12286
  ({ className, direction, state, ...props }, ref) => {
13098
- return /* @__PURE__ */ jsx31(
12287
+ return /* @__PURE__ */ jsx30(
13099
12288
  "div",
13100
12289
  {
13101
12290
  ref,
@@ -13112,7 +12301,7 @@ var DropIndicator = React10.forwardRef(
13112
12301
  DropIndicator.displayName = "DropIndicator";
13113
12302
 
13114
12303
  // src/ui/badge.tsx
13115
- import { jsx as jsx32 } from "react/jsx-runtime";
12304
+ import { jsx as jsx31 } from "react/jsx-runtime";
13116
12305
  var badgeVariants = cva(
13117
12306
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
13118
12307
  {
@@ -13130,12 +12319,12 @@ var badgeVariants = cva(
13130
12319
  }
13131
12320
  );
13132
12321
  function Badge({ className, variant, ...props }) {
13133
- return /* @__PURE__ */ jsx32("div", { className: cn(badgeVariants({ variant }), className), ...props });
12322
+ return /* @__PURE__ */ jsx31("div", { className: cn(badgeVariants({ variant }), className), ...props });
13134
12323
  }
13135
12324
 
13136
12325
  // src/OhhwellsBridge.tsx
13137
- import { Link as Link3 } from "lucide-react";
13138
- import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
12326
+ import { Link as Link2 } from "lucide-react";
12327
+ import { Fragment as Fragment8, jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
13139
12328
  var PRIMARY3 = "#0885FE";
13140
12329
  var IMAGE_FADE_MS = 300;
13141
12330
  function runOpacityFade(el, onDone) {
@@ -13229,10 +12418,21 @@ function parseSchedulingInsertAfter(insertAfter) {
13229
12418
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
13230
12419
  };
13231
12420
  }
13232
- function resolveEntryAnchor(entry) {
13233
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
13234
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
13235
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
12421
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
12422
+ const parsed = parseSchedulingInsertAfter(insertAfter);
12423
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
12424
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
12425
+ return { effectiveInsertAfter, insertBefore };
12426
+ }
12427
+ function getSchedulingMountPoint(insertAfter) {
12428
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
12429
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
12430
+ if (!anchorEl && anchor === "scheduling") {
12431
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
12432
+ anchorEl = widgets.at(-1) ?? null;
12433
+ }
12434
+ if (!anchorEl) return null;
12435
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13236
12436
  }
13237
12437
  function schedulingMountDepth(insertAfter) {
13238
12438
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -13249,7 +12449,8 @@ function getPageSchedulingEntries(raw) {
13249
12449
  }
13250
12450
  }
13251
12451
  function isSchedulingWidgetMissing(entry) {
13252
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
12452
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
12453
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
13253
12454
  }
13254
12455
  function hasMissingSchedulingWidgets(entries) {
13255
12456
  return entries.some(isSchedulingWidgetMissing);
@@ -13279,17 +12480,16 @@ function initSectionsFromContent(content, removeExisting = false) {
13279
12480
  } catch {
13280
12481
  }
13281
12482
  }
13282
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
13283
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
13284
- const sectionId = schedulingSectionId(widgetId);
12483
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
12484
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
12485
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
13285
12486
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
13286
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
13287
- if (!anchorEl) return false;
13288
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
12487
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
12488
+ if (!mountPoint) return false;
13289
12489
  const container = document.createElement("div");
13290
12490
  container.dataset.ohwSectionContainer = "scheduling";
13291
- if (beforeId) {
13292
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
12491
+ if (insertBefore) {
12492
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
13293
12493
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
13294
12494
  if (!beforePoint) return false;
13295
12495
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -13300,25 +12500,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13300
12500
  }
13301
12501
  tail.insertAdjacentElement("afterend", container);
13302
12502
  }
13303
- try {
13304
- const root = createRoot2(container);
13305
- flushSync2(() => {
13306
- root.render(
13307
- /* @__PURE__ */ jsx33(
13308
- SchedulingWidget,
13309
- {
13310
- notifyOnConnect,
13311
- initialScheduleId: scheduleId,
13312
- insertAfter: widgetId
13313
- }
13314
- )
13315
- );
13316
- });
13317
- } catch (err) {
13318
- console.error("[ow:scheduling] render threw", err);
13319
- container.remove();
13320
- return false;
13321
- }
12503
+ const root = createRoot2(container);
12504
+ flushSync2(() => {
12505
+ root.render(
12506
+ /* @__PURE__ */ jsx32(
12507
+ SchedulingWidget,
12508
+ {
12509
+ notifyOnConnect,
12510
+ initialScheduleId: scheduleId,
12511
+ insertAfter: effectiveInsertAfter
12512
+ }
12513
+ )
12514
+ );
12515
+ });
13322
12516
  const tracker = getSectionsTracker();
13323
12517
  let sections = [];
13324
12518
  try {
@@ -13326,12 +12520,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13326
12520
  } catch {
13327
12521
  }
13328
12522
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
13329
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
12523
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
13330
12524
  sections.push({
13331
12525
  type: "scheduling",
13332
- insertAfter: widgetId,
13333
- anchorId,
13334
- beforeId: beforeId ?? null,
12526
+ insertAfter: effectiveInsertAfter,
13335
12527
  pagePath: window.location.pathname,
13336
12528
  ...scheduleId ? { scheduleId } : {}
13337
12529
  });
@@ -13345,8 +12537,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
13345
12537
  for (let i = pending.length - 1; i >= 0; i--) {
13346
12538
  const entry = pending[i];
13347
12539
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
13348
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
13349
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
12540
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
13350
12541
  pending.splice(i, 1);
13351
12542
  }
13352
12543
  }
@@ -13490,13 +12681,6 @@ function isInsideLinkEditor(target) {
13490
12681
  target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
13491
12682
  );
13492
12683
  }
13493
- function isInsideFloatingPanel(target) {
13494
- return Boolean(target.closest("[data-ohw-floating-panel]"));
13495
- }
13496
- function isPointOverFloatingPanel(clientX, clientY) {
13497
- const el = document.elementFromPoint(clientX, clientY);
13498
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
13499
- }
13500
12684
  function getHrefKeyFromElement(el) {
13501
12685
  if (!el) return null;
13502
12686
  const anchor = el.closest("[data-ohw-href-key]");
@@ -13544,7 +12728,8 @@ function isNavItemPointerTarget(el) {
13544
12728
  function getNavigationItemAnchor(el) {
13545
12729
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
13546
12730
  if (!anchor) return null;
13547
- if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
12731
+ if (!anchor.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !anchor.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !getSocialItem(anchor))
12732
+ return null;
13548
12733
  if (!isNavItemPointerTarget(anchor)) return null;
13549
12734
  return anchor;
13550
12735
  }
@@ -13734,7 +12919,7 @@ function getNavigationSelectionParent(el) {
13734
12919
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
13735
12920
  return getFooterLinksContainer();
13736
12921
  }
13737
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
12922
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
13738
12923
  return getNavigationRoot(el);
13739
12924
  }
13740
12925
  return null;
@@ -13980,7 +13165,7 @@ function EditGlowChrome({
13980
13165
  hideHandle = false
13981
13166
  }) {
13982
13167
  const GAP = SELECTION_CHROME_GAP2;
13983
- return /* @__PURE__ */ jsxs20(
13168
+ return /* @__PURE__ */ jsxs19(
13984
13169
  "div",
13985
13170
  {
13986
13171
  ref: elRef,
@@ -13995,7 +13180,7 @@ function EditGlowChrome({
13995
13180
  zIndex: 2147483646
13996
13181
  },
13997
13182
  children: [
13998
- /* @__PURE__ */ jsx33(
13183
+ /* @__PURE__ */ jsx32(
13999
13184
  "div",
14000
13185
  {
14001
13186
  style: {
@@ -14008,7 +13193,7 @@ function EditGlowChrome({
14008
13193
  }
14009
13194
  }
14010
13195
  ),
14011
- reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx33(
13196
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx32(
14012
13197
  "div",
14013
13198
  {
14014
13199
  "data-ohw-drag-handle-container": "",
@@ -14020,7 +13205,7 @@ function EditGlowChrome({
14020
13205
  transform: "translate(calc(-100% - 7px), -50%)",
14021
13206
  pointerEvents: dragDisabled ? "none" : "auto"
14022
13207
  },
14023
- children: /* @__PURE__ */ jsx33(
13208
+ children: /* @__PURE__ */ jsx32(
14024
13209
  DragHandle,
14025
13210
  {
14026
13211
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -14230,7 +13415,7 @@ function FloatingToolbar({
14230
13415
  return () => ro.disconnect();
14231
13416
  }, [showEditLink, activeCommands]);
14232
13417
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
14233
- return /* @__PURE__ */ jsx33(
13418
+ return /* @__PURE__ */ jsx32(
14234
13419
  "div",
14235
13420
  {
14236
13421
  ref: setRefs,
@@ -14242,12 +13427,12 @@ function FloatingToolbar({
14242
13427
  zIndex: 2147483647,
14243
13428
  pointerEvents: "auto"
14244
13429
  },
14245
- children: /* @__PURE__ */ jsxs20(CustomToolbar, { children: [
14246
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs20(React11.Fragment, { children: [
14247
- gi > 0 && /* @__PURE__ */ jsx33(CustomToolbarDivider, {}),
13430
+ children: /* @__PURE__ */ jsxs19(CustomToolbar, { children: [
13431
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs19(React11.Fragment, { children: [
13432
+ gi > 0 && /* @__PURE__ */ jsx32(CustomToolbarDivider, {}),
14248
13433
  btns.map((btn) => {
14249
13434
  const isActive = activeCommands.has(btn.cmd);
14250
- return /* @__PURE__ */ jsx33(
13435
+ return /* @__PURE__ */ jsx32(
14251
13436
  CustomToolbarButton,
14252
13437
  {
14253
13438
  title: btn.title,
@@ -14256,7 +13441,7 @@ function FloatingToolbar({
14256
13441
  e.preventDefault();
14257
13442
  onCommand(btn.cmd);
14258
13443
  },
14259
- children: /* @__PURE__ */ jsx33(
13444
+ children: /* @__PURE__ */ jsx32(
14260
13445
  "svg",
14261
13446
  {
14262
13447
  width: "16",
@@ -14277,7 +13462,7 @@ function FloatingToolbar({
14277
13462
  );
14278
13463
  })
14279
13464
  ] }, gi)),
14280
- showEditLink ? /* @__PURE__ */ jsx33(
13465
+ showEditLink ? /* @__PURE__ */ jsx32(
14281
13466
  CustomToolbarButton,
14282
13467
  {
14283
13468
  type: "button",
@@ -14291,7 +13476,7 @@ function FloatingToolbar({
14291
13476
  e.preventDefault();
14292
13477
  e.stopPropagation();
14293
13478
  },
14294
- children: /* @__PURE__ */ jsx33(Link3, { className: "size-4 shrink-0", "aria-hidden": true })
13479
+ children: /* @__PURE__ */ jsx32(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
14295
13480
  }
14296
13481
  ) : null
14297
13482
  ] })
@@ -14308,7 +13493,7 @@ function StateToggle({
14308
13493
  states,
14309
13494
  onStateChange
14310
13495
  }) {
14311
- return /* @__PURE__ */ jsx33(
13496
+ return /* @__PURE__ */ jsx32(
14312
13497
  ToggleGroup,
14313
13498
  {
14314
13499
  "data-ohw-state-toggle": "",
@@ -14322,12 +13507,11 @@ function StateToggle({
14322
13507
  left: rect.right - 8,
14323
13508
  transform: "translateX(-100%)"
14324
13509
  },
14325
- children: states.map((state) => /* @__PURE__ */ jsx33(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
13510
+ children: states.map((state) => /* @__PURE__ */ jsx32(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14326
13511
  }
14327
13512
  );
14328
13513
  }
14329
13514
  var contentCache = /* @__PURE__ */ new Map();
14330
- var fetchedContentPaths = /* @__PURE__ */ new Set();
14331
13515
  function resolveSubdomain(subdomainFromQuery) {
14332
13516
  if (subdomainFromQuery) return subdomainFromQuery;
14333
13517
  if (typeof window !== "undefined") {
@@ -14422,14 +13606,8 @@ function OhhwellsBridge() {
14422
13606
  });
14423
13607
  const selectFrameRef = useRef9(() => {
14424
13608
  });
14425
- const selectLogoRef = useRef9(() => {
14426
- });
14427
- const openLogoSizePanelRef = useRef9(() => {
14428
- });
14429
13609
  const deselectRef = useRef9(() => {
14430
13610
  });
14431
- const closeFloatingPanelOnlyRef = useRef9(() => {
14432
- });
14433
13611
  const reselectNavigationItemRef = useRef9(() => {
14434
13612
  });
14435
13613
  const commitNavigationTextEditRef = useRef9(() => {
@@ -14490,6 +13668,11 @@ function OhhwellsBridge() {
14490
13668
  const [isItemDragging, setIsItemDragging] = useState11(false);
14491
13669
  const [isFooterFrameSelection, setIsFooterFrameSelection] = useState11(false);
14492
13670
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
13671
+ const [floatingPanel, setFloatingPanel] = useState11(null);
13672
+ const floatingPanelOpenRef = useRef9(false);
13673
+ floatingPanelOpenRef.current = floatingPanel !== null;
13674
+ const [floatingPanelPos, setFloatingPanelPos] = useState11(null);
13675
+ const [parentScrollSnap, setParentScrollSnap] = useState11(null);
14493
13676
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState11(null);
14494
13677
  const [footerHeadingVisible, setFooterHeadingVisible] = useState11(null);
14495
13678
  const footerDragRef = useRef9(null);
@@ -14504,16 +13687,7 @@ function OhhwellsBridge() {
14504
13687
  const addNavAfterAnchorRef = useRef9(null);
14505
13688
  const editContentRef = useRef9({});
14506
13689
  const aiSectionsRef = useRef9("");
14507
- const brandKitRef = useRef9("");
14508
- const stylesRef = useRef9("");
14509
13690
  const pendingDeleteUndoRef = useRef9(null);
14510
- const [floatingPanel, setFloatingPanel] = useState11(null);
14511
- const floatingPanelOpenRef = useRef9(false);
14512
- const setFloatingPanelRef = useRef9(setFloatingPanel);
14513
- const [floatingPanelPos, setFloatingPanelPos] = useState11(null);
14514
- const [logoSizeDraft, setLogoSizeDraft] = useState11(null);
14515
- const [editorViewport, setEditorViewport] = useState11("desktop");
14516
- const [parentScrollSnap, setParentScrollSnap] = useState11(null);
14517
13691
  const [sitePages, setSitePages] = useState11([]);
14518
13692
  const [sectionsByPath, setSectionsByPath] = useState11({});
14519
13693
  const sectionsPrefetchGenRef = useRef9(0);
@@ -14522,18 +13696,7 @@ function OhhwellsBridge() {
14522
13696
  const linkPopoverOpenRef = useRef9(false);
14523
13697
  const linkPopoverGraceUntilRef = useRef9(0);
14524
13698
  setLinkPopoverRef.current = setLinkPopover;
14525
- setFloatingPanelRef.current = setFloatingPanel;
14526
13699
  linkPopoverSessionRef.current = linkPopover;
14527
- floatingPanelOpenRef.current = Boolean(floatingPanel);
14528
- useEffect12(() => {
14529
- const syncViewport = () => {
14530
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
14531
- setEditorViewport((prev) => prev === next ? prev : next);
14532
- };
14533
- syncViewport();
14534
- window.addEventListener("resize", syncViewport);
14535
- return () => window.removeEventListener("resize", syncViewport);
14536
- }, []);
14537
13700
  const {
14538
13701
  navDragRef,
14539
13702
  navDropSlots,
@@ -14758,8 +13921,6 @@ function OhhwellsBridge() {
14758
13921
  setHoveredNavContainerRect(null);
14759
13922
  hoveredItemElRef.current = null;
14760
13923
  setHoveredItemRect(null);
14761
- setFloatingPanel(null);
14762
- setLogoSizeDraft(null);
14763
13924
  if (!activeElRef.current) {
14764
13925
  setNavGroupForceOpen(null, false);
14765
13926
  setToolbarRect(null);
@@ -15465,8 +14626,6 @@ function OhhwellsBridge() {
15465
14626
  setToolbarRect(anchor.getBoundingClientRect());
15466
14627
  setToolbarShowEditLink(false);
15467
14628
  setActiveCommands(/* @__PURE__ */ new Set());
15468
- setFloatingPanel(null);
15469
- setLogoSizeDraft(null);
15470
14629
  }, [deactivate, markSelected]);
15471
14630
  const selectFrame = useCallback7((el) => {
15472
14631
  if (!isNavigationContainer(el)) return;
@@ -15516,51 +14675,7 @@ function OhhwellsBridge() {
15516
14675
  setToolbarRect(el.getBoundingClientRect());
15517
14676
  setToolbarShowEditLink(false);
15518
14677
  setActiveCommands(/* @__PURE__ */ new Set());
15519
- setFloatingPanel(null);
15520
- setLogoSizeDraft(null);
15521
14678
  }, [deactivate, markSelected, postToParent2]);
15522
- const selectLogo = useCallback7(
15523
- (logoEl) => {
15524
- if (activeElRef.current) deactivate();
15525
- selectedElRef.current = logoEl;
15526
- selectedHrefKeyRef.current = null;
15527
- selectedFooterColAttrRef.current = null;
15528
- markSelected(logoEl);
15529
- setSelectedIsCta(false);
15530
- setSelectedIsSocial(false);
15531
- setSelectedIsSocialsRow(false);
15532
- clearHrefKeyHover(logoEl);
15533
- hoveredNavContainerRef.current = null;
15534
- setHoveredNavContainerRect(null);
15535
- setHoveredItemRect(null);
15536
- hoveredItemElRef.current = null;
15537
- siblingHintElRef.current = null;
15538
- setSiblingHintRect(null);
15539
- setSiblingHintRects([]);
15540
- setIsItemDragging(false);
15541
- setReorderHrefKey(null);
15542
- setReorderDragDisabled(false);
15543
- setIsFooterFrameSelection(false);
15544
- setToolbarVariant("logo");
15545
- setToolbarRect(getLogoInteractionRect(logoEl));
15546
- setToolbarShowEditLink(false);
15547
- setActiveCommands(/* @__PURE__ */ new Set());
15548
- },
15549
- [deactivate, markSelected]
15550
- );
15551
- const openLogoSizePanel = useCallback7((logoEl) => {
15552
- const placement = getLogoPlacement(logoEl);
15553
- const draft = readLogoSizeState(editContentRef.current, placement);
15554
- setLogoSizeDraft(draft);
15555
- setParentScrollSnap(parentScrollRef.current);
15556
- setFloatingPanel({
15557
- key: `logo-size:${placement}`,
15558
- title: "Logo",
15559
- context: placement === "navbar" ? "Navbar" : "Footer",
15560
- kind: "logo-size",
15561
- placement
15562
- });
15563
- }, []);
15564
14679
  const openSocialsDisplayPanel = useCallback7((row) => {
15565
14680
  setParentScrollSnap(parentScrollRef.current);
15566
14681
  setFloatingPanel({
@@ -15596,53 +14711,13 @@ function OhhwellsBridge() {
15596
14711
  );
15597
14712
  const closeFloatingPanelOnly = useCallback7(() => {
15598
14713
  setFloatingPanel(null);
15599
- setLogoSizeDraft(null);
15600
14714
  }, []);
14715
+ const closeFloatingPanelOnlyRef = useRef9(closeFloatingPanelOnly);
14716
+ closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
15601
14717
  const closeFloatingPanelAndDeselect = useCallback7(() => {
15602
14718
  setFloatingPanel(null);
15603
- setLogoSizeDraft(null);
15604
14719
  deselectRef.current();
15605
14720
  }, []);
15606
- const persistLogoSizeDraft = useCallback7(
15607
- (placement, draft) => {
15608
- const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
15609
- const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
15610
- const nodes = [
15611
- { key: desktopKey, text: String(draft.desktopPx) }
15612
- ];
15613
- if (draft.mobileFollowing) {
15614
- nodes.push({ key: mobileKey, text: "" });
15615
- } else {
15616
- nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
15617
- }
15618
- editContentRef.current = {
15619
- ...editContentRef.current,
15620
- [desktopKey]: String(draft.desktopPx),
15621
- [mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
15622
- };
15623
- applyLogoSizeToPlacement(
15624
- placement,
15625
- draft.desktopPx,
15626
- draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
15627
- draft.mobileFollowing
15628
- );
15629
- postToParent2({ type: "ow:change", nodes });
15630
- requestAnimationFrame(() => {
15631
- const selected = selectedElRef.current;
15632
- if (!selected || toolbarVariantRef.current !== "logo") return;
15633
- const rect = getLogoInteractionRect(selected);
15634
- setToolbarRect(rect);
15635
- if (glowElRef.current) {
15636
- const GAP = SELECTION_CHROME_GAP2;
15637
- glowElRef.current.style.top = `${rect.top - GAP}px`;
15638
- glowElRef.current.style.left = `${rect.left - GAP}px`;
15639
- glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
15640
- glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
15641
- }
15642
- });
15643
- },
15644
- [postToParent2]
15645
- );
15646
14721
  const activate = useCallback7((el, options) => {
15647
14722
  if (activeElRef.current === el) return;
15648
14723
  if (isIconEditable(el)) return;
@@ -15723,10 +14798,7 @@ function OhhwellsBridge() {
15723
14798
  deactivateRef.current = deactivate;
15724
14799
  selectRef.current = select;
15725
14800
  selectFrameRef.current = selectFrame;
15726
- selectLogoRef.current = selectLogo;
15727
- openLogoSizePanelRef.current = openLogoSizePanel;
15728
14801
  deselectRef.current = deselect;
15729
- closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
15730
14802
  const lastSiteWideScopeRef = useRef9(null);
15731
14803
  useEffect12(() => {
15732
14804
  if (!isEditMode) {
@@ -15765,23 +14837,9 @@ function OhhwellsBridge() {
15765
14837
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
15766
14838
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
15767
14839
  }
15768
- if (typeof content[BRAND_KIT_KEY] === "string") {
15769
- brandKitRef.current = content[BRAND_KIT_KEY];
15770
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
15771
- }
15772
- if (typeof content[STYLE_STORE_KEY] === "string") {
15773
- stylesRef.current = content[STYLE_STORE_KEY];
15774
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
15775
- }
15776
- applyBrandChrome(content);
15777
14840
  for (const [key, val] of Object.entries(content)) {
15778
14841
  if (key === "__ohw_sections") continue;
15779
14842
  if (key === AI_SECTIONS_KEY) continue;
15780
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15781
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15782
- if (key === BRAND_KIT_KEY) continue;
15783
- if (key === STYLE_STORE_KEY) continue;
15784
- if (BRAND_CHROME_KEYS.has(key)) continue;
15785
14843
  if (applyVideoSettingNode(key, val)) continue;
15786
14844
  if (applyCarouselNode(key, val)) continue;
15787
14845
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15816,8 +14874,6 @@ function OhhwellsBridge() {
15816
14874
  });
15817
14875
  applyLinkByKey(key, val);
15818
14876
  }
15819
- applyLogoFromContent(content);
15820
- applyLogoSizes(content);
15821
14877
  reconcileNavbarItemsFromContent(content);
15822
14878
  reconcileFooterOrderFromContent(content);
15823
14879
  reconcileSocialsFromContent(content);
@@ -15838,9 +14894,7 @@ function OhhwellsBridge() {
15838
14894
  let cancelled = false;
15839
14895
  setFetchState("loading");
15840
14896
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15841
- const initialPath = pathname;
15842
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
15843
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
14897
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15844
14898
  if (cancelled) return;
15845
14899
  const content = data?.content ?? {};
15846
14900
  contentCache.set(subdomain, content);
@@ -15864,21 +14918,8 @@ function OhhwellsBridge() {
15864
14918
  initSectionInstancesFromContent(content, window.location.pathname);
15865
14919
  observer?.disconnect();
15866
14920
  try {
15867
- applyBrandChrome(content);
15868
- if (typeof content[BRAND_KIT_KEY] === "string") {
15869
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
15870
- }
15871
- if (typeof content[STYLE_STORE_KEY] === "string") {
15872
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
15873
- }
15874
14921
  for (const [key, val] of Object.entries(content)) {
15875
14922
  if (key === "__ohw_sections") continue;
15876
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15877
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15878
- if (key === BRAND_KIT_KEY) continue;
15879
- if (key === STYLE_STORE_KEY) continue;
15880
- if (key === STYLE_STORE_KEY) continue;
15881
- if (BRAND_CHROME_KEYS.has(key)) continue;
15882
14923
  if (applyVideoSettingNode(key, val)) continue;
15883
14924
  if (applyCarouselNode(key, val)) continue;
15884
14925
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15899,7 +14940,6 @@ function OhhwellsBridge() {
15899
14940
  });
15900
14941
  applyLinkByKey(key, val);
15901
14942
  }
15902
- applyLogoFromContent(content);
15903
14943
  reconcileNavbarItemsFromContent(content);
15904
14944
  reconcileFooterOrderFromContent(content);
15905
14945
  reconcileSocialsFromContent(content);
@@ -15914,17 +14954,6 @@ function OhhwellsBridge() {
15914
14954
  debounceTimer = setTimeout(applyFromCache, 150);
15915
14955
  };
15916
14956
  applyFromCache();
15917
- const pathCacheKey = `${subdomain}::${pathname}`;
15918
- if (!fetchedContentPaths.has(pathCacheKey)) {
15919
- fetchedContentPaths.add(pathCacheKey);
15920
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15921
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15922
- if (!data?.content) return;
15923
- contentCache.set(subdomain, data.content);
15924
- applyFromCache();
15925
- }).catch(() => {
15926
- });
15927
- }
15928
14957
  observer = new MutationObserver(scheduleApply);
15929
14958
  observer.observe(document.body, { childList: true, subtree: true });
15930
14959
  return () => {
@@ -16018,31 +15047,26 @@ function OhhwellsBridge() {
16018
15047
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
16019
15048
  useEffect12(() => {
16020
15049
  if (!isEditMode) return;
16021
- let lastPosted = 0;
16022
15050
  const measure = () => {
16023
15051
  const h = document.body.scrollHeight;
16024
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
16025
- lastPosted = h;
16026
- postToParent2({ type: "ow:height", height: h });
16027
- }
16028
- };
16029
- let raf = null;
16030
- const schedule = () => {
16031
- if (raf != null) return;
16032
- raf = requestAnimationFrame(() => {
16033
- raf = null;
16034
- measure();
16035
- });
15052
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
16036
15053
  };
16037
15054
  const t1 = setTimeout(measure, 50);
16038
15055
  const t2 = setTimeout(measure, 500);
16039
- const ro = new ResizeObserver(schedule);
16040
- ro.observe(document.body);
15056
+ let lastWidth = window.innerWidth;
15057
+ let resizeTimer = null;
15058
+ const handleResize = () => {
15059
+ if (window.innerWidth === lastWidth) return;
15060
+ lastWidth = window.innerWidth;
15061
+ if (resizeTimer) clearTimeout(resizeTimer);
15062
+ resizeTimer = setTimeout(measure, 150);
15063
+ };
15064
+ window.addEventListener("resize", handleResize);
16041
15065
  return () => {
16042
15066
  clearTimeout(t1);
16043
15067
  clearTimeout(t2);
16044
- if (raf != null) cancelAnimationFrame(raf);
16045
- ro.disconnect();
15068
+ if (resizeTimer) clearTimeout(resizeTimer);
15069
+ window.removeEventListener("resize", handleResize);
16046
15070
  };
16047
15071
  }, [pathname, isEditMode, postToParent2]);
16048
15072
  useEffect12(() => {
@@ -16192,12 +15216,10 @@ function OhhwellsBridge() {
16192
15216
  return;
16193
15217
  }
16194
15218
  const target = e.target;
16195
- if (target.closest("[data-ohw-ai-review]")) return;
16196
15219
  if (target.closest("[data-ohw-toolbar]")) return;
16197
15220
  if (target.closest("[data-ohw-state-toggle]")) return;
16198
15221
  if (target.closest("[data-ohw-max-badge]")) return;
16199
15222
  if (isInsideLinkEditor(target)) return;
16200
- if (isInsideFloatingPanel(target)) return;
16201
15223
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
16202
15224
  const beneath = document.elementsFromPoint(e.clientX, e.clientY).find(
16203
15225
  (el) => el instanceof HTMLElement && !el.closest("[data-ohw-bridge-root]") && el.closest("[data-ohw-section]") != null
@@ -16265,15 +15287,9 @@ function OhhwellsBridge() {
16265
15287
  if (logoEl) {
16266
15288
  e.preventDefault();
16267
15289
  e.stopPropagation();
16268
- if (!logoHasUploadedImage(logoEl)) {
16269
- deselectRef.current();
16270
- deactivateRef.current();
16271
- const identity = readLogoIdentityFromDom();
16272
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
16273
- return;
16274
- }
16275
- selectLogoRef.current(logoEl);
16276
- openLogoSizePanelRef.current(logoEl);
15290
+ deselectRef.current();
15291
+ deactivateRef.current();
15292
+ postToParentRef.current({ type: "ow:open-logo-settings" });
16277
15293
  return;
16278
15294
  }
16279
15295
  const editable = target.closest("[data-ohw-editable]");
@@ -16428,12 +15444,10 @@ function OhhwellsBridge() {
16428
15444
  };
16429
15445
  const handleDblClick = (e) => {
16430
15446
  const target = e.target;
16431
- if (target.closest("[data-ohw-ai-review]")) return;
16432
15447
  if (target.closest("[data-ohw-toolbar]")) return;
16433
15448
  if (target.closest("[data-ohw-state-toggle]")) return;
16434
15449
  if (target.closest("[data-ohw-max-badge]")) return;
16435
15450
  if (isInsideLinkEditor(target)) return;
16436
- if (isInsideFloatingPanel(target)) return;
16437
15451
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
16438
15452
  return;
16439
15453
  }
@@ -16461,14 +15475,11 @@ function OhhwellsBridge() {
16461
15475
  setHoveredNavContainerRect(null);
16462
15476
  return;
16463
15477
  }
16464
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
15478
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
16465
15479
  hoveredItemElRef.current = null;
16466
15480
  setHoveredItemRect(null);
16467
15481
  hoveredNavContainerRef.current = null;
16468
15482
  setHoveredNavContainerRect(null);
16469
- siblingHintElRef.current = null;
16470
- setSiblingHintRect(null);
16471
- setSiblingHintRects([]);
16472
15483
  return;
16473
15484
  }
16474
15485
  {
@@ -16513,7 +15524,7 @@ function OhhwellsBridge() {
16513
15524
  setHoveredNavContainerRect(null);
16514
15525
  if (selectedElRef.current === logoEl) return;
16515
15526
  hoveredItemElRef.current = logoEl;
16516
- setHoveredItemRect(getLogoInteractionRect(logoEl));
15527
+ setHoveredItemRect(logoEl.getBoundingClientRect());
16517
15528
  return;
16518
15529
  }
16519
15530
  const navAnchor = getNavigationItemAnchor(target);
@@ -16557,6 +15568,7 @@ function OhhwellsBridge() {
16557
15568
  hoveredNavContainerRef.current = null;
16558
15569
  setHoveredNavContainerRect(null);
16559
15570
  hoveredItemElRef.current = editable;
15571
+ setHoveredItemRect(editable.getBoundingClientRect());
16560
15572
  }
16561
15573
  }
16562
15574
  }
@@ -16764,7 +15776,7 @@ function OhhwellsBridge() {
16764
15776
  setHoveredNavContainerRect(null);
16765
15777
  if (selectedElRef.current !== logo) {
16766
15778
  hoveredItemElRef.current = logo;
16767
- setHoveredItemRect(getLogoInteractionRect(logo));
15779
+ setHoveredItemRect(logo.getBoundingClientRect());
16768
15780
  }
16769
15781
  return;
16770
15782
  }
@@ -16853,7 +15865,7 @@ function OhhwellsBridge() {
16853
15865
  }
16854
15866
  };
16855
15867
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
16856
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
15868
+ if (linkPopoverOpenRef.current) {
16857
15869
  if (hoveredImageRef.current) {
16858
15870
  hoveredImageRef.current = null;
16859
15871
  hoveredImageHasTextOverlapRef.current = false;
@@ -17107,7 +16119,7 @@ function OhhwellsBridge() {
17107
16119
  }
17108
16120
  };
17109
16121
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
17110
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
16122
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17111
16123
  if (activeStateElRef.current) {
17112
16124
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
17113
16125
  activeStateElRef.current = null;
@@ -17173,21 +16185,16 @@ function OhhwellsBridge() {
17173
16185
  setSectionGap(null);
17174
16186
  }
17175
16187
  };
16188
+ const pointOwnedByFloatingPanel = (clientX, clientY) => {
16189
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return true;
16190
+ const panel = document.querySelector("[data-ohw-floating-panel]");
16191
+ if (!panel) return false;
16192
+ const rect = panel.getBoundingClientRect();
16193
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
16194
+ };
17176
16195
  const handleMouseMove = (e) => {
17177
16196
  const { clientX, clientY } = e;
17178
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17179
- hoveredItemElRef.current = null;
17180
- setHoveredItemRect(null);
17181
- hoveredNavContainerRef.current = null;
17182
- setHoveredNavContainerRect(null);
17183
- siblingHintElRef.current = null;
17184
- setSiblingHintRect(null);
17185
- setSiblingHintRects([]);
17186
- dismissImageHover();
17187
- clearImageHover();
17188
- setSectionGap(null);
17189
- return;
17190
- }
16197
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17191
16198
  probeSectionGapAt(clientX, clientY);
17192
16199
  probeImageAt(clientX, clientY);
17193
16200
  probeHoverCardsAt(clientX, clientY);
@@ -17196,11 +16203,7 @@ function OhhwellsBridge() {
17196
16203
  if (e.data?.type !== "ow:pointer-sync") return;
17197
16204
  const { clientX, clientY } = e.data;
17198
16205
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
17199
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17200
- dismissImageHover();
17201
- clearImageHover();
17202
- return;
17203
- }
16206
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17204
16207
  probeSectionGapAt(clientX, clientY);
17205
16208
  probeImageAt(clientX, clientY);
17206
16209
  probeHoverCardsAt(clientX, clientY);
@@ -17450,15 +16453,6 @@ function OhhwellsBridge() {
17450
16453
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
17451
16454
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
17452
16455
  }
17453
- if (typeof content[BRAND_KIT_KEY] === "string") {
17454
- brandKitRef.current = content[BRAND_KIT_KEY];
17455
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
17456
- }
17457
- if (typeof content[STYLE_STORE_KEY] === "string") {
17458
- stylesRef.current = content[STYLE_STORE_KEY];
17459
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17460
- }
17461
- applyBrandChrome(content);
17462
16456
  let sectionsJson = null;
17463
16457
  for (const [key, val] of Object.entries(content)) {
17464
16458
  if (key === "__ohw_sections") {
@@ -17466,11 +16460,6 @@ function OhhwellsBridge() {
17466
16460
  continue;
17467
16461
  }
17468
16462
  if (key === AI_SECTIONS_KEY) continue;
17469
- if (key === LOGO_PLACEHOLDER_KEY) continue;
17470
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
17471
- if (key === BRAND_KIT_KEY) continue;
17472
- if (key === STYLE_STORE_KEY) continue;
17473
- if (BRAND_CHROME_KEYS.has(key)) continue;
17474
16463
  if (applyVideoSettingNode(key, val)) continue;
17475
16464
  if (applyCarouselNode(key, val)) continue;
17476
16465
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -17490,8 +16479,6 @@ function OhhwellsBridge() {
17490
16479
  });
17491
16480
  applyLinkByKey(key, val);
17492
16481
  }
17493
- applyLogoFromContent(content);
17494
- applyLogoSizes(content);
17495
16482
  if (sectionsJson) {
17496
16483
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
17497
16484
  sectionsLoadedRef.current = true;
@@ -17507,58 +16494,6 @@ function OhhwellsBridge() {
17507
16494
  if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
17508
16495
  postToParentRef.current({ type: "ow:hydrate-done" });
17509
16496
  };
17510
- const handleUpdateLogoIdentity = (e) => {
17511
- if (e.data?.type !== "ow:update-logo-identity") return;
17512
- const rawText = typeof e.data.text === "string" ? e.data.text : "";
17513
- const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
17514
- const href = typeof e.data.href === "string" ? e.data.href : void 0;
17515
- const imageProvided = "image" in e.data;
17516
- const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
17517
- let isPlaceholder = e.data.isPlaceholder !== false;
17518
- if (imageUrl) isPlaceholder = false;
17519
- else if (imageProvided && imageUrl === null) {
17520
- isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
17521
- }
17522
- const display = applyLogoIdentity(rawText, isPlaceholder);
17523
- const displayAlt = resolveLogoDisplayText(alt || display);
17524
- if (imageUrl !== void 0) {
17525
- applyLogoImage(imageUrl, displayAlt);
17526
- } else {
17527
- for (const key of LOGO_IMAGE_KEYS) {
17528
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
17529
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
17530
- if (img) img.alt = displayAlt;
17531
- });
17532
- }
17533
- }
17534
- if (href !== void 0) {
17535
- applyLogoHref(href);
17536
- applyLinkByKey("nav-logo-href", href);
17537
- applyLinkByKey("footer-logo-href", href);
17538
- applyLinkByKey("logo-href", href);
17539
- }
17540
- const nodes = [
17541
- ...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
17542
- { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
17543
- { key: LOGO_ALT_KEY, text: displayAlt }
17544
- ];
17545
- if (imageUrl !== void 0) {
17546
- if (imageUrl) {
17547
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
17548
- } else {
17549
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
17550
- }
17551
- }
17552
- if (href !== void 0) {
17553
- for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
17554
- }
17555
- editContentRef.current = {
17556
- ...editContentRef.current,
17557
- ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
17558
- };
17559
- applyLogoSizes(editContentRef.current);
17560
- postToParentRef.current({ type: "ow:change", nodes });
17561
- };
17562
16497
  window.addEventListener("message", handleHydrate);
17563
16498
  const postAiSectionsChanged = () => {
17564
16499
  postToParentRef.current({
@@ -17572,10 +16507,7 @@ function OhhwellsBridge() {
17572
16507
  const payload = e.data.payload;
17573
16508
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
17574
16509
  const previous = aiSectionsRef.current;
17575
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
17576
- ...payload,
17577
- path: payload.path ?? window.location.pathname
17578
- });
16510
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
17579
16511
  const nextValue = serializeAiSectionsState(nextState);
17580
16512
  aiSectionsRef.current = nextValue;
17581
16513
  applyAiSectionsToDom(nextState);
@@ -17612,42 +16544,12 @@ function OhhwellsBridge() {
17612
16544
  const value = typeof e.data.value === "string" ? e.data.value : "";
17613
16545
  aiSectionsRef.current = value;
17614
16546
  applyAiSectionsToDom(parseAiSectionsState(value));
17615
- applyStylesToDom(parseStyleStore(stylesRef.current));
17616
16547
  const restoredHeight = document.documentElement.scrollHeight;
17617
16548
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
17618
16549
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
17619
16550
  postAiSectionsChanged();
17620
16551
  };
17621
16552
  window.addEventListener("message", handleAiSetSections);
17622
- const handleAiSetBrand = (e) => {
17623
- if (e.data?.type !== "ow:ai-set-brand") return;
17624
- const value = typeof e.data.value === "string" ? e.data.value : "";
17625
- const previous = brandKitRef.current;
17626
- brandKitRef.current = value;
17627
- applyBrandToDom(parseBrandKit(value));
17628
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
17629
- applyStylesToDom(parseStyleStore(stylesRef.current));
17630
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
17631
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
17632
- };
17633
- window.addEventListener("message", handleAiSetBrand);
17634
- const handleAiSetStyles = (e) => {
17635
- if (e.data?.type !== "ow:ai-set-styles") return;
17636
- const value = typeof e.data.value === "string" ? e.data.value : "";
17637
- const previous = stylesRef.current;
17638
- stylesRef.current = value;
17639
- applyStylesToDom(parseStyleStore(value));
17640
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
17641
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
17642
- };
17643
- window.addEventListener("message", handleAiSetStyles);
17644
- const handleGetBrand = (e) => {
17645
- if (e.data?.type !== "ow:get-brand") return;
17646
- const template = deriveTemplateBrand();
17647
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
17648
- postToParentRef.current({ type: "ow:brand-value", value });
17649
- };
17650
- window.addEventListener("message", handleGetBrand);
17651
16553
  const handleDeactivate = (e) => {
17652
16554
  if (e.data?.type !== "ow:deactivate") return;
17653
16555
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -17656,12 +16558,6 @@ function OhhwellsBridge() {
17656
16558
  closeLinkPopoverRef.current();
17657
16559
  return;
17658
16560
  }
17659
- if (floatingPanelOpenRef.current) {
17660
- setFloatingPanelRef.current(null);
17661
- deselectRef.current();
17662
- deactivateRef.current();
17663
- return;
17664
- }
17665
16561
  deselectRef.current();
17666
16562
  deactivateRef.current();
17667
16563
  };
@@ -17715,10 +16611,6 @@ function OhhwellsBridge() {
17715
16611
  return;
17716
16612
  }
17717
16613
  if (selectedElRef.current) {
17718
- if (toolbarVariantRef.current === "logo") {
17719
- deselectRef.current();
17720
- return;
17721
- }
17722
16614
  if (toolbarVariantRef.current === "select-frame") {
17723
16615
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
17724
16616
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -17758,10 +16650,6 @@ function OhhwellsBridge() {
17758
16650
  return;
17759
16651
  }
17760
16652
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
17761
- if (toolbarVariantRef.current === "logo") {
17762
- deselectRef.current();
17763
- return;
17764
- }
17765
16653
  if (toolbarVariantRef.current === "select-frame") {
17766
16654
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
17767
16655
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -17839,8 +16727,7 @@ function OhhwellsBridge() {
17839
16727
  const handleScroll = () => {
17840
16728
  const focusEl = activeElRef.current ?? selectedElRef.current;
17841
16729
  if (focusEl) {
17842
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
17843
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
16730
+ const r2 = activeElRef.current ? getEditMeasureEl(activeElRef.current).getBoundingClientRect() : focusEl.getBoundingClientRect();
17844
16731
  applyToolbarPos(r2);
17845
16732
  setToolbarRect(r2);
17846
16733
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -17850,9 +16737,7 @@ function OhhwellsBridge() {
17850
16737
  setToggleState((prev) => prev ? { ...prev, rect } : null);
17851
16738
  }
17852
16739
  if (hoveredItemElRef.current) {
17853
- const hoverEl = hoveredItemElRef.current;
17854
- const logo = getLogoElement(hoverEl);
17855
- setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
16740
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
17856
16741
  }
17857
16742
  if (hoveredNavContainerRef.current) {
17858
16743
  setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
@@ -17896,12 +16781,6 @@ function OhhwellsBridge() {
17896
16781
  if (aiSectionsRef.current) {
17897
16782
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
17898
16783
  }
17899
- if (stylesRef.current) {
17900
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
17901
- }
17902
- if (brandKitRef.current) {
17903
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
17904
- }
17905
16784
  postToParentRef.current({ type: "ow:save-result", nodes });
17906
16785
  };
17907
16786
  const handleInsertSection = (e) => {
@@ -17912,12 +16791,8 @@ function OhhwellsBridge() {
17912
16791
  if (inserted) {
17913
16792
  const tracker = getSectionsTracker();
17914
16793
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
17915
- const reportHeight = () => {
17916
- const h = document.body.scrollHeight;
17917
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17918
- };
17919
- reportHeight();
17920
- setTimeout(reportHeight, 500);
16794
+ const h = document.documentElement.scrollHeight;
16795
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17921
16796
  }
17922
16797
  };
17923
16798
  const handleSwitchSchedule = (e) => {
@@ -18110,17 +16985,13 @@ function OhhwellsBridge() {
18110
16985
  if (e.data?.type !== "ow:parent-scroll") return;
18111
16986
  const { iframeOffsetTop, headerH, canvasH } = e.data;
18112
16987
  parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
18113
- if (floatingPanelOpenRef.current) {
18114
- setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
18115
- }
18116
16988
  if (visibleViewportRef.current) {
18117
16989
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
18118
16990
  }
18119
16991
  const focusEl = activeElRef.current ?? selectedElRef.current;
18120
16992
  if (focusEl) {
18121
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
18122
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
18123
- applyToolbarPos(r2);
16993
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
16994
+ applyToolbarPos(measureEl.getBoundingClientRect());
18124
16995
  }
18125
16996
  };
18126
16997
  const handleClickAt = (e) => {
@@ -18153,15 +17024,9 @@ function OhhwellsBridge() {
18153
17024
  return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
18154
17025
  });
18155
17026
  if (logoAtPoint) {
18156
- if (!logoHasUploadedImage(logoAtPoint)) {
18157
- deselectRef.current();
18158
- deactivateRef.current();
18159
- const identity = readLogoIdentityFromDom();
18160
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
18161
- return;
18162
- }
18163
- selectLogoRef.current(logoAtPoint);
18164
- openLogoSizePanelRef.current(logoAtPoint);
17027
+ deselectRef.current();
17028
+ deactivateRef.current();
17029
+ postToParentRef.current({ type: "ow:open-logo-settings" });
18165
17030
  return;
18166
17031
  }
18167
17032
  const textEditable = Array.from(
@@ -18235,14 +17100,6 @@ function OhhwellsBridge() {
18235
17100
  window.addEventListener("message", handleParentScroll);
18236
17101
  window.addEventListener("message", handlePointerSync);
18237
17102
  window.addEventListener("message", handleClickAt);
18238
- window.addEventListener("message", handleUpdateLogoIdentity);
18239
- const handleViewMode = (e) => {
18240
- if (e.data?.type !== "ow:view-mode") return;
18241
- const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
18242
- setEditorViewport(mode);
18243
- applyLogoSizes(editContentRef.current);
18244
- };
18245
- window.addEventListener("message", handleViewMode);
18246
17103
  const handleViewportResize = () => {
18247
17104
  if (visibleViewportRef.current) {
18248
17105
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
@@ -18298,15 +17155,10 @@ function OhhwellsBridge() {
18298
17155
  window.removeEventListener("resize", handleViewportResize);
18299
17156
  window.removeEventListener("message", handlePointerSync);
18300
17157
  window.removeEventListener("message", handleClickAt);
18301
- window.removeEventListener("message", handleUpdateLogoIdentity);
18302
- window.removeEventListener("message", handleViewMode);
18303
17158
  window.removeEventListener("message", handleHydrate);
18304
17159
  window.removeEventListener("message", handleAiApplyTree);
18305
17160
  window.removeEventListener("message", handleAiDeleteSection);
18306
17161
  window.removeEventListener("message", handleAiSetSections);
18307
- window.removeEventListener("message", handleAiSetBrand);
18308
- window.removeEventListener("message", handleAiSetStyles);
18309
- window.removeEventListener("message", handleGetBrand);
18310
17162
  window.removeEventListener("message", handleDeactivate);
18311
17163
  window.removeEventListener("message", handleToastAction);
18312
17164
  window.removeEventListener("message", handleUiEscape);
@@ -18510,7 +17362,7 @@ function OhhwellsBridge() {
18510
17362
  postToParent2({
18511
17363
  type: "ow:ready",
18512
17364
  version: "1",
18513
- bridgeVersion: "0.1.63",
17365
+ bridgeVersion: "0.1.62",
18514
17366
  path: pathname,
18515
17367
  nodes: collectEditableNodes(editContentRef.current),
18516
17368
  sections
@@ -18905,10 +17757,10 @@ function OhhwellsBridge() {
18905
17757
  [postToParent2]
18906
17758
  );
18907
17759
  return bridgeRoot ? createPortal2(
18908
- /* @__PURE__ */ jsxs20(Fragment8, { children: [
18909
- /* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
18910
- isEditMode && /* @__PURE__ */ jsx33(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
18911
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx33(
17760
+ /* @__PURE__ */ jsxs19(Fragment8, { children: [
17761
+ /* @__PURE__ */ jsx32("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
17762
+ isEditMode && /* @__PURE__ */ jsx32(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
17763
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx32(
18912
17764
  MediaOverlay,
18913
17765
  {
18914
17766
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -18919,7 +17771,7 @@ function OhhwellsBridge() {
18919
17771
  },
18920
17772
  `uploading-${key}`
18921
17773
  )),
18922
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx33(
17774
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx32(
18923
17775
  MediaOverlay,
18924
17776
  {
18925
17777
  hover: mediaHover,
@@ -18928,11 +17780,11 @@ function OhhwellsBridge() {
18928
17780
  onVideoSettingsChange: handleVideoSettingsChange
18929
17781
  }
18930
17782
  ),
18931
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
18932
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
18933
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
18934
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
18935
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
17783
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx32(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
17784
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
17785
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
17786
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
17787
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx32(
18936
17788
  "div",
18937
17789
  {
18938
17790
  className: "pointer-events-none fixed z-2147483646",
@@ -18942,7 +17794,7 @@ function OhhwellsBridge() {
18942
17794
  width: slot.width,
18943
17795
  height: slot.height
18944
17796
  },
18945
- children: /* @__PURE__ */ jsx33(
17797
+ children: /* @__PURE__ */ jsx32(
18946
17798
  DropIndicator,
18947
17799
  {
18948
17800
  direction: slot.direction,
@@ -18953,7 +17805,7 @@ function OhhwellsBridge() {
18953
17805
  },
18954
17806
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
18955
17807
  )),
18956
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
17808
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx32(
18957
17809
  "div",
18958
17810
  {
18959
17811
  className: "pointer-events-none fixed z-2147483646",
@@ -18963,7 +17815,7 @@ function OhhwellsBridge() {
18963
17815
  width: slot.width,
18964
17816
  height: slot.height
18965
17817
  },
18966
- children: /* @__PURE__ */ jsx33(
17818
+ children: /* @__PURE__ */ jsx32(
18967
17819
  DropIndicator,
18968
17820
  {
18969
17821
  direction: slot.direction,
@@ -18974,11 +17826,11 @@ function OhhwellsBridge() {
18974
17826
  },
18975
17827
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
18976
17828
  )),
18977
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
18978
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
18979
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
18980
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx33(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
18981
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
17829
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
17830
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
17831
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
17832
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx32(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
17833
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx32(
18982
17834
  FooterContainerChrome,
18983
17835
  {
18984
17836
  rect: toolbarRect,
@@ -18986,7 +17838,7 @@ function OhhwellsBridge() {
18986
17838
  addDisabled: !canAddFooterColumn()
18987
17839
  }
18988
17840
  ),
18989
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
17841
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx32(
18990
17842
  ItemInteractionLayer,
18991
17843
  {
18992
17844
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -18998,10 +17850,10 @@ function OhhwellsBridge() {
18998
17850
  dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
18999
17851
  onDragHandleDragStart: handleItemDragStart,
19000
17852
  onDragHandleDragEnd: handleItemDragEnd,
19001
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
19002
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
19003
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
19004
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
17853
+ onItemPointerDown: handleItemChromePointerDown,
17854
+ onItemClick: handleItemChromeClick,
17855
+ itemDragSurface: !isFooterFrameSelection,
17856
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx32(
19005
17857
  ItemActionToolbar,
19006
17858
  {
19007
17859
  onEditLink: openLinkPopoverForSelected,
@@ -19037,8 +17889,8 @@ function OhhwellsBridge() {
19037
17889
  ) : void 0
19038
17890
  }
19039
17891
  ),
19040
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
19041
- /* @__PURE__ */ jsx33(
17892
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs19(Fragment8, { children: [
17893
+ /* @__PURE__ */ jsx32(
19042
17894
  EditGlowChrome,
19043
17895
  {
19044
17896
  rect: toolbarRect,
@@ -19048,7 +17900,7 @@ function OhhwellsBridge() {
19048
17900
  hideHandle: isItemDragging
19049
17901
  }
19050
17902
  ),
19051
- /* @__PURE__ */ jsx33(
17903
+ /* @__PURE__ */ jsx32(
19052
17904
  FloatingToolbar,
19053
17905
  {
19054
17906
  rect: toolbarRect,
@@ -19061,7 +17913,7 @@ function OhhwellsBridge() {
19061
17913
  }
19062
17914
  )
19063
17915
  ] }),
19064
- maxBadge && /* @__PURE__ */ jsxs20(
17916
+ maxBadge && /* @__PURE__ */ jsxs19(
19065
17917
  "div",
19066
17918
  {
19067
17919
  "data-ohw-max-badge": "",
@@ -19087,7 +17939,7 @@ function OhhwellsBridge() {
19087
17939
  ]
19088
17940
  }
19089
17941
  ),
19090
- toggleState && !linkPopover && /* @__PURE__ */ jsx33(
17942
+ toggleState && !linkPopover && /* @__PURE__ */ jsx32(
19091
17943
  StateToggle,
19092
17944
  {
19093
17945
  rect: toggleState.rect,
@@ -19096,15 +17948,15 @@ function OhhwellsBridge() {
19096
17948
  onStateChange: handleStateChange
19097
17949
  }
19098
17950
  ),
19099
- sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
17951
+ sectionGap && !linkPopover && /* @__PURE__ */ jsxs19(
19100
17952
  "div",
19101
17953
  {
19102
17954
  "data-ohw-section-insert-line": "",
19103
17955
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
19104
17956
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
19105
17957
  children: [
19106
- /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19107
- /* @__PURE__ */ jsx33(
17958
+ /* @__PURE__ */ jsx32("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
17959
+ /* @__PURE__ */ jsx32(
19108
17960
  Badge,
19109
17961
  {
19110
17962
  className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
@@ -19121,11 +17973,11 @@ function OhhwellsBridge() {
19121
17973
  children: "Add Section"
19122
17974
  }
19123
17975
  ),
19124
- /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
17976
+ /* @__PURE__ */ jsx32("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19125
17977
  ]
19126
17978
  }
19127
17979
  ),
19128
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx33(
17980
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx32(
19129
17981
  LinkPopover,
19130
17982
  {
19131
17983
  panelRef: linkPopoverPanelRef,
@@ -19142,7 +17994,7 @@ function OhhwellsBridge() {
19142
17994
  },
19143
17995
  linkPopover.key
19144
17996
  ) : null,
19145
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx33(
17997
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx32(
19146
17998
  FloatingPanel,
19147
17999
  {
19148
18000
  open: true,
@@ -19152,7 +18004,7 @@ function OhhwellsBridge() {
19152
18004
  onPositionChange: setFloatingPanelPos,
19153
18005
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
19154
18006
  onClose: closeFloatingPanelOnly,
19155
- children: /* @__PURE__ */ jsx33(
18007
+ children: /* @__PURE__ */ jsx32(
19156
18008
  SocialsDisplayPanel,
19157
18009
  {
19158
18010
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -19163,115 +18015,11 @@ function OhhwellsBridge() {
19163
18015
  }
19164
18016
  )
19165
18017
  }
19166
- ) : null,
19167
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ jsx33(
19168
- FloatingPanel,
19169
- {
19170
- open: true,
19171
- title: floatingPanel.title,
19172
- context: floatingPanel.context,
19173
- position: floatingPanelPos,
19174
- onPositionChange: setFloatingPanelPos,
19175
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
19176
- onClose: closeFloatingPanelAndDeselect,
19177
- children: /* @__PURE__ */ jsx33(
19178
- LogoSizePanel,
19179
- {
19180
- viewport: editorViewport,
19181
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
19182
- mobileFollowing: logoSizeDraft.mobileFollowing,
19183
- onSizeChange: (px) => {
19184
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
19185
- ...logoSizeDraft,
19186
- desktopPx: px,
19187
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
19188
- };
19189
- setLogoSizeDraft(next);
19190
- persistLogoSizeDraft(floatingPanel.placement, next);
19191
- },
19192
- onCustomizeMobile: () => {
19193
- const next = {
19194
- ...logoSizeDraft,
19195
- mobileFollowing: false,
19196
- mobilePx: logoSizeDraft.desktopPx
19197
- };
19198
- setLogoSizeDraft(next);
19199
- persistLogoSizeDraft(floatingPanel.placement, next);
19200
- },
19201
- onResetMobile: () => {
19202
- const next = {
19203
- ...logoSizeDraft,
19204
- mobileFollowing: true,
19205
- mobilePx: logoSizeDraft.desktopPx
19206
- };
19207
- setLogoSizeDraft(next);
19208
- persistLogoSizeDraft(floatingPanel.placement, next);
19209
- },
19210
- onUpdateEverywhere: () => {
19211
- const identity = readLogoIdentityFromDom();
19212
- postToParent2({ type: "ow:open-logo-settings", ...identity });
19213
- }
19214
- }
19215
- )
19216
- }
19217
18018
  ) : null
19218
18019
  ] }),
19219
18020
  bridgeRoot
19220
18021
  ) : null;
19221
18022
  }
19222
-
19223
- // src/ui/EmptySection.tsx
19224
- import Link4 from "next/link";
19225
- import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
19226
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
19227
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
19228
- /* @__PURE__ */ jsx34(
19229
- "p",
19230
- {
19231
- style: {
19232
- fontFamily: "var(--brand-font-body)",
19233
- fontSize: "0.75rem",
19234
- fontWeight: 500,
19235
- letterSpacing: "0.15em",
19236
- textTransform: "uppercase",
19237
- color: "var(--brand-accent)",
19238
- marginBottom: "1.5rem"
19239
- },
19240
- children: /* @__PURE__ */ jsx34(Link4, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx34("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
19241
- }
19242
- ),
19243
- /* @__PURE__ */ jsx34(
19244
- "h1",
19245
- {
19246
- style: {
19247
- fontFamily: "var(--brand-font-heading)",
19248
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
19249
- lineHeight: 1.1,
19250
- letterSpacing: "-0.025em",
19251
- color: "var(--brand-text)",
19252
- marginBottom: "1rem"
19253
- },
19254
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
19255
- children: title
19256
- }
19257
- ),
19258
- /* @__PURE__ */ jsx34(
19259
- "p",
19260
- {
19261
- style: {
19262
- fontFamily: "var(--brand-font-body)",
19263
- fontSize: "1rem",
19264
- lineHeight: 1.7,
19265
- fontWeight: 300,
19266
- color: "var(--brand-text-muted)",
19267
- maxWidth: "340px"
19268
- },
19269
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
19270
- children: "This page doesn't have any content yet."
19271
- }
19272
- )
19273
- ] });
19274
- }
19275
18023
  export {
19276
18024
  AI_DEFAULT_BRAND,
19277
18025
  AI_TREE_SCHEMA_VERSIONS,
@@ -19288,7 +18036,6 @@ export {
19288
18036
  DropdownMenuItem,
19289
18037
  DropdownMenuSeparator,
19290
18038
  DropdownMenuTrigger,
19291
- EmptySection,
19292
18039
  ItemActionToolbar,
19293
18040
  ItemInteractionLayer,
19294
18041
  LinkEditorPanel,