@ohhwells/bridge 0.1.63-next.175 → 0.1.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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,314 +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 STYLE_FONT_LINK_ID = "ohw-style-fonts";
376
- function loadStyleFonts(families) {
377
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
378
- const existing = document.getElementById(STYLE_FONT_LINK_ID);
379
- if (unique.length === 0) {
380
- existing?.remove();
381
- return;
382
- }
383
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
384
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
385
- let link = existing;
386
- if (!link) {
387
- link = document.createElement("link");
388
- link.id = STYLE_FONT_LINK_ID;
389
- link.rel = "stylesheet";
390
- document.head.appendChild(link);
391
- }
392
- if (link.href !== href) link.href = href;
393
- }
394
- var SECTION_ATTRS = {
395
- sectionBackground: "data-ohw-style-bg",
396
- textDistribution: "data-ohw-style-distribution",
397
- headlineScale: "data-ohw-style-headline",
398
- imageAspect: "data-ohw-style-aspect",
399
- spacing: "data-ohw-style-spacing"
400
- };
401
- var NODE_WROTE_ATTR = "data-ohw-style-node";
402
- var NODE_PROPS = ["color", "font-family", "font-size", "background"];
403
- function saveInline(el, prop) {
404
- const attr = `data-ohw-style-prev-${prop}`;
405
- if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
406
- }
407
- function restoreInline(el, prop) {
408
- const attr = `data-ohw-style-prev-${prop}`;
409
- if (!el.hasAttribute(attr)) return;
410
- const prev = el.getAttribute(attr) ?? "";
411
- if (prev) el.style.setProperty(prop, prev);
412
- else el.style.removeProperty(prop);
413
- el.removeAttribute(attr);
414
- }
415
- function ensureStyleSheet() {
416
- let el = document.getElementById(STYLE_SHEET_ID);
417
- if (!el) {
418
- el = document.createElement("style");
419
- el.id = STYLE_SHEET_ID;
420
- document.head.appendChild(el);
421
- }
422
- const css = styleSheetCss();
423
- if (el.textContent !== css) el.textContent = css;
424
- }
425
- function clearSectionAttrs(root) {
426
- for (const attr of Object.values(SECTION_ATTRS)) {
427
- for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
428
- }
429
- for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
430
- restoreInline(el, "background");
431
- el.removeAttribute("data-ohw-style-bgcolor");
432
- }
433
- }
434
- function clearNodeProps(root) {
435
- for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
436
- const h = el;
437
- for (const prop of NODE_PROPS) restoreInline(h, prop);
438
- h.removeAttribute(NODE_WROTE_ATTR);
439
- }
440
- }
441
- function buttonSurfaceOf(el) {
442
- return el.closest("a, button") ?? el;
443
- }
444
- function applyStylesToDom(store) {
445
- ensureStyleSheet();
446
- clearSectionAttrs(document);
447
- clearNodeProps(document);
448
- loadStyleFonts(
449
- store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
450
- );
451
- if (!store) return;
452
- for (const [sectionId, override] of Object.entries(store.sections)) {
453
- const sections = document.querySelectorAll(
454
- `[data-ohw-section="${CSS.escape(sectionId)}"]`
455
- );
456
- for (const section of Array.from(sections)) {
457
- for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
458
- const value = override[prop];
459
- if (value === void 0) continue;
460
- if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
461
- section.setAttribute(attr, String(value).replace(":", "-"));
462
- }
463
- if (override.sectionBackgroundColor !== void 0) {
464
- saveInline(section, "background");
465
- section.style.setProperty("background", override.sectionBackgroundColor, "important");
466
- section.setAttribute("data-ohw-style-bgcolor", "");
467
- }
468
- }
469
- }
470
- for (const [key, override] of Object.entries(store.nodes)) {
471
- const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
472
- for (const el of Array.from(nodes)) {
473
- if (override.color !== void 0) {
474
- saveInline(el, "color");
475
- el.style.setProperty("color", override.color, "important");
476
- el.setAttribute(NODE_WROTE_ATTR, "");
477
- }
478
- if (override.fontFamily !== void 0) {
479
- saveInline(el, "font-family");
480
- el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
481
- el.setAttribute(NODE_WROTE_ATTR, "");
482
- }
483
- if (override.fontSize !== void 0) {
484
- saveInline(el, "font-size");
485
- el.style.setProperty("font-size", `${override.fontSize}px`, "important");
486
- el.setAttribute(NODE_WROTE_ATTR, "");
487
- }
488
- if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
489
- const surface = buttonSurfaceOf(el);
490
- if (override.buttonBackground !== void 0) {
491
- saveInline(surface, "background");
492
- surface.style.setProperty("background", override.buttonBackground, "important");
493
- }
494
- if (override.buttonText !== void 0) {
495
- saveInline(surface, "color");
496
- surface.style.setProperty("color", override.buttonText, "important");
497
- }
498
- surface.setAttribute(NODE_WROTE_ATTR, "");
499
- }
500
- }
501
- }
502
- }
503
-
504
194
  // src/ui/ai-tree/aiSectionsManager.tsx
505
195
  var import_react_dom = require("react-dom");
506
196
  var import_client = require("react-dom/client");
@@ -515,8 +205,7 @@ function lucideByName(name) {
515
205
  }
516
206
  var typeStyle = (spec, font) => ({
517
207
  fontFamily: font,
518
- // Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
519
- 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,
520
209
  lineHeight: spec.line,
521
210
  fontWeight: spec.weight
522
211
  });
@@ -543,8 +232,6 @@ var AI_RESPONSIVE_CSS = [
543
232
  " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
544
233
  " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
545
234
  " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
546
- " [data-ai-responsive] { overflow-x: hidden; }",
547
- " [data-ai-responsive] img { max-width: 100%; }",
548
235
  "}"
549
236
  ].join("\n");
550
237
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
@@ -1552,20 +1239,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1552
1239
  const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
1553
1240
  const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
1554
1241
  const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
1555
- const toneBackground = (() => {
1556
- const { dark, primary, light } = resolvedBrand.palette;
1557
- switch (settings.sectionBackground) {
1558
- case "surface":
1559
- return `color-mix(in srgb, ${light} 94%, ${dark})`;
1560
- case "accent":
1561
- return primary;
1562
- case "accent-soft":
1563
- return `color-mix(in srgb, ${primary} 12%, ${light})`;
1564
- default:
1565
- return void 0;
1566
- }
1567
- })();
1568
- const distributed = !isOverlay && settings.textDistribution;
1569
1242
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1570
1243
  "section",
1571
1244
  {
@@ -1575,11 +1248,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1575
1248
  style: {
1576
1249
  position: "relative",
1577
1250
  padding: `${pad}px 0`,
1578
- background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
1251
+ background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
1579
1252
  backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
1580
1253
  backgroundSize: "cover",
1581
- backgroundPosition: "center",
1582
- color: settings.sectionBackground === "accent" ? resolvedBrand.palette.light : void 0
1254
+ backgroundPosition: "center"
1583
1255
  },
1584
1256
  children: [
1585
1257
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
@@ -1603,24 +1275,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1603
1275
  display: "grid",
1604
1276
  gridTemplateColumns: "repeat(12, 1fr)",
1605
1277
  gap: AI_TREE_TOKENS.spacing6,
1606
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1278
+ alignItems: settings.verticalPosition === "top" ? "start" : "center",
1607
1279
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1608
1280
  },
1609
- children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1610
- "div",
1611
- {
1612
- "data-ai-cell": "",
1613
- style: {
1614
- gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1615
- minWidth: 0,
1616
- // space-between: each column becomes a flex column whose content spreads over
1617
- // the full row height instead of clumping at the top.
1618
- ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
1619
- },
1620
- children: renderNode(block, ctx, `r${r2}.b${b}`)
1621
- },
1622
- b
1623
- ))
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))
1624
1282
  },
1625
1283
  r2
1626
1284
  ))
@@ -1636,34 +1294,17 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
1636
1294
  var CONTAINER_ATTR = "data-ohw-ai-generated";
1637
1295
  var REPLACED_ATTR = "data-ohw-ai-replaced-by";
1638
1296
  var REMOVED_ATTR = "data-ohw-ai-removed";
