@ohhwells/bridge 0.1.62-next.174 → 0.1.62

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.cjs CHANGED
@@ -46,7 +46,6 @@ __export(index_exports, {
46
46
  DropdownMenuItem: () => DropdownMenuItem,
47
47
  DropdownMenuSeparator: () => DropdownMenuSeparator,
48
48
  DropdownMenuTrigger: () => DropdownMenuTrigger,
49
- EmptySection: () => EmptySection,
50
49
  ItemActionToolbar: () => ItemActionToolbar,
51
50
  ItemInteractionLayer: () => ItemInteractionLayer,
52
51
  LinkEditorPanel: () => LinkEditorPanel,
@@ -170,7 +169,6 @@ function applyTreeToState(state, payload) {
170
169
  const entry = {
171
170
  id: payload.id,
172
171
  label: payload.label ?? "Generated section",
173
- ...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
174
172
  afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
175
173
  ...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
176
174
  ...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
@@ -193,287 +191,6 @@ function deleteSectionFromState(state, sectionId) {
193
191
  return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
194
192
  }
195
193
 
196
- // src/lib/brand-chrome.ts
197
- var BRAND_NAME_KEY = "__ohw_brand_name";
198
- var BRAND_TITLE_KEY = "__ohw_site_title";
199
- var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
200
- var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
201
- BRAND_NAME_KEY,
202
- BRAND_TITLE_KEY,
203
- BRAND_FAVICON_LETTER_KEY
204
- ]);
205
- function upsertMeta(selector, attr, token, value) {
206
- let el = document.head.querySelector(selector);
207
- if (!el) {
208
- el = document.createElement("meta");
209
- el.setAttribute(attr, token);
210
- document.head.appendChild(el);
211
- }
212
- if (el.getAttribute("content") !== value) el.setAttribute("content", value);
213
- }
214
- function escapeXml(value) {
215
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
216
- }
217
- function applyLetterFavicon(letter) {
218
- 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>`;
219
- const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
220
- let link = document.head.querySelector('link[rel="icon"]');
221
- if (!link) {
222
- link = document.createElement("link");
223
- link.rel = "icon";
224
- document.head.appendChild(link);
225
- }
226
- link.type = "image/svg+xml";
227
- if (link.href !== href) link.href = href;
228
- }
229
- function applyBrandChrome(content) {
230
- const name = content[BRAND_NAME_KEY];
231
- if (typeof name === "string" && name.length > 0) {
232
- document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
233
- if (el.textContent !== name) el.textContent = name;
234
- if (el.getAttribute("title") !== name) el.setAttribute("title", name);
235
- });
236
- }
237
- const title = content[BRAND_TITLE_KEY];
238
- if (typeof title === "string" && title.length > 0) {
239
- if (document.title !== title) document.title = title;
240
- upsertMeta('meta[property="og:title"]', "property", "og:title", title);
241
- upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
242
- }
243
- const letter = content[BRAND_FAVICON_LETTER_KEY];
244
- if (typeof letter === "string" && letter.length > 0) {
245
- applyLetterFavicon(letter);
246
- }
247
- }
248
-
249
- // src/lib/brand-kit.ts
250
- var BRAND_KIT_KEY = "__ohw_brand";
251
- var BRAND_VAR_PREFIX = "--ohw-brand-";
252
- var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
253
- (role) => `${BRAND_VAR_PREFIX}${role}`
254
- );
255
- var FONT_VARS = { heading: ["--font-heading", "--font-display"], body: ["--font-body"] };
256
- var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
257
- function brandColorVars(kit) {
258
- const { dark, primary, accent, light } = kit.palette;
259
- const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
260
- return {
261
- [`${BRAND_VAR_PREFIX}primary`]: primary,
262
- [`${BRAND_VAR_PREFIX}accent`]: accent,
263
- [`${BRAND_VAR_PREFIX}light`]: light,
264
- [`${BRAND_VAR_PREFIX}dark`]: dark,
265
- [`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
266
- [`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
267
- [`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
268
- };
269
- }
270
- function parseBrandKit(raw) {
271
- if (!raw) return null;
272
- try {
273
- const parsed = JSON.parse(raw);
274
- const p = parsed?.palette;
275
- const f = parsed?.fonts;
276
- 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") {
277
- return null;
278
- }
279
- return {
280
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
281
- fonts: { heading: f.heading, body: f.body }
282
- };
283
- } catch {
284
- return null;
285
- }
286
- }
287
- function familyOf(stack) {
288
- const first = stack.split(",")[0]?.trim() ?? "";
289
- return first.replace(/^['"]|['"]$/g, "");
290
- }
291
- function loadBrandFonts(families) {
292
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
293
- if (unique.length === 0) return;
294
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
295
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
296
- let link = document.getElementById(BRAND_FONT_LINK_ID);
297
- if (!link) {
298
- link = document.createElement("link");
299
- link.id = BRAND_FONT_LINK_ID;
300
- link.rel = "stylesheet";
301
- document.head.appendChild(link);
302
- }
303
- if (link.href !== href) link.href = href;
304
- }
305
- function applyBrandToDom(kit) {
306
- const root = document.documentElement;
307
- if (!kit) {
308
- for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
309
- for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
310
- document.getElementById(BRAND_FONT_LINK_ID)?.remove();
311
- return;
312
- }
313
- for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
314
- for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
315
- for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
316
- loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
317
- }
318
-
319
- // src/lib/section-styles.ts
320
- var STYLE_STORE_KEY = "__ohw_styles";
321
- var STYLE_SHEET_ID = "ohw-section-styles";
322
- function parseStyleStore(raw) {
323
- if (!raw) return null;
324
- try {
325
- const parsed = JSON.parse(raw);
326
- if (parsed?.v !== 1) return null;
327
- return {
328
- v: 1,
329
- sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
330
- nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
331
- };
332
- } catch {
333
- return null;
334
- }
335
- }
336
- var BG_VALUES = {
337
- surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
338
- accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
339
- "accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
340
- };
341
- var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
342
- function styleSheetCss() {
343
- const rules = [];
344
- for (const [tone, value] of Object.entries(BG_VALUES)) {
345
- rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
346
- }
347
- rules.push(
348
- `[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
349
- );
350
- rules.push(
351
- `[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
352
- `[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
353
- );
354
- for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
355
- rules.push(
356
- `[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
357
- );
358
- }
359
- rules.push(
360
- `[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
361
- );
362
- for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
363
- rules.push(
364
- `[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
365
- );
366
- }
367
- const pad = { tight: 40, balanced: 64, airy: 96 };
368
- for (const [spacing, px] of Object.entries(pad)) {
369
- rules.push(
370
- `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
371
- );
372
- }
373
- return rules.join("\n");
374
- }
375
- var SECTION_ATTRS = {
376
- sectionBackground: "data-ohw-style-bg",
377
- textDistribution: "data-ohw-style-distribution",
378
- headlineScale: "data-ohw-style-headline",
379
- imageAspect: "data-ohw-style-aspect",
380
- spacing: "data-ohw-style-spacing"
381
- };
382
- var NODE_WROTE_ATTR = "data-ohw-style-node";
383
- var NODE_PROPS = ["color", "font-size", "background"];
384
- function saveInline(el, prop) {
385
- const attr = `data-ohw-style-prev-${prop}`;
386
- if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
387
- }
388
- function restoreInline(el, prop) {
389
- const attr = `data-ohw-style-prev-${prop}`;
390
- if (!el.hasAttribute(attr)) return;
391
- const prev = el.getAttribute(attr) ?? "";
392
- if (prev) el.style.setProperty(prop, prev);
393
- else el.style.removeProperty(prop);
394
- el.removeAttribute(attr);
395
- }
396
- function ensureStyleSheet() {
397
- let el = document.getElementById(STYLE_SHEET_ID);
398
- if (!el) {
399
- el = document.createElement("style");
400
- el.id = STYLE_SHEET_ID;
401
- document.head.appendChild(el);
402
- }
403
- const css = styleSheetCss();
404
- if (el.textContent !== css) el.textContent = css;
405
- }
406
- function clearSectionAttrs(root) {
407
- for (const attr of Object.values(SECTION_ATTRS)) {
408
- for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
409
- }
410
- for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
411
- restoreInline(el, "background");
412
- el.removeAttribute("data-ohw-style-bgcolor");
413
- }
414
- }
415
- function clearNodeProps(root) {
416
- for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
417
- const h = el;
418
- for (const prop of NODE_PROPS) restoreInline(h, prop);
419
- h.removeAttribute(NODE_WROTE_ATTR);
420
- }
421
- }
422
- function buttonSurfaceOf(el) {
423
- return el.closest("a, button") ?? el;
424
- }
425
- function applyStylesToDom(store) {
426
- ensureStyleSheet();
427
- clearSectionAttrs(document);
428
- clearNodeProps(document);
429
- if (!store) return;
430
- for (const [sectionId, override] of Object.entries(store.sections)) {
431
- const sections = document.querySelectorAll(
432
- `[data-ohw-section="${CSS.escape(sectionId)}"]`
433
- );
434
- for (const section of Array.from(sections)) {
435
- for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
436
- const value = override[prop];
437
- if (value === void 0) continue;
438
- if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
439
- section.setAttribute(attr, String(value).replace(":", "-"));
440
- }
441
- if (override.sectionBackgroundColor !== void 0) {
442
- saveInline(section, "background");
443
- section.style.setProperty("background", override.sectionBackgroundColor, "important");
444
- section.setAttribute("data-ohw-style-bgcolor", "");
445
- }
446
- }
447
- }
448
- for (const [key, override] of Object.entries(store.nodes)) {
449
- const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
450
- for (const el of Array.from(nodes)) {
451
- if (override.color !== void 0) {
452
- saveInline(el, "color");
453
- el.style.setProperty("color", override.color, "important");
454
- el.setAttribute(NODE_WROTE_ATTR, "");
455
- }
456
- if (override.fontSize !== void 0) {
457
- saveInline(el, "font-size");
458
- el.style.setProperty("font-size", `${override.fontSize}px`, "important");
459
- el.setAttribute(NODE_WROTE_ATTR, "");
460
- }
461
- if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
462
- const surface = buttonSurfaceOf(el);
463
- if (override.buttonBackground !== void 0) {
464
- saveInline(surface, "background");
465
- surface.style.setProperty("background", override.buttonBackground, "important");
466
- }
467
- if (override.buttonText !== void 0) {
468
- saveInline(surface, "color");
469
- surface.style.setProperty("color", override.buttonText, "important");
470
- }
471
- surface.setAttribute(NODE_WROTE_ATTR, "");
472
- }
473
- }
474
- }
475
- }
476
-
477
194
  // src/ui/ai-tree/aiSectionsManager.tsx
478
195
  var import_react_dom = require("react-dom");
479
196
  var import_client = require("react-dom/client");
@@ -488,8 +205,7 @@ function lucideByName(name) {
488
205
  }
489
206
  var typeStyle = (spec, font) => ({
490
207
  fontFamily: font,
491
- // Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
492
- 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,
208
+ fontSize: spec.size,
493
209
  lineHeight: spec.line,
494
210
  fontWeight: spec.weight
495
211
  });
@@ -516,8 +232,6 @@ var AI_RESPONSIVE_CSS = [
516
232
  " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
517
233
  " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
518
234
  " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
519
- " [data-ai-responsive] { overflow-x: hidden; }",
520
- " [data-ai-responsive] img { max-width: 100%; }",
521
235
  "}"
522
236
  ].join("\n");
523
237
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
@@ -1525,20 +1239,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1525
1239
  const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
1526
1240
  const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
1527
1241
  const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
1528
- const toneBackground = (() => {
1529
- const { dark, primary, light } = resolvedBrand.palette;
1530
- switch (settings.sectionBackground) {
1531
- case "surface":
1532
- return `color-mix(in srgb, ${light} 94%, ${dark})`;
1533
- case "accent":
1534
- return primary;
1535
- case "accent-soft":
1536
- return `color-mix(in srgb, ${primary} 12%, ${light})`;
1537
- default:
1538
- return void 0;
1539
- }
1540
- })();
1541
- const distributed = !isOverlay && settings.textDistribution;
1542
1242
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1543
1243
  "section",
1544
1244
  {
@@ -1548,11 +1248,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1548
1248
  style: {
1549
1249
  position: "relative",
1550
1250
  padding: `${pad}px 0`,
1551
- background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
1251
+ background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
1552
1252
  backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
1553
1253
  backgroundSize: "cover",
1554
- backgroundPosition: "center",
1555
- color: settings.sectionBackground === "accent" ? resolvedBrand.palette.light : void 0
1254
+ backgroundPosition: "center"
1556
1255
  },
1557
1256
  children: [
1558
1257
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
@@ -1576,24 +1275,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1576
1275
  display: "grid",
1577
1276
  gridTemplateColumns: "repeat(12, 1fr)",
1578
1277
  gap: AI_TREE_TOKENS.spacing6,
1579
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1278
+ alignItems: settings.verticalPosition === "top" ? "start" : "center",
1580
1279
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1581
1280
  },
1582
- children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1583
- "div",
1584
- {
1585
- "data-ai-cell": "",
1586
- style: {
1587
- gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1588
- minWidth: 0,
1589
- // space-between: each column becomes a flex column whose content spreads over
1590
- // the full row height instead of clumping at the top.
1591
- ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
1592
- },
1593
- children: renderNode(block, ctx, `r${r2}.b${b}`)
1594
- },
1595
- b
1596
- ))
1281
+ children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`, minWidth: 0 }, children: renderNode(block, ctx, `r${r2}.b${b}`) }, b))
1597
1282
  },
1598
1283
  r2
1599
1284
  ))
@@ -1609,34 +1294,17 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
1609
1294
  var CONTAINER_ATTR = "data-ohw-ai-generated";
1610
1295
  var REPLACED_ATTR = "data-ohw-ai-replaced-by";
1611
1296
  var REMOVED_ATTR = "data-ohw-ai-removed";
1612
- function readRootVar(name) {
1613
- if (typeof document === "undefined") return "";
1614
- return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1615
- }
1616
- function deriveBrandOverride() {
1617
- const dark = readRootVar("--ohw-brand-dark");
1618
- const primary = readRootVar("--ohw-brand-primary");
1619
- const light = readRootVar("--ohw-brand-light");
1620
- if (!dark || !primary || !light) return null;
1621
- const accent = readRootVar("--ohw-brand-accent");
1622
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1623
- const body = readRootVar("--font-body");
1624
- return {
1625
- palette: { dark, primary, accent: accent || dark, light },
1626
- fonts: {
1627
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
1628
- body: body || AI_DEFAULT_BRAND.fonts.body
1629
- }
1630
- };
1631
- }
1632
1297
  function deriveTemplateBrand() {
1633
- const dark = readRootVar("--color-dark");
1634
- const primary = readRootVar("--color-primary");
1635
- const light = readRootVar("--color-light");
1298
+ if (typeof document === "undefined") return null;
1299
+ const cs = getComputedStyle(document.documentElement);
1300
+ const read = (name) => cs.getPropertyValue(name).trim();
1301
+ const dark = read("--color-dark");
1302
+ const primary = read("--color-primary");
1303
+ const light = read("--color-light");
1636
1304
  if (!dark || !primary || !light) return null;
1637
- const accent = readRootVar("--color-accent");
1638
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1639
- const body = readRootVar("--font-body");
1305
+ const accent = read("--color-accent");
1306
+ const heading = read("--font-heading") || read("--font-display");
1307
+ const body = read("--font-body");
1640
1308
  return {
1641
1309
  palette: { dark, primary, accent: accent || dark, light },
1642
1310
  fonts: {
@@ -1728,12 +1396,8 @@ function syncReplacedOriginals(state) {
1728
1396
  }
1729
1397
  function applyAiSectionsToDom(state, options) {
1730
1398
  if (typeof document === "undefined") return;
1731
- const brandOverride = deriveBrandOverride();
1732
1399
  const templateBrand = deriveTemplateBrand();
1733
- const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
1734
- const pagePath = window.location.pathname;
1735
- const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
1736
- const activeIds = new Set(pageSections.map((entry) => entry.id));
1400
+ const activeIds = new Set(state.sections.map((entry) => entry.id));
1737
1401
  for (const [id, section] of mounted) {
1738
1402
  if (!activeIds.has(id)) {
1739
1403
  section.root.unmount();
@@ -1741,8 +1405,8 @@ function applyAiSectionsToDom(state, options) {
1741
1405
  mounted.delete(id);
1742
1406
  }
1743
1407
  }
1744
- for (const entry of pageSections) {
1745
- const serialized = JSON.stringify(entry) + brandKey;
1408
+ for (const entry of state.sections) {
1409
+ const serialized = JSON.stringify(entry);
1746
1410
  const existing = mounted.get(entry.id);
1747
1411
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
1748
1412
  continue;
@@ -1756,7 +1420,6 @@ function applyAiSectionsToDom(state, options) {
1756
1420
  mounted.delete(entry.id);
1757
1421
  }
1758
1422
  container.setAttribute("data-ohw-section", entry.id);
1759
- container.setAttribute("data-ohw-instance", entry.id);
1760
1423
  container.setAttribute("data-ohw-section-label", entry.label);
1761
1424
  placeContainer(container, entry);
1762
1425
  const root = mounted.get(entry.id)?.root ?? (0, import_client.createRoot)(container);
@@ -1767,7 +1430,7 @@ function applyAiSectionsToDom(state, options) {
1767
1430
  AiTreeRenderer,
1768
1431
  {
1769
1432
  tree: entry.tree,
1770
- brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1433
+ brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1771
1434
  resolveMedia,
1772
1435
  editKeyPrefix: `ai.${entry.id}`
1773
1436
  }
@@ -2384,7 +2047,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2384
2047
  const autoId = (0, import_react5.useId)();
2385
2048
  const insertAfter = insertAfterProp ?? autoId;
2386
2049
  const [schedule, setSchedule] = (0, import_react5.useState)(null);
2387
- const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
2050
+ const [loading, setLoading] = (0, import_react5.useState)(true);
2388
2051
  const [inEditor, setInEditor] = (0, import_react5.useState)(false);
2389
2052
  const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
2390
2053
  const [modalState, setModalState] = (0, import_react5.useState)(null);
@@ -2558,10 +2221,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2558
2221
  "*"
2559
2222
  );
2560
2223
  };
2224
+ if (!inEditor && !loading && !schedule) return null;
2561
2225
  const sectionId = `scheduling-${insertAfter}`;
2562
- if (!inEditor && !loading && !schedule) {
2563
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2564
- }
2565
2226
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2566
2227
  "section",
2567
2228
  {
@@ -7080,12 +6741,8 @@ function parseSectionsFromHtml(html) {
7080
6741
 
7081
6742
  // src/ui/ai-section/AiSectionOverlay.tsx
7082
6743
  var import_jsx_runtime16 = require("react/jsx-runtime");
7083
- function findSectionElement(instanceId) {
7084
- const escaped = CSS.escape(instanceId);
7085
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7086
- }
7087
- function readRect(instanceId) {
7088
- const el = findSectionElement(instanceId);
6744
+ function readRect(sectionId) {
6745
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7089
6746
  if (!el) return null;
7090
6747
  const r2 = el.getBoundingClientRect();
7091
6748
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7108,7 +6765,7 @@ function useLiveSectionRect(sectionId) {
7108
6765
  const opts = { capture: true, passive: true };
7109
6766
  window.addEventListener("scroll", update, opts);
7110
6767
  window.addEventListener("resize", update);
7111
- const el = findSectionElement(sectionId);
6768
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7112
6769
  const ro = el ? new ResizeObserver(update) : null;
7113
6770
  if (el && ro) ro.observe(el);
7114
6771
  const interval = setInterval(update, 500);
@@ -7121,14 +6778,6 @@ function useLiveSectionRect(sectionId) {
7121
6778
  }, [sectionId]);
7122
6779
  return rect;
7123
6780
  }
7124
- function computeSectionBoundaryFlags(instanceId) {
7125
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7126
- (el) => !el.parentElement?.closest("[data-ohw-section]")
7127
- );
7128
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7129
- if (index === -1) return { isFirst: true, isLast: true };
7130
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7131
- }
7132
6781
  var PRIMARY2 = "#0885FE";
7133
6782
  function edgeAwareRadius(rect) {
7134
6783
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7202,7 +6851,6 @@ function AiSectionOverlay({
7202
6851
  }) {
7203
6852
  const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
7204
6853
  const [reviewId, setReviewId] = (0, import_react8.useState)(null);
7205
- const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
7206
6854
  const reviewIdRef = (0, import_react8.useRef)(null);
7207
6855
  reviewIdRef.current = reviewId;
7208
6856
  const selectedIdRef = (0, import_react8.useRef)(null);
@@ -7211,7 +6859,7 @@ function AiSectionOverlay({
7211
6859
  (el) => {
7212
6860
  postToParent2({
7213
6861
  type: "ow:section-selected",
7214
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
6862
+ sectionId: el?.dataset.ohwSection ?? null,
7215
6863
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7216
6864
  });
7217
6865
  },
@@ -7220,7 +6868,7 @@ function AiSectionOverlay({
7220
6868
  const selectFromElement = (0, import_react8.useCallback)(
7221
6869
  (el, options) => {
7222
6870
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7223
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
6871
+ const id = sectionEl?.dataset.ohwSection ?? null;
7224
6872
  if (id === selectedIdRef.current) return;
7225
6873
  setSelectedId(id);
7226
6874
  if (options?.report !== false) report(sectionEl);
@@ -7261,10 +6909,9 @@ function AiSectionOverlay({
7261
6909
  }
7262
6910
  const found = readRect(sectionId) != null;
7263
6911
  setReviewId(found ? sectionId : null);
7264
- setReviewButtonsHidden(e.data.hideButtons === true);
7265
6912
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7266
6913
  if (found) {
7267
- document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
6914
+ document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7268
6915
  }
7269
6916
  }
7270
6917
  };
@@ -7283,7 +6930,7 @@ function AiSectionOverlay({
7283
6930
  return;
7284
6931
  }
7285
6932
  const sec = t.closest("[data-ohw-section]");
7286
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
6933
+ setHoveredId(sec?.dataset.ohwSection ?? null);
7287
6934
  };
7288
6935
  const onLeave = () => setHoveredId(null);
7289
6936
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -7315,29 +6962,9 @@ function AiSectionOverlay({
7315
6962
  },
7316
6963
  [postToParent2]
7317
6964
  );
7318
- const activeSelectionId = reviewId ? null : selectedId;
7319
- const selectionRect = useLiveSectionRect(activeSelectionId);
6965
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
7320
6966
  const reviewRect = useLiveSectionRect(reviewId);
7321
6967
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
7322
- (0, import_react8.useEffect)(() => {
7323
- if (!activeSelectionId || !selectionRect) {
7324
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
7325
- return;
7326
- }
7327
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
7328
- postToParent2({
7329
- type: "ow:section-rect",
7330
- instanceId: activeSelectionId,
7331
- rect: {
7332
- top: selectionRect.top + window.scrollY,
7333
- left: selectionRect.left + window.scrollX,
7334
- width: selectionRect.width,
7335
- height: selectionRect.height
7336
- },
7337
- isFirst,
7338
- isLast
7339
- });
7340
- }, [activeSelectionId, selectionRect, postToParent2]);
7341
6968
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
7342
6969
  hoverRect && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7343
6970
  "div",
@@ -7388,16 +7015,13 @@ function AiSectionOverlay({
7388
7015
  border: `2px solid ${PRIMARY2}`,
7389
7016
  borderRadius: edgeAwareRadius(reviewRect),
7390
7017
  zIndex: 2147483200,
7391
- // The veil itself: swallows clicks so the section stays locked until decided. This
7392
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
7393
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
7394
- // Accept/Discard resolves to the media beneath and opens the file picker.
7018
+ // The veil itself: swallows clicks so the section stays locked until decided.
7395
7019
  background: "rgba(8, 133, 254, 0.04)",
7396
7020
  pointerEvents: "auto",
7397
7021
  cursor: "default"
7398
7022
  },
7399
7023
  onClick: (e) => e.stopPropagation(),
7400
- children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7024
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7401
7025
  "div",
7402
7026
  {
7403
7027
  style: {
@@ -11297,329 +10921,6 @@ function deleteFooterColumn(column) {
11297
10921
  };
11298
10922
  }
11299
10923
 
11300
- // src/lib/logo-identity.ts
11301
- var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
11302
- var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
11303
- var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
11304
- var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
11305
- var LOGO_ALT_KEY = "logo-alt";
11306
- var LOGO_IMAGE_URL_KEY = "nav-logo-image";
11307
- var PLACEHOLDER_BUSINESS_NAME = "Business name";
11308
- function resolveLogoDisplayText(text) {
11309
- const trimmed = (text ?? "").trim();
11310
- return trimmed || PLACEHOLDER_BUSINESS_NAME;
11311
- }
11312
- function isFooterLogoRoot(root) {
11313
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11314
- }
11315
- function imageKeyForRoot(root) {
11316
- return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
11317
- }
11318
- function textKeyForRoot(root) {
11319
- return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
11320
- }
11321
- function ensureLogoHrefKey(root) {
11322
- if (!(root instanceof HTMLAnchorElement)) return;
11323
- if (root.hasAttribute("data-ohw-href-key")) return;
11324
- root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
11325
- }
11326
- function applyLogoIdentity(text, isPlaceholder) {
11327
- const display = resolveLogoDisplayText(text);
11328
- const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
11329
- for (const key of LOGO_TEXT_KEYS) {
11330
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11331
- if (el.textContent !== display) el.textContent = display;
11332
- });
11333
- }
11334
- for (const key of LOGO_IMAGE_KEYS) {
11335
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11336
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
11337
- if (img) img.alt = display;
11338
- });
11339
- }
11340
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
11341
- if (placeholder) el.setAttribute("data-ohw-placeholder", "");
11342
- else el.removeAttribute("data-ohw-placeholder");
11343
- });
11344
- return display;
11345
- }
11346
- function applyLogoImage(url, alt) {
11347
- const displayAlt = resolveLogoDisplayText(alt);
11348
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11349
- ensureLogoHrefKey(root);
11350
- const imageKey = imageKeyForRoot(root);
11351
- const textKey = textKeyForRoot(root);
11352
- 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");
11353
- let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
11354
- if (url) {
11355
- if (!img) {
11356
- img = document.createElement("img");
11357
- img.setAttribute("data-ohw-editable", "image");
11358
- img.setAttribute("data-ohw-key", imageKey);
11359
- img.alt = displayAlt;
11360
- img.style.height = "";
11361
- img.style.maxHeight = "none";
11362
- img.style.width = "auto";
11363
- img.style.display = "block";
11364
- img.style.objectFit = "contain";
11365
- root.insertBefore(img, root.firstChild);
11366
- } else {
11367
- img.setAttribute("data-ohw-editable", "image");
11368
- img.setAttribute("data-ohw-key", imageKey);
11369
- }
11370
- img.removeAttribute("srcset");
11371
- img.removeAttribute("sizes");
11372
- img.src = url;
11373
- img.alt = displayAlt;
11374
- img.style.display = "block";
11375
- if (textEl) textEl.style.display = "none";
11376
- root.removeAttribute("data-ohw-placeholder");
11377
- return;
11378
- }
11379
- if (img) {
11380
- img.removeAttribute("src");
11381
- img.removeAttribute("srcset");
11382
- img.removeAttribute("sizes");
11383
- img.alt = displayAlt;
11384
- img.style.display = "none";
11385
- }
11386
- if (!textEl) {
11387
- textEl = document.createElement("span");
11388
- textEl.setAttribute("data-ohw-editable", "plain");
11389
- textEl.setAttribute("data-ohw-key", textKey);
11390
- root.appendChild(textEl);
11391
- }
11392
- textEl.style.display = "";
11393
- if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
11394
- if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
11395
- root.setAttribute("data-ohw-placeholder", "");
11396
- } else {
11397
- root.removeAttribute("data-ohw-placeholder");
11398
- }
11399
- });
11400
- }
11401
- function applyLogoHref(href) {
11402
- const target = href.trim() || "/";
11403
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11404
- ensureLogoHrefKey(root);
11405
- if (root instanceof HTMLAnchorElement) {
11406
- root.setAttribute("href", target);
11407
- }
11408
- });
11409
- for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
11410
- }
11411
- function readLogoIdentityFromDom() {
11412
- let imageUrl = null;
11413
- for (const key of LOGO_IMAGE_KEYS) {
11414
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
11415
- const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
11416
- const attrSrc = img?.getAttribute("src")?.trim() ?? "";
11417
- if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
11418
- imageUrl = img.currentSrc || img.src;
11419
- break;
11420
- }
11421
- }
11422
- let text = PLACEHOLDER_BUSINESS_NAME;
11423
- let isPlaceholder = true;
11424
- for (const key of LOGO_TEXT_KEYS) {
11425
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
11426
- if (el?.textContent?.trim()) {
11427
- text = el.textContent.trim();
11428
- const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
11429
- isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
11430
- break;
11431
- }
11432
- }
11433
- if (imageUrl) {
11434
- const logoImg = document.querySelector(
11435
- '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
11436
- );
11437
- const alt = logoImg?.alt?.trim() || text;
11438
- isPlaceholder = false;
11439
- const hrefEl = document.querySelector(
11440
- 'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
11441
- );
11442
- const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
11443
- return { text, isPlaceholder, imageUrl, href: href2, alt };
11444
- }
11445
- const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
11446
- const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
11447
- return { text, isPlaceholder, imageUrl: null, href, alt: text };
11448
- }
11449
- function applyLogoFromContent(content) {
11450
- 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);
11451
- if (!hasLogoIdentity) return false;
11452
- const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
11453
- const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
11454
- const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
11455
- const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
11456
- const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
11457
- const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
11458
- if (logoImageUrl) {
11459
- applyLogoImage(logoImageUrl, logoAlt);
11460
- } else {
11461
- if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
11462
- applyLogoIdentity(logoText, logoIsPlaceholder);
11463
- }
11464
- const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
11465
- if (typeof logoHref === "string" && logoHref.trim()) {
11466
- applyLogoHref(logoHref);
11467
- }
11468
- return true;
11469
- }
11470
-
11471
- // src/lib/logo-size.ts
11472
- var LOGO_SIZE_DEFAULTS = {
11473
- navbar: 28,
11474
- footer: 32
11475
- };
11476
- var LOGO_SIZE_MIN = 16;
11477
- var LOGO_SIZE_MAX = 80;
11478
- var LOGO_SIZE_DESKTOP_KEYS = {
11479
- navbar: "nav-logo-size",
11480
- footer: "footer-logo-size"
11481
- };
11482
- var LOGO_SIZE_MOBILE_KEYS = {
11483
- navbar: "nav-logo-size-mobile",
11484
- footer: "footer-logo-size-mobile"
11485
- };
11486
- var LOGO_SIZE_KEYS = [
11487
- LOGO_SIZE_DESKTOP_KEYS.navbar,
11488
- LOGO_SIZE_DESKTOP_KEYS.footer,
11489
- LOGO_SIZE_MOBILE_KEYS.navbar,
11490
- LOGO_SIZE_MOBILE_KEYS.footer
11491
- ];
11492
- function isFooterLogoRoot2(root) {
11493
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11494
- }
11495
- function getLogoPlacement(root) {
11496
- return isFooterLogoRoot2(root) ? "footer" : "navbar";
11497
- }
11498
- function parseLogoSizePx(raw, fallback) {
11499
- if (raw == null || raw === "") return fallback;
11500
- const n = Number.parseFloat(raw);
11501
- if (!Number.isFinite(n)) return fallback;
11502
- return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
11503
- }
11504
- function isMobileLogoSizeFollowing(content, placement) {
11505
- const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
11506
- return raw == null || raw.trim() === "";
11507
- }
11508
- function resolveDesktopLogoSize(content, placement) {
11509
- return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
11510
- }
11511
- function resolveMobileLogoSize(content, placement) {
11512
- if (isMobileLogoSizeFollowing(content, placement)) {
11513
- return resolveDesktopLogoSize(content, placement);
11514
- }
11515
- return parseLogoSizePx(
11516
- content[LOGO_SIZE_MOBILE_KEYS[placement]],
11517
- resolveDesktopLogoSize(content, placement)
11518
- );
11519
- }
11520
- function setRootSizeVars(root, desktopPx, mobilePx, following) {
11521
- root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
11522
- if (following) {
11523
- root.style.removeProperty("--ohw-logo-size-mobile");
11524
- } else {
11525
- root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
11526
- }
11527
- root.querySelectorAll("img").forEach((img) => {
11528
- img.style.height = "";
11529
- img.style.maxHeight = "none";
11530
- img.style.width = "auto";
11531
- img.style.objectFit = "contain";
11532
- });
11533
- }
11534
- function applyLogoSizes(content) {
11535
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11536
- const placement = getLogoPlacement(root);
11537
- const desktop = resolveDesktopLogoSize(content, placement);
11538
- const following = isMobileLogoSizeFollowing(content, placement);
11539
- const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
11540
- setRootSizeVars(root, desktop, mobile, following);
11541
- });
11542
- }
11543
- function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
11544
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11545
- if (getLogoPlacement(root) !== placement) return;
11546
- setRootSizeVars(root, desktopPx, mobilePx, following);
11547
- });
11548
- }
11549
- function logoHasUploadedImage(logoEl) {
11550
- if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
11551
- 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");
11552
- if (!img) return false;
11553
- const src = img.getAttribute("src")?.trim() ?? "";
11554
- if (!src || src.startsWith("data:")) return false;
11555
- if (img.style.display === "none") return false;
11556
- return true;
11557
- }
11558
- function getLogoInteractionRect(logoEl) {
11559
- if (logoHasUploadedImage(logoEl)) {
11560
- 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");
11561
- if (img) {
11562
- const r2 = img.getBoundingClientRect();
11563
- if (r2.width > 0 && r2.height > 0) return r2;
11564
- }
11565
- }
11566
- const text = logoEl.querySelector(
11567
- '[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
11568
- );
11569
- if (text) {
11570
- const style = window.getComputedStyle(text);
11571
- if (style.display !== "none" && style.visibility !== "hidden") {
11572
- const r2 = text.getBoundingClientRect();
11573
- if (r2.width > 0 && r2.height > 0) return r2;
11574
- }
11575
- }
11576
- return logoEl.getBoundingClientRect();
11577
- }
11578
- function readLogoSizeState(content, placement) {
11579
- const desktopPx = resolveDesktopLogoSize(content, placement);
11580
- const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
11581
- const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
11582
- return { desktopPx, mobilePx, mobileFollowing };
11583
- }
11584
-
11585
- // src/lib/site-wide-scope.ts
11586
- function getLogoElement(el) {
11587
- const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
11588
- if (marked) return marked;
11589
- if (el.closest('[data-ohw-editable="icon"]')) return null;
11590
- const root = el.closest("nav, [data-ohw-nav-root], footer");
11591
- if (!root) return null;
11592
- const anchor = el.closest("a");
11593
- if (anchor && root.contains(anchor) && !anchor.hasAttribute("data-ohw-href-key") && !anchor.closest("[data-ohw-nav-container]") && Boolean(anchor.querySelector("img") || anchor.matches("img"))) {
11594
- return anchor;
11595
- }
11596
- const img = el.matches("img") ? el : null;
11597
- if (img && !img.closest("[data-ohw-href-key]") && !img.closest("[data-ohw-nav-container]") && (img.closest("footer") || img.closest("nav, [data-ohw-nav-root]"))) {
11598
- return img;
11599
- }
11600
- return null;
11601
- }
11602
- function isInFooter(el) {
11603
- if (!el) return false;
11604
- return Boolean(el.closest("footer") || el.closest('[data-ohw-section="footer"]'));
11605
- }
11606
- function isSiteWideElement(el) {
11607
- if (!el) return false;
11608
- if (getLogoElement(el)) return true;
11609
- if (isInFooter(el)) return true;
11610
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-root")) {
11611
- return true;
11612
- }
11613
- if (el.hasAttribute("data-ohw-href-key") && el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer], aside")) {
11614
- return true;
11615
- }
11616
- if (el.closest('[data-ohw-role="navbar-button"]')) return true;
11617
- return false;
11618
- }
11619
- function isSiteWideScopeActive(args) {
11620
- return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
11621
- }
11622
-
11623
10924
  // src/lib/add-footer-column.ts