1639
- function readRootVar(name) {
1640
- if (typeof document === "undefined") return "";
1641
- return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1642
- }
1643
- function deriveBrandOverride() {
1644
- const dark = readRootVar("--ohw-brand-dark");
1645
- const primary = readRootVar("--ohw-brand-primary");
1646
- const light = readRootVar("--ohw-brand-light");
1647
- if (!dark || !primary || !light) return null;
1648
- const accent = readRootVar("--ohw-brand-accent");
1649
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1650
- const body = readRootVar("--font-body");
1651
- return {
1652
- palette: { dark, primary, accent: accent || dark, light },
1653
- fonts: {
1654
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
1655
- body: body || AI_DEFAULT_BRAND.fonts.body
1656
- }
1657
- };
1658
- }
1659
1297
  function deriveTemplateBrand() {
1660
- const dark = readRootVar("--color-dark");
1661
- const primary = readRootVar("--color-primary");
1662
- 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");
1663
1304
  if (!dark || !primary || !light) return null;
1664
- const accent = readRootVar("--color-accent");
1665
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1666
- 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");
1667
1308
  return {
1668
1309
  palette: { dark, primary, accent: accent || dark, light },
1669
1310
  fonts: {
@@ -1755,12 +1396,8 @@ function syncReplacedOriginals(state) {
1755
1396
  }
1756
1397
  function applyAiSectionsToDom(state, options) {
1757
1398
  if (typeof document === "undefined") return;
1758
- const brandOverride = deriveBrandOverride();
1759
1399
  const templateBrand = deriveTemplateBrand();
1760
- const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
1761
- const pagePath = window.location.pathname;
1762
- const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
1763
- const activeIds = new Set(pageSections.map((entry) => entry.id));
1400
+ const activeIds = new Set(state.sections.map((entry) => entry.id));
1764
1401
  for (const [id, section] of mounted) {
1765
1402
  if (!activeIds.has(id)) {
1766
1403
  section.root.unmount();
@@ -1768,8 +1405,8 @@ function applyAiSectionsToDom(state, options) {
1768
1405
  mounted.delete(id);
1769
1406
  }
1770
1407
  }
1771
- for (const entry of pageSections) {
1772
- const serialized = JSON.stringify(entry) + brandKey;
1408
+ for (const entry of state.sections) {
1409
+ const serialized = JSON.stringify(entry);
1773
1410
  const existing = mounted.get(entry.id);
1774
1411
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
1775
1412
  continue;
@@ -1783,7 +1420,6 @@ function applyAiSectionsToDom(state, options) {
1783
1420
  mounted.delete(entry.id);
1784
1421
  }
1785
1422
  container.setAttribute("data-ohw-section", entry.id);
1786
- container.setAttribute("data-ohw-instance", entry.id);
1787
1423
  container.setAttribute("data-ohw-section-label", entry.label);
1788
1424
  placeContainer(container, entry);
1789
1425
  const root = mounted.get(entry.id)?.root ?? (0, import_client.createRoot)(container);
@@ -1794,7 +1430,7 @@ function applyAiSectionsToDom(state, options) {
1794
1430
  AiTreeRenderer,
1795
1431
  {
1796
1432
  tree: entry.tree,
1797
- brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1433
+ brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1798
1434
  resolveMedia,
1799
1435
  editKeyPrefix: `ai.${entry.id}`
1800
1436
  }
@@ -2411,7 +2047,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2411
2047
  const autoId = (0, import_react5.useId)();
2412
2048
  const insertAfter = insertAfterProp ?? autoId;
2413
2049
  const [schedule, setSchedule] = (0, import_react5.useState)(null);
2414
- const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
2050
+ const [loading, setLoading] = (0, import_react5.useState)(true);
2415
2051
  const [inEditor, setInEditor] = (0, import_react5.useState)(false);
2416
2052
  const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
2417
2053
  const [modalState, setModalState] = (0, import_react5.useState)(null);
@@ -2585,10 +2221,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2585
2221
  "*"
2586
2222
  );
2587
2223
  };
2224
+ if (!inEditor && !loading && !schedule) return null;
2588
2225
  const sectionId = `scheduling-${insertAfter}`;
2589
- if (!inEditor && !loading && !schedule) {
2590
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2591
- }
2592
2226
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2593
2227
  "section",
2594
2228
  {
@@ -7107,12 +6741,8 @@ function parseSectionsFromHtml(html) {
7107
6741
 
7108
6742
  // src/ui/ai-section/AiSectionOverlay.tsx
7109
6743
  var import_jsx_runtime16 = require("react/jsx-runtime");
7110
- function findSectionElement(instanceId) {
7111
- const escaped = CSS.escape(instanceId);
7112
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7113
- }
7114
- function readRect(instanceId) {
7115
- const el = findSectionElement(instanceId);
6744
+ function readRect(sectionId) {
6745
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7116
6746
  if (!el) return null;
7117
6747
  const r2 = el.getBoundingClientRect();
7118
6748
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7135,7 +6765,7 @@ function useLiveSectionRect(sectionId) {
7135
6765
  const opts = { capture: true, passive: true };
7136
6766
  window.addEventListener("scroll", update, opts);
7137
6767
  window.addEventListener("resize", update);
7138
- const el = findSectionElement(sectionId);
6768
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7139
6769
  const ro = el ? new ResizeObserver(update) : null;
7140
6770
  if (el && ro) ro.observe(el);
7141
6771
  const interval = setInterval(update, 500);
@@ -7148,14 +6778,6 @@ function useLiveSectionRect(sectionId) {
7148
6778
  }, [sectionId]);
7149
6779
  return rect;
7150
6780
  }
7151
- function computeSectionBoundaryFlags(instanceId) {
7152
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7153
- (el) => !el.parentElement?.closest("[data-ohw-section]")
7154
- );
7155
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7156
- if (index === -1) return { isFirst: true, isLast: true };
7157
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7158
- }
7159
6781
  var PRIMARY2 = "#0885FE";
7160
6782
  function edgeAwareRadius(rect) {
7161
6783
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7229,7 +6851,6 @@ function AiSectionOverlay({
7229
6851
  }) {
7230
6852
  const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
7231
6853
  const [reviewId, setReviewId] = (0, import_react8.useState)(null);
7232
- const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
7233
6854
  const reviewIdRef = (0, import_react8.useRef)(null);
7234
6855
  reviewIdRef.current = reviewId;
7235
6856
  const selectedIdRef = (0, import_react8.useRef)(null);
@@ -7238,7 +6859,7 @@ function AiSectionOverlay({
7238
6859
  (el) => {
7239
6860
  postToParent2({
7240
6861
  type: "ow:section-selected",
7241
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
6862
+ sectionId: el?.dataset.ohwSection ?? null,
7242
6863
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7243
6864
  });
7244
6865
  },
@@ -7247,7 +6868,7 @@ function AiSectionOverlay({
7247
6868
  const selectFromElement = (0, import_react8.useCallback)(
7248
6869
  (el, options) => {
7249
6870
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7250
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
6871
+ const id = sectionEl?.dataset.ohwSection ?? null;
7251
6872
  if (id === selectedIdRef.current) return;
7252
6873
  setSelectedId(id);
7253
6874
  if (options?.report !== false) report(sectionEl);
@@ -7288,10 +6909,9 @@ function AiSectionOverlay({
7288
6909
  }
7289
6910
  const found = readRect(sectionId) != null;
7290
6911
  setReviewId(found ? sectionId : null);
7291
- setReviewButtonsHidden(e.data.hideButtons === true);
7292
6912
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7293
6913
  if (found) {
7294
- 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" });
7295
6915
  }
7296
6916
  }
7297
6917
  };
@@ -7310,7 +6930,7 @@ function AiSectionOverlay({
7310
6930
  return;
7311
6931
  }
7312
6932
  const sec = t.closest("[data-ohw-section]");
7313
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
6933
+ setHoveredId(sec?.dataset.ohwSection ?? null);
7314
6934
  };
7315
6935
  const onLeave = () => setHoveredId(null);
7316
6936
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -7342,29 +6962,9 @@ function AiSectionOverlay({
7342
6962
  },
7343
6963
  [postToParent2]
7344
6964
  );
7345
- const activeSelectionId = reviewId ? null : selectedId;
7346
- const selectionRect = useLiveSectionRect(activeSelectionId);
6965
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
7347
6966
  const reviewRect = useLiveSectionRect(reviewId);
7348
6967
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
7349
- (0, import_react8.useEffect)(() => {
7350
- if (!activeSelectionId || !selectionRect) {
7351
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
7352
- return;
7353
- }
7354
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
7355
- postToParent2({
7356
- type: "ow:section-rect",
7357
- instanceId: activeSelectionId,
7358
- rect: {
7359
- top: selectionRect.top + window.scrollY,
7360
- left: selectionRect.left + window.scrollX,
7361
- width: selectionRect.width,
7362
- height: selectionRect.height
7363
- },
7364
- isFirst,
7365
- isLast
7366
- });
7367
- }, [activeSelectionId, selectionRect, postToParent2]);
7368
6968
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
7369
6969
  hoverRect && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7370
6970
  "div",
@@ -7415,16 +7015,13 @@ function AiSectionOverlay({
7415
7015
  border: `2px solid ${PRIMARY2}`,
7416
7016
  borderRadius: edgeAwareRadius(reviewRect),
7417
7017
  zIndex: 2147483200,
7418
- // The veil itself: swallows clicks so the section stays locked until decided. This
7419
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
7420
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
7421
- // 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.
7422
7019
  background: "rgba(8, 133, 254, 0.04)",
7423
7020
  pointerEvents: "auto",
7424
7021
  cursor: "default"
7425
7022
  },
7426
7023
  onClick: (e) => e.stopPropagation(),
7427
- children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7024
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7428
7025
  "div",
7429
7026
  {
7430
7027
  style: {
@@ -11324,296 +10921,42 @@ function deleteFooterColumn(column) {
11324
10921
  };
11325
10922
  }
11326
10923
 
11327
- // src/lib/logo-identity.ts
11328
- var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
11329
- var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
11330
- var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
11331
- var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
11332
- var LOGO_ALT_KEY = "logo-alt";
11333
- var LOGO_IMAGE_URL_KEY = "nav-logo-image";
11334
- var PLACEHOLDER_BUSINESS_NAME = "Business name";
11335
- function resolveLogoDisplayText(text) {
11336
- const trimmed = (text ?? "").trim();
11337
- return trimmed || PLACEHOLDER_BUSINESS_NAME;
11338
- }
11339
- function isFooterLogoRoot(root) {
11340
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11341
- }
11342
- function imageKeyForRoot(root) {
11343
- return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
11344
- }
11345
- function textKeyForRoot(root) {
11346
- return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
11347
- }
11348
- function ensureLogoHrefKey(root) {
11349
- if (!(root instanceof HTMLAnchorElement)) return;
11350
- if (root.hasAttribute("data-ohw-href-key")) return;
11351
- root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
11352
- }
11353
- function applyLogoIdentity(text, isPlaceholder) {
11354
- const display = resolveLogoDisplayText(text);
11355
- const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
11356
- for (const key of LOGO_TEXT_KEYS) {
11357
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11358
- if (el.textContent !== display) el.textContent = display;
11359
- });
11360
- }
11361
- for (const key of LOGO_IMAGE_KEYS) {
11362
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11363
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
11364
- if (img) img.alt = display;
11365
- });
11366
- }
11367
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
11368
- if (placeholder) el.setAttribute("data-ohw-placeholder", "");
11369
- else el.removeAttribute("data-ohw-placeholder");
11370
- });
11371
- return display;
11372
- }
11373
- function applyLogoImage(url, alt) {
11374
- const displayAlt = resolveLogoDisplayText(alt);
11375
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11376
- ensureLogoHrefKey(root);
11377
- const imageKey = imageKeyForRoot(root);
11378
- const textKey = textKeyForRoot(root);
11379
- 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");
11380
- let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
11381
- if (url) {
11382
- if (!img) {
11383
- img = document.createElement("img");
11384
- img.setAttribute("data-ohw-editable", "image");
11385
- img.setAttribute("data-ohw-key", imageKey);
11386
- img.alt = displayAlt;
11387
- img.style.height = "";
11388
- img.style.maxHeight = "none";
11389
- img.style.width = "auto";
11390
- img.style.display = "block";
11391
- img.style.objectFit = "contain";
11392
- root.insertBefore(img, root.firstChild);
11393
- } else {
11394
- img.setAttribute("data-ohw-editable", "image");
11395
- img.setAttribute("data-ohw-key", imageKey);
11396
- }
11397
- img.removeAttribute("srcset");
11398
- img.removeAttribute("sizes");
11399
- img.src = url;
11400
- img.alt = displayAlt;
11401
- img.style.display = "block";
11402
- if (textEl) textEl.style.display = "none";
11403
- root.removeAttribute("data-ohw-placeholder");
11404
- return;
11405
- }
11406
- if (img) {
11407
- img.removeAttribute("src");
11408
- img.removeAttribute("srcset");
11409
- img.removeAttribute("sizes");
11410
- img.alt = displayAlt;
11411
- img.style.display = "none";
11412
- }
11413
- if (!textEl) {
11414
- textEl = document.createElement("span");
11415
- textEl.setAttribute("data-ohw-editable", "plain");
11416
- textEl.setAttribute("data-ohw-key", textKey);
11417
- root.appendChild(textEl);
11418
- }
11419
- textEl.style.display = "";
11420
- if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
11421
- if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
11422
- root.setAttribute("data-ohw-placeholder", "");
11423
- } else {
11424
- root.removeAttribute("data-ohw-placeholder");
11425
- }
11426
- });
11427
- }
11428
- function applyLogoHref(href) {
11429
- const target = href.trim() || "/";
11430
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11431
- ensureLogoHrefKey(root);
11432
- if (root instanceof HTMLAnchorElement) {
11433
- root.setAttribute("href", target);
11434
- }
11435
- });
11436
- for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
11437
- }
11438
- function readLogoIdentityFromDom() {
11439
- let imageUrl = null;
11440
- for (const key of LOGO_IMAGE_KEYS) {
11441
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
11442
- const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
11443
- const attrSrc = img?.getAttribute("src")?.trim() ?? "";
11444
- if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
11445
- imageUrl = img.currentSrc || img.src;
11446
- break;
11447
- }
11448
- }
11449
- let text = PLACEHOLDER_BUSINESS_NAME;
11450
- let isPlaceholder = true;
11451
- for (const key of LOGO_TEXT_KEYS) {
11452
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
11453
- if (el?.textContent?.trim()) {
11454
- text = el.textContent.trim();
11455
- const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
11456
- isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
11457
- break;
11458
- }
11459
- }
11460
- if (imageUrl) {
11461
- const logoImg = document.querySelector(
11462
- '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
11463
- );
11464
- const alt = logoImg?.alt?.trim() || text;
11465
- isPlaceholder = false;
11466
- const hrefEl = document.querySelector(
11467
- 'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
11468
- );
11469
- const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
11470
- return { text, isPlaceholder, imageUrl, href: href2, alt };
11471
- }
11472
- const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
11473
- const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
11474
- return { text, isPlaceholder, imageUrl: null, href, alt: text };
11475
- }
11476
- function applyLogoFromContent(content) {
11477
- 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);
11478
- if (!hasLogoIdentity) return false;
11479
- const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
11480
- const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
11481
- const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
11482
- const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
11483
- const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
11484
- const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
11485
- if (logoImageUrl) {
11486
- applyLogoImage(logoImageUrl, logoAlt);
11487
- } else {
11488
- if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
11489
- applyLogoIdentity(logoText, logoIsPlaceholder);
11490
- }
11491
- const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
11492
- if (typeof logoHref === "string" && logoHref.trim()) {
11493
- applyLogoHref(logoHref);
11494
- }
11495
- return true;
11496
- }
11497
-
11498
- // src/lib/logo-size.ts
11499
- var LOGO_SIZE_DEFAULTS = {
11500
- navbar: 28,
11501
- footer: 32
11502
- };
11503
- var LOGO_SIZE_MIN = 16;
11504
- var LOGO_SIZE_MAX = 80;
11505
- var LOGO_SIZE_DESKTOP_KEYS = {
11506
- navbar: "nav-logo-size",
11507
- footer: "footer-logo-size"
11508
- };
11509
- var LOGO_SIZE_MOBILE_KEYS = {
11510
- navbar: "nav-logo-size-mobile",
11511
- footer: "footer-logo-size-mobile"
11512
- };
11513
- var LOGO_SIZE_KEYS = [
11514
- LOGO_SIZE_DESKTOP_KEYS.navbar,
11515
- LOGO_SIZE_DESKTOP_KEYS.footer,
11516
- LOGO_SIZE_MOBILE_KEYS.navbar,
11517
- LOGO_SIZE_MOBILE_KEYS.footer
11518
- ];
11519
- function isFooterLogoRoot2(root) {
11520
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11521
- }
11522
- function getLogoPlacement(root) {
11523
- return isFooterLogoRoot2(root) ? "footer" : "navbar";
11524
- }
11525
- function parseLogoSizePx(raw, fallback) {
11526
- if (raw == null || raw === "") return fallback;
11527
- const n = Number.parseFloat(raw);
11528
- if (!Number.isFinite(n)) return fallback;
11529
- return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
11530
- }
11531
- function isMobileLogoSizeFollowing(content, placement) {
11532
- const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
11533
- return raw == null || raw.trim() === "";
11534
- }
11535
- function resolveDesktopLogoSize(content, placement) {
11536
- return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
11537
- }
11538
- function resolveMobileLogoSize(content, placement) {
11539
- if (isMobileLogoSizeFollowing(content, placement)) {
11540
- return resolveDesktopLogoSize(content, placement);
11541
- }
11542
- return parseLogoSizePx(
11543
- content[LOGO_SIZE_MOBILE_KEYS[placement]],
11544
- resolveDesktopLogoSize(content, placement)
11545
- );
10924
+ // src/lib/add-footer-column.ts
10925
+ function buildFooterColumnEditContentPatch(result) {
10926
+ return {
10927
+ [result.headingKey]: result.heading,
10928
+ [result.hrefKey]: result.href,
10929
+ [result.labelKey]: result.label,
10930
+ [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
10931
+ };
11546
10932
  }
11547
- function setRootSizeVars(root, desktopPx, mobilePx, following) {
11548
- root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
11549
- if (following) {
11550
- root.style.removeProperty("--ohw-logo-size-mobile");
11551
- } else {
11552
- root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
10933
+ function addFooterColumnWithPersist({
10934
+ postToParent: postToParent2
10935
+ }) {
10936
+ if (!canAddFooterColumn()) {
10937
+ postToParent2({
10938
+ type: "ow:toast",
10939
+ title: `Maximum ${MAX_FOOTER_COLUMNS} columns`,
10940
+ toastType: "error"
10941
+ });
10942
+ return null;
11553
10943
  }
11554
- root.querySelectorAll("img").forEach((img) => {
11555
- img.style.height = "";
11556
- img.style.maxHeight = "none";
11557
- img.style.width = "auto";
11558
- img.style.objectFit = "contain";
11559
- });
11560
- }
11561
- function applyLogoSizes(content) {
11562
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11563
- const placement = getLogoPlacement(root);
11564
- const desktop = resolveDesktopLogoSize(content, placement);
11565
- const following = isMobileLogoSizeFollowing(content, placement);
11566
- const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
11567
- setRootSizeVars(root, desktop, mobile, following);
11568
- });
11569
- }
11570
- function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
11571
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11572
- if (getLogoPlacement(root) !== placement) return;
11573
- setRootSizeVars(root, desktopPx, mobilePx, following);
10944
+ const result = insertFooterColumn();
10945
+ const patch = buildFooterColumnEditContentPatch(result);
10946
+ setStoredLinkHref(result.hrefKey, result.href);
10947
+ postToParent2({
10948
+ type: "ow:change",
10949
+ nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
11574
10950
  });
11575
- }
11576
- function logoHasUploadedImage(logoEl) {
11577
- if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
11578
- 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");
11579
- if (!img) return false;
11580
- const src = img.getAttribute("src")?.trim() ?? "";
11581
- if (!src || src.startsWith("data:")) return false;
11582
- if (img.style.display === "none") return false;
11583
- return true;
11584
- }
11585
- function getLogoInteractionRect(logoEl) {
11586
- if (logoHasUploadedImage(logoEl)) {
11587
- 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");
11588
- if (img) {
11589
- const r2 = img.getBoundingClientRect();
11590
- if (r2.width > 0 && r2.height > 0) return r2;
11591
- }
11592
- }
11593
- const text = logoEl.querySelector(
11594
- '[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
11595
- );
11596
- if (text) {
11597
- const style = window.getComputedStyle(text);
11598
- if (style.display !== "none" && style.visibility !== "hidden") {
11599
- const r2 = text.getBoundingClientRect();
11600
- if (r2.width > 0 && r2.height > 0) return r2;
11601
- }
11602
- }
11603
- return logoEl.getBoundingClientRect();
11604
- }
11605
- function readLogoSizeState(content, placement) {
11606
- const desktopPx = resolveDesktopLogoSize(content, placement);
11607
- const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
11608
- const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
11609
- return { desktopPx, mobilePx, mobileFollowing };
10951
+ postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
10952
+ enforceLinkHrefs();
10953
+ return result;
11610
10954
  }
11611
10955
 
11612
10956
  // src/lib/site-wide-scope.ts
11613
10957
  function getLogoElement(el) {
11614
10958
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
11615
10959
  if (marked) return marked;
11616
- if (el.closest('[data-ohw-editable="icon"]')) return null;
11617
10960
  const root = el.closest("nav, [data-ohw-nav-root], footer");
11618
10961
  if (!root) return null;
11619
10962
  const anchor = el.closest("a");
@@ -11647,38 +10990,6 @@ function isSiteWideScopeActive(args) {
11647
10990
  return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
11648
10991
  }
11649
10992
 
11650
- // src/lib/add-footer-column.ts
11651
- function buildFooterColumnEditContentPatch(result) {
11652
- return {
11653
- [result.headingKey]: result.heading,
11654
- [result.hrefKey]: result.href,
11655
- [result.labelKey]: result.label,
11656
- [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
11657
- };
11658
- }
11659
- function addFooterColumnWithPersist({
11660
- postToParent: postToParent2
11661
- }) {
11662
- if (!canAddFooterColumn()) {
11663
- postToParent2({
11664
- type: "ow:toast",
11665
- title: `Maximum ${MAX_FOOTER_COLUMNS} columns`,
11666
- toastType: "error"
11667
- });
11668
- return null;
11669
- }
11670
- const result = insertFooterColumn();
11671
- const patch = buildFooterColumnEditContentPatch(result);
11672
- setStoredLinkHref(result.hrefKey, result.href);
11673
- postToParent2({
11674
- type: "ow:change",
11675
- nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
11676
- });
11677
- postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
11678
- enforceLinkHrefs();
11679
- return result;
11680
- }
11681
-
11682
10993
  // src/ui/FloatingPanel.tsx
11683
10994
  var import_react13 = require("react");
11684
10995
  var import_lucide_react13 = require("lucide-react");
@@ -11862,127 +11173,16 @@ function FloatingPanel({
11862
11173
  );
11863
11174
  }
11864
11175
 
11865
- // src/ui/logo-size-panel.tsx
11866
- var import_lucide_react14 = require("lucide-react");
11867
- var import_jsx_runtime27 = require("react/jsx-runtime");
11868
- function SizeSlider({
11869
- value,
11870
- onChange
11871
- }) {
11872
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
11873
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-3", children: [
11874
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
11875
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
11876
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
11877
- value,
11878
- " px"
11879
- ] })
11880
- ] }),
11881
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
11882
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11883
- "div",
11884
- {
11885
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
11886
- style: { width: `${pct}%` }
11887
- }
11888
- ),
11889
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11890
- "input",
11891
- {
11892
- type: "range",
11893
- min: LOGO_SIZE_MIN,
11894
- max: LOGO_SIZE_MAX,
11895
- step: 1,
11896
- value,
11897
- "aria-label": "Logo size",
11898
- className: cn(
11899
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
11900
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
11901
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
11902
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
11903
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
11904
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
11905
- "[&::-moz-range-thumb]:bg-background"
11906
- ),
11907
- onChange: (e) => onChange(Number(e.target.value))
11908
- }
11909
- )
11910
- ] })
11911
- ] });
11912
- }
11913
- function LogoSizePanel({
11914
- viewport,
11915
- sizePx,
11916
- mobileFollowing = true,
11917
- onSizeChange,
11918
- onCustomizeMobile,
11919
- onResetMobile,
11920
- onUpdateEverywhere,
11921
- className
11922
- }) {
11923
- const showFollowing = viewport === "mobile" && mobileFollowing;
11924
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
11925
- const showDesktopSlider = viewport === "desktop";
11926
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-4", className), children: [
11927
- showFollowing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
11928
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-start gap-1", children: [
11929
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Link, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
11930
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
11931
- ] }),
11932
- /* @__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." }),
11933
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11934
- Button,
11935
- {
11936
- type: "button",
11937
- variant: "outline",
11938
- size: "sm",
11939
- className: "h-9 w-full min-w-0 cursor-pointer",
11940
- onClick: onCustomizeMobile,
11941
- children: "Customize for mobile"
11942
- }
11943
- )
11944
- ] }) : null,
11945
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
11946
- showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11947
- Button,
11948
- {
11949
- type: "button",
11950
- variant: "outline",
11951
- size: "sm",
11952
- className: "h-9 w-full min-w-0 cursor-pointer",
11953
- onClick: onResetMobile,
11954
- children: "Reset to desktop size"
11955
- }
11956
- ) : null,
11957
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px w-full bg-border", role: "separator" }),
11958
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
11959
- Button,
11960
- {
11961
- type: "button",
11962
- variant: "outline",
11963
- size: "sm",
11964
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
11965
- onClick: onUpdateEverywhere,
11966
- children: [
11967
- "Update logo everywhere",
11968
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.ArrowUpRight, { size: 16, "aria-hidden": true })
11969
- ]
11970
- }
11971
- ),
11972
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
11973
- ] });
11974
- }
11975
-
11976
11176
  // src/ui/socials-display-panel.tsx
11977
- var import_jsx_runtime28 = require("react/jsx-runtime");
11177
+ var import_jsx_runtime27 = require("react/jsx-runtime");
11978
11178
  function DisplaySwitch({
11979
11179
  label,
11980
11180
  checked,
11981
11181
  disabled,
11982
11182
  onChange
11983
11183
  }) {
11984
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
11985
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11184
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
11185
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11986
11186
  "span",
11987
11187
  {
11988
11188
  className: cn(
@@ -11992,7 +11192,7 @@ function DisplaySwitch({
11992
11192
  children: label
11993
11193
  }
11994
11194
  ),
11995
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11195
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11996
11196
  "button",
11997
11197
  {
11998
11198
  type: "button",
@@ -12006,7 +11206,7 @@ function DisplaySwitch({
12006
11206
  checked ? "bg-primary" : "bg-primary-50",
12007
11207
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
12008
11208
  ),
12009
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11209
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12010
11210
  "span",
12011
11211
  {
12012
11212
  className: cn(
@@ -12020,8 +11220,8 @@ function DisplaySwitch({
12020
11220
  ] });
12021
11221
  }
12022
11222
  function SocialsDisplayPanel({ display, onChange, className }) {
12023
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
12024
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11223
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11224
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12025
11225
  DisplaySwitch,
12026
11226
  {
12027
11227
  label: "Text",
@@ -12030,7 +11230,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
12030
11230
  onChange: (text) => onChange({ ...display, text })
12031
11231
  }
12032
11232
  ),
12033
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11233
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12034
11234
  DisplaySwitch,
12035
11235
  {
12036
11236
  label: "Icon",
@@ -12590,8 +11790,8 @@ function useNavItemDrag({
12590
11790
  }
12591
11791
 
12592
11792
  // src/ui/footer-container-chrome.tsx
12593
- var import_lucide_react15 = require("lucide-react");
12594
- var import_jsx_runtime29 = require("react/jsx-runtime");
11793
+ var import_lucide_react14 = require("lucide-react");
11794
+ var import_jsx_runtime28 = require("react/jsx-runtime");
12595
11795
  function FooterContainerChrome({
12596
11796
  rect,
12597
11797
  onAdd,
@@ -12599,7 +11799,7 @@ function FooterContainerChrome({
12599
11799
  }) {
12600
11800
  const chromeGap = 6;
12601
11801
  const buttonMargin = 7;
12602
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11802
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12603
11803
  "div",
12604
11804
  {
12605
11805
  "data-ohw-footer-container-chrome": "",
@@ -12611,8 +11811,8 @@ function FooterContainerChrome({
12611
11811
  width: rect.width + chromeGap * 2,
12612
11812
  height: rect.height + chromeGap * 2
12613
11813
  },
12614
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
12615
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11814
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Tooltip, { children: [
11815
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12616
11816
  "button",
12617
11817
  {
12618
11818
  type: "button",
@@ -12631,10 +11831,10 @@ function FooterContainerChrome({
12631
11831
  if (addDisabled) return;
12632
11832
  onAdd();
12633
11833
  },
12634
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
11834
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react14.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12635
11835
  }
12636
11836
  ) }),
12637
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
11837
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12638
11838
  ] })
12639
11839
  }
12640
11840
  ) });
@@ -12817,18 +12017,6 @@ function collectEditableNodes(extraContent, root = document) {
12817
12017
  }
12818
12018
  if (extraContent && !isScoped) {
12819
12019
  applyNavFooterDeleteOverrides(byKey, extraContent);
12820
- for (const key of LOGO_IMAGE_KEYS) {
12821
- if (!(key in extraContent)) continue;
12822
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
12823
- }
12824
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
12825
- if (!(key in extraContent)) continue;
12826
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12827
- }
12828
- for (const key of LOGO_SIZE_KEYS) {
12829
- if (!(key in extraContent)) continue;
12830
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12831
- }
12832
12020
  }
12833
12021
  return Array.from(byKey.values());
12834
12022
  }
@@ -13094,14 +12282,14 @@ function deleteSelectedNavFooterItem(deps) {
13094
12282
  }
13095
12283
 
13096
12284
  // src/ui/navbar-container-chrome.tsx
13097
- var import_lucide_react16 = require("lucide-react");
13098
- var import_jsx_runtime30 = require("react/jsx-runtime");
12285
+ var import_lucide_react15 = require("lucide-react");
12286
+ var import_jsx_runtime29 = require("react/jsx-runtime");
13099
12287
  function NavbarContainerChrome({
13100
12288
  rect,
13101
12289
  onAdd
13102
12290
  }) {
13103
12291
  const chromeGap = 6;
13104
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12292
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13105
12293
  "div",
13106
12294
  {
13107
12295
  "data-ohw-navbar-container-chrome": "",
@@ -13113,7 +12301,7 @@ function NavbarContainerChrome({
13113
12301
  width: rect.width + chromeGap * 2,
13114
12302
  height: rect.height + chromeGap * 2
13115
12303
  },
13116
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12304
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13117
12305
  "button",
13118
12306
  {
13119
12307
  type: "button",
@@ -13130,7 +12318,7 @@ function NavbarContainerChrome({
13130
12318
  e.stopPropagation();
13131
12319
  onAdd();
13132
12320
  },
13133
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12321
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13134
12322
  }
13135
12323
  )
13136
12324
  }
@@ -13139,7 +12327,7 @@ function NavbarContainerChrome({
13139
12327
 
13140
12328
  // src/ui/drop-indicator.tsx
13141
12329
  var React10 = __toESM(require("react"), 1);
13142
- var import_jsx_runtime31 = require("react/jsx-runtime");
12330
+ var import_jsx_runtime30 = require("react/jsx-runtime");
13143
12331
  var dropIndicatorVariants = cva(
13144
12332
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
13145
12333
  {
@@ -13163,7 +12351,7 @@ var dropIndicatorVariants = cva(
13163
12351
  );
13164
12352
  var DropIndicator = React10.forwardRef(
13165
12353
  ({ className, direction, state, ...props }, ref) => {
13166
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
12354
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13167
12355
  "div",
13168
12356
  {
13169
12357
  ref,
@@ -13180,7 +12368,7 @@ var DropIndicator = React10.forwardRef(
13180
12368
  DropIndicator.displayName = "DropIndicator";
13181
12369
 
13182
12370
  // src/ui/badge.tsx
13183
- var import_jsx_runtime32 = require("react/jsx-runtime");
12371
+ var import_jsx_runtime31 = require("react/jsx-runtime");
13184
12372
  var badgeVariants = cva(
13185
12373
  "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",
13186
12374
  {
@@ -13198,12 +12386,12 @@ var badgeVariants = cva(
13198
12386
  }
13199
12387
  );
13200
12388
  function Badge({ className, variant, ...props }) {
13201
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
12389
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
13202
12390
  }
13203
12391
 
13204
12392
  // src/OhhwellsBridge.tsx
13205
- var import_lucide_react17 = require("lucide-react");
13206
- var import_jsx_runtime33 = require("react/jsx-runtime");
12393
+ var import_lucide_react16 = require("lucide-react");
12394
+ var import_jsx_runtime32 = require("react/jsx-runtime");
13207
12395
  var PRIMARY3 = "#0885FE";
13208
12396
  var IMAGE_FADE_MS = 300;
13209
12397
  function runOpacityFade(el, onDone) {
@@ -13297,10 +12485,21 @@ function parseSchedulingInsertAfter(insertAfter) {
13297
12485
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
13298
12486
  };
13299
12487
  }
13300
- function resolveEntryAnchor(entry) {
13301
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
13302
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
13303
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
12488
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
12489
+ const parsed = parseSchedulingInsertAfter(insertAfter);
12490
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
12491
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
12492
+ return { effectiveInsertAfter, insertBefore };
12493
+ }
12494
+ function getSchedulingMountPoint(insertAfter) {
12495
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
12496
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
12497
+ if (!anchorEl && anchor === "scheduling") {
12498
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
12499
+ anchorEl = widgets.at(-1) ?? null;
12500
+ }
12501
+ if (!anchorEl) return null;
12502
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13304
12503
  }
13305
12504
  function schedulingMountDepth(insertAfter) {
13306
12505
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -13317,7 +12516,8 @@ function getPageSchedulingEntries(raw) {
13317
12516
  }
13318
12517
  }
13319
12518
  function isSchedulingWidgetMissing(entry) {
13320
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
12519
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
12520
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
13321
12521
  }
13322
12522
  function hasMissingSchedulingWidgets(entries) {
13323
12523
  return entries.some(isSchedulingWidgetMissing);
@@ -13347,17 +12547,16 @@ function initSectionsFromContent(content, removeExisting = false) {
13347
12547
  } catch {
13348
12548
  }
13349
12549
  }
13350
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
13351
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
13352
- const sectionId = schedulingSectionId(widgetId);
12550
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
12551
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
12552
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
13353
12553
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
13354
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
13355
- if (!anchorEl) return false;
13356
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
12554
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
12555
+ if (!mountPoint) return false;
13357
12556
  const container = document.createElement("div");
13358
12557
  container.dataset.ohwSectionContainer = "scheduling";
13359
- if (beforeId) {
13360
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
12558
+ if (insertBefore) {
12559
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
13361
12560
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
13362
12561
  if (!beforePoint) return false;
13363
12562
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -13368,25 +12567,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13368
12567
  }
13369
12568
  tail.insertAdjacentElement("afterend", container);
13370
12569
  }
13371
- try {
13372
- const root = (0, import_client2.createRoot)(container);
13373
- (0, import_react_dom3.flushSync)(() => {
13374
- root.render(
13375
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13376
- SchedulingWidget,
13377
- {
13378
- notifyOnConnect,
13379
- initialScheduleId: scheduleId,
13380
- insertAfter: widgetId
13381
- }
13382
- )
13383
- );
13384
- });
13385
- } catch (err) {
13386
- console.error("[ow:scheduling] render threw", err);
13387
- container.remove();
13388
- return false;
13389
- }
12570
+ const root = (0, import_client2.createRoot)(container);
12571
+ (0, import_react_dom3.flushSync)(() => {
12572
+ root.render(
12573
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12574
+ SchedulingWidget,
12575
+ {
12576
+ notifyOnConnect,
12577
+ initialScheduleId: scheduleId,
12578
+ insertAfter: effectiveInsertAfter
12579
+ }
12580
+ )
12581
+ );
12582
+ });
13390
12583
  const tracker = getSectionsTracker();
13391
12584
  let sections = [];
13392
12585
  try {
@@ -13394,12 +12587,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13394
12587
  } catch {
13395
12588
  }
13396
12589
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
13397
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
12590
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
13398
12591
  sections.push({
13399
12592
  type: "scheduling",
13400
- insertAfter: widgetId,
13401
- anchorId,
13402
- beforeId: beforeId ?? null,
12593
+ insertAfter: effectiveInsertAfter,
13403
12594
  pagePath: window.location.pathname,
13404
12595
  ...scheduleId ? { scheduleId } : {}
13405
12596
  });
@@ -13413,8 +12604,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
13413
12604
  for (let i = pending.length - 1; i >= 0; i--) {
13414
12605
  const entry = pending[i];
13415
12606
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
13416
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
13417
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
12607
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
13418
12608
  pending.splice(i, 1);
13419
12609
  }
13420
12610
  }
@@ -13558,13 +12748,6 @@ function isInsideLinkEditor(target) {
13558
12748
  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"]')
13559
12749
  );
13560
12750
  }
13561
- function isInsideFloatingPanel(target) {
13562
- return Boolean(target.closest("[data-ohw-floating-panel]"));
13563
- }
13564
- function isPointOverFloatingPanel(clientX, clientY) {
13565
- const el = document.elementFromPoint(clientX, clientY);
13566
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
13567
- }
13568
12751
  function getHrefKeyFromElement(el) {
13569
12752
  if (!el) return null;
13570
12753
  const anchor = el.closest("[data-ohw-href-key]");
@@ -13612,7 +12795,8 @@ function isNavItemPointerTarget(el) {
13612
12795
  function getNavigationItemAnchor(el) {
13613
12796
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
13614
12797
  if (!anchor) return null;
13615
- if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
12798
+ if (!anchor.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !anchor.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !getSocialItem(anchor))
12799
+ return null;
13616
12800
  if (!isNavItemPointerTarget(anchor)) return null;
13617
12801
  return anchor;
13618
12802
  }
@@ -13802,7 +12986,7 @@ function getNavigationSelectionParent(el) {
13802
12986
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
13803
12987
  return getFooterLinksContainer();
13804
12988
  }
13805
- 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)) {
12989
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
13806
12990
  return getNavigationRoot(el);
13807
12991
  }
13808
12992
  return null;
@@ -14048,7 +13232,7 @@ function EditGlowChrome({
14048
13232
  hideHandle = false
14049
13233
  }) {
14050
13234
  const GAP = SELECTION_CHROME_GAP2;
14051
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
13235
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
14052
13236
  "div",
14053
13237
  {
14054
13238
  ref: elRef,
@@ -14063,7 +13247,7 @@ function EditGlowChrome({
14063
13247
  zIndex: 2147483646
14064
13248
  },
14065
13249
  children: [
14066
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13250
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14067
13251
  "div",
14068
13252
  {
14069
13253
  style: {
@@ -14076,7 +13260,7 @@ function EditGlowChrome({
14076
13260
  }
14077
13261
  }
14078
13262
  ),
14079
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13263
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14080
13264
  "div",
14081
13265
  {
14082
13266
  "data-ohw-drag-handle-container": "",
@@ -14088,7 +13272,7 @@ function EditGlowChrome({
14088
13272
  transform: "translate(calc(-100% - 7px), -50%)",
14089
13273
  pointerEvents: dragDisabled ? "none" : "auto"
14090
13274
  },
14091
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13275
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14092
13276
  DragHandle,
14093
13277
  {
14094
13278
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -14298,7 +13482,7 @@ function FloatingToolbar({
14298
13482
  return () => ro.disconnect();
14299
13483
  }, [showEditLink, activeCommands]);
14300
13484
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
14301
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13485
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14302
13486
  "div",
14303
13487
  {
14304
13488
  ref: setRefs,
@@ -14310,12 +13494,12 @@ function FloatingToolbar({
14310
13494
  zIndex: 2147483647,
14311
13495
  pointerEvents: "auto"
14312
13496
  },
14313
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
14314
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
14315
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
13497
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(CustomToolbar, { children: [
13498
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react16.default.Fragment, { children: [
13499
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CustomToolbarDivider, {}),
14316
13500
  btns.map((btn) => {
14317
13501
  const isActive = activeCommands.has(btn.cmd);
14318
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13502
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14319
13503
  CustomToolbarButton,
14320
13504
  {
14321
13505
  title: btn.title,
@@ -14324,7 +13508,7 @@ function FloatingToolbar({
14324
13508
  e.preventDefault();
14325
13509
  onCommand(btn.cmd);
14326
13510
  },
14327
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13511
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14328
13512
  "svg",
14329
13513
  {
14330
13514
  width: "16",
@@ -14345,7 +13529,7 @@ function FloatingToolbar({
14345
13529
  );
14346
13530
  })
14347
13531
  ] }, gi)),
14348
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13532
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14349
13533
  CustomToolbarButton,
14350
13534
  {
14351
13535
  type: "button",
@@ -14359,7 +13543,7 @@ function FloatingToolbar({
14359
13543
  e.preventDefault();
14360
13544
  e.stopPropagation();
14361
13545
  },
14362
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
13546
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react16.Link, { className: "size-4 shrink-0", "aria-hidden": true })
14363
13547
  }
14364
13548
  ) : null
14365
13549
  ] })
@@ -14376,7 +13560,7 @@ function StateToggle({
14376
13560
  states,
14377
13561
  onStateChange
14378
13562
  }) {
14379
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13563
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14380
13564
  ToggleGroup,
14381
13565
  {
14382
13566
  "data-ohw-state-toggle": "",
@@ -14390,12 +13574,11 @@ function StateToggle({
14390
13574
  left: rect.right - 8,
14391
13575
  transform: "translateX(-100%)"
14392
13576
  },
14393
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
13577
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14394
13578
  }
14395
13579
  );
14396
13580
  }
14397
13581
  var contentCache = /* @__PURE__ */ new Map();