11624
10925
  function buildFooterColumnEditContentPatch(result) {
11625
10926
  return {
@@ -11835,127 +11136,16 @@ function FloatingPanel({
11835
11136
  );
11836
11137
  }
11837
11138
 
11838
- // src/ui/logo-size-panel.tsx
11839
- var import_lucide_react14 = require("lucide-react");
11840
- var import_jsx_runtime27 = require("react/jsx-runtime");
11841
- function SizeSlider({
11842
- value,
11843
- onChange
11844
- }) {
11845
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
11846
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-3", children: [
11847
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
11848
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
11849
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
11850
- value,
11851
- " px"
11852
- ] })
11853
- ] }),
11854
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
11855
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11856
- "div",
11857
- {
11858
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
11859
- style: { width: `${pct}%` }
11860
- }
11861
- ),
11862
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11863
- "input",
11864
- {
11865
- type: "range",
11866
- min: LOGO_SIZE_MIN,
11867
- max: LOGO_SIZE_MAX,
11868
- step: 1,
11869
- value,
11870
- "aria-label": "Logo size",
11871
- className: cn(
11872
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
11873
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
11874
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
11875
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
11876
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
11877
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
11878
- "[&::-moz-range-thumb]:bg-background"
11879
- ),
11880
- onChange: (e) => onChange(Number(e.target.value))
11881
- }
11882
- )
11883
- ] })
11884
- ] });
11885
- }
11886
- function LogoSizePanel({
11887
- viewport,
11888
- sizePx,
11889
- mobileFollowing = true,
11890
- onSizeChange,
11891
- onCustomizeMobile,
11892
- onResetMobile,
11893
- onUpdateEverywhere,
11894
- className
11895
- }) {
11896
- const showFollowing = viewport === "mobile" && mobileFollowing;
11897
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
11898
- const showDesktopSlider = viewport === "desktop";
11899
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-4", className), children: [
11900
- showFollowing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
11901
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-start gap-1", children: [
11902
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Link, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
11903
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
11904
- ] }),
11905
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("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." }),
11906
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11907
- Button,
11908
- {
11909
- type: "button",
11910
- variant: "outline",
11911
- size: "sm",
11912
- className: "h-9 w-full min-w-0 cursor-pointer",
11913
- onClick: onCustomizeMobile,
11914
- children: "Customize for mobile"
11915
- }
11916
- )
11917
- ] }) : null,
11918
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
11919
- showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11920
- Button,
11921
- {
11922
- type: "button",
11923
- variant: "outline",
11924
- size: "sm",
11925
- className: "h-9 w-full min-w-0 cursor-pointer",
11926
- onClick: onResetMobile,
11927
- children: "Reset to desktop size"
11928
- }
11929
- ) : null,
11930
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px w-full bg-border", role: "separator" }),
11931
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
11932
- Button,
11933
- {
11934
- type: "button",
11935
- variant: "outline",
11936
- size: "sm",
11937
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
11938
- onClick: onUpdateEverywhere,
11939
- children: [
11940
- "Update logo everywhere",
11941
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.ArrowUpRight, { size: 16, "aria-hidden": true })
11942
- ]
11943
- }
11944
- ),
11945
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
11946
- ] });
11947
- }
11948
-
11949
11139
  // src/ui/socials-display-panel.tsx