14398
- var fetchedContentPaths = /* @__PURE__ */ new Set();
14399
13582
  function resolveSubdomain(subdomainFromQuery) {
14400
13583
  if (subdomainFromQuery) return subdomainFromQuery;
14401
13584
  if (typeof window !== "undefined") {
@@ -14490,14 +13673,8 @@ function OhhwellsBridge() {
14490
13673
  });
14491
13674
  const selectFrameRef = (0, import_react16.useRef)(() => {
14492
13675
  });
14493
- const selectLogoRef = (0, import_react16.useRef)(() => {
14494
- });
14495
- const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
14496
- });
14497
13676
  const deselectRef = (0, import_react16.useRef)(() => {
14498
13677
  });
14499
- const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
14500
- });
14501
13678
  const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
14502
13679
  });
14503
13680
  const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
@@ -14558,6 +13735,11 @@ function OhhwellsBridge() {
14558
13735
  const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
14559
13736
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
14560
13737
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
13738
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
13739
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
13740
+ floatingPanelOpenRef.current = floatingPanel !== null;
13741
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
13742
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
14561
13743
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
14562
13744
  const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
14563
13745
  const footerDragRef = (0, import_react16.useRef)(null);
@@ -14572,16 +13754,7 @@ function OhhwellsBridge() {
14572
13754
  const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
14573
13755
  const editContentRef = (0, import_react16.useRef)({});
14574
13756
  const aiSectionsRef = (0, import_react16.useRef)("");
14575
- const brandKitRef = (0, import_react16.useRef)("");
14576
- const stylesRef = (0, import_react16.useRef)("");
14577
13757
  const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
14578
- const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
14579
- const floatingPanelOpenRef = (0, import_react16.useRef)(false);
14580
- const setFloatingPanelRef = (0, import_react16.useRef)(setFloatingPanel);
14581
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
14582
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
14583
- const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
14584
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
14585
13758
  const [sitePages, setSitePages] = (0, import_react16.useState)([]);
14586
13759
  const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
14587
13760
  const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
@@ -14590,18 +13763,7 @@ function OhhwellsBridge() {
14590
13763
  const linkPopoverOpenRef = (0, import_react16.useRef)(false);
14591
13764
  const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
14592
13765
  setLinkPopoverRef.current = setLinkPopover;
14593
- setFloatingPanelRef.current = setFloatingPanel;
14594
13766
  linkPopoverSessionRef.current = linkPopover;
14595
- floatingPanelOpenRef.current = Boolean(floatingPanel);
14596
- (0, import_react16.useEffect)(() => {
14597
- const syncViewport = () => {
14598
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
14599
- setEditorViewport((prev) => prev === next ? prev : next);
14600
- };
14601
- syncViewport();
14602
- window.addEventListener("resize", syncViewport);
14603
- return () => window.removeEventListener("resize", syncViewport);
14604
- }, []);
14605
13767
  const {
14606
13768
  navDragRef,
14607
13769
  navDropSlots,
@@ -14826,8 +13988,6 @@ function OhhwellsBridge() {
14826
13988
  setHoveredNavContainerRect(null);
14827
13989
  hoveredItemElRef.current = null;
14828
13990
  setHoveredItemRect(null);
14829
- setFloatingPanel(null);
14830
- setLogoSizeDraft(null);
14831
13991
  if (!activeElRef.current) {
14832
13992
  setNavGroupForceOpen(null, false);
14833
13993
  setToolbarRect(null);
@@ -15533,8 +14693,6 @@ function OhhwellsBridge() {
15533
14693
  setToolbarRect(anchor.getBoundingClientRect());
15534
14694
  setToolbarShowEditLink(false);
15535
14695
  setActiveCommands(/* @__PURE__ */ new Set());
15536
- setFloatingPanel(null);
15537
- setLogoSizeDraft(null);
15538
14696
  }, [deactivate, markSelected]);
15539
14697
  const selectFrame = (0, import_react16.useCallback)((el) => {
15540
14698
  if (!isNavigationContainer(el)) return;
@@ -15584,51 +14742,7 @@ function OhhwellsBridge() {
15584
14742
  setToolbarRect(el.getBoundingClientRect());
15585
14743
  setToolbarShowEditLink(false);
15586
14744
  setActiveCommands(/* @__PURE__ */ new Set());
15587
- setFloatingPanel(null);
15588
- setLogoSizeDraft(null);
15589
14745
  }, [deactivate, markSelected, postToParent2]);
15590
- const selectLogo = (0, import_react16.useCallback)(
15591
- (logoEl) => {
15592
- if (activeElRef.current) deactivate();
15593
- selectedElRef.current = logoEl;
15594
- selectedHrefKeyRef.current = null;
15595
- selectedFooterColAttrRef.current = null;
15596
- markSelected(logoEl);
15597
- setSelectedIsCta(false);
15598
- setSelectedIsSocial(false);
15599
- setSelectedIsSocialsRow(false);
15600
- clearHrefKeyHover(logoEl);
15601
- hoveredNavContainerRef.current = null;
15602
- setHoveredNavContainerRect(null);
15603
- setHoveredItemRect(null);
15604
- hoveredItemElRef.current = null;
15605
- siblingHintElRef.current = null;
15606
- setSiblingHintRect(null);
15607
- setSiblingHintRects([]);
15608
- setIsItemDragging(false);
15609
- setReorderHrefKey(null);
15610
- setReorderDragDisabled(false);
15611
- setIsFooterFrameSelection(false);
15612
- setToolbarVariant("logo");
15613
- setToolbarRect(getLogoInteractionRect(logoEl));
15614
- setToolbarShowEditLink(false);
15615
- setActiveCommands(/* @__PURE__ */ new Set());
15616
- },
15617
- [deactivate, markSelected]
15618
- );
15619
- const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
15620
- const placement = getLogoPlacement(logoEl);
15621
- const draft = readLogoSizeState(editContentRef.current, placement);
15622
- setLogoSizeDraft(draft);
15623
- setParentScrollSnap(parentScrollRef.current);
15624
- setFloatingPanel({
15625
- key: `logo-size:${placement}`,
15626
- title: "Logo",
15627
- context: placement === "navbar" ? "Navbar" : "Footer",
15628
- kind: "logo-size",
15629
- placement
15630
- });
15631
- }, []);
15632
14746
  const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
15633
14747
  setParentScrollSnap(parentScrollRef.current);
15634
14748
  setFloatingPanel({
@@ -15664,53 +14778,13 @@ function OhhwellsBridge() {
15664
14778
  );
15665
14779
  const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
15666
14780
  setFloatingPanel(null);
15667
- setLogoSizeDraft(null);
15668
14781
  }, []);
14782
+ const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(closeFloatingPanelOnly);
14783
+ closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
15669
14784
  const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
15670
14785
  setFloatingPanel(null);
15671
- setLogoSizeDraft(null);
15672
14786
  deselectRef.current();
15673
14787
  }, []);
15674
- const persistLogoSizeDraft = (0, import_react16.useCallback)(
15675
- (placement, draft) => {
15676
- const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
15677
- const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
15678
- const nodes = [
15679
- { key: desktopKey, text: String(draft.desktopPx) }
15680
- ];
15681
- if (draft.mobileFollowing) {
15682
- nodes.push({ key: mobileKey, text: "" });
15683
- } else {
15684
- nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
15685
- }
15686
- editContentRef.current = {
15687
- ...editContentRef.current,
15688
- [desktopKey]: String(draft.desktopPx),
15689
- [mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
15690
- };
15691
- applyLogoSizeToPlacement(
15692
- placement,
15693
- draft.desktopPx,
15694
- draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
15695
- draft.mobileFollowing
15696
- );
15697
- postToParent2({ type: "ow:change", nodes });
15698
- requestAnimationFrame(() => {
15699
- const selected = selectedElRef.current;
15700
- if (!selected || toolbarVariantRef.current !== "logo") return;
15701
- const rect = getLogoInteractionRect(selected);
15702
- setToolbarRect(rect);
15703
- if (glowElRef.current) {
15704
- const GAP = SELECTION_CHROME_GAP2;
15705
- glowElRef.current.style.top = `${rect.top - GAP}px`;
15706
- glowElRef.current.style.left = `${rect.left - GAP}px`;
15707
- glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
15708
- glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
15709
- }
15710
- });
15711
- },
15712
- [postToParent2]
15713
- );
15714
14788
  const activate = (0, import_react16.useCallback)((el, options) => {
15715
14789
  if (activeElRef.current === el) return;
15716
14790
  if (isIconEditable(el)) return;
@@ -15791,10 +14865,7 @@ function OhhwellsBridge() {
15791
14865
  deactivateRef.current = deactivate;
15792
14866
  selectRef.current = select;
15793
14867
  selectFrameRef.current = selectFrame;
15794
- selectLogoRef.current = selectLogo;
15795
- openLogoSizePanelRef.current = openLogoSizePanel;
15796
14868
  deselectRef.current = deselect;
15797
- closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
15798
14869
  const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
15799
14870
  (0, import_react16.useEffect)(() => {
15800
14871
  if (!isEditMode) {
@@ -15833,23 +14904,9 @@ function OhhwellsBridge() {
15833
14904
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
15834
14905
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
15835
14906
  }
15836
- if (typeof content[BRAND_KIT_KEY] === "string") {
15837
- brandKitRef.current = content[BRAND_KIT_KEY];
15838
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
15839
- }
15840
- if (typeof content[STYLE_STORE_KEY] === "string") {
15841
- stylesRef.current = content[STYLE_STORE_KEY];
15842
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
15843
- }
15844
- applyBrandChrome(content);
15845
14907
  for (const [key, val] of Object.entries(content)) {
15846
14908
  if (key === "__ohw_sections") continue;
15847
14909
  if (key === AI_SECTIONS_KEY) continue;
15848
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15849
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15850
- if (key === BRAND_KIT_KEY) continue;
15851
- if (key === STYLE_STORE_KEY) continue;
15852
- if (BRAND_CHROME_KEYS.has(key)) continue;
15853
14910
  if (applyVideoSettingNode(key, val)) continue;
15854
14911
  if (applyCarouselNode(key, val)) continue;
15855
14912
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15884,8 +14941,6 @@ function OhhwellsBridge() {
15884
14941
  });
15885
14942
  applyLinkByKey(key, val);
15886
14943
  }
15887
- applyLogoFromContent(content);
15888
- applyLogoSizes(content);
15889
14944
  reconcileNavbarItemsFromContent(content);
15890
14945
  reconcileFooterOrderFromContent(content);
15891
14946
  reconcileSocialsFromContent(content);
@@ -15906,9 +14961,7 @@ function OhhwellsBridge() {
15906
14961
  let cancelled = false;
15907
14962
  setFetchState("loading");
15908
14963
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15909
- const initialPath = pathname;
15910
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
15911
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
14964
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15912
14965
  if (cancelled) return;
15913
14966
  const content = data?.content ?? {};
15914
14967
  contentCache.set(subdomain, content);
@@ -15932,21 +14985,8 @@ function OhhwellsBridge() {
15932
14985
  initSectionInstancesFromContent(content, window.location.pathname);
15933
14986
  observer?.disconnect();
15934
14987
  try {
15935
- applyBrandChrome(content);
15936
- if (typeof content[BRAND_KIT_KEY] === "string") {
15937
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
15938
- }
15939
- if (typeof content[STYLE_STORE_KEY] === "string") {
15940
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
15941
- }
15942
14988
  for (const [key, val] of Object.entries(content)) {
15943
14989
  if (key === "__ohw_sections") continue;
15944
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15945
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15946
- if (key === BRAND_KIT_KEY) continue;
15947
- if (key === STYLE_STORE_KEY) continue;
15948
- if (key === STYLE_STORE_KEY) continue;
15949
- if (BRAND_CHROME_KEYS.has(key)) continue;
15950
14990
  if (applyVideoSettingNode(key, val)) continue;
15951
14991
  if (applyCarouselNode(key, val)) continue;
15952
14992
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15967,7 +15007,6 @@ function OhhwellsBridge() {
15967
15007
  });
15968
15008
  applyLinkByKey(key, val);
15969
15009
  }
15970
- applyLogoFromContent(content);
15971
15010
  reconcileNavbarItemsFromContent(content);
15972
15011
  reconcileFooterOrderFromContent(content);
15973
15012
  reconcileSocialsFromContent(content);
@@ -15982,17 +15021,6 @@ function OhhwellsBridge() {
15982
15021
  debounceTimer = setTimeout(applyFromCache, 150);
15983
15022
  };
15984
15023
  applyFromCache();
15985
- const pathCacheKey = `${subdomain}::${pathname}`;
15986
- if (!fetchedContentPaths.has(pathCacheKey)) {
15987
- fetchedContentPaths.add(pathCacheKey);
15988
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15989
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15990
- if (!data?.content) return;
15991
- contentCache.set(subdomain, data.content);
15992
- applyFromCache();
15993
- }).catch(() => {
15994
- });
15995
- }
15996
15024
  observer = new MutationObserver(scheduleApply);
15997
15025
  observer.observe(document.body, { childList: true, subtree: true });
15998
15026
  return () => {
@@ -16086,31 +15114,26 @@ function OhhwellsBridge() {
16086
15114
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
16087
15115
  (0, import_react16.useEffect)(() => {
16088
15116
  if (!isEditMode) return;
16089
- let lastPosted = 0;
16090
15117
  const measure = () => {
16091
15118
  const h = document.body.scrollHeight;
16092
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
16093
- lastPosted = h;
16094
- postToParent2({ type: "ow:height", height: h });
16095
- }
16096
- };
16097
- let raf = null;
16098
- const schedule = () => {
16099
- if (raf != null) return;
16100
- raf = requestAnimationFrame(() => {
16101
- raf = null;
16102
- measure();
16103
- });
15119
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
16104
15120
  };
16105
15121
  const t1 = setTimeout(measure, 50);
16106
15122
  const t2 = setTimeout(measure, 500);
16107
- const ro = new ResizeObserver(schedule);
16108
- ro.observe(document.body);
15123
+ let lastWidth = window.innerWidth;
15124
+ let resizeTimer = null;
15125
+ const handleResize = () => {
15126
+ if (window.innerWidth === lastWidth) return;
15127
+ lastWidth = window.innerWidth;
15128
+ if (resizeTimer) clearTimeout(resizeTimer);
15129
+ resizeTimer = setTimeout(measure, 150);
15130
+ };
15131
+ window.addEventListener("resize", handleResize);
16109
15132
  return () => {
16110
15133
  clearTimeout(t1);
16111
15134
  clearTimeout(t2);
16112
- if (raf != null) cancelAnimationFrame(raf);
16113
- ro.disconnect();
15135
+ if (resizeTimer) clearTimeout(resizeTimer);
15136
+ window.removeEventListener("resize", handleResize);
16114
15137
  };
16115
15138
  }, [pathname, isEditMode, postToParent2]);
16116
15139
  (0, import_react16.useEffect)(() => {
@@ -16260,12 +15283,10 @@ function OhhwellsBridge() {
16260
15283
  return;
16261
15284
  }
16262
15285
  const target = e.target;
16263
- if (target.closest("[data-ohw-ai-review]")) return;
16264
15286
  if (target.closest("[data-ohw-toolbar]")) return;
16265
15287
  if (target.closest("[data-ohw-state-toggle]")) return;
16266
15288
  if (target.closest("[data-ohw-max-badge]")) return;
16267
15289
  if (isInsideLinkEditor(target)) return;
16268
- if (isInsideFloatingPanel(target)) return;
16269
15290
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
16270
15291
  const beneath = document.elementsFromPoint(e.clientX, e.clientY).find(
16271
15292
  (el) => el instanceof HTMLElement && !el.closest("[data-ohw-bridge-root]") && el.closest("[data-ohw-section]") != null
@@ -16333,15 +15354,9 @@ function OhhwellsBridge() {
16333
15354
  if (logoEl) {
16334
15355
  e.preventDefault();
16335
15356
  e.stopPropagation();
16336
- if (!logoHasUploadedImage(logoEl)) {
16337
- deselectRef.current();
16338
- deactivateRef.current();
16339
- const identity = readLogoIdentityFromDom();
16340
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
16341
- return;
16342
- }
16343
- selectLogoRef.current(logoEl);
16344
- openLogoSizePanelRef.current(logoEl);
15357
+ deselectRef.current();
15358
+ deactivateRef.current();
15359
+ postToParentRef.current({ type: "ow:open-logo-settings" });
16345
15360
  return;
16346
15361
  }
16347
15362
  const editable = target.closest("[data-ohw-editable]");
@@ -16496,12 +15511,10 @@ function OhhwellsBridge() {
16496
15511
  };
16497
15512
  const handleDblClick = (e) => {
16498
15513
  const target = e.target;
16499
- if (target.closest("[data-ohw-ai-review]")) return;
16500
15514
  if (target.closest("[data-ohw-toolbar]")) return;
16501
15515
  if (target.closest("[data-ohw-state-toggle]")) return;
16502
15516
  if (target.closest("[data-ohw-max-badge]")) return;
16503
15517
  if (isInsideLinkEditor(target)) return;
16504
- if (isInsideFloatingPanel(target)) return;
16505
15518
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
16506
15519
  return;
16507
15520
  }
@@ -16529,14 +15542,11 @@ function OhhwellsBridge() {
16529
15542
  setHoveredNavContainerRect(null);
16530
15543
  return;
16531
15544
  }
16532
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
15545
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
16533
15546
  hoveredItemElRef.current = null;
16534
15547
  setHoveredItemRect(null);
16535
15548
  hoveredNavContainerRef.current = null;
16536
15549
  setHoveredNavContainerRect(null);
16537
- siblingHintElRef.current = null;
16538
- setSiblingHintRect(null);
16539
- setSiblingHintRects([]);
16540
15550
  return;
16541
15551
  }
16542
15552
  {
@@ -16581,7 +15591,7 @@ function OhhwellsBridge() {
16581
15591
  setHoveredNavContainerRect(null);
16582
15592
  if (selectedElRef.current === logoEl) return;
16583
15593
  hoveredItemElRef.current = logoEl;
16584
- setHoveredItemRect(getLogoInteractionRect(logoEl));
15594
+ setHoveredItemRect(logoEl.getBoundingClientRect());
16585
15595
  return;
16586
15596
  }
16587
15597
  const navAnchor = getNavigationItemAnchor(target);
@@ -16625,6 +15635,7 @@ function OhhwellsBridge() {
16625
15635
  hoveredNavContainerRef.current = null;
16626
15636
  setHoveredNavContainerRect(null);
16627
15637
  hoveredItemElRef.current = editable;
15638
+ setHoveredItemRect(editable.getBoundingClientRect());
16628
15639
  }
16629
15640
  }
16630
15641
  }
@@ -16832,7 +15843,7 @@ function OhhwellsBridge() {
16832
15843
  setHoveredNavContainerRect(null);
16833
15844
  if (selectedElRef.current !== logo) {
16834
15845
  hoveredItemElRef.current = logo;
16835
- setHoveredItemRect(getLogoInteractionRect(logo));
15846
+ setHoveredItemRect(logo.getBoundingClientRect());
16836
15847
  }
16837
15848
  return;
16838
15849
  }
@@ -16921,7 +15932,7 @@ function OhhwellsBridge() {
16921
15932
  }
16922
15933
  };
16923
15934
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
16924
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
15935
+ if (linkPopoverOpenRef.current) {
16925
15936
  if (hoveredImageRef.current) {
16926
15937
  hoveredImageRef.current = null;
16927
15938
  hoveredImageHasTextOverlapRef.current = false;
@@ -17175,7 +16186,7 @@ function OhhwellsBridge() {
17175
16186
  }
17176
16187
  };
17177
16188
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
17178
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
16189
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17179
16190
  if (activeStateElRef.current) {
17180
16191
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
17181
16192
  activeStateElRef.current = null;
@@ -17241,21 +16252,16 @@ function OhhwellsBridge() {
17241
16252
  setSectionGap(null);
17242
16253
  }
17243
16254
  };
16255
+ const pointOwnedByFloatingPanel = (clientX, clientY) => {
16256
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return true;
16257
+ const panel = document.querySelector("[data-ohw-floating-panel]");
16258
+ if (!panel) return false;
16259
+ const rect = panel.getBoundingClientRect();
16260
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
16261
+ };
17244
16262
  const handleMouseMove = (e) => {
17245
16263
  const { clientX, clientY } = e;
17246
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17247
- hoveredItemElRef.current = null;
17248
- setHoveredItemRect(null);
17249
- hoveredNavContainerRef.current = null;
17250
- setHoveredNavContainerRect(null);
17251
- siblingHintElRef.current = null;
17252
- setSiblingHintRect(null);
17253
- setSiblingHintRects([]);
17254
- dismissImageHover();
17255
- clearImageHover();
17256
- setSectionGap(null);
17257
- return;
17258
- }
16264
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17259
16265
  probeSectionGapAt(clientX, clientY);
17260
16266
  probeImageAt(clientX, clientY);
17261
16267
  probeHoverCardsAt(clientX, clientY);
@@ -17264,11 +16270,7 @@ function OhhwellsBridge() {
17264
16270
  if (e.data?.type !== "ow:pointer-sync") return;
17265
16271
  const { clientX, clientY } = e.data;
17266
16272
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
17267
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17268
- dismissImageHover();
17269
- clearImageHover();
17270
- return;
17271
- }
16273
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17272
16274
  probeSectionGapAt(clientX, clientY);
17273
16275
  probeImageAt(clientX, clientY);
17274
16276
  probeHoverCardsAt(clientX, clientY);
@@ -17518,15 +16520,6 @@ function OhhwellsBridge() {
17518
16520
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
17519
16521
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
17520
16522
  }
17521
- if (typeof content[BRAND_KIT_KEY] === "string") {
17522
- brandKitRef.current = content[BRAND_KIT_KEY];
17523
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
17524
- }
17525
- if (typeof content[STYLE_STORE_KEY] === "string") {
17526
- stylesRef.current = content[STYLE_STORE_KEY];
17527
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17528
- }
17529
- applyBrandChrome(content);
17530
16523
  let sectionsJson = null;
17531
16524
  for (const [key, val] of Object.entries(content)) {
17532
16525
  if (key === "__ohw_sections") {
@@ -17534,11 +16527,6 @@ function OhhwellsBridge() {
17534
16527
  continue;
17535
16528
  }
17536
16529
  if (key === AI_SECTIONS_KEY) continue;
17537
- if (key === LOGO_PLACEHOLDER_KEY) continue;
17538
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
17539
- if (key === BRAND_KIT_KEY) continue;
17540
- if (key === STYLE_STORE_KEY) continue;
17541
- if (BRAND_CHROME_KEYS.has(key)) continue;
17542
16530
  if (applyVideoSettingNode(key, val)) continue;
17543
16531
  if (applyCarouselNode(key, val)) continue;
17544
16532
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -17558,8 +16546,6 @@ function OhhwellsBridge() {
17558
16546
  });
17559
16547
  applyLinkByKey(key, val);
17560
16548
  }
17561
- applyLogoFromContent(content);
17562
- applyLogoSizes(content);
17563
16549
  if (sectionsJson) {
17564
16550
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
17565
16551
  sectionsLoadedRef.current = true;
@@ -17575,58 +16561,6 @@ function OhhwellsBridge() {
17575
16561
  if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
17576
16562
  postToParentRef.current({ type: "ow:hydrate-done" });
17577
16563
  };
17578
- const handleUpdateLogoIdentity = (e) => {
17579
- if (e.data?.type !== "ow:update-logo-identity") return;
17580
- const rawText = typeof e.data.text === "string" ? e.data.text : "";
17581
- const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
17582
- const href = typeof e.data.href === "string" ? e.data.href : void 0;
17583
- const imageProvided = "image" in e.data;
17584
- const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
17585
- let isPlaceholder = e.data.isPlaceholder !== false;
17586
- if (imageUrl) isPlaceholder = false;
17587
- else if (imageProvided && imageUrl === null) {
17588
- isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
17589
- }
17590
- const display = applyLogoIdentity(rawText, isPlaceholder);
17591
- const displayAlt = resolveLogoDisplayText(alt || display);
17592
- if (imageUrl !== void 0) {
17593
- applyLogoImage(imageUrl, displayAlt);
17594
- } else {
17595
- for (const key of LOGO_IMAGE_KEYS) {
17596
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
17597
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
17598
- if (img) img.alt = displayAlt;
17599
- });
17600
- }
17601
- }
17602
- if (href !== void 0) {
17603
- applyLogoHref(href);
17604
- applyLinkByKey("nav-logo-href", href);
17605
- applyLinkByKey("footer-logo-href", href);
17606
- applyLinkByKey("logo-href", href);
17607
- }
17608
- const nodes = [
17609
- ...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
17610
- { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
17611
- { key: LOGO_ALT_KEY, text: displayAlt }
17612
- ];
17613
- if (imageUrl !== void 0) {
17614
- if (imageUrl) {
17615
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
17616
- } else {
17617
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
17618
- }
17619
- }
17620
- if (href !== void 0) {
17621
- for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
17622
- }
17623
- editContentRef.current = {
17624
- ...editContentRef.current,
17625
- ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
17626
- };
17627
- applyLogoSizes(editContentRef.current);
17628
- postToParentRef.current({ type: "ow:change", nodes });
17629
- };
17630
16564
  window.addEventListener("message", handleHydrate);
17631
16565
  const postAiSectionsChanged = () => {
17632
16566
  postToParentRef.current({
@@ -17640,10 +16574,7 @@ function OhhwellsBridge() {
17640
16574
  const payload = e.data.payload;
17641
16575
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
17642
16576
  const previous = aiSectionsRef.current;
17643
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
17644
- ...payload,
17645
- path: payload.path ?? window.location.pathname
17646
- });
16577
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
17647
16578
  const nextValue = serializeAiSectionsState(nextState);
17648
16579
  aiSectionsRef.current = nextValue;
17649
16580
  applyAiSectionsToDom(nextState);
@@ -17680,42 +16611,12 @@ function OhhwellsBridge() {
17680
16611
  const value = typeof e.data.value === "string" ? e.data.value : "";
17681
16612
  aiSectionsRef.current = value;
17682
16613
  applyAiSectionsToDom(parseAiSectionsState(value));
17683
- applyStylesToDom(parseStyleStore(stylesRef.current));
17684
16614
  const restoredHeight = document.documentElement.scrollHeight;
17685
16615
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
17686
16616
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
17687
16617
  postAiSectionsChanged();
17688
16618
  };
17689
16619
  window.addEventListener("message", handleAiSetSections);
17690
- const handleAiSetBrand = (e) => {
17691
- if (e.data?.type !== "ow:ai-set-brand") return;
17692
- const value = typeof e.data.value === "string" ? e.data.value : "";
17693
- const previous = brandKitRef.current;
17694
- brandKitRef.current = value;
17695
- applyBrandToDom(parseBrandKit(value));
17696
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
17697
- applyStylesToDom(parseStyleStore(stylesRef.current));
17698
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
17699
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
17700
- };
17701
- window.addEventListener("message", handleAiSetBrand);
17702
- const handleAiSetStyles = (e) => {
17703
- if (e.data?.type !== "ow:ai-set-styles") return;
17704
- const value = typeof e.data.value === "string" ? e.data.value : "";
17705
- const previous = stylesRef.current;
17706
- stylesRef.current = value;
17707
- applyStylesToDom(parseStyleStore(value));
17708
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
17709
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
17710
- };
17711
- window.addEventListener("message", handleAiSetStyles);
17712
- const handleGetBrand = (e) => {
17713
- if (e.data?.type !== "ow:get-brand") return;
17714
- const template = deriveTemplateBrand();
17715
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
17716
- postToParentRef.current({ type: "ow:brand-value", value });
17717
- };
17718
- window.addEventListener("message", handleGetBrand);
17719
16620
  const handleDeactivate = (e) => {
17720
16621
  if (e.data?.type !== "ow:deactivate") return;
17721
16622
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -17724,12 +16625,6 @@ function OhhwellsBridge() {
17724
16625
  closeLinkPopoverRef.current();
17725
16626
  return;
17726
16627
  }
17727
- if (floatingPanelOpenRef.current) {
17728
- setFloatingPanelRef.current(null);
17729
- deselectRef.current();
17730
- deactivateRef.current();
17731
- return;
17732
- }
17733
16628
  deselectRef.current();
17734
16629
  deactivateRef.current();
17735
16630
  };
@@ -17783,10 +16678,6 @@ function OhhwellsBridge() {
17783
16678
  return;
17784
16679
  }
17785
16680
  if (selectedElRef.current) {
17786
- if (toolbarVariantRef.current === "logo") {
17787
- deselectRef.current();
17788
- return;
17789
- }
17790
16681
  if (toolbarVariantRef.current === "select-frame") {
17791
16682
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
17792
16683
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -17826,10 +16717,6 @@ function OhhwellsBridge() {
17826
16717
  return;
17827
16718
  }
17828
16719
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
17829
- if (toolbarVariantRef.current === "logo") {
17830
- deselectRef.current();
17831
- return;
17832
- }
17833
16720
  if (toolbarVariantRef.current === "select-frame") {
17834
16721
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
17835
16722
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -17907,8 +16794,7 @@ function OhhwellsBridge() {
17907
16794
  const handleScroll = () => {
17908
16795
  const focusEl = activeElRef.current ?? selectedElRef.current;
17909
16796
  if (focusEl) {
17910
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
17911
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
16797
+ const r2 = activeElRef.current ? getEditMeasureEl(activeElRef.current).getBoundingClientRect() : focusEl.getBoundingClientRect();
17912
16798
  applyToolbarPos(r2);
17913
16799
  setToolbarRect(r2);
17914
16800
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -17918,9 +16804,7 @@ function OhhwellsBridge() {
17918
16804
  setToggleState((prev) => prev ? { ...prev, rect } : null);
17919
16805
  }
17920
16806
  if (hoveredItemElRef.current) {
17921
- const hoverEl = hoveredItemElRef.current;
17922
- const logo = getLogoElement(hoverEl);
17923
- setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
16807
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
17924
16808
  }
17925
16809
  if (hoveredNavContainerRef.current) {
17926
16810
  setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
@@ -17964,12 +16848,6 @@ function OhhwellsBridge() {
17964
16848
  if (aiSectionsRef.current) {
17965
16849
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
17966
16850
  }
17967
- if (stylesRef.current) {
17968
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
17969
- }
17970
- if (brandKitRef.current) {
17971
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
17972
- }
17973
16851
  postToParentRef.current({ type: "ow:save-result", nodes });
17974
16852
  };
17975
16853
  const handleInsertSection = (e) => {
@@ -17980,12 +16858,8 @@ function OhhwellsBridge() {
17980
16858
  if (inserted) {
17981
16859
  const tracker = getSectionsTracker();
17982
16860
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
17983
- const reportHeight = () => {
17984
- const h = document.body.scrollHeight;
17985
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17986
- };
17987
- reportHeight();
17988
- setTimeout(reportHeight, 500);
16861
+ const h = document.documentElement.scrollHeight;
16862
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17989
16863
  }
17990
16864
  };
17991
16865
  const handleSwitchSchedule = (e) => {
@@ -18178,17 +17052,13 @@ function OhhwellsBridge() {
18178
17052
  if (e.data?.type !== "ow:parent-scroll") return;
18179
17053
  const { iframeOffsetTop, headerH, canvasH } = e.data;
18180
17054
  parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
18181
- if (floatingPanelOpenRef.current) {
18182
- setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
18183
- }
18184
17055
  if (visibleViewportRef.current) {
18185
17056
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
18186
17057
  }
18187
17058
  const focusEl = activeElRef.current ?? selectedElRef.current;
18188
17059
  if (focusEl) {
18189
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
18190
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
18191
- applyToolbarPos(r2);
17060
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
17061
+ applyToolbarPos(measureEl.getBoundingClientRect());
18192
17062
  }
18193
17063
  };
18194
17064
  const handleClickAt = (e) => {
@@ -18221,15 +17091,9 @@ function OhhwellsBridge() {
18221
17091
  return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
18222
17092
  });
18223
17093
  if (logoAtPoint) {
18224
- if (!logoHasUploadedImage(logoAtPoint)) {
18225
- deselectRef.current();
18226
- deactivateRef.current();
18227
- const identity = readLogoIdentityFromDom();
18228
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
18229
- return;
18230
- }
18231
- selectLogoRef.current(logoAtPoint);
18232
- openLogoSizePanelRef.current(logoAtPoint);
17094
+ deselectRef.current();
17095
+ deactivateRef.current();
17096
+ postToParentRef.current({ type: "ow:open-logo-settings" });
18233
17097
  return;
18234
17098
  }
18235
17099
  const textEditable = Array.from(
@@ -18303,14 +17167,6 @@ function OhhwellsBridge() {
18303
17167
  window.addEventListener("message", handleParentScroll);
18304
17168
  window.addEventListener("message", handlePointerSync);
18305
17169
  window.addEventListener("message", handleClickAt);
18306
- window.addEventListener("message", handleUpdateLogoIdentity);
18307
- const handleViewMode = (e) => {
18308
- if (e.data?.type !== "ow:view-mode") return;
18309
- const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
18310
- setEditorViewport(mode);
18311
- applyLogoSizes(editContentRef.current);
18312
- };
18313
- window.addEventListener("message", handleViewMode);
18314
17170
  const handleViewportResize = () => {
18315
17171
  if (visibleViewportRef.current) {
18316
17172
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
@@ -18366,15 +17222,10 @@ function OhhwellsBridge() {
18366
17222
  window.removeEventListener("resize", handleViewportResize);
18367
17223
  window.removeEventListener("message", handlePointerSync);
18368
17224
  window.removeEventListener("message", handleClickAt);
18369
- window.removeEventListener("message", handleUpdateLogoIdentity);
18370
- window.removeEventListener("message", handleViewMode);
18371
17225
  window.removeEventListener("message", handleHydrate);
18372
17226
  window.removeEventListener("message", handleAiApplyTree);
18373
17227
  window.removeEventListener("message", handleAiDeleteSection);
18374
17228
  window.removeEventListener("message", handleAiSetSections);
18375
- window.removeEventListener("message", handleAiSetBrand);
18376
- window.removeEventListener("message", handleAiSetStyles);
18377
- window.removeEventListener("message", handleGetBrand);
18378
17229
  window.removeEventListener("message", handleDeactivate);
18379
17230
  window.removeEventListener("message", handleToastAction);
18380
17231
  window.removeEventListener("message", handleUiEscape);
@@ -18578,7 +17429,7 @@ function OhhwellsBridge() {
18578
17429
  postToParent2({
18579
17430
  type: "ow:ready",
18580
17431
  version: "1",
18581
- bridgeVersion: "0.1.63",
17432
+ bridgeVersion: "0.1.62",
18582
17433
  path: pathname,
18583
17434
  nodes: collectEditableNodes(editContentRef.current),
18584
17435
  sections
@@ -18973,10 +17824,10 @@ function OhhwellsBridge() {
18973
17824
  [postToParent2]
18974
17825
  );
18975
17826
  return bridgeRoot ? (0, import_react_dom4.createPortal)(
18976
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
18977
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
18978
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
18979
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17827
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
17828
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
17829
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
17830
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18980
17831
  MediaOverlay,
18981
17832
  {
18982
17833
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -18987,7 +17838,7 @@ function OhhwellsBridge() {
18987
17838
  },
18988
17839
  `uploading-${key}`
18989
17840
  )),
18990
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17841
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18991
17842
  MediaOverlay,
18992
17843
  {
18993
17844
  hover: mediaHover,
@@ -18996,11 +17847,11 @@ function OhhwellsBridge() {
18996
17847
  onVideoSettingsChange: handleVideoSettingsChange
18997
17848
  }
18998
17849
  ),
18999
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
19000
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
19001
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
19002
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
19003
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17850
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
17851
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
17852
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
17853
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
17854
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19004
17855
  "div",
19005
17856
  {
19006
17857
  className: "pointer-events-none fixed z-2147483646",
@@ -19010,7 +17861,7 @@ function OhhwellsBridge() {
19010
17861
  width: slot.width,
19011
17862
  height: slot.height
19012
17863
  },
19013
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17864
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19014
17865
  DropIndicator,
19015
17866
  {
19016
17867
  direction: slot.direction,
@@ -19021,7 +17872,7 @@ function OhhwellsBridge() {
19021
17872
  },
19022
17873
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
19023
17874
  )),
19024
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17875
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19025
17876
  "div",
19026
17877
  {
19027
17878
  className: "pointer-events-none fixed z-2147483646",
@@ -19031,7 +17882,7 @@ function OhhwellsBridge() {
19031
17882
  width: slot.width,
19032
17883
  height: slot.height
19033
17884
  },
19034
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17885
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19035
17886
  DropIndicator,
19036
17887
  {
19037
17888
  direction: slot.direction,
@@ -19042,11 +17893,11 @@ function OhhwellsBridge() {
19042
17893
  },
19043
17894
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
19044
17895
  )),
19045
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19046
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19047
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19048
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19049
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17896
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
17897
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
17898
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
17899
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
17900
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19050
17901
  FooterContainerChrome,
19051
17902
  {
19052
17903
  rect: toolbarRect,
@@ -19054,7 +17905,7 @@ function OhhwellsBridge() {
19054
17905
  addDisabled: !canAddFooterColumn()
19055
17906
  }
19056
17907
  ),
19057
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17908
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19058
17909
  ItemInteractionLayer,
19059
17910
  {
19060
17911
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -19066,10 +17917,10 @@ function OhhwellsBridge() {
19066
17917
  dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
19067
17918
  onDragHandleDragStart: handleItemDragStart,
19068
17919
  onDragHandleDragEnd: handleItemDragEnd,
19069
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
19070
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
19071
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
19072
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17920
+ onItemPointerDown: handleItemChromePointerDown,
17921
+ onItemClick: handleItemChromeClick,
17922
+ itemDragSurface: !isFooterFrameSelection,
17923
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19073
17924
  ItemActionToolbar,
19074
17925
  {
19075
17926
  onEditLink: openLinkPopoverForSelected,
@@ -19105,8 +17956,8 @@ function OhhwellsBridge() {
19105
17956
  ) : void 0
19106
17957
  }
19107
17958
  ),
19108
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19109
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17959
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
17960
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19110
17961
  EditGlowChrome,
19111
17962
  {
19112
17963
  rect: toolbarRect,
@@ -19116,7 +17967,7 @@ function OhhwellsBridge() {
19116
17967
  hideHandle: isItemDragging
19117
17968
  }
19118
17969
  ),
19119
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17970
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19120
17971
  FloatingToolbar,
19121
17972
  {
19122
17973
  rect: toolbarRect,
@@ -19129,7 +17980,7 @@ function OhhwellsBridge() {
19129
17980
  }
19130
17981
  )
19131
17982
  ] }),
19132
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
17983
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
19133
17984
  "div",
19134
17985
  {
19135
17986
  "data-ohw-max-badge": "",
@@ -19155,7 +18006,7 @@ function OhhwellsBridge() {
19155
18006
  ]
19156
18007
  }
19157
18008
  ),
19158
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18009
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19159
18010
  StateToggle,
19160
18011
  {
19161
18012
  rect: toggleState.rect,
@@ -19164,15 +18015,15 @@ function OhhwellsBridge() {
19164
18015
  onStateChange: handleStateChange
19165
18016
  }
19166
18017
  ),
19167
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
18018
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
19168
18019
  "div",
19169
18020
  {
19170
18021
  "data-ohw-section-insert-line": "",
19171
18022
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
19172
18023
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
19173
18024
  children: [
19174
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19175
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18025
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
18026
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19176
18027
  Badge,
19177
18028
  {
19178
18029
  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",
@@ -19189,11 +18040,11 @@ function OhhwellsBridge() {
19189
18040
  children: "Add Section"
19190
18041
  }
19191
18042
  ),
19192
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
18043
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19193
18044
  ]
19194
18045
  }
19195
18046
  ),
19196
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18047
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19197
18048
  LinkPopover,
19198
18049
  {
19199
18050
  panelRef: linkPopoverPanelRef,
@@ -19210,7 +18061,7 @@ function OhhwellsBridge() {
19210
18061
  },
19211
18062
  linkPopover.key
19212
18063
  ) : null,
19213
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18064
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19214
18065
  FloatingPanel,
19215
18066
  {
19216
18067
  open: true,
@@ -19220,7 +18071,7 @@ function OhhwellsBridge() {
19220
18071
  onPositionChange: setFloatingPanelPos,
19221
18072
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
19222
18073
  onClose: closeFloatingPanelOnly,
19223
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18074
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19224
18075
  SocialsDisplayPanel,
19225
18076
  {
19226
18077
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -19231,115 +18082,11 @@ function OhhwellsBridge() {
19231
18082
  }
19232
18083
  )
19233
18084
  }
19234
- ) : null,
19235
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19236
- FloatingPanel,
19237
- {
19238
- open: true,
19239
- title: floatingPanel.title,
19240
- context: floatingPanel.context,
19241
- position: floatingPanelPos,
19242
- onPositionChange: setFloatingPanelPos,
19243
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
19244
- onClose: closeFloatingPanelAndDeselect,
19245
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19246
- LogoSizePanel,
19247
- {
19248
- viewport: editorViewport,
19249
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
19250
- mobileFollowing: logoSizeDraft.mobileFollowing,
19251
- onSizeChange: (px) => {
19252
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
19253
- ...logoSizeDraft,
19254
- desktopPx: px,
19255
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
19256
- };
19257
- setLogoSizeDraft(next);
19258
- persistLogoSizeDraft(floatingPanel.placement, next);
19259
- },
19260
- onCustomizeMobile: () => {
19261
- const next = {
19262
- ...logoSizeDraft,
19263
- mobileFollowing: false,
19264
- mobilePx: logoSizeDraft.desktopPx
19265
- };
19266
- setLogoSizeDraft(next);
19267
- persistLogoSizeDraft(floatingPanel.placement, next);
19268
- },
19269
- onResetMobile: () => {
19270
- const next = {
19271
- ...logoSizeDraft,
19272
- mobileFollowing: true,
19273
- mobilePx: logoSizeDraft.desktopPx
19274
- };
19275
- setLogoSizeDraft(next);
19276
- persistLogoSizeDraft(floatingPanel.placement, next);
19277
- },
19278
- onUpdateEverywhere: () => {
19279
- const identity = readLogoIdentityFromDom();
19280
- postToParent2({ type: "ow:open-logo-settings", ...identity });
19281
- }
19282
- }
19283
- )
19284
- }
19285
18085
  ) : null
19286
18086
  ] }),
19287
18087
  bridgeRoot
19288
18088
  ) : null;
19289
18089
  }
19290
-
19291
- // src/ui/EmptySection.tsx
19292
- var import_link = __toESM(require("next/link"), 1);
19293
- var import_jsx_runtime34 = require("react/jsx-runtime");
19294
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
19295
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
19296
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19297
- "p",
19298
- {
19299
- style: {
19300
- fontFamily: "var(--brand-font-body)",
19301
- fontSize: "0.75rem",
19302
- fontWeight: 500,
19303
- letterSpacing: "0.15em",
19304
- textTransform: "uppercase",
19305
- color: "var(--brand-accent)",
19306
- marginBottom: "1.5rem"
19307
- },
19308
- 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" }) })
19309
- }
19310
- ),
19311
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19312
- "h1",
19313
- {
19314
- style: {
19315
- fontFamily: "var(--brand-font-heading)",
19316
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
19317
- lineHeight: 1.1,
19318
- letterSpacing: "-0.025em",
19319
- color: "var(--brand-text)",
19320
- marginBottom: "1rem"
19321
- },
19322
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
19323
- children: title
19324
- }
19325
- ),
19326
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19327
- "p",
19328
- {
19329
- style: {
19330
- fontFamily: "var(--brand-font-body)",
19331
- fontSize: "1rem",
19332
- lineHeight: 1.7,
19333
- fontWeight: 300,
19334
- color: "var(--brand-text-muted)",
19335
- maxWidth: "340px"
19336
- },
19337
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
19338
- children: "This page doesn't have any content yet."
19339
- }
19340
- )
19341
- ] });
19342
- }
19343
18090
  // Annotate the CommonJS export names for ESM import in node:
19344
18091
  0 && (module.exports = {
19345
18092
  AI_DEFAULT_BRAND,
@@ -19357,7 +18104,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
19357
18104
  DropdownMenuItem,
19358
18105
  DropdownMenuSeparator,
19359
18106
  DropdownMenuTrigger,
19360
- EmptySection,
19361
18107
  ItemActionToolbar,
19362
18108
  ItemInteractionLayer,
19363
18109
  LinkEditorPanel,