11950
- var import_jsx_runtime28 = require("react/jsx-runtime");
11140
+ var import_jsx_runtime27 = require("react/jsx-runtime");
11951
11141
  function DisplaySwitch({
11952
11142
  label,
11953
11143
  checked,
11954
11144
  disabled,
11955
11145
  onChange
11956
11146
  }) {
11957
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
11958
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11147
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
11148
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11959
11149
  "span",
11960
11150
  {
11961
11151
  className: cn(
@@ -11965,7 +11155,7 @@ function DisplaySwitch({
11965
11155
  children: label
11966
11156
  }
11967
11157
  ),
11968
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11158
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11969
11159
  "button",
11970
11160
  {
11971
11161
  type: "button",
@@ -11979,7 +11169,7 @@ function DisplaySwitch({
11979
11169
  checked ? "bg-primary" : "bg-primary-50",
11980
11170
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
11981
11171
  ),
11982
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11172
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11983
11173
  "span",
11984
11174
  {
11985
11175
  className: cn(
@@ -11993,8 +11183,8 @@ function DisplaySwitch({
11993
11183
  ] });
11994
11184
  }
11995
11185
  function SocialsDisplayPanel({ display, onChange, className }) {
11996
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11997
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11186
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11187
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11998
11188
  DisplaySwitch,
11999
11189
  {
12000
11190
  label: "Text",
@@ -12003,7 +11193,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
12003
11193
  onChange: (text) => onChange({ ...display, text })
12004
11194
  }
12005
11195
  ),
12006
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11196
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12007
11197
  DisplaySwitch,
12008
11198
  {
12009
11199
  label: "Icon",
@@ -12563,8 +11753,8 @@ function useNavItemDrag({
12563
11753
  }
12564
11754
 
12565
11755
  // src/ui/footer-container-chrome.tsx
12566
- var import_lucide_react15 = require("lucide-react");
12567
- var import_jsx_runtime29 = require("react/jsx-runtime");
11756
+ var import_lucide_react14 = require("lucide-react");
11757
+ var import_jsx_runtime28 = require("react/jsx-runtime");
12568
11758
  function FooterContainerChrome({
12569
11759
  rect,
12570
11760
  onAdd,
@@ -12572,7 +11762,7 @@ function FooterContainerChrome({
12572
11762
  }) {
12573
11763
  const chromeGap = 6;
12574
11764
  const buttonMargin = 7;
12575
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11765
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12576
11766
  "div",
12577
11767
  {
12578
11768
  "data-ohw-footer-container-chrome": "",
@@ -12584,8 +11774,8 @@ function FooterContainerChrome({
12584
11774
  width: rect.width + chromeGap * 2,
12585
11775
  height: rect.height + chromeGap * 2
12586
11776
  },
12587
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
12588
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11777
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Tooltip, { children: [
11778
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12589
11779
  "button",
12590
11780
  {
12591
11781
  type: "button",
@@ -12604,10 +11794,10 @@ function FooterContainerChrome({
12604
11794
  if (addDisabled) return;
12605
11795
  onAdd();
12606
11796
  },
12607
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
11797
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react14.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12608
11798
  }
12609
11799
  ) }),
12610
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
11800
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12611
11801
  ] })
12612
11802
  }
12613
11803
  ) });
@@ -12790,18 +11980,6 @@ function collectEditableNodes(extraContent, root = document) {
12790
11980
  }
12791
11981
  if (extraContent && !isScoped) {
12792
11982
  applyNavFooterDeleteOverrides(byKey, extraContent);
12793
- for (const key of LOGO_IMAGE_KEYS) {
12794
- if (!(key in extraContent)) continue;
12795
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
12796
- }
12797
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
12798
- if (!(key in extraContent)) continue;
12799
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12800
- }
12801
- for (const key of LOGO_SIZE_KEYS) {
12802
- if (!(key in extraContent)) continue;
12803
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12804
- }
12805
11983
  }
12806
11984
  return Array.from(byKey.values());
12807
11985
  }
@@ -13067,14 +12245,14 @@ function deleteSelectedNavFooterItem(deps) {
13067
12245
  }
13068
12246
 
13069
12247
  // src/ui/navbar-container-chrome.tsx
13070
- var import_lucide_react16 = require("lucide-react");
13071
- var import_jsx_runtime30 = require("react/jsx-runtime");
12248
+ var import_lucide_react15 = require("lucide-react");
12249
+ var import_jsx_runtime29 = require("react/jsx-runtime");
13072
12250
  function NavbarContainerChrome({
13073
12251
  rect,
13074
12252
  onAdd
13075
12253
  }) {
13076
12254
  const chromeGap = 6;
13077
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12255
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13078
12256
  "div",
13079
12257
  {
13080
12258
  "data-ohw-navbar-container-chrome": "",
@@ -13086,7 +12264,7 @@ function NavbarContainerChrome({
13086
12264
  width: rect.width + chromeGap * 2,
13087
12265
  height: rect.height + chromeGap * 2
13088
12266
  },
13089
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12267
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13090
12268
  "button",
13091
12269
  {
13092
12270
  type: "button",
@@ -13103,7 +12281,7 @@ function NavbarContainerChrome({
13103
12281
  e.stopPropagation();
13104
12282
  onAdd();
13105
12283
  },
13106
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12284
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13107
12285
  }
13108
12286
  )
13109
12287
  }
@@ -13112,7 +12290,7 @@ function NavbarContainerChrome({
13112
12290
 
13113
12291
  // src/ui/drop-indicator.tsx
13114
12292
  var React10 = __toESM(require("react"), 1);
13115
- var import_jsx_runtime31 = require("react/jsx-runtime");
12293
+ var import_jsx_runtime30 = require("react/jsx-runtime");
13116
12294
  var dropIndicatorVariants = cva(
13117
12295
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
13118
12296
  {
@@ -13136,7 +12314,7 @@ var dropIndicatorVariants = cva(
13136
12314
  );
13137
12315
  var DropIndicator = React10.forwardRef(
13138
12316
  ({ className, direction, state, ...props }, ref) => {
13139
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
12317
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13140
12318
  "div",
13141
12319
  {
13142
12320
  ref,
@@ -13153,7 +12331,7 @@ var DropIndicator = React10.forwardRef(
13153
12331
  DropIndicator.displayName = "DropIndicator";
13154
12332
 
13155
12333
  // src/ui/badge.tsx
13156
- var import_jsx_runtime32 = require("react/jsx-runtime");
12334
+ var import_jsx_runtime31 = require("react/jsx-runtime");
13157
12335
  var badgeVariants = cva(
13158
12336
  "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",
13159
12337
  {
@@ -13171,12 +12349,12 @@ var badgeVariants = cva(
13171
12349
  }
13172
12350
  );
13173
12351
  function Badge({ className, variant, ...props }) {
13174
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
12352
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
13175
12353
  }
13176
12354
 
13177
12355
  // src/OhhwellsBridge.tsx
13178
- var import_lucide_react17 = require("lucide-react");
13179
- var import_jsx_runtime33 = require("react/jsx-runtime");
12356
+ var import_lucide_react16 = require("lucide-react");
12357
+ var import_jsx_runtime32 = require("react/jsx-runtime");
13180
12358
  var PRIMARY3 = "#0885FE";
13181
12359
  var IMAGE_FADE_MS = 300;
13182
12360
  function runOpacityFade(el, onDone) {
@@ -13270,10 +12448,21 @@ function parseSchedulingInsertAfter(insertAfter) {
13270
12448
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
13271
12449
  };
13272
12450
  }
13273
- function resolveEntryAnchor(entry) {
13274
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
13275
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
13276
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
12451
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
12452
+ const parsed = parseSchedulingInsertAfter(insertAfter);
12453
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
12454
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
12455
+ return { effectiveInsertAfter, insertBefore };
12456
+ }
12457
+ function getSchedulingMountPoint(insertAfter) {
12458
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
12459
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
12460
+ if (!anchorEl && anchor === "scheduling") {
12461
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
12462
+ anchorEl = widgets.at(-1) ?? null;
12463
+ }
12464
+ if (!anchorEl) return null;
12465
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13277
12466
  }
13278
12467
  function schedulingMountDepth(insertAfter) {
13279
12468
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -13290,7 +12479,8 @@ function getPageSchedulingEntries(raw) {
13290
12479
  }
13291
12480
  }
13292
12481
  function isSchedulingWidgetMissing(entry) {
13293
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
12482
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
12483
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
13294
12484
  }
13295
12485
  function hasMissingSchedulingWidgets(entries) {
13296
12486
  return entries.some(isSchedulingWidgetMissing);
@@ -13320,17 +12510,16 @@ function initSectionsFromContent(content, removeExisting = false) {
13320
12510
  } catch {
13321
12511
  }
13322
12512
  }
13323
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
13324
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
13325
- const sectionId = schedulingSectionId(widgetId);
12513
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
12514
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
12515
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
13326
12516
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
13327
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
13328
- if (!anchorEl) return false;
13329
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
12517
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
12518
+ if (!mountPoint) return false;
13330
12519
  const container = document.createElement("div");
13331
12520
  container.dataset.ohwSectionContainer = "scheduling";
13332
- if (beforeId) {
13333
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
12521
+ if (insertBefore) {
12522
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
13334
12523
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
13335
12524
  if (!beforePoint) return false;
13336
12525
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -13341,25 +12530,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13341
12530
  }
13342
12531
  tail.insertAdjacentElement("afterend", container);
13343
12532
  }
13344
- try {
13345
- const root = (0, import_client2.createRoot)(container);
13346
- (0, import_react_dom3.flushSync)(() => {
13347
- root.render(
13348
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13349
- SchedulingWidget,
13350
- {
13351
- notifyOnConnect,
13352
- initialScheduleId: scheduleId,
13353
- insertAfter: widgetId
13354
- }
13355
- )
13356
- );
13357
- });
13358
- } catch (err) {
13359
- console.error("[ow:scheduling] render threw", err);
13360
- container.remove();
13361
- return false;
13362
- }
12533
+ const root = (0, import_client2.createRoot)(container);
12534
+ (0, import_react_dom3.flushSync)(() => {
12535
+ root.render(
12536
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12537
+ SchedulingWidget,
12538
+ {
12539
+ notifyOnConnect,
12540
+ initialScheduleId: scheduleId,
12541
+ insertAfter: effectiveInsertAfter
12542
+ }
12543
+ )
12544
+ );
12545
+ });
13363
12546
  const tracker = getSectionsTracker();
13364
12547
  let sections = [];
13365
12548
  try {
@@ -13367,12 +12550,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13367
12550
  } catch {
13368
12551
  }
13369
12552
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
13370
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
12553
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
13371
12554
  sections.push({
13372
12555
  type: "scheduling",
13373
- insertAfter: widgetId,
13374
- anchorId,
13375
- beforeId: beforeId ?? null,
12556
+ insertAfter: effectiveInsertAfter,
13376
12557
  pagePath: window.location.pathname,
13377
12558
  ...scheduleId ? { scheduleId } : {}
13378
12559
  });
@@ -13386,8 +12567,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
13386
12567
  for (let i = pending.length - 1; i >= 0; i--) {
13387
12568
  const entry = pending[i];
13388
12569
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
13389
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
13390
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
12570
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
13391
12571
  pending.splice(i, 1);
13392
12572
  }
13393
12573
  }
@@ -13531,13 +12711,6 @@ function isInsideLinkEditor(target) {
13531
12711
  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"]')
13532
12712
  );
13533
12713
  }
13534
- function isInsideFloatingPanel(target) {
13535
- return Boolean(target.closest("[data-ohw-floating-panel]"));
13536
- }
13537
- function isPointOverFloatingPanel(clientX, clientY) {
13538
- const el = document.elementFromPoint(clientX, clientY);
13539
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
13540
- }
13541
12714
  function getHrefKeyFromElement(el) {
13542
12715
  if (!el) return null;
13543
12716
  const anchor = el.closest("[data-ohw-href-key]");
@@ -13585,7 +12758,8 @@ function isNavItemPointerTarget(el) {
13585
12758
  function getNavigationItemAnchor(el) {
13586
12759
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
13587
12760
  if (!anchor) return null;
13588
- if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
12761
+ if (!anchor.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !anchor.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !getSocialItem(anchor))
12762
+ return null;
13589
12763
  if (!isNavItemPointerTarget(anchor)) return null;
13590
12764
  return anchor;
13591
12765
  }
@@ -13775,7 +12949,7 @@ function getNavigationSelectionParent(el) {
13775
12949
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
13776
12950
  return getFooterLinksContainer();
13777
12951
  }
13778
- 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)) {
12952
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
13779
12953
  return getNavigationRoot(el);
13780
12954
  }
13781
12955
  return null;
@@ -14021,7 +13195,7 @@ function EditGlowChrome({
14021
13195
  hideHandle = false
14022
13196
  }) {
14023
13197
  const GAP = SELECTION_CHROME_GAP2;
14024
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
13198
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
14025
13199
  "div",
14026
13200
  {
14027
13201
  ref: elRef,
@@ -14036,7 +13210,7 @@ function EditGlowChrome({
14036
13210
  zIndex: 2147483646
14037
13211
  },
14038
13212
  children: [
14039
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13213
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14040
13214
  "div",
14041
13215
  {
14042
13216
  style: {
@@ -14049,7 +13223,7 @@ function EditGlowChrome({
14049
13223
  }
14050
13224
  }
14051
13225
  ),
14052
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13226
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14053
13227
  "div",
14054
13228
  {
14055
13229
  "data-ohw-drag-handle-container": "",
@@ -14061,7 +13235,7 @@ function EditGlowChrome({
14061
13235
  transform: "translate(calc(-100% - 7px), -50%)",
14062
13236
  pointerEvents: dragDisabled ? "none" : "auto"
14063
13237
  },
14064
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13238
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14065
13239
  DragHandle,
14066
13240
  {
14067
13241
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -14271,7 +13445,7 @@ function FloatingToolbar({
14271
13445
  return () => ro.disconnect();
14272
13446
  }, [showEditLink, activeCommands]);
14273
13447
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
14274
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13448
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14275
13449
  "div",
14276
13450
  {
14277
13451
  ref: setRefs,
@@ -14283,12 +13457,12 @@ function FloatingToolbar({
14283
13457
  zIndex: 2147483647,
14284
13458
  pointerEvents: "auto"
14285
13459
  },
14286
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
14287
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
14288
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
13460
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(CustomToolbar, { children: [
13461
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react16.default.Fragment, { children: [
13462
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CustomToolbarDivider, {}),
14289
13463
  btns.map((btn) => {
14290
13464
  const isActive = activeCommands.has(btn.cmd);
14291
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13465
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14292
13466
  CustomToolbarButton,
14293
13467
  {
14294
13468
  title: btn.title,
@@ -14297,7 +13471,7 @@ function FloatingToolbar({
14297
13471
  e.preventDefault();
14298
13472
  onCommand(btn.cmd);
14299
13473
  },
14300
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13474
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14301
13475
  "svg",
14302
13476
  {
14303
13477
  width: "16",
@@ -14318,7 +13492,7 @@ function FloatingToolbar({
14318
13492
  );
14319
13493
  })
14320
13494
  ] }, gi)),
14321
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13495
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14322
13496
  CustomToolbarButton,
14323
13497
  {
14324
13498
  type: "button",
@@ -14332,7 +13506,7 @@ function FloatingToolbar({
14332
13506
  e.preventDefault();
14333
13507
  e.stopPropagation();
14334
13508
  },
14335
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
13509
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react16.Link, { className: "size-4 shrink-0", "aria-hidden": true })
14336
13510
  }
14337
13511
  ) : null
14338
13512
  ] })
@@ -14349,7 +13523,7 @@ function StateToggle({
14349
13523
  states,
14350
13524
  onStateChange
14351
13525
  }) {
14352
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13526
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14353
13527
  ToggleGroup,
14354
13528
  {
14355
13529
  "data-ohw-state-toggle": "",
@@ -14363,12 +13537,11 @@ function StateToggle({
14363
13537
  left: rect.right - 8,
14364
13538
  transform: "translateX(-100%)"
14365
13539
  },
14366
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
13540
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14367
13541
  }
14368
13542
  );
14369
13543
  }
14370
13544
  var contentCache = /* @__PURE__ */ new Map();
14371
- var fetchedContentPaths = /* @__PURE__ */ new Set();
14372
13545
  function resolveSubdomain(subdomainFromQuery) {
14373
13546
  if (subdomainFromQuery) return subdomainFromQuery;
14374
13547
  if (typeof window !== "undefined") {
@@ -14463,14 +13636,8 @@ function OhhwellsBridge() {
14463
13636
  });
14464
13637
  const selectFrameRef = (0, import_react16.useRef)(() => {
14465
13638
  });
14466
- const selectLogoRef = (0, import_react16.useRef)(() => {
14467
- });
14468
- const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
14469
- });
14470
13639
  const deselectRef = (0, import_react16.useRef)(() => {
14471
13640
  });
14472
- const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
14473
- });
14474
13641
  const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
14475
13642
  });
14476
13643
  const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
@@ -14531,6 +13698,11 @@ function OhhwellsBridge() {
14531
13698
  const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
14532
13699
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
14533
13700
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
13701
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
13702
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
13703
+ floatingPanelOpenRef.current = floatingPanel !== null;
13704
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
13705
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
14534
13706
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
14535
13707
  const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
14536
13708
  const footerDragRef = (0, import_react16.useRef)(null);
@@ -14545,16 +13717,7 @@ function OhhwellsBridge() {
14545
13717
  const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
14546
13718
  const editContentRef = (0, import_react16.useRef)({});
14547
13719
  const aiSectionsRef = (0, import_react16.useRef)("");
14548
- const brandKitRef = (0, import_react16.useRef)("");
14549
- const stylesRef = (0, import_react16.useRef)("");
14550
13720
  const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
14551
- const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
14552
- const floatingPanelOpenRef = (0, import_react16.useRef)(false);
14553
- const setFloatingPanelRef = (0, import_react16.useRef)(setFloatingPanel);
14554
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
14555
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
14556
- const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
14557
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
14558
13721
  const [sitePages, setSitePages] = (0, import_react16.useState)([]);
14559
13722
  const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
14560
13723
  const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
@@ -14563,18 +13726,7 @@ function OhhwellsBridge() {
14563
13726
  const linkPopoverOpenRef = (0, import_react16.useRef)(false);
14564
13727
  const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
14565
13728
  setLinkPopoverRef.current = setLinkPopover;
14566
- setFloatingPanelRef.current = setFloatingPanel;
14567
13729
  linkPopoverSessionRef.current = linkPopover;
14568
- floatingPanelOpenRef.current = Boolean(floatingPanel);
14569
- (0, import_react16.useEffect)(() => {
14570
- const syncViewport = () => {
14571
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
14572
- setEditorViewport((prev) => prev === next ? prev : next);
14573
- };
14574
- syncViewport();
14575
- window.addEventListener("resize", syncViewport);
14576
- return () => window.removeEventListener("resize", syncViewport);
14577
- }, []);
14578
13730
  const {
14579
13731
  navDragRef,
14580
13732
  navDropSlots,
@@ -14797,10 +13949,6 @@ function OhhwellsBridge() {
14797
13949
  setIsItemDragging(false);
14798
13950
  hoveredNavContainerRef.current = null;
14799
13951
  setHoveredNavContainerRect(null);
14800
- hoveredItemElRef.current = null;
14801
- setHoveredItemRect(null);
14802
- setFloatingPanel(null);
14803
- setLogoSizeDraft(null);
14804
13952
  if (!activeElRef.current) {
14805
13953
  setNavGroupForceOpen(null, false);
14806
13954
  setToolbarRect(null);
@@ -15506,8 +14654,6 @@ function OhhwellsBridge() {
15506
14654
  setToolbarRect(anchor.getBoundingClientRect());
15507
14655
  setToolbarShowEditLink(false);
15508
14656
  setActiveCommands(/* @__PURE__ */ new Set());
15509
- setFloatingPanel(null);
15510
- setLogoSizeDraft(null);
15511
14657
  }, [deactivate, markSelected]);
15512
14658
  const selectFrame = (0, import_react16.useCallback)((el) => {
15513
14659
  if (!isNavigationContainer(el)) return;
@@ -15557,51 +14703,7 @@ function OhhwellsBridge() {
15557
14703
  setToolbarRect(el.getBoundingClientRect());
15558
14704
  setToolbarShowEditLink(false);
15559
14705
  setActiveCommands(/* @__PURE__ */ new Set());
15560
- setFloatingPanel(null);
15561
- setLogoSizeDraft(null);
15562
14706
  }, [deactivate, markSelected, postToParent2]);
15563
- const selectLogo = (0, import_react16.useCallback)(
15564
- (logoEl) => {
15565
- if (activeElRef.current) deactivate();
15566
- selectedElRef.current = logoEl;
15567
- selectedHrefKeyRef.current = null;
15568
- selectedFooterColAttrRef.current = null;
15569
- markSelected(logoEl);
15570
- setSelectedIsCta(false);
15571
- setSelectedIsSocial(false);
15572
- setSelectedIsSocialsRow(false);
15573
- clearHrefKeyHover(logoEl);
15574
- hoveredNavContainerRef.current = null;
15575
- setHoveredNavContainerRect(null);
15576
- setHoveredItemRect(null);
15577
- hoveredItemElRef.current = null;
15578
- siblingHintElRef.current = null;
15579
- setSiblingHintRect(null);
15580
- setSiblingHintRects([]);
15581
- setIsItemDragging(false);
15582
- setReorderHrefKey(null);
15583
- setReorderDragDisabled(false);
15584
- setIsFooterFrameSelection(false);
15585
- setToolbarVariant("logo");
15586
- setToolbarRect(getLogoInteractionRect(logoEl));
15587
- setToolbarShowEditLink(false);
15588
- setActiveCommands(/* @__PURE__ */ new Set());
15589
- },
15590
- [deactivate, markSelected]
15591
- );
15592
- const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
15593
- const placement = getLogoPlacement(logoEl);
15594
- const draft = readLogoSizeState(editContentRef.current, placement);
15595
- setLogoSizeDraft(draft);
15596
- setParentScrollSnap(parentScrollRef.current);
15597
- setFloatingPanel({
15598
- key: `logo-size:${placement}`,
15599
- title: "Logo",
15600
- context: placement === "navbar" ? "Navbar" : "Footer",
15601
- kind: "logo-size",
15602
- placement
15603
- });
15604
- }, []);
15605
14707
  const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
15606
14708
  setParentScrollSnap(parentScrollRef.current);
15607
14709
  setFloatingPanel({
@@ -15637,53 +14739,13 @@ function OhhwellsBridge() {
15637
14739
  );
15638
14740
  const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
15639
14741
  setFloatingPanel(null);
15640
- setLogoSizeDraft(null);
15641
14742
  }, []);
14743
+ const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(closeFloatingPanelOnly);
14744
+ closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
15642
14745
  const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
15643
14746
  setFloatingPanel(null);
15644
- setLogoSizeDraft(null);
15645
14747
  deselectRef.current();
15646
14748
  }, []);
15647
- const persistLogoSizeDraft = (0, import_react16.useCallback)(
15648
- (placement, draft) => {
15649
- const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
15650
- const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
15651
- const nodes = [
15652
- { key: desktopKey, text: String(draft.desktopPx) }
15653
- ];
15654
- if (draft.mobileFollowing) {
15655
- nodes.push({ key: mobileKey, text: "" });
15656
- } else {
15657
- nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
15658
- }
15659
- editContentRef.current = {
15660
- ...editContentRef.current,
15661
- [desktopKey]: String(draft.desktopPx),
15662
- [mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
15663
- };
15664
- applyLogoSizeToPlacement(
15665
- placement,
15666
- draft.desktopPx,
15667
- draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
15668
- draft.mobileFollowing
15669
- );
15670
- postToParent2({ type: "ow:change", nodes });
15671
- requestAnimationFrame(() => {
15672
- const selected = selectedElRef.current;
15673
- if (!selected || toolbarVariantRef.current !== "logo") return;
15674
- const rect = getLogoInteractionRect(selected);
15675
- setToolbarRect(rect);
15676
- if (glowElRef.current) {
15677
- const GAP = SELECTION_CHROME_GAP2;
15678
- glowElRef.current.style.top = `${rect.top - GAP}px`;
15679
- glowElRef.current.style.left = `${rect.left - GAP}px`;
15680
- glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
15681
- glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
15682
- }
15683
- });
15684
- },
15685
- [postToParent2]
15686
- );
15687
14749
  const activate = (0, import_react16.useCallback)((el, options) => {
15688
14750
  if (activeElRef.current === el) return;
15689
14751
  if (isIconEditable(el)) return;
@@ -15764,37 +14826,7 @@ function OhhwellsBridge() {
15764
14826
  deactivateRef.current = deactivate;
15765
14827
  selectRef.current = select;
15766
14828
  selectFrameRef.current = selectFrame;
15767
- selectLogoRef.current = selectLogo;
15768
- openLogoSizePanelRef.current = openLogoSizePanel;
15769
14829
  deselectRef.current = deselect;
15770
- closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
15771
- const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
15772
- (0, import_react16.useEffect)(() => {
15773
- if (!isEditMode) {
15774
- if (lastSiteWideScopeRef.current !== false) {
15775
- lastSiteWideScopeRef.current = false;
15776
- postToParent2({ type: "ow:site-wide-scope", active: false });
15777
- }
15778
- return;
15779
- }
15780
- const active = isSiteWideScopeActive({
15781
- selected: selectedElRef.current,
15782
- hoveredItem: hoveredItemElRef.current,
15783
- hoveredNavContainer: hoveredNavContainerRef.current,
15784
- active: activeElRef.current
15785
- });
15786
- if (lastSiteWideScopeRef.current === active) return;
15787
- lastSiteWideScopeRef.current = active;
15788
- postToParent2({ type: "ow:site-wide-scope", active });
15789
- }, [
15790
- isEditMode,
15791
- hoveredItemRect,
15792
- hoveredNavContainerRect,
15793
- toolbarVariant,
15794
- toolbarRect,
15795
- isFooterFrameSelection,
15796
- postToParent2
15797
- ]);
15798
14830
  (0, import_react16.useLayoutEffect)(() => {
15799
14831
  if (!subdomain || isEditMode) {
15800
14832
  setFetchState("done");
@@ -15806,23 +14838,9 @@ function OhhwellsBridge() {
15806
14838
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
15807
14839
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
15808
14840
  }
15809
- if (typeof content[BRAND_KIT_KEY] === "string") {
15810
- brandKitRef.current = content[BRAND_KIT_KEY];
15811
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
15812
- }
15813
- if (typeof content[STYLE_STORE_KEY] === "string") {
15814
- stylesRef.current = content[STYLE_STORE_KEY];
15815
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
15816
- }
15817
- applyBrandChrome(content);
15818
14841
  for (const [key, val] of Object.entries(content)) {
15819
14842
  if (key === "__ohw_sections") continue;
15820
14843
  if (key === AI_SECTIONS_KEY) continue;
15821
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15822
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15823
- if (key === BRAND_KIT_KEY) continue;
15824
- if (key === STYLE_STORE_KEY) continue;
15825
- if (BRAND_CHROME_KEYS.has(key)) continue;
15826
14844
  if (applyVideoSettingNode(key, val)) continue;
15827
14845
  if (applyCarouselNode(key, val)) continue;
15828
14846
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15857,8 +14875,6 @@ function OhhwellsBridge() {
15857
14875
  });
15858
14876
  applyLinkByKey(key, val);
15859
14877
  }
15860
- applyLogoFromContent(content);
15861
- applyLogoSizes(content);
15862
14878
  reconcileNavbarItemsFromContent(content);
15863
14879
  reconcileFooterOrderFromContent(content);
15864
14880
  reconcileSocialsFromContent(content);
@@ -15879,9 +14895,7 @@ function OhhwellsBridge() {
15879
14895
  let cancelled = false;
15880
14896
  setFetchState("loading");
15881
14897
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15882
- const initialPath = pathname;
15883
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
15884
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
14898
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15885
14899
  if (cancelled) return;
15886
14900
  const content = data?.content ?? {};
15887
14901
  contentCache.set(subdomain, content);
@@ -15905,21 +14919,8 @@ function OhhwellsBridge() {
15905
14919
  initSectionInstancesFromContent(content, window.location.pathname);
15906
14920
  observer?.disconnect();
15907
14921
  try {
15908
- applyBrandChrome(content);
15909
- if (typeof content[BRAND_KIT_KEY] === "string") {
15910
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
15911
- }
15912
- if (typeof content[STYLE_STORE_KEY] === "string") {
15913
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
15914
- }
15915
14922
  for (const [key, val] of Object.entries(content)) {
15916
14923
  if (key === "__ohw_sections") continue;
15917
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15918
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15919
- if (key === BRAND_KIT_KEY) continue;
15920
- if (key === STYLE_STORE_KEY) continue;
15921
- if (key === STYLE_STORE_KEY) continue;
15922
- if (BRAND_CHROME_KEYS.has(key)) continue;
15923
14924
  if (applyVideoSettingNode(key, val)) continue;
15924
14925
  if (applyCarouselNode(key, val)) continue;
15925
14926
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15940,7 +14941,6 @@ function OhhwellsBridge() {
15940
14941
  });
15941
14942
  applyLinkByKey(key, val);
15942
14943
  }
15943
- applyLogoFromContent(content);
15944
14944
  reconcileNavbarItemsFromContent(content);
15945
14945
  reconcileFooterOrderFromContent(content);
15946
14946
  reconcileSocialsFromContent(content);
@@ -15955,17 +14955,6 @@ function OhhwellsBridge() {
15955
14955
  debounceTimer = setTimeout(applyFromCache, 150);
15956
14956
  };
15957
14957
  applyFromCache();
15958
- const pathCacheKey = `${subdomain}::${pathname}`;
15959
- if (!fetchedContentPaths.has(pathCacheKey)) {
15960
- fetchedContentPaths.add(pathCacheKey);
15961
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15962
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15963
- if (!data?.content) return;
15964
- contentCache.set(subdomain, data.content);
15965
- applyFromCache();
15966
- }).catch(() => {
15967
- });
15968
- }
15969
14958
  observer = new MutationObserver(scheduleApply);
15970
14959
  observer.observe(document.body, { childList: true, subtree: true });
15971
14960
  return () => {
@@ -16059,31 +15048,26 @@ function OhhwellsBridge() {
16059
15048
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
16060
15049
  (0, import_react16.useEffect)(() => {
16061
15050
  if (!isEditMode) return;
16062
- let lastPosted = 0;
16063
15051
  const measure = () => {
16064
15052
  const h = document.body.scrollHeight;
16065
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
16066
- lastPosted = h;
16067
- postToParent2({ type: "ow:height", height: h });
16068
- }
16069
- };
16070
- let raf = null;
16071
- const schedule = () => {
16072
- if (raf != null) return;
16073
- raf = requestAnimationFrame(() => {
16074
- raf = null;
16075
- measure();
16076
- });
15053
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
16077
15054
  };
16078
15055
  const t1 = setTimeout(measure, 50);
16079
15056
  const t2 = setTimeout(measure, 500);
16080
- const ro = new ResizeObserver(schedule);
16081
- ro.observe(document.body);
15057
+ let lastWidth = window.innerWidth;
15058
+ let resizeTimer = null;
15059
+ const handleResize = () => {
15060
+ if (window.innerWidth === lastWidth) return;
15061
+ lastWidth = window.innerWidth;
15062
+ if (resizeTimer) clearTimeout(resizeTimer);
15063
+ resizeTimer = setTimeout(measure, 150);
15064
+ };
15065
+ window.addEventListener("resize", handleResize);
16082
15066
  return () => {
16083
15067
  clearTimeout(t1);
16084
15068
  clearTimeout(t2);
16085
- if (raf != null) cancelAnimationFrame(raf);
16086
- ro.disconnect();
15069
+ if (resizeTimer) clearTimeout(resizeTimer);
15070
+ window.removeEventListener("resize", handleResize);
16087
15071
  };
16088
15072
  }, [pathname, isEditMode, postToParent2]);
16089
15073
  (0, import_react16.useEffect)(() => {
@@ -16233,12 +15217,10 @@ function OhhwellsBridge() {
16233
15217
  return;
16234
15218
  }
16235
15219
  const target = e.target;
16236
- if (target.closest("[data-ohw-ai-review]")) return;
16237
15220
  if (target.closest("[data-ohw-toolbar]")) return;
16238
15221
  if (target.closest("[data-ohw-state-toggle]")) return;
16239
15222
  if (target.closest("[data-ohw-max-badge]")) return;
16240
15223
  if (isInsideLinkEditor(target)) return;
16241
- if (isInsideFloatingPanel(target)) return;
16242
15224
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
16243
15225
  const beneath = document.elementsFromPoint(e.clientX, e.clientY).find(
16244
15226
  (el) => el instanceof HTMLElement && !el.closest("[data-ohw-bridge-root]") && el.closest("[data-ohw-section]") != null
@@ -16302,21 +15284,6 @@ function OhhwellsBridge() {
16302
15284
  return;
16303
15285
  }
16304
15286
  }
16305
- const logoEl = getLogoElement(target);
16306
- if (logoEl) {
16307
- e.preventDefault();
16308
- e.stopPropagation();
16309
- if (!logoHasUploadedImage(logoEl)) {
16310
- deselectRef.current();
16311
- deactivateRef.current();
16312
- const identity = readLogoIdentityFromDom();
16313
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
16314
- return;
16315
- }
16316
- selectLogoRef.current(logoEl);
16317
- openLogoSizePanelRef.current(logoEl);
16318
- return;
16319
- }
16320
15287
  const editable = target.closest("[data-ohw-editable]");
16321
15288
  if (editable) {
16322
15289
  if (editable.dataset.ohwEditable === "link") {
@@ -16469,12 +15436,10 @@ function OhhwellsBridge() {
16469
15436
  };
16470
15437
  const handleDblClick = (e) => {
16471
15438
  const target = e.target;
16472
- if (target.closest("[data-ohw-ai-review]")) return;
16473
15439
  if (target.closest("[data-ohw-toolbar]")) return;
16474
15440
  if (target.closest("[data-ohw-state-toggle]")) return;
16475
15441
  if (target.closest("[data-ohw-max-badge]")) return;
16476
15442
  if (isInsideLinkEditor(target)) return;
16477
- if (isInsideFloatingPanel(target)) return;
16478
15443
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
16479
15444
  return;
16480
15445
  }
@@ -16502,14 +15467,11 @@ function OhhwellsBridge() {
16502
15467
  setHoveredNavContainerRect(null);
16503
15468
  return;
16504
15469
  }
16505
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
15470
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
16506
15471
  hoveredItemElRef.current = null;
16507
15472
  setHoveredItemRect(null);
16508
15473
  hoveredNavContainerRef.current = null;
16509
15474
  setHoveredNavContainerRect(null);
16510
- siblingHintElRef.current = null;
16511
- setSiblingHintRect(null);
16512
- setSiblingHintRects([]);
16513
15475
  return;
16514
15476
  }
16515
15477
  {
@@ -16519,7 +15481,7 @@ function OhhwellsBridge() {
16519
15481
  const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
16520
15482
  if (allowNavContainerHover) {
16521
15483
  const navContainer = target.closest("[data-ohw-nav-container]");
16522
- if (navContainer && !getNavigationItemAnchor(target) && !getLogoElement(target)) {
15484
+ if (navContainer && !getNavigationItemAnchor(target)) {
16523
15485
  hoveredNavContainerRef.current = navContainer;
16524
15486
  setHoveredNavContainerRect(navContainer.getBoundingClientRect());
16525
15487
  hoveredItemElRef.current = null;
@@ -16548,15 +15510,6 @@ function OhhwellsBridge() {
16548
15510
  setHoveredNavContainerRect(null);
16549
15511
  }
16550
15512
  }
16551
- const logoEl = getLogoElement(target);
16552
- if (logoEl) {
16553
- hoveredNavContainerRef.current = null;
16554
- setHoveredNavContainerRect(null);
16555
- if (selectedElRef.current === logoEl) return;
16556
- hoveredItemElRef.current = logoEl;
16557
- setHoveredItemRect(getLogoInteractionRect(logoEl));
16558
- return;
16559
- }
16560
15513
  const navAnchor = getNavigationItemAnchor(target);
16561
15514
  if (navAnchor) {
16562
15515
  hoveredNavContainerRef.current = null;
@@ -16594,11 +15547,6 @@ function OhhwellsBridge() {
16594
15547
  setHoveredItemRect(hoverTarget.getBoundingClientRect());
16595
15548
  } else if (!isInsideNavigationItem(editable)) {
16596
15549
  hoverTarget.setAttribute("data-ohw-hovered", "");
16597
- if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
16598
- hoveredNavContainerRef.current = null;
16599
- setHoveredNavContainerRect(null);
16600
- hoveredItemElRef.current = editable;
16601
- }
16602
15550
  }
16603
15551
  }
16604
15552
  };
@@ -16634,18 +15582,6 @@ function OhhwellsBridge() {
16634
15582
  }
16635
15583
  return;
16636
15584
  }
16637
- const logoEl = getLogoElement(target);
16638
- if (logoEl) {
16639
- const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
16640
- if (related2 && (logoEl === related2 || logoEl.contains(related2) || related2.closest?.('[data-ohw-role="logo"], [data-ohw-logo]'))) {
16641
- return;
16642
- }
16643
- if (hoveredItemElRef.current === logoEl) {
16644
- hoveredItemElRef.current = null;
16645
- setHoveredItemRect(null);
16646
- }
16647
- return;
16648
- }
16649
15585
  const editable = target.closest("[data-ohw-editable]");
16650
15586
  if (!editable) return;
16651
15587
  const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
@@ -16666,13 +15602,6 @@ function OhhwellsBridge() {
16666
15602
  }
16667
15603
  } else {
16668
15604
  hoverTarget.removeAttribute("data-ohw-hovered");
16669
- if (hoveredItemElRef.current === editable) {
16670
- const stillOnEditable = related instanceof Element && related.closest("[data-ohw-editable]") === editable;
16671
- if (!stillOnEditable) {
16672
- hoveredItemElRef.current = null;
16673
- setHoveredItemRect(null);
16674
- }
16675
- }
16676
15605
  }
16677
15606
  }
16678
15607
  };
@@ -16789,26 +15718,6 @@ function OhhwellsBridge() {
16789
15718
  hoveredNavContainerRef.current = null;
16790
15719
  setHoveredNavContainerRect(null);
16791
15720
  }
16792
- const logoCandidates = [
16793
- ...document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]'),
16794
- ...document.querySelectorAll("nav a:not([data-ohw-href-key]), [data-ohw-nav-root] a:not([data-ohw-href-key])"),
16795
- ...document.querySelectorAll("footer img")
16796
- ];
16797
- const seenLogos = /* @__PURE__ */ new Set();
16798
- for (const candidate of logoCandidates) {
16799
- const logo = getLogoElement(candidate);
16800
- if (!logo || seenLogos.has(logo)) continue;
16801
- seenLogos.add(logo);
16802
- const r2 = logo.getBoundingClientRect();
16803
- if (x < r2.left || x > r2.right || y < r2.top || y > r2.bottom) continue;
16804
- hoveredNavContainerRef.current = null;
16805
- setHoveredNavContainerRect(null);
16806
- if (selectedElRef.current !== logo) {
16807
- hoveredItemElRef.current = logo;
16808
- setHoveredItemRect(getLogoInteractionRect(logo));
16809
- }
16810
- return;
16811
- }
16812
15721
  const navContainers = Array.from(
16813
15722
  document.querySelectorAll("[data-ohw-nav-container]")
16814
15723
  );
@@ -16894,7 +15803,7 @@ function OhhwellsBridge() {
16894
15803
  }
16895
15804
  };
16896
15805
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
16897
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
15806
+ if (linkPopoverOpenRef.current) {
16898
15807
  if (hoveredImageRef.current) {
16899
15808
  hoveredImageRef.current = null;
16900
15809
  hoveredImageHasTextOverlapRef.current = false;
@@ -17148,7 +16057,7 @@ function OhhwellsBridge() {
17148
16057
  }
17149
16058
  };
17150
16059
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
17151
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
16060
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17152
16061
  if (activeStateElRef.current) {
17153
16062
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
17154
16063
  activeStateElRef.current = null;
@@ -17214,21 +16123,16 @@ function OhhwellsBridge() {
17214
16123
  setSectionGap(null);
17215
16124
  }
17216
16125
  };
16126
+ const pointOwnedByFloatingPanel = (clientX, clientY) => {
16127
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return true;
16128
+ const panel = document.querySelector("[data-ohw-floating-panel]");
16129
+ if (!panel) return false;
16130
+ const rect = panel.getBoundingClientRect();
16131
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
16132
+ };
17217
16133
  const handleMouseMove = (e) => {
17218
16134
  const { clientX, clientY } = e;
17219
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17220
- hoveredItemElRef.current = null;
17221
- setHoveredItemRect(null);
17222
- hoveredNavContainerRef.current = null;
17223
- setHoveredNavContainerRect(null);
17224
- siblingHintElRef.current = null;
17225
- setSiblingHintRect(null);
17226
- setSiblingHintRects([]);
17227
- dismissImageHover();
17228
- clearImageHover();
17229
- setSectionGap(null);
17230
- return;
17231
- }
16135
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17232
16136
  probeSectionGapAt(clientX, clientY);
17233
16137
  probeImageAt(clientX, clientY);
17234
16138
  probeHoverCardsAt(clientX, clientY);
@@ -17237,11 +16141,7 @@ function OhhwellsBridge() {
17237
16141
  if (e.data?.type !== "ow:pointer-sync") return;
17238
16142
  const { clientX, clientY } = e.data;
17239
16143
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
17240
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17241
- dismissImageHover();
17242
- clearImageHover();
17243
- return;
17244
- }
16144
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17245
16145
  probeSectionGapAt(clientX, clientY);
17246
16146
  probeImageAt(clientX, clientY);
17247
16147
  probeHoverCardsAt(clientX, clientY);
@@ -17491,15 +16391,6 @@ function OhhwellsBridge() {
17491
16391
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
17492
16392
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
17493
16393
  }
17494
- if (typeof content[BRAND_KIT_KEY] === "string") {
17495
- brandKitRef.current = content[BRAND_KIT_KEY];
17496
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
17497
- }
17498
- if (typeof content[STYLE_STORE_KEY] === "string") {
17499
- stylesRef.current = content[STYLE_STORE_KEY];
17500
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17501
- }
17502
- applyBrandChrome(content);
17503
16394
  let sectionsJson = null;
17504
16395
  for (const [key, val] of Object.entries(content)) {
17505
16396
  if (key === "__ohw_sections") {
@@ -17507,11 +16398,6 @@ function OhhwellsBridge() {
17507
16398
  continue;
17508
16399
  }
17509
16400
  if (key === AI_SECTIONS_KEY) continue;
17510
- if (key === LOGO_PLACEHOLDER_KEY) continue;
17511
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
17512
- if (key === BRAND_KIT_KEY) continue;
17513
- if (key === STYLE_STORE_KEY) continue;
17514
- if (BRAND_CHROME_KEYS.has(key)) continue;
17515
16401
  if (applyVideoSettingNode(key, val)) continue;
17516
16402
  if (applyCarouselNode(key, val)) continue;
17517
16403
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -17531,8 +16417,6 @@ function OhhwellsBridge() {
17531
16417
  });
17532
16418
  applyLinkByKey(key, val);
17533
16419
  }
17534
- applyLogoFromContent(content);
17535
- applyLogoSizes(content);
17536
16420
  if (sectionsJson) {
17537
16421
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
17538
16422
  sectionsLoadedRef.current = true;
@@ -17548,58 +16432,6 @@ function OhhwellsBridge() {
17548
16432
  if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
17549
16433
  postToParentRef.current({ type: "ow:hydrate-done" });
17550
16434
  };
17551
- const handleUpdateLogoIdentity = (e) => {
17552
- if (e.data?.type !== "ow:update-logo-identity") return;
17553
- const rawText = typeof e.data.text === "string" ? e.data.text : "";
17554
- const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
17555
- const href = typeof e.data.href === "string" ? e.data.href : void 0;
17556
- const imageProvided = "image" in e.data;
17557
- const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
17558
- let isPlaceholder = e.data.isPlaceholder !== false;
17559
- if (imageUrl) isPlaceholder = false;
17560
- else if (imageProvided && imageUrl === null) {
17561
- isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
17562
- }
17563
- const display = applyLogoIdentity(rawText, isPlaceholder);
17564
- const displayAlt = resolveLogoDisplayText(alt || display);
17565
- if (imageUrl !== void 0) {
17566
- applyLogoImage(imageUrl, displayAlt);
17567
- } else {
17568
- for (const key of LOGO_IMAGE_KEYS) {
17569
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
17570
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
17571
- if (img) img.alt = displayAlt;
17572
- });
17573
- }
17574
- }
17575
- if (href !== void 0) {
17576
- applyLogoHref(href);
17577
- applyLinkByKey("nav-logo-href", href);
17578
- applyLinkByKey("footer-logo-href", href);
17579
- applyLinkByKey("logo-href", href);
17580
- }
17581
- const nodes = [
17582
- ...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
17583
- { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
17584
- { key: LOGO_ALT_KEY, text: displayAlt }
17585
- ];
17586
- if (imageUrl !== void 0) {
17587
- if (imageUrl) {
17588
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
17589
- } else {
17590
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
17591
- }
17592
- }
17593
- if (href !== void 0) {
17594
- for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
17595
- }
17596
- editContentRef.current = {
17597
- ...editContentRef.current,
17598
- ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
17599
- };
17600
- applyLogoSizes(editContentRef.current);
17601
- postToParentRef.current({ type: "ow:change", nodes });
17602
- };
17603
16435
  window.addEventListener("message", handleHydrate);
17604
16436
  const postAiSectionsChanged = () => {
17605
16437
  postToParentRef.current({
@@ -17613,10 +16445,7 @@ function OhhwellsBridge() {
17613
16445
  const payload = e.data.payload;
17614
16446
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
17615
16447
  const previous = aiSectionsRef.current;
17616
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
17617
- ...payload,
17618
- path: payload.path ?? window.location.pathname
17619
- });
16448
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
17620
16449
  const nextValue = serializeAiSectionsState(nextState);
17621
16450
  aiSectionsRef.current = nextValue;
17622
16451
  applyAiSectionsToDom(nextState);
@@ -17653,42 +16482,12 @@ function OhhwellsBridge() {
17653
16482
  const value = typeof e.data.value === "string" ? e.data.value : "";
17654
16483
  aiSectionsRef.current = value;
17655
16484
  applyAiSectionsToDom(parseAiSectionsState(value));
17656
- applyStylesToDom(parseStyleStore(stylesRef.current));
17657
16485
  const restoredHeight = document.documentElement.scrollHeight;
17658
16486
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
17659
16487
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
17660
16488
  postAiSectionsChanged();
17661
16489
  };
17662
16490
  window.addEventListener("message", handleAiSetSections);
17663
- const handleAiSetBrand = (e) => {
17664
- if (e.data?.type !== "ow:ai-set-brand") return;
17665
- const value = typeof e.data.value === "string" ? e.data.value : "";
17666
- const previous = brandKitRef.current;
17667
- brandKitRef.current = value;
17668
- applyBrandToDom(parseBrandKit(value));
17669
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
17670
- applyStylesToDom(parseStyleStore(stylesRef.current));
17671
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
17672
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
17673
- };
17674
- window.addEventListener("message", handleAiSetBrand);
17675
- const handleAiSetStyles = (e) => {
17676
- if (e.data?.type !== "ow:ai-set-styles") return;
17677
- const value = typeof e.data.value === "string" ? e.data.value : "";
17678
- const previous = stylesRef.current;
17679
- stylesRef.current = value;
17680
- applyStylesToDom(parseStyleStore(value));
17681
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
17682
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
17683
- };
17684
- window.addEventListener("message", handleAiSetStyles);
17685
- const handleGetBrand = (e) => {
17686
- if (e.data?.type !== "ow:get-brand") return;
17687
- const template = deriveTemplateBrand();
17688
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
17689
- postToParentRef.current({ type: "ow:brand-value", value });
17690
- };
17691
- window.addEventListener("message", handleGetBrand);
17692
16491
  const handleDeactivate = (e) => {
17693
16492
  if (e.data?.type !== "ow:deactivate") return;
17694
16493
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -17697,12 +16496,6 @@ function OhhwellsBridge() {
17697
16496
  closeLinkPopoverRef.current();
17698
16497
  return;
17699
16498
  }
17700
- if (floatingPanelOpenRef.current) {
17701
- setFloatingPanelRef.current(null);
17702
- deselectRef.current();
17703
- deactivateRef.current();
17704
- return;
17705
- }
17706
16499
  deselectRef.current();
17707
16500
  deactivateRef.current();
17708
16501
  };
@@ -17756,10 +16549,6 @@ function OhhwellsBridge() {
17756
16549
  return;
17757
16550
  }
17758
16551
  if (selectedElRef.current) {
17759
- if (toolbarVariantRef.current === "logo") {
17760
- deselectRef.current();
17761
- return;
17762
- }
17763
16552
  if (toolbarVariantRef.current === "select-frame") {
17764
16553
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
17765
16554
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -17799,10 +16588,6 @@ function OhhwellsBridge() {
17799
16588
  return;
17800
16589
  }
17801
16590
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
17802
- if (toolbarVariantRef.current === "logo") {
17803
- deselectRef.current();
17804
- return;
17805
- }
17806
16591
  if (toolbarVariantRef.current === "select-frame") {
17807
16592
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
17808
16593
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -17880,8 +16665,7 @@ function OhhwellsBridge() {
17880
16665
  const handleScroll = () => {
17881
16666
  const focusEl = activeElRef.current ?? selectedElRef.current;
17882
16667
  if (focusEl) {
17883
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
17884
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
16668
+ const r2 = activeElRef.current ? getEditMeasureEl(activeElRef.current).getBoundingClientRect() : focusEl.getBoundingClientRect();
17885
16669
  applyToolbarPos(r2);
17886
16670
  setToolbarRect(r2);
17887
16671
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -17891,9 +16675,7 @@ function OhhwellsBridge() {
17891
16675
  setToggleState((prev) => prev ? { ...prev, rect } : null);
17892
16676
  }
17893
16677
  if (hoveredItemElRef.current) {
17894
- const hoverEl = hoveredItemElRef.current;
17895
- const logo = getLogoElement(hoverEl);
17896
- setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
16678
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
17897
16679
  }
17898
16680
  if (hoveredNavContainerRef.current) {
17899
16681
  setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
@@ -17937,12 +16719,6 @@ function OhhwellsBridge() {
17937
16719
  if (aiSectionsRef.current) {
17938
16720
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
17939
16721
  }
17940
- if (stylesRef.current) {
17941
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
17942
- }
17943
- if (brandKitRef.current) {
17944
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
17945
- }
17946
16722
  postToParentRef.current({ type: "ow:save-result", nodes });
17947
16723
  };
17948
16724
  const handleInsertSection = (e) => {
@@ -17953,12 +16729,8 @@ function OhhwellsBridge() {
17953
16729
  if (inserted) {
17954
16730
  const tracker = getSectionsTracker();
17955
16731
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
17956
- const reportHeight = () => {
17957
- const h = document.body.scrollHeight;
17958
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17959
- };
17960
- reportHeight();
17961
- setTimeout(reportHeight, 500);
16732
+ const h = document.documentElement.scrollHeight;
16733
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17962
16734
  }
17963
16735
  };
17964
16736
  const handleSwitchSchedule = (e) => {
@@ -18151,17 +16923,13 @@ function OhhwellsBridge() {
18151
16923
  if (e.data?.type !== "ow:parent-scroll") return;
18152
16924
  const { iframeOffsetTop, headerH, canvasH } = e.data;
18153
16925
  parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
18154
- if (floatingPanelOpenRef.current) {
18155
- setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
18156
- }
18157
16926
  if (visibleViewportRef.current) {
18158
16927
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
18159
16928
  }
18160
16929
  const focusEl = activeElRef.current ?? selectedElRef.current;
18161
16930
  if (focusEl) {
18162
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
18163
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
18164
- applyToolbarPos(r2);
16931
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
16932
+ applyToolbarPos(measureEl.getBoundingClientRect());
18165
16933
  }
18166
16934
  };
18167
16935
  const handleClickAt = (e) => {
@@ -18186,25 +16954,6 @@ function OhhwellsBridge() {
18186
16954
  postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "", elementType: stateCardImage.dataset.ohwEditable ?? "image" });
18187
16955
  return;
18188
16956
  }
18189
- const logoAtPoint = Array.from(
18190
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]')
18191
- ).map((el) => getLogoElement(el)).find((logo) => {
18192
- if (!logo) return false;
18193
- const r2 = logo.getBoundingClientRect();
18194
- return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
18195
- });
18196
- if (logoAtPoint) {
18197
- if (!logoHasUploadedImage(logoAtPoint)) {
18198
- deselectRef.current();
18199
- deactivateRef.current();
18200
- const identity = readLogoIdentityFromDom();
18201
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
18202
- return;
18203
- }
18204
- selectLogoRef.current(logoAtPoint);
18205
- openLogoSizePanelRef.current(logoAtPoint);
18206
- return;
18207
- }
18208
16957
  const textEditable = Array.from(
18209
16958
  document.querySelectorAll(NON_MEDIA_SELECTOR)
18210
16959
  ).find((el) => {
@@ -18276,14 +17025,6 @@ function OhhwellsBridge() {
18276
17025
  window.addEventListener("message", handleParentScroll);
18277
17026
  window.addEventListener("message", handlePointerSync);
18278
17027
  window.addEventListener("message", handleClickAt);
18279
- window.addEventListener("message", handleUpdateLogoIdentity);
18280
- const handleViewMode = (e) => {
18281
- if (e.data?.type !== "ow:view-mode") return;
18282
- const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
18283
- setEditorViewport(mode);
18284
- applyLogoSizes(editContentRef.current);
18285
- };
18286
- window.addEventListener("message", handleViewMode);
18287
17028
  const handleViewportResize = () => {
18288
17029
  if (visibleViewportRef.current) {
18289
17030
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
@@ -18339,15 +17080,10 @@ function OhhwellsBridge() {
18339
17080
  window.removeEventListener("resize", handleViewportResize);
18340
17081
  window.removeEventListener("message", handlePointerSync);
18341
17082
  window.removeEventListener("message", handleClickAt);
18342
- window.removeEventListener("message", handleUpdateLogoIdentity);
18343
- window.removeEventListener("message", handleViewMode);
18344
17083
  window.removeEventListener("message", handleHydrate);
18345
17084
  window.removeEventListener("message", handleAiApplyTree);
18346
17085
  window.removeEventListener("message", handleAiDeleteSection);
18347
17086
  window.removeEventListener("message", handleAiSetSections);
18348
- window.removeEventListener("message", handleAiSetBrand);
18349
- window.removeEventListener("message", handleAiSetStyles);
18350
- window.removeEventListener("message", handleGetBrand);
18351
17087
  window.removeEventListener("message", handleDeactivate);
18352
17088
  window.removeEventListener("message", handleToastAction);
18353
17089
  window.removeEventListener("message", handleUiEscape);
@@ -18551,7 +17287,7 @@ function OhhwellsBridge() {
18551
17287
  postToParent2({
18552
17288
  type: "ow:ready",
18553
17289
  version: "1",
18554
- bridgeVersion: "0.1.62",
17290
+ bridgeVersion: "0.1.61",
18555
17291
  path: pathname,
18556
17292
  nodes: collectEditableNodes(editContentRef.current),
18557
17293
  sections
@@ -18946,10 +17682,10 @@ function OhhwellsBridge() {
18946
17682
  [postToParent2]
18947
17683
  );
18948
17684
  return bridgeRoot ? (0, import_react_dom4.createPortal)(
18949
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
18950
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
18951
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
18952
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17685
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
17686
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
17687
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
17688
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18953
17689
  MediaOverlay,
18954
17690
  {
18955
17691
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -18960,7 +17696,7 @@ function OhhwellsBridge() {
18960
17696
  },
18961
17697
  `uploading-${key}`
18962
17698
  )),
18963
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17699
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18964
17700
  MediaOverlay,
18965
17701
  {
18966
17702
  hover: mediaHover,
@@ -18969,11 +17705,11 @@ function OhhwellsBridge() {
18969
17705
  onVideoSettingsChange: handleVideoSettingsChange
18970
17706
  }
18971
17707
  ),
18972
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
18973
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
18974
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
18975
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
18976
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17708
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
17709
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
17710
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
17711
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
17712
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18977
17713
  "div",
18978
17714
  {
18979
17715
  className: "pointer-events-none fixed z-2147483646",
@@ -18983,7 +17719,7 @@ function OhhwellsBridge() {
18983
17719
  width: slot.width,
18984
17720
  height: slot.height
18985
17721
  },
18986
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17722
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18987
17723
  DropIndicator,
18988
17724
  {
18989
17725
  direction: slot.direction,
@@ -18994,7 +17730,7 @@ function OhhwellsBridge() {
18994
17730
  },
18995
17731
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
18996
17732
  )),
18997
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17733
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18998
17734
  "div",
18999
17735
  {
19000
17736
  className: "pointer-events-none fixed z-2147483646",
@@ -19004,7 +17740,7 @@ function OhhwellsBridge() {
19004
17740
  width: slot.width,
19005
17741
  height: slot.height
19006
17742
  },
19007
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17743
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19008
17744
  DropIndicator,
19009
17745
  {
19010
17746
  direction: slot.direction,
@@ -19015,11 +17751,11 @@ function OhhwellsBridge() {
19015
17751
  },
19016
17752
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
19017
17753
  )),
19018
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19019
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19020
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19021
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19022
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17754
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
17755
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
17756
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
17757
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
17758
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19023
17759
  FooterContainerChrome,
19024
17760
  {
19025
17761
  rect: toolbarRect,
@@ -19027,7 +17763,7 @@ function OhhwellsBridge() {
19027
17763
  addDisabled: !canAddFooterColumn()
19028
17764
  }
19029
17765
  ),
19030
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17766
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19031
17767
  ItemInteractionLayer,
19032
17768
  {
19033
17769
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -19039,10 +17775,10 @@ function OhhwellsBridge() {
19039
17775
  dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
19040
17776
  onDragHandleDragStart: handleItemDragStart,
19041
17777
  onDragHandleDragEnd: handleItemDragEnd,
19042
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
19043
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
19044
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
19045
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17778
+ onItemPointerDown: handleItemChromePointerDown,
17779
+ onItemClick: handleItemChromeClick,
17780
+ itemDragSurface: !isFooterFrameSelection,
17781
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19046
17782
  ItemActionToolbar,
19047
17783
  {
19048
17784
  onEditLink: openLinkPopoverForSelected,
@@ -19078,8 +17814,8 @@ function OhhwellsBridge() {
19078
17814
  ) : void 0
19079
17815
  }
19080
17816
  ),
19081
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19082
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17817
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
17818
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19083
17819
  EditGlowChrome,
19084
17820
  {
19085
17821
  rect: toolbarRect,
@@ -19089,7 +17825,7 @@ function OhhwellsBridge() {
19089
17825
  hideHandle: isItemDragging
19090
17826
  }
19091
17827
  ),
19092
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17828
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19093
17829
  FloatingToolbar,
19094
17830
  {
19095
17831
  rect: toolbarRect,
@@ -19102,7 +17838,7 @@ function OhhwellsBridge() {
19102
17838
  }
19103
17839
  )
19104
17840
  ] }),
19105
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
17841
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
19106
17842
  "div",
19107
17843
  {
19108
17844
  "data-ohw-max-badge": "",
@@ -19128,7 +17864,7 @@ function OhhwellsBridge() {
19128
17864
  ]
19129
17865
  }
19130
17866
  ),
19131
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17867
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19132
17868
  StateToggle,
19133
17869
  {
19134
17870
  rect: toggleState.rect,
@@ -19137,15 +17873,15 @@ function OhhwellsBridge() {
19137
17873
  onStateChange: handleStateChange
19138
17874
  }
19139
17875
  ),
19140
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
17876
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
19141
17877
  "div",
19142
17878
  {
19143
17879
  "data-ohw-section-insert-line": "",
19144
17880
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
19145
17881
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
19146
17882
  children: [
19147
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19148
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17883
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
17884
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19149
17885
  Badge,
19150
17886
  {
19151
17887
  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",
@@ -19162,11 +17898,11 @@ function OhhwellsBridge() {
19162
17898
  children: "Add Section"
19163
17899
  }
19164
17900
  ),
19165
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
17901
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19166
17902
  ]
19167
17903
  }
19168
17904
  ),
19169
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17905
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19170
17906
  LinkPopover,
19171
17907
  {
19172
17908
  panelRef: linkPopoverPanelRef,
@@ -19183,7 +17919,7 @@ function OhhwellsBridge() {
19183
17919
  },
19184
17920
  linkPopover.key
19185
17921
  ) : null,
19186
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17922
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19187
17923
  FloatingPanel,
19188
17924
  {
19189
17925
  open: true,
@@ -19193,7 +17929,7 @@ function OhhwellsBridge() {
19193
17929
  onPositionChange: setFloatingPanelPos,
19194
17930
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
19195
17931
  onClose: closeFloatingPanelOnly,
19196
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17932
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19197
17933
  SocialsDisplayPanel,
19198
17934
  {
19199
17935
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -19204,115 +17940,11 @@ function OhhwellsBridge() {
19204
17940
  }
19205
17941
  )
19206
17942
  }
19207
- ) : null,
19208
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19209
- FloatingPanel,
19210
- {
19211
- open: true,
19212
- title: floatingPanel.title,
19213
- context: floatingPanel.context,
19214
- position: floatingPanelPos,
19215
- onPositionChange: setFloatingPanelPos,
19216
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
19217
- onClose: closeFloatingPanelAndDeselect,
19218
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19219
- LogoSizePanel,
19220
- {
19221
- viewport: editorViewport,
19222
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
19223
- mobileFollowing: logoSizeDraft.mobileFollowing,
19224
- onSizeChange: (px) => {
19225
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
19226
- ...logoSizeDraft,
19227
- desktopPx: px,
19228
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
19229
- };
19230
- setLogoSizeDraft(next);
19231
- persistLogoSizeDraft(floatingPanel.placement, next);
19232
- },
19233
- onCustomizeMobile: () => {
19234
- const next = {
19235
- ...logoSizeDraft,
19236
- mobileFollowing: false,
19237
- mobilePx: logoSizeDraft.desktopPx
19238
- };
19239
- setLogoSizeDraft(next);
19240
- persistLogoSizeDraft(floatingPanel.placement, next);
19241
- },
19242
- onResetMobile: () => {
19243
- const next = {
19244
- ...logoSizeDraft,
19245
- mobileFollowing: true,
19246
- mobilePx: logoSizeDraft.desktopPx
19247
- };
19248
- setLogoSizeDraft(next);
19249
- persistLogoSizeDraft(floatingPanel.placement, next);
19250
- },
19251
- onUpdateEverywhere: () => {
19252
- const identity = readLogoIdentityFromDom();
19253
- postToParent2({ type: "ow:open-logo-settings", ...identity });
19254
- }
19255
- }
19256
- )
19257
- }
19258
17943
  ) : null
19259
17944
  ] }),
19260
17945
  bridgeRoot
19261
17946
  ) : null;
19262
17947
  }
19263
-
19264
- // src/ui/EmptySection.tsx
19265
- var import_link = __toESM(require("next/link"), 1);
19266
- var import_jsx_runtime34 = require("react/jsx-runtime");
19267
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
19268
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
19269
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19270
- "p",
19271
- {
19272
- style: {
19273
- fontFamily: "var(--brand-font-body)",
19274
- fontSize: "0.75rem",
19275
- fontWeight: 500,
19276
- letterSpacing: "0.15em",
19277
- textTransform: "uppercase",
19278
- color: "var(--brand-accent)",
19279
- marginBottom: "1.5rem"
19280
- },
19281
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
19282
- }
19283
- ),
19284
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19285
- "h1",
19286
- {
19287
- style: {
19288
- fontFamily: "var(--brand-font-heading)",
19289
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
19290
- lineHeight: 1.1,
19291
- letterSpacing: "-0.025em",
19292
- color: "var(--brand-text)",
19293
- marginBottom: "1rem"
19294
- },
19295
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
19296
- children: title
19297
- }
19298
- ),
19299
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19300
- "p",
19301
- {
19302
- style: {
19303
- fontFamily: "var(--brand-font-body)",
19304
- fontSize: "1rem",
19305
- lineHeight: 1.7,
19306
- fontWeight: 300,
19307
- color: "var(--brand-text-muted)",
19308
- maxWidth: "340px"
19309
- },
19310
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
19311
- children: "This page doesn't have any content yet."
19312
- }
19313
- )
19314
- ] });
19315
- }
19316
17948
  // Annotate the CommonJS export names for ESM import in node:
19317
17949
  0 && (module.exports = {
19318
17950
  AI_DEFAULT_BRAND,
@@ -19330,7 +17962,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
19330
17962
  DropdownMenuItem,
19331
17963
  DropdownMenuSeparator,
19332
17964
  DropdownMenuTrigger,
19333
- EmptySection,
19334
17965
  ItemActionToolbar,
19335
17966
  ItemInteractionLayer,
19336
17967
  LinkEditorPanel,