@ohhwells/bridge 0.1.61-next.172 → 0.1.61

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,272 +191,6 @@ function deleteSectionFromState(state, sectionId) {
193
191
  return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
194
192
  }
195
193
 
196
- // src/lib/brand-chrome.ts
197
- var BRAND_NAME_KEY = "__ohw_brand_name";
198
- var BRAND_TITLE_KEY = "__ohw_site_title";
199
- var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
200
- var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
201
- BRAND_NAME_KEY,
202
- BRAND_TITLE_KEY,
203
- BRAND_FAVICON_LETTER_KEY
204
- ]);
205
- function upsertMeta(selector, attr, token, value) {
206
- let el = document.head.querySelector(selector);
207
- if (!el) {
208
- el = document.createElement("meta");
209
- el.setAttribute(attr, token);
210
- document.head.appendChild(el);
211
- }
212
- if (el.getAttribute("content") !== value) el.setAttribute("content", value);
213
- }
214
- function escapeXml(value) {
215
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
216
- }
217
- function applyLetterFavicon(letter) {
218
- const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="12" fill="#111827"/><text x="32" y="46" font-family="system-ui,-apple-system,Segoe UI,sans-serif" font-size="40" font-weight="700" text-anchor="middle" fill="#ffffff">${escapeXml(letter)}</text></svg>`;
219
- const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
220
- let link = document.head.querySelector('link[rel="icon"]');
221
- if (!link) {
222
- link = document.createElement("link");
223
- link.rel = "icon";
224
- document.head.appendChild(link);
225
- }
226
- link.type = "image/svg+xml";
227
- if (link.href !== href) link.href = href;
228
- }
229
- function applyBrandChrome(content) {
230
- const name = content[BRAND_NAME_KEY];
231
- if (typeof name === "string" && name.length > 0) {
232
- document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
233
- if (el.textContent !== name) el.textContent = name;
234
- if (el.getAttribute("title") !== name) el.setAttribute("title", name);
235
- });
236
- }
237
- const title = content[BRAND_TITLE_KEY];
238
- if (typeof title === "string" && title.length > 0) {
239
- if (document.title !== title) document.title = title;
240
- upsertMeta('meta[property="og:title"]', "property", "og:title", title);
241
- upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
242
- }
243
- const letter = content[BRAND_FAVICON_LETTER_KEY];
244
- if (typeof letter === "string" && letter.length > 0) {
245
- applyLetterFavicon(letter);
246
- }
247
- }
248
-
249
- // src/lib/brand-kit.ts
250
- var BRAND_KIT_KEY = "__ohw_brand";
251
- var BRAND_VAR_PREFIX = "--ohw-brand-";
252
- var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
253
- (role) => `${BRAND_VAR_PREFIX}${role}`
254
- );
255
- var FONT_VARS = { heading: ["--font-heading", "--font-display"], body: ["--font-body"] };
256
- var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
257
- function brandColorVars(kit) {
258
- const { dark, primary, accent, light } = kit.palette;
259
- const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
260
- return {
261
- [`${BRAND_VAR_PREFIX}primary`]: primary,
262
- [`${BRAND_VAR_PREFIX}accent`]: accent,
263
- [`${BRAND_VAR_PREFIX}light`]: light,
264
- [`${BRAND_VAR_PREFIX}dark`]: dark,
265
- [`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
266
- [`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
267
- [`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
268
- };
269
- }
270
- function parseBrandKit(raw) {
271
- if (!raw) return null;
272
- try {
273
- const parsed = JSON.parse(raw);
274
- const p = parsed?.palette;
275
- const f = parsed?.fonts;
276
- if (!p || !f || typeof p.dark !== "string" || typeof p.primary !== "string" || typeof p.accent !== "string" || typeof p.light !== "string" || typeof f.heading !== "string" || typeof f.body !== "string") {
277
- return null;
278
- }
279
- return {
280
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
281
- fonts: { heading: f.heading, body: f.body }
282
- };
283
- } catch {
284
- return null;
285
- }
286
- }
287
- function familyOf(stack) {
288
- const first = stack.split(",")[0]?.trim() ?? "";
289
- return first.replace(/^['"]|['"]$/g, "");
290
- }
291
- function loadBrandFonts(families) {
292
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
293
- if (unique.length === 0) return;
294
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
295
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
296
- let link = document.getElementById(BRAND_FONT_LINK_ID);
297
- if (!link) {
298
- link = document.createElement("link");
299
- link.id = BRAND_FONT_LINK_ID;
300
- link.rel = "stylesheet";
301
- document.head.appendChild(link);
302
- }
303
- if (link.href !== href) link.href = href;
304
- }
305
- function applyBrandToDom(kit) {
306
- const root = document.documentElement;
307
- if (!kit) {
308
- for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
309
- for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
310
- document.getElementById(BRAND_FONT_LINK_ID)?.remove();
311
- return;
312
- }
313
- for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
314
- for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
315
- for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
316
- loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
317
- }
318
-
319
- // src/lib/section-styles.ts
320
- var STYLE_STORE_KEY = "__ohw_styles";
321
- var STYLE_SHEET_ID = "ohw-section-styles";
322
- function parseStyleStore(raw) {
323
- if (!raw) return null;
324
- try {
325
- const parsed = JSON.parse(raw);
326
- if (parsed?.v !== 1) return null;
327
- return {
328
- v: 1,
329
- sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
330
- nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
331
- };
332
- } catch {
333
- return null;
334
- }
335
- }
336
- var BG_VALUES = {
337
- surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
338
- accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
339
- "accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
340
- };
341
- var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
342
- function styleSheetCss() {
343
- const rules = [];
344
- for (const [tone, value] of Object.entries(BG_VALUES)) {
345
- rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
346
- }
347
- rules.push(
348
- `[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
349
- );
350
- rules.push(
351
- `[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
352
- `[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
353
- );
354
- for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
355
- rules.push(
356
- `[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
357
- );
358
- }
359
- rules.push(
360
- `[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
361
- );
362
- for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
363
- rules.push(
364
- `[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
365
- );
366
- }
367
- const pad = { tight: 40, balanced: 64, airy: 96 };
368
- for (const [spacing, px] of Object.entries(pad)) {
369
- rules.push(
370
- `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
371
- );
372
- }
373
- return rules.join("\n");
374
- }
375
- var SECTION_ATTRS = {
376
- sectionBackground: "data-ohw-style-bg",
377
- textDistribution: "data-ohw-style-distribution",
378
- headlineScale: "data-ohw-style-headline",
379
- imageAspect: "data-ohw-style-aspect",
380
- spacing: "data-ohw-style-spacing"
381
- };
382
- var NODE_WROTE_ATTR = "data-ohw-style-node";
383
- function ensureStyleSheet() {
384
- let el = document.getElementById(STYLE_SHEET_ID);
385
- if (!el) {
386
- el = document.createElement("style");
387
- el.id = STYLE_SHEET_ID;
388
- document.head.appendChild(el);
389
- }
390
- const css = styleSheetCss();
391
- if (el.textContent !== css) el.textContent = css;
392
- }
393
- function clearSectionAttrs(root) {
394
- for (const attr of Object.values(SECTION_ATTRS)) {
395
- for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
396
- }
397
- for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
398
- ;
399
- el.style.removeProperty("background");
400
- el.removeAttribute("data-ohw-style-bgcolor");
401
- }
402
- }
403
- function clearNodeProps(root) {
404
- for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
405
- const h = el;
406
- h.style.removeProperty("color");
407
- h.style.removeProperty("font-size");
408
- h.style.removeProperty("background");
409
- h.removeAttribute(NODE_WROTE_ATTR);
410
- }
411
- }
412
- function buttonSurfaceOf(el) {
413
- return el.closest("a, button") ?? el;
414
- }
415
- function applyStylesToDom(store) {
416
- ensureStyleSheet();
417
- clearSectionAttrs(document);
418
- clearNodeProps(document);
419
- if (!store) return;
420
- for (const [sectionId, override] of Object.entries(store.sections)) {
421
- const sections = document.querySelectorAll(
422
- `[data-ohw-section="${CSS.escape(sectionId)}"]`
423
- );
424
- for (const section of Array.from(sections)) {
425
- for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
426
- const value = override[prop];
427
- if (value === void 0) continue;
428
- if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
429
- section.setAttribute(attr, String(value).replace(":", "-"));
430
- }
431
- if (override.sectionBackgroundColor !== void 0) {
432
- section.style.setProperty("background", override.sectionBackgroundColor, "important");
433
- section.setAttribute("data-ohw-style-bgcolor", "");
434
- }
435
- }
436
- }
437
- for (const [key, override] of Object.entries(store.nodes)) {
438
- const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
439
- for (const el of Array.from(nodes)) {
440
- if (override.color !== void 0) {
441
- el.style.setProperty("color", override.color, "important");
442
- el.setAttribute(NODE_WROTE_ATTR, "");
443
- }
444
- if (override.fontSize !== void 0) {
445
- el.style.setProperty("font-size", `${override.fontSize}px`, "important");
446
- el.setAttribute(NODE_WROTE_ATTR, "");
447
- }
448
- if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
449
- const surface = buttonSurfaceOf(el);
450
- if (override.buttonBackground !== void 0) {
451
- surface.style.setProperty("background", override.buttonBackground, "important");
452
- }
453
- if (override.buttonText !== void 0) {
454
- surface.style.setProperty("color", override.buttonText, "important");
455
- }
456
- surface.setAttribute(NODE_WROTE_ATTR, "");
457
- }
458
- }
459
- }
460
- }
461
-
462
194
  // src/ui/ai-tree/aiSectionsManager.tsx
463
195
  var import_react_dom = require("react-dom");
464
196
  var import_client = require("react-dom/client");
@@ -473,8 +205,7 @@ function lucideByName(name) {
473
205
  }
474
206
  var typeStyle = (spec, font) => ({
475
207
  fontFamily: font,
476
- // Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
477
- 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,
478
209
  lineHeight: spec.line,
479
210
  fontWeight: spec.weight
480
211
  });
@@ -501,8 +232,6 @@ var AI_RESPONSIVE_CSS = [
501
232
  " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
502
233
  " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
503
234
  " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
504
- " [data-ai-responsive] { overflow-x: hidden; }",
505
- " [data-ai-responsive] img { max-width: 100%; }",
506
235
  "}"
507
236
  ].join("\n");
508
237
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
@@ -1510,20 +1239,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1510
1239
  const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
1511
1240
  const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
1512
1241
  const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
1513
- const toneBackground = (() => {
1514
- const { dark, primary, light } = resolvedBrand.palette;
1515
- switch (settings.sectionBackground) {
1516
- case "surface":
1517
- return `color-mix(in srgb, ${light} 94%, ${dark})`;
1518
- case "accent":
1519
- return primary;
1520
- case "accent-soft":
1521
- return `color-mix(in srgb, ${primary} 12%, ${light})`;
1522
- default:
1523
- return void 0;
1524
- }
1525
- })();
1526
- const distributed = !isOverlay && settings.textDistribution;
1527
1242
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1528
1243
  "section",
1529
1244
  {
@@ -1533,11 +1248,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1533
1248
  style: {
1534
1249
  position: "relative",
1535
1250
  padding: `${pad}px 0`,
1536
- background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
1251
+ background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
1537
1252
  backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
1538
1253
  backgroundSize: "cover",
1539
- backgroundPosition: "center",
1540
- color: settings.sectionBackground === "accent" ? resolvedBrand.palette.light : void 0
1254
+ backgroundPosition: "center"
1541
1255
  },
1542
1256
  children: [
1543
1257
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
@@ -1561,24 +1275,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1561
1275
  display: "grid",
1562
1276
  gridTemplateColumns: "repeat(12, 1fr)",
1563
1277
  gap: AI_TREE_TOKENS.spacing6,
1564
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1278
+ alignItems: settings.verticalPosition === "top" ? "start" : "center",
1565
1279
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1566
1280
  },
1567
- children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1568
- "div",
1569
- {
1570
- "data-ai-cell": "",
1571
- style: {
1572
- gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1573
- minWidth: 0,
1574
- // space-between: each column becomes a flex column whose content spreads over
1575
- // the full row height instead of clumping at the top.
1576
- ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
1577
- },
1578
- children: renderNode(block, ctx, `r${r2}.b${b}`)
1579
- },
1580
- b
1581
- ))
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))
1582
1282
  },
1583
1283
  r2
1584
1284
  ))
@@ -1594,34 +1294,17 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
1594
1294
  var CONTAINER_ATTR = "data-ohw-ai-generated";
1595
1295
  var REPLACED_ATTR = "data-ohw-ai-replaced-by";
1596
1296
  var REMOVED_ATTR = "data-ohw-ai-removed";
1597
- function readRootVar(name) {
1598
- if (typeof document === "undefined") return "";
1599
- return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1600
- }
1601
- function deriveBrandOverride() {
1602
- const dark = readRootVar("--ohw-brand-dark");
1603
- const primary = readRootVar("--ohw-brand-primary");
1604
- const light = readRootVar("--ohw-brand-light");
1605
- if (!dark || !primary || !light) return null;
1606
- const accent = readRootVar("--ohw-brand-accent");
1607
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1608
- const body = readRootVar("--font-body");
1609
- return {
1610
- palette: { dark, primary, accent: accent || dark, light },
1611
- fonts: {
1612
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
1613
- body: body || AI_DEFAULT_BRAND.fonts.body
1614
- }
1615
- };
1616
- }
1617
1297
  function deriveTemplateBrand() {
1618
- const dark = readRootVar("--color-dark");
1619
- const primary = readRootVar("--color-primary");
1620
- 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");
1621
1304
  if (!dark || !primary || !light) return null;
1622
- const accent = readRootVar("--color-accent");
1623
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1624
- 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");
1625
1308
  return {
1626
1309
  palette: { dark, primary, accent: accent || dark, light },
1627
1310
  fonts: {
@@ -1713,12 +1396,8 @@ function syncReplacedOriginals(state) {
1713
1396
  }
1714
1397
  function applyAiSectionsToDom(state, options) {
1715
1398
  if (typeof document === "undefined") return;
1716
- const brandOverride = deriveBrandOverride();
1717
1399
  const templateBrand = deriveTemplateBrand();
1718
- const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
1719
- const pagePath = window.location.pathname;
1720
- const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
1721
- const activeIds = new Set(pageSections.map((entry) => entry.id));
1400
+ const activeIds = new Set(state.sections.map((entry) => entry.id));
1722
1401
  for (const [id, section] of mounted) {
1723
1402
  if (!activeIds.has(id)) {
1724
1403
  section.root.unmount();
@@ -1726,8 +1405,8 @@ function applyAiSectionsToDom(state, options) {
1726
1405
  mounted.delete(id);
1727
1406
  }
1728
1407
  }
1729
- for (const entry of pageSections) {
1730
- const serialized = JSON.stringify(entry) + brandKey;
1408
+ for (const entry of state.sections) {
1409
+ const serialized = JSON.stringify(entry);
1731
1410
  const existing = mounted.get(entry.id);
1732
1411
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
1733
1412
  continue;
@@ -1741,7 +1420,6 @@ function applyAiSectionsToDom(state, options) {
1741
1420
  mounted.delete(entry.id);
1742
1421
  }
1743
1422
  container.setAttribute("data-ohw-section", entry.id);
1744
- container.setAttribute("data-ohw-instance", entry.id);
1745
1423
  container.setAttribute("data-ohw-section-label", entry.label);
1746
1424
  placeContainer(container, entry);
1747
1425
  const root = mounted.get(entry.id)?.root ?? (0, import_client.createRoot)(container);
@@ -1752,7 +1430,7 @@ function applyAiSectionsToDom(state, options) {
1752
1430
  AiTreeRenderer,
1753
1431
  {
1754
1432
  tree: entry.tree,
1755
- brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1433
+ brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1756
1434
  resolveMedia,
1757
1435
  editKeyPrefix: `ai.${entry.id}`
1758
1436
  }
@@ -2369,7 +2047,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2369
2047
  const autoId = (0, import_react5.useId)();
2370
2048
  const insertAfter = insertAfterProp ?? autoId;
2371
2049
  const [schedule, setSchedule] = (0, import_react5.useState)(null);
2372
- const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
2050
+ const [loading, setLoading] = (0, import_react5.useState)(true);
2373
2051
  const [inEditor, setInEditor] = (0, import_react5.useState)(false);
2374
2052
  const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
2375
2053
  const [modalState, setModalState] = (0, import_react5.useState)(null);
@@ -2543,10 +2221,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2543
2221
  "*"
2544
2222
  );
2545
2223
  };
2224
+ if (!inEditor && !loading && !schedule) return null;
2546
2225
  const sectionId = `scheduling-${insertAfter}`;
2547
- if (!inEditor && !loading && !schedule) {
2548
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2549
- }
2550
2226
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2551
2227
  "section",
2552
2228
  {
@@ -7065,12 +6741,8 @@ function parseSectionsFromHtml(html) {
7065
6741
 
7066
6742
  // src/ui/ai-section/AiSectionOverlay.tsx
7067
6743
  var import_jsx_runtime16 = require("react/jsx-runtime");
7068
- function findSectionElement(instanceId) {
7069
- const escaped = CSS.escape(instanceId);
7070
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7071
- }
7072
- function readRect(instanceId) {
7073
- const el = findSectionElement(instanceId);
6744
+ function readRect(sectionId) {
6745
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7074
6746
  if (!el) return null;
7075
6747
  const r2 = el.getBoundingClientRect();
7076
6748
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7093,7 +6765,7 @@ function useLiveSectionRect(sectionId) {
7093
6765
  const opts = { capture: true, passive: true };
7094
6766
  window.addEventListener("scroll", update, opts);
7095
6767
  window.addEventListener("resize", update);
7096
- const el = findSectionElement(sectionId);
6768
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7097
6769
  const ro = el ? new ResizeObserver(update) : null;
7098
6770
  if (el && ro) ro.observe(el);
7099
6771
  const interval = setInterval(update, 500);
@@ -7106,14 +6778,6 @@ function useLiveSectionRect(sectionId) {
7106
6778
  }, [sectionId]);
7107
6779
  return rect;
7108
6780
  }
7109
- function computeSectionBoundaryFlags(instanceId) {
7110
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7111
- (el) => !el.parentElement?.closest("[data-ohw-section]")
7112
- );
7113
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7114
- if (index === -1) return { isFirst: true, isLast: true };
7115
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7116
- }
7117
6781
  var PRIMARY2 = "#0885FE";
7118
6782
  function edgeAwareRadius(rect) {
7119
6783
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7187,7 +6851,6 @@ function AiSectionOverlay({
7187
6851
  }) {
7188
6852
  const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
7189
6853
  const [reviewId, setReviewId] = (0, import_react8.useState)(null);
7190
- const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
7191
6854
  const reviewIdRef = (0, import_react8.useRef)(null);
7192
6855
  reviewIdRef.current = reviewId;
7193
6856
  const selectedIdRef = (0, import_react8.useRef)(null);
@@ -7196,7 +6859,7 @@ function AiSectionOverlay({
7196
6859
  (el) => {
7197
6860
  postToParent2({
7198
6861
  type: "ow:section-selected",
7199
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
6862
+ sectionId: el?.dataset.ohwSection ?? null,
7200
6863
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7201
6864
  });
7202
6865
  },
@@ -7205,7 +6868,7 @@ function AiSectionOverlay({
7205
6868
  const selectFromElement = (0, import_react8.useCallback)(
7206
6869
  (el, options) => {
7207
6870
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7208
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
6871
+ const id = sectionEl?.dataset.ohwSection ?? null;
7209
6872
  if (id === selectedIdRef.current) return;
7210
6873
  setSelectedId(id);
7211
6874
  if (options?.report !== false) report(sectionEl);
@@ -7246,10 +6909,9 @@ function AiSectionOverlay({
7246
6909
  }
7247
6910
  const found = readRect(sectionId) != null;
7248
6911
  setReviewId(found ? sectionId : null);
7249
- setReviewButtonsHidden(e.data.hideButtons === true);
7250
6912
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7251
6913
  if (found) {
7252
- 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" });
7253
6915
  }
7254
6916
  }
7255
6917
  };
@@ -7268,7 +6930,7 @@ function AiSectionOverlay({
7268
6930
  return;
7269
6931
  }
7270
6932
  const sec = t.closest("[data-ohw-section]");
7271
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
6933
+ setHoveredId(sec?.dataset.ohwSection ?? null);
7272
6934
  };
7273
6935
  const onLeave = () => setHoveredId(null);
7274
6936
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -7300,29 +6962,9 @@ function AiSectionOverlay({
7300
6962
  },
7301
6963
  [postToParent2]
7302
6964
  );
7303
- const activeSelectionId = reviewId ? null : selectedId;
7304
- const selectionRect = useLiveSectionRect(activeSelectionId);
6965
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
7305
6966
  const reviewRect = useLiveSectionRect(reviewId);
7306
6967
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
7307
- (0, import_react8.useEffect)(() => {
7308
- if (!activeSelectionId || !selectionRect) {
7309
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
7310
- return;
7311
- }
7312
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
7313
- postToParent2({
7314
- type: "ow:section-rect",
7315
- instanceId: activeSelectionId,
7316
- rect: {
7317
- top: selectionRect.top + window.scrollY,
7318
- left: selectionRect.left + window.scrollX,
7319
- width: selectionRect.width,
7320
- height: selectionRect.height
7321
- },
7322
- isFirst,
7323
- isLast
7324
- });
7325
- }, [activeSelectionId, selectionRect, postToParent2]);
7326
6968
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
7327
6969
  hoverRect && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7328
6970
  "div",
@@ -7373,16 +7015,13 @@ function AiSectionOverlay({
7373
7015
  border: `2px solid ${PRIMARY2}`,
7374
7016
  borderRadius: edgeAwareRadius(reviewRect),
7375
7017
  zIndex: 2147483200,
7376
- // The veil itself: swallows clicks so the section stays locked until decided. This
7377
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
7378
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
7379
- // 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.
7380
7019
  background: "rgba(8, 133, 254, 0.04)",
7381
7020
  pointerEvents: "auto",
7382
7021
  cursor: "default"
7383
7022
  },
7384
7023
  onClick: (e) => e.stopPropagation(),
7385
- children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7024
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7386
7025
  "div",
7387
7026
  {
7388
7027
  style: {
@@ -11282,329 +10921,6 @@ function deleteFooterColumn(column) {
11282
10921
  };
11283
10922
  }
11284
10923
 
11285
- // src/lib/logo-identity.ts
11286
- var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
11287
- var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
11288
- var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
11289
- var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
11290
- var LOGO_ALT_KEY = "logo-alt";
11291
- var LOGO_IMAGE_URL_KEY = "nav-logo-image";
11292
- var PLACEHOLDER_BUSINESS_NAME = "Business name";
11293
- function resolveLogoDisplayText(text) {
11294
- const trimmed = (text ?? "").trim();
11295
- return trimmed || PLACEHOLDER_BUSINESS_NAME;
11296
- }
11297
- function isFooterLogoRoot(root) {
11298
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11299
- }
11300
- function imageKeyForRoot(root) {
11301
- return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
11302
- }
11303
- function textKeyForRoot(root) {
11304
- return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
11305
- }
11306
- function ensureLogoHrefKey(root) {
11307
- if (!(root instanceof HTMLAnchorElement)) return;
11308
- if (root.hasAttribute("data-ohw-href-key")) return;
11309
- root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
11310
- }
11311
- function applyLogoIdentity(text, isPlaceholder) {
11312
- const display = resolveLogoDisplayText(text);
11313
- const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
11314
- for (const key of LOGO_TEXT_KEYS) {
11315
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11316
- if (el.textContent !== display) el.textContent = display;
11317
- });
11318
- }
11319
- for (const key of LOGO_IMAGE_KEYS) {
11320
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11321
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
11322
- if (img) img.alt = display;
11323
- });
11324
- }
11325
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
11326
- if (placeholder) el.setAttribute("data-ohw-placeholder", "");
11327
- else el.removeAttribute("data-ohw-placeholder");
11328
- });
11329
- return display;
11330
- }
11331
- function applyLogoImage(url, alt) {
11332
- const displayAlt = resolveLogoDisplayText(alt);
11333
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11334
- ensureLogoHrefKey(root);
11335
- const imageKey = imageKeyForRoot(root);
11336
- const textKey = textKeyForRoot(root);
11337
- 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");
11338
- let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
11339
- if (url) {
11340
- if (!img) {
11341
- img = document.createElement("img");
11342
- img.setAttribute("data-ohw-editable", "image");
11343
- img.setAttribute("data-ohw-key", imageKey);
11344
- img.alt = displayAlt;
11345
- img.style.height = "";
11346
- img.style.maxHeight = "none";
11347
- img.style.width = "auto";
11348
- img.style.display = "block";
11349
- img.style.objectFit = "contain";
11350
- root.insertBefore(img, root.firstChild);
11351
- } else {
11352
- img.setAttribute("data-ohw-editable", "image");
11353
- img.setAttribute("data-ohw-key", imageKey);
11354
- }
11355
- img.removeAttribute("srcset");
11356
- img.removeAttribute("sizes");
11357
- img.src = url;
11358
- img.alt = displayAlt;
11359
- img.style.display = "block";
11360
- if (textEl) textEl.style.display = "none";
11361
- root.removeAttribute("data-ohw-placeholder");
11362
- return;
11363
- }
11364
- if (img) {
11365
- img.removeAttribute("src");
11366
- img.removeAttribute("srcset");
11367
- img.removeAttribute("sizes");
11368
- img.alt = displayAlt;
11369
- img.style.display = "none";
11370
- }
11371
- if (!textEl) {
11372
- textEl = document.createElement("span");
11373
- textEl.setAttribute("data-ohw-editable", "plain");
11374
- textEl.setAttribute("data-ohw-key", textKey);
11375
- root.appendChild(textEl);
11376
- }
11377
- textEl.style.display = "";
11378
- if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
11379
- if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
11380
- root.setAttribute("data-ohw-placeholder", "");
11381
- } else {
11382
- root.removeAttribute("data-ohw-placeholder");
11383
- }
11384
- });
11385
- }
11386
- function applyLogoHref(href) {
11387
- const target = href.trim() || "/";
11388
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11389
- ensureLogoHrefKey(root);
11390
- if (root instanceof HTMLAnchorElement) {
11391
- root.setAttribute("href", target);
11392
- }
11393
- });
11394
- for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
11395
- }
11396
- function readLogoIdentityFromDom() {
11397
- let imageUrl = null;
11398
- for (const key of LOGO_IMAGE_KEYS) {
11399
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
11400
- const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
11401
- const attrSrc = img?.getAttribute("src")?.trim() ?? "";
11402
- if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
11403
- imageUrl = img.currentSrc || img.src;
11404
- break;
11405
- }
11406
- }
11407
- let text = PLACEHOLDER_BUSINESS_NAME;
11408
- let isPlaceholder = true;
11409
- for (const key of LOGO_TEXT_KEYS) {
11410
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
11411
- if (el?.textContent?.trim()) {
11412
- text = el.textContent.trim();
11413
- const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
11414
- isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
11415
- break;
11416
- }
11417
- }
11418
- if (imageUrl) {
11419
- const logoImg = document.querySelector(
11420
- '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
11421
- );
11422
- const alt = logoImg?.alt?.trim() || text;
11423
- isPlaceholder = false;
11424
- const hrefEl = document.querySelector(
11425
- 'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
11426
- );
11427
- const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
11428
- return { text, isPlaceholder, imageUrl, href: href2, alt };
11429
- }
11430
- const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
11431
- const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
11432
- return { text, isPlaceholder, imageUrl: null, href, alt: text };
11433
- }
11434
- function applyLogoFromContent(content) {
11435
- 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);
11436
- if (!hasLogoIdentity) return false;
11437
- const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
11438
- const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
11439
- const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
11440
- const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
11441
- const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
11442
- const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
11443
- if (logoImageUrl) {
11444
- applyLogoImage(logoImageUrl, logoAlt);
11445
- } else {
11446
- if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
11447
- applyLogoIdentity(logoText, logoIsPlaceholder);
11448
- }
11449
- const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
11450
- if (typeof logoHref === "string" && logoHref.trim()) {
11451
- applyLogoHref(logoHref);
11452
- }
11453
- return true;
11454
- }
11455
-
11456
- // src/lib/logo-size.ts
11457
- var LOGO_SIZE_DEFAULTS = {
11458
- navbar: 28,
11459
- footer: 32
11460
- };
11461
- var LOGO_SIZE_MIN = 16;
11462
- var LOGO_SIZE_MAX = 80;
11463
- var LOGO_SIZE_DESKTOP_KEYS = {
11464
- navbar: "nav-logo-size",
11465
- footer: "footer-logo-size"
11466
- };
11467
- var LOGO_SIZE_MOBILE_KEYS = {
11468
- navbar: "nav-logo-size-mobile",
11469
- footer: "footer-logo-size-mobile"
11470
- };
11471
- var LOGO_SIZE_KEYS = [
11472
- LOGO_SIZE_DESKTOP_KEYS.navbar,
11473
- LOGO_SIZE_DESKTOP_KEYS.footer,
11474
- LOGO_SIZE_MOBILE_KEYS.navbar,
11475
- LOGO_SIZE_MOBILE_KEYS.footer
11476
- ];
11477
- function isFooterLogoRoot2(root) {
11478
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11479
- }
11480
- function getLogoPlacement(root) {
11481
- return isFooterLogoRoot2(root) ? "footer" : "navbar";
11482
- }
11483
- function parseLogoSizePx(raw, fallback) {
11484
- if (raw == null || raw === "") return fallback;
11485
- const n = Number.parseFloat(raw);
11486
- if (!Number.isFinite(n)) return fallback;
11487
- return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
11488
- }
11489
- function isMobileLogoSizeFollowing(content, placement) {
11490
- const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
11491
- return raw == null || raw.trim() === "";
11492
- }
11493
- function resolveDesktopLogoSize(content, placement) {
11494
- return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
11495
- }
11496
- function resolveMobileLogoSize(content, placement) {
11497
- if (isMobileLogoSizeFollowing(content, placement)) {
11498
- return resolveDesktopLogoSize(content, placement);
11499
- }
11500
- return parseLogoSizePx(
11501
- content[LOGO_SIZE_MOBILE_KEYS[placement]],
11502
- resolveDesktopLogoSize(content, placement)
11503
- );
11504
- }
11505
- function setRootSizeVars(root, desktopPx, mobilePx, following) {
11506
- root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
11507
- if (following) {
11508
- root.style.removeProperty("--ohw-logo-size-mobile");
11509
- } else {
11510
- root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
11511
- }
11512
- root.querySelectorAll("img").forEach((img) => {
11513
- img.style.height = "";
11514
- img.style.maxHeight = "none";
11515
- img.style.width = "auto";
11516
- img.style.objectFit = "contain";
11517
- });
11518
- }
11519
- function applyLogoSizes(content) {
11520
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11521
- const placement = getLogoPlacement(root);
11522
- const desktop = resolveDesktopLogoSize(content, placement);
11523
- const following = isMobileLogoSizeFollowing(content, placement);
11524
- const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
11525
- setRootSizeVars(root, desktop, mobile, following);
11526
- });
11527
- }
11528
- function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
11529
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11530
- if (getLogoPlacement(root) !== placement) return;
11531
- setRootSizeVars(root, desktopPx, mobilePx, following);
11532
- });
11533
- }
11534
- function logoHasUploadedImage(logoEl) {
11535
- if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
11536
- 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");
11537
- if (!img) return false;
11538
- const src = img.getAttribute("src")?.trim() ?? "";
11539
- if (!src || src.startsWith("data:")) return false;
11540
- if (img.style.display === "none") return false;
11541
- return true;
11542
- }
11543
- function getLogoInteractionRect(logoEl) {
11544
- if (logoHasUploadedImage(logoEl)) {
11545
- 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");
11546
- if (img) {
11547
- const r2 = img.getBoundingClientRect();
11548
- if (r2.width > 0 && r2.height > 0) return r2;
11549
- }
11550
- }
11551
- const text = logoEl.querySelector(
11552
- '[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
11553
- );
11554
- if (text) {
11555
- const style = window.getComputedStyle(text);
11556
- if (style.display !== "none" && style.visibility !== "hidden") {
11557
- const r2 = text.getBoundingClientRect();
11558
- if (r2.width > 0 && r2.height > 0) return r2;
11559
- }
11560
- }
11561
- return logoEl.getBoundingClientRect();
11562
- }
11563
- function readLogoSizeState(content, placement) {
11564
- const desktopPx = resolveDesktopLogoSize(content, placement);
11565
- const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
11566
- const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
11567
- return { desktopPx, mobilePx, mobileFollowing };
11568
- }
11569
-
11570
- // src/lib/site-wide-scope.ts
11571
- function getLogoElement(el) {
11572
- const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
11573
- if (marked) return marked;
11574
- if (el.closest('[data-ohw-editable="icon"]')) return null;
11575
- const root = el.closest("nav, [data-ohw-nav-root], footer");
11576
- if (!root) return null;
11577
- const anchor = el.closest("a");
11578
- if (anchor && root.contains(anchor) && !anchor.hasAttribute("data-ohw-href-key") && !anchor.closest("[data-ohw-nav-container]") && Boolean(anchor.querySelector("img") || anchor.matches("img"))) {
11579
- return anchor;
11580
- }
11581
- const img = el.matches("img") ? el : null;
11582
- if (img && !img.closest("[data-ohw-href-key]") && !img.closest("[data-ohw-nav-container]") && (img.closest("footer") || img.closest("nav, [data-ohw-nav-root]"))) {
11583
- return img;
11584
- }
11585
- return null;
11586
- }
11587
- function isInFooter(el) {
11588
- if (!el) return false;
11589
- return Boolean(el.closest("footer") || el.closest('[data-ohw-section="footer"]'));
11590
- }
11591
- function isSiteWideElement(el) {
11592
- if (!el) return false;
11593
- if (getLogoElement(el)) return true;
11594
- if (isInFooter(el)) return true;
11595
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-root")) {
11596
- return true;
11597
- }
11598
- if (el.hasAttribute("data-ohw-href-key") && el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer], aside")) {
11599
- return true;
11600
- }
11601
- if (el.closest('[data-ohw-role="navbar-button"]')) return true;
11602
- return false;
11603
- }
11604
- function isSiteWideScopeActive(args) {
11605
- return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
11606
- }
11607
-
11608
10924
  // src/lib/add-footer-column.ts
11609
10925
  function buildFooterColumnEditContentPatch(result) {
11610
10926
  return {
@@ -11820,127 +11136,16 @@ function FloatingPanel({
11820
11136
  );
11821
11137
  }
11822
11138
 
11823
- // src/ui/logo-size-panel.tsx
11824
- var import_lucide_react14 = require("lucide-react");
11825
- var import_jsx_runtime27 = require("react/jsx-runtime");
11826
- function SizeSlider({
11827
- value,
11828
- onChange
11829
- }) {
11830
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
11831
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-3", children: [
11832
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
11833
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
11834
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
11835
- value,
11836
- " px"
11837
- ] })
11838
- ] }),
11839
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
11840
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11841
- "div",
11842
- {
11843
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
11844
- style: { width: `${pct}%` }
11845
- }
11846
- ),
11847
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11848
- "input",
11849
- {
11850
- type: "range",
11851
- min: LOGO_SIZE_MIN,
11852
- max: LOGO_SIZE_MAX,
11853
- step: 1,
11854
- value,
11855
- "aria-label": "Logo size",
11856
- className: cn(
11857
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
11858
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
11859
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
11860
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
11861
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
11862
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
11863
- "[&::-moz-range-thumb]:bg-background"
11864
- ),
11865
- onChange: (e) => onChange(Number(e.target.value))
11866
- }
11867
- )
11868
- ] })
11869
- ] });
11870
- }
11871
- function LogoSizePanel({
11872
- viewport,
11873
- sizePx,
11874
- mobileFollowing = true,
11875
- onSizeChange,
11876
- onCustomizeMobile,
11877
- onResetMobile,
11878
- onUpdateEverywhere,
11879
- className
11880
- }) {
11881
- const showFollowing = viewport === "mobile" && mobileFollowing;
11882
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
11883
- const showDesktopSlider = viewport === "desktop";
11884
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-4", className), children: [
11885
- showFollowing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
11886
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-start gap-1", children: [
11887
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Link, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
11888
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
11889
- ] }),
11890
- /* @__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." }),
11891
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11892
- Button,
11893
- {
11894
- type: "button",
11895
- variant: "outline",
11896
- size: "sm",
11897
- className: "h-9 w-full min-w-0 cursor-pointer",
11898
- onClick: onCustomizeMobile,
11899
- children: "Customize for mobile"
11900
- }
11901
- )
11902
- ] }) : null,
11903
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
11904
- showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11905
- Button,
11906
- {
11907
- type: "button",
11908
- variant: "outline",
11909
- size: "sm",
11910
- className: "h-9 w-full min-w-0 cursor-pointer",
11911
- onClick: onResetMobile,
11912
- children: "Reset to desktop size"
11913
- }
11914
- ) : null,
11915
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px w-full bg-border", role: "separator" }),
11916
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
11917
- Button,
11918
- {
11919
- type: "button",
11920
- variant: "outline",
11921
- size: "sm",
11922
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
11923
- onClick: onUpdateEverywhere,
11924
- children: [
11925
- "Update logo everywhere",
11926
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.ArrowUpRight, { size: 16, "aria-hidden": true })
11927
- ]
11928
- }
11929
- ),
11930
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
11931
- ] });
11932
- }
11933
-
11934
11139
  // src/ui/socials-display-panel.tsx
11935
- var import_jsx_runtime28 = require("react/jsx-runtime");
11140
+ var import_jsx_runtime27 = require("react/jsx-runtime");
11936
11141
  function DisplaySwitch({
11937
11142
  label,
11938
11143
  checked,
11939
11144
  disabled,
11940
11145
  onChange
11941
11146
  }) {
11942
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
11943
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11147
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
11148
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11944
11149
  "span",
11945
11150
  {
11946
11151
  className: cn(
@@ -11950,7 +11155,7 @@ function DisplaySwitch({
11950
11155
  children: label
11951
11156
  }
11952
11157
  ),
11953
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11158
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11954
11159
  "button",
11955
11160
  {
11956
11161
  type: "button",
@@ -11964,7 +11169,7 @@ function DisplaySwitch({
11964
11169
  checked ? "bg-primary" : "bg-primary-50",
11965
11170
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
11966
11171
  ),
11967
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11172
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11968
11173
  "span",
11969
11174
  {
11970
11175
  className: cn(
@@ -11978,8 +11183,8 @@ function DisplaySwitch({
11978
11183
  ] });
11979
11184
  }
11980
11185
  function SocialsDisplayPanel({ display, onChange, className }) {
11981
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11982
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11186
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11187
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11983
11188
  DisplaySwitch,
11984
11189
  {
11985
11190
  label: "Text",
@@ -11988,7 +11193,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
11988
11193
  onChange: (text) => onChange({ ...display, text })
11989
11194
  }
11990
11195
  ),
11991
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
11196
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11992
11197
  DisplaySwitch,
11993
11198
  {
11994
11199
  label: "Icon",
@@ -12548,8 +11753,8 @@ function useNavItemDrag({
12548
11753
  }
12549
11754
 
12550
11755
  // src/ui/footer-container-chrome.tsx
12551
- var import_lucide_react15 = require("lucide-react");
12552
- var import_jsx_runtime29 = require("react/jsx-runtime");
11756
+ var import_lucide_react14 = require("lucide-react");
11757
+ var import_jsx_runtime28 = require("react/jsx-runtime");
12553
11758
  function FooterContainerChrome({
12554
11759
  rect,
12555
11760
  onAdd,
@@ -12557,7 +11762,7 @@ function FooterContainerChrome({
12557
11762
  }) {
12558
11763
  const chromeGap = 6;
12559
11764
  const buttonMargin = 7;
12560
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11765
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12561
11766
  "div",
12562
11767
  {
12563
11768
  "data-ohw-footer-container-chrome": "",
@@ -12569,8 +11774,8 @@ function FooterContainerChrome({
12569
11774
  width: rect.width + chromeGap * 2,
12570
11775
  height: rect.height + chromeGap * 2
12571
11776
  },
12572
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
12573
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11777
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Tooltip, { children: [
11778
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12574
11779
  "button",
12575
11780
  {
12576
11781
  type: "button",
@@ -12589,10 +11794,10 @@ function FooterContainerChrome({
12589
11794
  if (addDisabled) return;
12590
11795
  onAdd();
12591
11796
  },
12592
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
11797
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react14.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12593
11798
  }
12594
11799
  ) }),
12595
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
11800
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12596
11801
  ] })
12597
11802
  }
12598
11803
  ) });
@@ -12775,18 +11980,6 @@ function collectEditableNodes(extraContent, root = document) {
12775
11980
  }
12776
11981
  if (extraContent && !isScoped) {
12777
11982
  applyNavFooterDeleteOverrides(byKey, extraContent);
12778
- for (const key of LOGO_IMAGE_KEYS) {
12779
- if (!(key in extraContent)) continue;
12780
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
12781
- }
12782
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
12783
- if (!(key in extraContent)) continue;
12784
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12785
- }
12786
- for (const key of LOGO_SIZE_KEYS) {
12787
- if (!(key in extraContent)) continue;
12788
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12789
- }
12790
11983
  }
12791
11984
  return Array.from(byKey.values());
12792
11985
  }
@@ -13052,14 +12245,14 @@ function deleteSelectedNavFooterItem(deps) {
13052
12245
  }
13053
12246
 
13054
12247
  // src/ui/navbar-container-chrome.tsx
13055
- var import_lucide_react16 = require("lucide-react");
13056
- var import_jsx_runtime30 = require("react/jsx-runtime");
12248
+ var import_lucide_react15 = require("lucide-react");
12249
+ var import_jsx_runtime29 = require("react/jsx-runtime");
13057
12250
  function NavbarContainerChrome({
13058
12251
  rect,
13059
12252
  onAdd
13060
12253
  }) {
13061
12254
  const chromeGap = 6;
13062
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12255
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13063
12256
  "div",
13064
12257
  {
13065
12258
  "data-ohw-navbar-container-chrome": "",
@@ -13071,7 +12264,7 @@ function NavbarContainerChrome({
13071
12264
  width: rect.width + chromeGap * 2,
13072
12265
  height: rect.height + chromeGap * 2
13073
12266
  },
13074
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12267
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13075
12268
  "button",
13076
12269
  {
13077
12270
  type: "button",
@@ -13088,7 +12281,7 @@ function NavbarContainerChrome({
13088
12281
  e.stopPropagation();
13089
12282
  onAdd();
13090
12283
  },
13091
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12284
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13092
12285
  }
13093
12286
  )
13094
12287
  }
@@ -13097,7 +12290,7 @@ function NavbarContainerChrome({
13097
12290
 
13098
12291
  // src/ui/drop-indicator.tsx
13099
12292
  var React10 = __toESM(require("react"), 1);
13100
- var import_jsx_runtime31 = require("react/jsx-runtime");
12293
+ var import_jsx_runtime30 = require("react/jsx-runtime");
13101
12294
  var dropIndicatorVariants = cva(
13102
12295
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
13103
12296
  {
@@ -13121,7 +12314,7 @@ var dropIndicatorVariants = cva(
13121
12314
  );
13122
12315
  var DropIndicator = React10.forwardRef(
13123
12316
  ({ className, direction, state, ...props }, ref) => {
13124
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
12317
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13125
12318
  "div",
13126
12319
  {
13127
12320
  ref,
@@ -13138,7 +12331,7 @@ var DropIndicator = React10.forwardRef(
13138
12331
  DropIndicator.displayName = "DropIndicator";
13139
12332
 
13140
12333
  // src/ui/badge.tsx
13141
- var import_jsx_runtime32 = require("react/jsx-runtime");
12334
+ var import_jsx_runtime31 = require("react/jsx-runtime");
13142
12335
  var badgeVariants = cva(
13143
12336
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
13144
12337
  {
@@ -13156,12 +12349,12 @@ var badgeVariants = cva(
13156
12349
  }
13157
12350
  );
13158
12351
  function Badge({ className, variant, ...props }) {
13159
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
12352
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
13160
12353
  }
13161
12354
 
13162
12355
  // src/OhhwellsBridge.tsx
13163
- var import_lucide_react17 = require("lucide-react");
13164
- var import_jsx_runtime33 = require("react/jsx-runtime");
12356
+ var import_lucide_react16 = require("lucide-react");
12357
+ var import_jsx_runtime32 = require("react/jsx-runtime");
13165
12358
  var PRIMARY3 = "#0885FE";
13166
12359
  var IMAGE_FADE_MS = 300;
13167
12360
  function runOpacityFade(el, onDone) {
@@ -13255,10 +12448,21 @@ function parseSchedulingInsertAfter(insertAfter) {
13255
12448
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
13256
12449
  };
13257
12450
  }
13258
- function resolveEntryAnchor(entry) {
13259
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
13260
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
13261
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
12451
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
12452
+ const parsed = parseSchedulingInsertAfter(insertAfter);
12453
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
12454
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
12455
+ return { effectiveInsertAfter, insertBefore };
12456
+ }
12457
+ function getSchedulingMountPoint(insertAfter) {
12458
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
12459
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
12460
+ if (!anchorEl && anchor === "scheduling") {
12461
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
12462
+ anchorEl = widgets.at(-1) ?? null;
12463
+ }
12464
+ if (!anchorEl) return null;
12465
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13262
12466
  }
13263
12467
  function schedulingMountDepth(insertAfter) {
13264
12468
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -13275,7 +12479,8 @@ function getPageSchedulingEntries(raw) {
13275
12479
  }
13276
12480
  }
13277
12481
  function isSchedulingWidgetMissing(entry) {
13278
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
12482
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
12483
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
13279
12484
  }
13280
12485
  function hasMissingSchedulingWidgets(entries) {
13281
12486
  return entries.some(isSchedulingWidgetMissing);
@@ -13305,17 +12510,16 @@ function initSectionsFromContent(content, removeExisting = false) {
13305
12510
  } catch {
13306
12511
  }
13307
12512
  }
13308
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
13309
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
13310
- const sectionId = schedulingSectionId(widgetId);
12513
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
12514
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
12515
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
13311
12516
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
13312
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
13313
- if (!anchorEl) return false;
13314
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
12517
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
12518
+ if (!mountPoint) return false;
13315
12519
  const container = document.createElement("div");
13316
12520
  container.dataset.ohwSectionContainer = "scheduling";
13317
- if (beforeId) {
13318
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
12521
+ if (insertBefore) {
12522
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
13319
12523
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
13320
12524
  if (!beforePoint) return false;
13321
12525
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -13326,25 +12530,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13326
12530
  }
13327
12531
  tail.insertAdjacentElement("afterend", container);
13328
12532
  }
13329
- try {
13330
- const root = (0, import_client2.createRoot)(container);
13331
- (0, import_react_dom3.flushSync)(() => {
13332
- root.render(
13333
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13334
- SchedulingWidget,
13335
- {
13336
- notifyOnConnect,
13337
- initialScheduleId: scheduleId,
13338
- insertAfter: widgetId
13339
- }
13340
- )
13341
- );
13342
- });
13343
- } catch (err) {
13344
- console.error("[ow:scheduling] render threw", err);
13345
- container.remove();
13346
- return false;
13347
- }
12533
+ const root = (0, import_client2.createRoot)(container);
12534
+ (0, import_react_dom3.flushSync)(() => {
12535
+ root.render(
12536
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12537
+ SchedulingWidget,
12538
+ {
12539
+ notifyOnConnect,
12540
+ initialScheduleId: scheduleId,
12541
+ insertAfter: effectiveInsertAfter
12542
+ }
12543
+ )
12544
+ );
12545
+ });
13348
12546
  const tracker = getSectionsTracker();
13349
12547
  let sections = [];
13350
12548
  try {
@@ -13352,12 +12550,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13352
12550
  } catch {
13353
12551
  }
13354
12552
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
13355
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
12553
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
13356
12554
  sections.push({
13357
12555
  type: "scheduling",
13358
- insertAfter: widgetId,
13359
- anchorId,
13360
- beforeId: beforeId ?? null,
12556
+ insertAfter: effectiveInsertAfter,
13361
12557
  pagePath: window.location.pathname,
13362
12558
  ...scheduleId ? { scheduleId } : {}
13363
12559
  });
@@ -13371,8 +12567,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
13371
12567
  for (let i = pending.length - 1; i >= 0; i--) {
13372
12568
  const entry = pending[i];
13373
12569
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
13374
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
13375
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
12570
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
13376
12571
  pending.splice(i, 1);
13377
12572
  }
13378
12573
  }
@@ -13516,13 +12711,6 @@ function isInsideLinkEditor(target) {
13516
12711
  target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
13517
12712
  );
13518
12713
  }
13519
- function isInsideFloatingPanel(target) {
13520
- return Boolean(target.closest("[data-ohw-floating-panel]"));
13521
- }
13522
- function isPointOverFloatingPanel(clientX, clientY) {
13523
- const el = document.elementFromPoint(clientX, clientY);
13524
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
13525
- }
13526
12714
  function getHrefKeyFromElement(el) {
13527
12715
  if (!el) return null;
13528
12716
  const anchor = el.closest("[data-ohw-href-key]");
@@ -13570,7 +12758,8 @@ function isNavItemPointerTarget(el) {
13570
12758
  function getNavigationItemAnchor(el) {
13571
12759
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
13572
12760
  if (!anchor) return null;
13573
- if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
12761
+ if (!anchor.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !getSocialItem(anchor))
12762
+ return null;
13574
12763
  if (!isNavItemPointerTarget(anchor)) return null;
13575
12764
  return anchor;
13576
12765
  }
@@ -13760,7 +12949,7 @@ function getNavigationSelectionParent(el) {
13760
12949
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
13761
12950
  return getFooterLinksContainer();
13762
12951
  }
13763
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
12952
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
13764
12953
  return getNavigationRoot(el);
13765
12954
  }
13766
12955
  return null;
@@ -14006,7 +13195,7 @@ function EditGlowChrome({
14006
13195
  hideHandle = false
14007
13196
  }) {
14008
13197
  const GAP = SELECTION_CHROME_GAP2;
14009
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
13198
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
14010
13199
  "div",
14011
13200
  {
14012
13201
  ref: elRef,
@@ -14021,7 +13210,7 @@ function EditGlowChrome({
14021
13210
  zIndex: 2147483646
14022
13211
  },
14023
13212
  children: [
14024
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13213
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14025
13214
  "div",
14026
13215
  {
14027
13216
  style: {
@@ -14034,7 +13223,7 @@ function EditGlowChrome({
14034
13223
  }
14035
13224
  }
14036
13225
  ),
14037
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13226
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14038
13227
  "div",
14039
13228
  {
14040
13229
  "data-ohw-drag-handle-container": "",
@@ -14046,7 +13235,7 @@ function EditGlowChrome({
14046
13235
  transform: "translate(calc(-100% - 7px), -50%)",
14047
13236
  pointerEvents: dragDisabled ? "none" : "auto"
14048
13237
  },
14049
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13238
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14050
13239
  DragHandle,
14051
13240
  {
14052
13241
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -14256,7 +13445,7 @@ function FloatingToolbar({
14256
13445
  return () => ro.disconnect();
14257
13446
  }, [showEditLink, activeCommands]);
14258
13447
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
14259
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13448
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14260
13449
  "div",
14261
13450
  {
14262
13451
  ref: setRefs,
@@ -14268,12 +13457,12 @@ function FloatingToolbar({
14268
13457
  zIndex: 2147483647,
14269
13458
  pointerEvents: "auto"
14270
13459
  },
14271
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
14272
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
14273
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
13460
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(CustomToolbar, { children: [
13461
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react16.default.Fragment, { children: [
13462
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CustomToolbarDivider, {}),
14274
13463
  btns.map((btn) => {
14275
13464
  const isActive = activeCommands.has(btn.cmd);
14276
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13465
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14277
13466
  CustomToolbarButton,
14278
13467
  {
14279
13468
  title: btn.title,
@@ -14282,7 +13471,7 @@ function FloatingToolbar({
14282
13471
  e.preventDefault();
14283
13472
  onCommand(btn.cmd);
14284
13473
  },
14285
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13474
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14286
13475
  "svg",
14287
13476
  {
14288
13477
  width: "16",
@@ -14303,7 +13492,7 @@ function FloatingToolbar({
14303
13492
  );
14304
13493
  })
14305
13494
  ] }, gi)),
14306
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13495
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14307
13496
  CustomToolbarButton,
14308
13497
  {
14309
13498
  type: "button",
@@ -14317,7 +13506,7 @@ function FloatingToolbar({
14317
13506
  e.preventDefault();
14318
13507
  e.stopPropagation();
14319
13508
  },
14320
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
13509
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react16.Link, { className: "size-4 shrink-0", "aria-hidden": true })
14321
13510
  }
14322
13511
  ) : null
14323
13512
  ] })
@@ -14334,7 +13523,7 @@ function StateToggle({
14334
13523
  states,
14335
13524
  onStateChange
14336
13525
  }) {
14337
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13526
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14338
13527
  ToggleGroup,
14339
13528
  {
14340
13529
  "data-ohw-state-toggle": "",
@@ -14348,12 +13537,11 @@ function StateToggle({
14348
13537
  left: rect.right - 8,
14349
13538
  transform: "translateX(-100%)"
14350
13539
  },
14351
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
13540
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14352
13541
  }
14353
13542
  );
14354
13543
  }
14355
13544
  var contentCache = /* @__PURE__ */ new Map();
14356
- var fetchedContentPaths = /* @__PURE__ */ new Set();
14357
13545
  function resolveSubdomain(subdomainFromQuery) {
14358
13546
  if (subdomainFromQuery) return subdomainFromQuery;
14359
13547
  if (typeof window !== "undefined") {
@@ -14448,14 +13636,8 @@ function OhhwellsBridge() {
14448
13636
  });
14449
13637
  const selectFrameRef = (0, import_react16.useRef)(() => {
14450
13638
  });
14451
- const selectLogoRef = (0, import_react16.useRef)(() => {
14452
- });
14453
- const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
14454
- });
14455
13639
  const deselectRef = (0, import_react16.useRef)(() => {
14456
13640
  });
14457
- const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
14458
- });
14459
13641
  const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
14460
13642
  });
14461
13643
  const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
@@ -14516,6 +13698,11 @@ function OhhwellsBridge() {
14516
13698
  const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
14517
13699
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
14518
13700
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
13701
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
13702
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
13703
+ floatingPanelOpenRef.current = floatingPanel !== null;
13704
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
13705
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
14519
13706
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
14520
13707
  const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
14521
13708
  const footerDragRef = (0, import_react16.useRef)(null);
@@ -14530,16 +13717,7 @@ function OhhwellsBridge() {
14530
13717
  const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
14531
13718
  const editContentRef = (0, import_react16.useRef)({});
14532
13719
  const aiSectionsRef = (0, import_react16.useRef)("");
14533
- const brandKitRef = (0, import_react16.useRef)("");
14534
- const stylesRef = (0, import_react16.useRef)("");
14535
13720
  const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
14536
- const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
14537
- const floatingPanelOpenRef = (0, import_react16.useRef)(false);
14538
- const setFloatingPanelRef = (0, import_react16.useRef)(setFloatingPanel);
14539
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
14540
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
14541
- const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
14542
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
14543
13721
  const [sitePages, setSitePages] = (0, import_react16.useState)([]);
14544
13722
  const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
14545
13723
  const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
@@ -14548,18 +13726,7 @@ function OhhwellsBridge() {
14548
13726
  const linkPopoverOpenRef = (0, import_react16.useRef)(false);
14549
13727
  const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
14550
13728
  setLinkPopoverRef.current = setLinkPopover;
14551
- setFloatingPanelRef.current = setFloatingPanel;
14552
13729
  linkPopoverSessionRef.current = linkPopover;
14553
- floatingPanelOpenRef.current = Boolean(floatingPanel);
14554
- (0, import_react16.useEffect)(() => {
14555
- const syncViewport = () => {
14556
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
14557
- setEditorViewport((prev) => prev === next ? prev : next);
14558
- };
14559
- syncViewport();
14560
- window.addEventListener("resize", syncViewport);
14561
- return () => window.removeEventListener("resize", syncViewport);
14562
- }, []);
14563
13730
  const {
14564
13731
  navDragRef,
14565
13732
  navDropSlots,
@@ -14782,10 +13949,6 @@ function OhhwellsBridge() {
14782
13949
  setIsItemDragging(false);
14783
13950
  hoveredNavContainerRef.current = null;
14784
13951
  setHoveredNavContainerRect(null);
14785
- hoveredItemElRef.current = null;
14786
- setHoveredItemRect(null);
14787
- setFloatingPanel(null);
14788
- setLogoSizeDraft(null);
14789
13952
  if (!activeElRef.current) {
14790
13953
  setNavGroupForceOpen(null, false);
14791
13954
  setToolbarRect(null);
@@ -15491,8 +14654,6 @@ function OhhwellsBridge() {
15491
14654
  setToolbarRect(anchor.getBoundingClientRect());
15492
14655
  setToolbarShowEditLink(false);
15493
14656
  setActiveCommands(/* @__PURE__ */ new Set());
15494
- setFloatingPanel(null);
15495
- setLogoSizeDraft(null);
15496
14657
  }, [deactivate, markSelected]);
15497
14658
  const selectFrame = (0, import_react16.useCallback)((el) => {
15498
14659
  if (!isNavigationContainer(el)) return;
@@ -15542,51 +14703,7 @@ function OhhwellsBridge() {
15542
14703
  setToolbarRect(el.getBoundingClientRect());
15543
14704
  setToolbarShowEditLink(false);
15544
14705
  setActiveCommands(/* @__PURE__ */ new Set());
15545
- setFloatingPanel(null);
15546
- setLogoSizeDraft(null);
15547
14706
  }, [deactivate, markSelected, postToParent2]);
15548
- const selectLogo = (0, import_react16.useCallback)(
15549
- (logoEl) => {
15550
- if (activeElRef.current) deactivate();
15551
- selectedElRef.current = logoEl;
15552
- selectedHrefKeyRef.current = null;
15553
- selectedFooterColAttrRef.current = null;
15554
- markSelected(logoEl);
15555
- setSelectedIsCta(false);
15556
- setSelectedIsSocial(false);
15557
- setSelectedIsSocialsRow(false);
15558
- clearHrefKeyHover(logoEl);
15559
- hoveredNavContainerRef.current = null;
15560
- setHoveredNavContainerRect(null);
15561
- setHoveredItemRect(null);
15562
- hoveredItemElRef.current = null;
15563
- siblingHintElRef.current = null;
15564
- setSiblingHintRect(null);
15565
- setSiblingHintRects([]);
15566
- setIsItemDragging(false);
15567
- setReorderHrefKey(null);
15568
- setReorderDragDisabled(false);
15569
- setIsFooterFrameSelection(false);
15570
- setToolbarVariant("logo");
15571
- setToolbarRect(getLogoInteractionRect(logoEl));
15572
- setToolbarShowEditLink(false);
15573
- setActiveCommands(/* @__PURE__ */ new Set());
15574
- },
15575
- [deactivate, markSelected]
15576
- );
15577
- const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
15578
- const placement = getLogoPlacement(logoEl);
15579
- const draft = readLogoSizeState(editContentRef.current, placement);
15580
- setLogoSizeDraft(draft);
15581
- setParentScrollSnap(parentScrollRef.current);
15582
- setFloatingPanel({
15583
- key: `logo-size:${placement}`,
15584
- title: "Logo",
15585
- context: placement === "navbar" ? "Navbar" : "Footer",
15586
- kind: "logo-size",
15587
- placement
15588
- });
15589
- }, []);
15590
14707
  const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
15591
14708
  setParentScrollSnap(parentScrollRef.current);
15592
14709
  setFloatingPanel({
@@ -15622,53 +14739,13 @@ function OhhwellsBridge() {
15622
14739
  );
15623
14740
  const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
15624
14741
  setFloatingPanel(null);
15625
- setLogoSizeDraft(null);
15626
14742
  }, []);
14743
+ const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(closeFloatingPanelOnly);
14744
+ closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
15627
14745
  const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
15628
14746
  setFloatingPanel(null);
15629
- setLogoSizeDraft(null);
15630
14747
  deselectRef.current();
15631
14748
  }, []);
15632
- const persistLogoSizeDraft = (0, import_react16.useCallback)(
15633
- (placement, draft) => {
15634
- const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
15635
- const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
15636
- const nodes = [
15637
- { key: desktopKey, text: String(draft.desktopPx) }
15638
- ];
15639
- if (draft.mobileFollowing) {
15640
- nodes.push({ key: mobileKey, text: "" });
15641
- } else {
15642
- nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
15643
- }
15644
- editContentRef.current = {
15645
- ...editContentRef.current,
15646
- [desktopKey]: String(draft.desktopPx),
15647
- [mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
15648
- };
15649
- applyLogoSizeToPlacement(
15650
- placement,
15651
- draft.desktopPx,
15652
- draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
15653
- draft.mobileFollowing
15654
- );
15655
- postToParent2({ type: "ow:change", nodes });
15656
- requestAnimationFrame(() => {
15657
- const selected = selectedElRef.current;
15658
- if (!selected || toolbarVariantRef.current !== "logo") return;
15659
- const rect = getLogoInteractionRect(selected);
15660
- setToolbarRect(rect);
15661
- if (glowElRef.current) {
15662
- const GAP = SELECTION_CHROME_GAP2;
15663
- glowElRef.current.style.top = `${rect.top - GAP}px`;
15664
- glowElRef.current.style.left = `${rect.left - GAP}px`;
15665
- glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
15666
- glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
15667
- }
15668
- });
15669
- },
15670
- [postToParent2]
15671
- );
15672
14749
  const activate = (0, import_react16.useCallback)((el, options) => {
15673
14750
  if (activeElRef.current === el) return;
15674
14751
  if (isIconEditable(el)) return;
@@ -15749,37 +14826,7 @@ function OhhwellsBridge() {
15749
14826
  deactivateRef.current = deactivate;
15750
14827
  selectRef.current = select;
15751
14828
  selectFrameRef.current = selectFrame;
15752
- selectLogoRef.current = selectLogo;
15753
- openLogoSizePanelRef.current = openLogoSizePanel;
15754
14829
  deselectRef.current = deselect;
15755
- closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
15756
- const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
15757
- (0, import_react16.useEffect)(() => {
15758
- if (!isEditMode) {
15759
- if (lastSiteWideScopeRef.current !== false) {
15760
- lastSiteWideScopeRef.current = false;
15761
- postToParent2({ type: "ow:site-wide-scope", active: false });
15762
- }
15763
- return;
15764
- }
15765
- const active = isSiteWideScopeActive({
15766
- selected: selectedElRef.current,
15767
- hoveredItem: hoveredItemElRef.current,
15768
- hoveredNavContainer: hoveredNavContainerRef.current,
15769
- active: activeElRef.current
15770
- });
15771
- if (lastSiteWideScopeRef.current === active) return;
15772
- lastSiteWideScopeRef.current = active;
15773
- postToParent2({ type: "ow:site-wide-scope", active });
15774
- }, [
15775
- isEditMode,
15776
- hoveredItemRect,
15777
- hoveredNavContainerRect,
15778
- toolbarVariant,
15779
- toolbarRect,
15780
- isFooterFrameSelection,
15781
- postToParent2
15782
- ]);
15783
14830
  (0, import_react16.useLayoutEffect)(() => {
15784
14831
  if (!subdomain || isEditMode) {
15785
14832
  setFetchState("done");
@@ -15791,23 +14838,9 @@ function OhhwellsBridge() {
15791
14838
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
15792
14839
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
15793
14840
  }
15794
- if (typeof content[BRAND_KIT_KEY] === "string") {
15795
- brandKitRef.current = content[BRAND_KIT_KEY];
15796
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
15797
- }
15798
- if (typeof content[STYLE_STORE_KEY] === "string") {
15799
- stylesRef.current = content[STYLE_STORE_KEY];
15800
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
15801
- }
15802
- applyBrandChrome(content);
15803
14841
  for (const [key, val] of Object.entries(content)) {
15804
14842
  if (key === "__ohw_sections") continue;
15805
14843
  if (key === AI_SECTIONS_KEY) continue;
15806
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15807
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15808
- if (key === BRAND_KIT_KEY) continue;
15809
- if (key === STYLE_STORE_KEY) continue;
15810
- if (BRAND_CHROME_KEYS.has(key)) continue;
15811
14844
  if (applyVideoSettingNode(key, val)) continue;
15812
14845
  if (applyCarouselNode(key, val)) continue;
15813
14846
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15842,8 +14875,6 @@ function OhhwellsBridge() {
15842
14875
  });
15843
14876
  applyLinkByKey(key, val);
15844
14877
  }
15845
- applyLogoFromContent(content);
15846
- applyLogoSizes(content);
15847
14878
  reconcileNavbarItemsFromContent(content);
15848
14879
  reconcileFooterOrderFromContent(content);
15849
14880
  reconcileSocialsFromContent(content);
@@ -15864,9 +14895,7 @@ function OhhwellsBridge() {
15864
14895
  let cancelled = false;
15865
14896
  setFetchState("loading");
15866
14897
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15867
- const initialPath = pathname;
15868
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
15869
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
14898
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15870
14899
  if (cancelled) return;
15871
14900
  const content = data?.content ?? {};
15872
14901
  contentCache.set(subdomain, content);
@@ -15890,21 +14919,8 @@ function OhhwellsBridge() {
15890
14919
  initSectionInstancesFromContent(content, window.location.pathname);
15891
14920
  observer?.disconnect();
15892
14921
  try {
15893
- applyBrandChrome(content);
15894
- if (typeof content[BRAND_KIT_KEY] === "string") {
15895
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
15896
- }
15897
- if (typeof content[STYLE_STORE_KEY] === "string") {
15898
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
15899
- }
15900
14922
  for (const [key, val] of Object.entries(content)) {
15901
14923
  if (key === "__ohw_sections") continue;
15902
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15903
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15904
- if (key === BRAND_KIT_KEY) continue;
15905
- if (key === STYLE_STORE_KEY) continue;
15906
- if (key === STYLE_STORE_KEY) continue;
15907
- if (BRAND_CHROME_KEYS.has(key)) continue;
15908
14924
  if (applyVideoSettingNode(key, val)) continue;
15909
14925
  if (applyCarouselNode(key, val)) continue;
15910
14926
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15925,7 +14941,6 @@ function OhhwellsBridge() {
15925
14941
  });
15926
14942
  applyLinkByKey(key, val);
15927
14943
  }
15928
- applyLogoFromContent(content);
15929
14944
  reconcileNavbarItemsFromContent(content);
15930
14945
  reconcileFooterOrderFromContent(content);
15931
14946
  reconcileSocialsFromContent(content);
@@ -15940,17 +14955,6 @@ function OhhwellsBridge() {
15940
14955
  debounceTimer = setTimeout(applyFromCache, 150);
15941
14956
  };
15942
14957
  applyFromCache();
15943
- const pathCacheKey = `${subdomain}::${pathname}`;
15944
- if (!fetchedContentPaths.has(pathCacheKey)) {
15945
- fetchedContentPaths.add(pathCacheKey);
15946
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15947
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15948
- if (!data?.content) return;
15949
- contentCache.set(subdomain, data.content);
15950
- applyFromCache();
15951
- }).catch(() => {
15952
- });
15953
- }
15954
14958
  observer = new MutationObserver(scheduleApply);
15955
14959
  observer.observe(document.body, { childList: true, subtree: true });
15956
14960
  return () => {
@@ -16044,31 +15048,26 @@ function OhhwellsBridge() {
16044
15048
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
16045
15049
  (0, import_react16.useEffect)(() => {
16046
15050
  if (!isEditMode) return;
16047
- let lastPosted = 0;
16048
15051
  const measure = () => {
16049
15052
  const h = document.body.scrollHeight;
16050
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
16051
- lastPosted = h;
16052
- postToParent2({ type: "ow:height", height: h });
16053
- }
16054
- };
16055
- let raf = null;
16056
- const schedule = () => {
16057
- if (raf != null) return;
16058
- raf = requestAnimationFrame(() => {
16059
- raf = null;
16060
- measure();
16061
- });
15053
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
16062
15054
  };
16063
15055
  const t1 = setTimeout(measure, 50);
16064
15056
  const t2 = setTimeout(measure, 500);
16065
- const ro = new ResizeObserver(schedule);
16066
- ro.observe(document.body);
15057
+ let lastWidth = window.innerWidth;
15058
+ let resizeTimer = null;
15059
+ const handleResize = () => {
15060
+ if (window.innerWidth === lastWidth) return;
15061
+ lastWidth = window.innerWidth;
15062
+ if (resizeTimer) clearTimeout(resizeTimer);
15063
+ resizeTimer = setTimeout(measure, 150);
15064
+ };
15065
+ window.addEventListener("resize", handleResize);
16067
15066
  return () => {
16068
15067
  clearTimeout(t1);
16069
15068
  clearTimeout(t2);
16070
- if (raf != null) cancelAnimationFrame(raf);
16071
- ro.disconnect();
15069
+ if (resizeTimer) clearTimeout(resizeTimer);
15070
+ window.removeEventListener("resize", handleResize);
16072
15071
  };
16073
15072
  }, [pathname, isEditMode, postToParent2]);
16074
15073
  (0, import_react16.useEffect)(() => {
@@ -16218,12 +15217,10 @@ function OhhwellsBridge() {
16218
15217
  return;
16219
15218
  }
16220
15219
  const target = e.target;
16221
- if (target.closest("[data-ohw-ai-review]")) return;
16222
15220
  if (target.closest("[data-ohw-toolbar]")) return;
16223
15221
  if (target.closest("[data-ohw-state-toggle]")) return;
16224
15222
  if (target.closest("[data-ohw-max-badge]")) return;
16225
15223
  if (isInsideLinkEditor(target)) return;
16226
- if (isInsideFloatingPanel(target)) return;
16227
15224
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
16228
15225
  const beneath = document.elementsFromPoint(e.clientX, e.clientY).find(
16229
15226
  (el) => el instanceof HTMLElement && !el.closest("[data-ohw-bridge-root]") && el.closest("[data-ohw-section]") != null
@@ -16287,21 +15284,6 @@ function OhhwellsBridge() {
16287
15284
  return;
16288
15285
  }
16289
15286
  }
16290
- const logoEl = getLogoElement(target);
16291
- if (logoEl) {
16292
- e.preventDefault();
16293
- e.stopPropagation();
16294
- if (!logoHasUploadedImage(logoEl)) {
16295
- deselectRef.current();
16296
- deactivateRef.current();
16297
- const identity = readLogoIdentityFromDom();
16298
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
16299
- return;
16300
- }
16301
- selectLogoRef.current(logoEl);
16302
- openLogoSizePanelRef.current(logoEl);
16303
- return;
16304
- }
16305
15287
  const editable = target.closest("[data-ohw-editable]");
16306
15288
  if (editable) {
16307
15289
  if (editable.dataset.ohwEditable === "link") {
@@ -16454,12 +15436,10 @@ function OhhwellsBridge() {
16454
15436
  };
16455
15437
  const handleDblClick = (e) => {
16456
15438
  const target = e.target;
16457
- if (target.closest("[data-ohw-ai-review]")) return;
16458
15439
  if (target.closest("[data-ohw-toolbar]")) return;
16459
15440
  if (target.closest("[data-ohw-state-toggle]")) return;
16460
15441
  if (target.closest("[data-ohw-max-badge]")) return;
16461
15442
  if (isInsideLinkEditor(target)) return;
16462
- if (isInsideFloatingPanel(target)) return;
16463
15443
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
16464
15444
  return;
16465
15445
  }
@@ -16487,14 +15467,11 @@ function OhhwellsBridge() {
16487
15467
  setHoveredNavContainerRect(null);
16488
15468
  return;
16489
15469
  }
16490
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
15470
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
16491
15471
  hoveredItemElRef.current = null;
16492
15472
  setHoveredItemRect(null);
16493
15473
  hoveredNavContainerRef.current = null;
16494
15474
  setHoveredNavContainerRect(null);
16495
- siblingHintElRef.current = null;
16496
- setSiblingHintRect(null);
16497
- setSiblingHintRects([]);
16498
15475
  return;
16499
15476
  }
16500
15477
  {
@@ -16504,7 +15481,7 @@ function OhhwellsBridge() {
16504
15481
  const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
16505
15482
  if (allowNavContainerHover) {
16506
15483
  const navContainer = target.closest("[data-ohw-nav-container]");
16507
- if (navContainer && !getNavigationItemAnchor(target) && !getLogoElement(target)) {
15484
+ if (navContainer && !getNavigationItemAnchor(target)) {
16508
15485
  hoveredNavContainerRef.current = navContainer;
16509
15486
  setHoveredNavContainerRect(navContainer.getBoundingClientRect());
16510
15487
  hoveredItemElRef.current = null;
@@ -16533,15 +15510,6 @@ function OhhwellsBridge() {
16533
15510
  setHoveredNavContainerRect(null);
16534
15511
  }
16535
15512
  }
16536
- const logoEl = getLogoElement(target);
16537
- if (logoEl) {
16538
- hoveredNavContainerRef.current = null;
16539
- setHoveredNavContainerRect(null);
16540
- if (selectedElRef.current === logoEl) return;
16541
- hoveredItemElRef.current = logoEl;
16542
- setHoveredItemRect(getLogoInteractionRect(logoEl));
16543
- return;
16544
- }
16545
15513
  const navAnchor = getNavigationItemAnchor(target);
16546
15514
  if (navAnchor) {
16547
15515
  hoveredNavContainerRef.current = null;
@@ -16579,11 +15547,6 @@ function OhhwellsBridge() {
16579
15547
  setHoveredItemRect(hoverTarget.getBoundingClientRect());
16580
15548
  } else if (!isInsideNavigationItem(editable)) {
16581
15549
  hoverTarget.setAttribute("data-ohw-hovered", "");
16582
- if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
16583
- hoveredNavContainerRef.current = null;
16584
- setHoveredNavContainerRect(null);
16585
- hoveredItemElRef.current = editable;
16586
- }
16587
15550
  }
16588
15551
  }
16589
15552
  };
@@ -16619,18 +15582,6 @@ function OhhwellsBridge() {
16619
15582
  }
16620
15583
  return;
16621
15584
  }
16622
- const logoEl = getLogoElement(target);
16623
- if (logoEl) {
16624
- const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
16625
- if (related2 && (logoEl === related2 || logoEl.contains(related2) || related2.closest?.('[data-ohw-role="logo"], [data-ohw-logo]'))) {
16626
- return;
16627
- }
16628
- if (hoveredItemElRef.current === logoEl) {
16629
- hoveredItemElRef.current = null;
16630
- setHoveredItemRect(null);
16631
- }
16632
- return;
16633
- }
16634
15585
  const editable = target.closest("[data-ohw-editable]");
16635
15586
  if (!editable) return;
16636
15587
  const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
@@ -16651,13 +15602,6 @@ function OhhwellsBridge() {
16651
15602
  }
16652
15603
  } else {
16653
15604
  hoverTarget.removeAttribute("data-ohw-hovered");
16654
- if (hoveredItemElRef.current === editable) {
16655
- const stillOnEditable = related instanceof Element && related.closest("[data-ohw-editable]") === editable;
16656
- if (!stillOnEditable) {
16657
- hoveredItemElRef.current = null;
16658
- setHoveredItemRect(null);
16659
- }
16660
- }
16661
15605
  }
16662
15606
  }
16663
15607
  };
@@ -16774,26 +15718,6 @@ function OhhwellsBridge() {
16774
15718
  hoveredNavContainerRef.current = null;
16775
15719
  setHoveredNavContainerRect(null);
16776
15720
  }
16777
- const logoCandidates = [
16778
- ...document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]'),
16779
- ...document.querySelectorAll("nav a:not([data-ohw-href-key]), [data-ohw-nav-root] a:not([data-ohw-href-key])"),
16780
- ...document.querySelectorAll("footer img")
16781
- ];
16782
- const seenLogos = /* @__PURE__ */ new Set();
16783
- for (const candidate of logoCandidates) {
16784
- const logo = getLogoElement(candidate);
16785
- if (!logo || seenLogos.has(logo)) continue;
16786
- seenLogos.add(logo);
16787
- const r2 = logo.getBoundingClientRect();
16788
- if (x < r2.left || x > r2.right || y < r2.top || y > r2.bottom) continue;
16789
- hoveredNavContainerRef.current = null;
16790
- setHoveredNavContainerRect(null);
16791
- if (selectedElRef.current !== logo) {
16792
- hoveredItemElRef.current = logo;
16793
- setHoveredItemRect(getLogoInteractionRect(logo));
16794
- }
16795
- return;
16796
- }
16797
15721
  const navContainers = Array.from(
16798
15722
  document.querySelectorAll("[data-ohw-nav-container]")
16799
15723
  );
@@ -16879,7 +15803,7 @@ function OhhwellsBridge() {
16879
15803
  }
16880
15804
  };
16881
15805
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
16882
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
15806
+ if (linkPopoverOpenRef.current) {
16883
15807
  if (hoveredImageRef.current) {
16884
15808
  hoveredImageRef.current = null;
16885
15809
  hoveredImageHasTextOverlapRef.current = false;
@@ -17133,7 +16057,7 @@ function OhhwellsBridge() {
17133
16057
  }
17134
16058
  };
17135
16059
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
17136
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
16060
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17137
16061
  if (activeStateElRef.current) {
17138
16062
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
17139
16063
  activeStateElRef.current = null;
@@ -17199,21 +16123,16 @@ function OhhwellsBridge() {
17199
16123
  setSectionGap(null);
17200
16124
  }
17201
16125
  };
16126
+ const pointOwnedByFloatingPanel = (clientX, clientY) => {
16127
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return true;
16128
+ const panel = document.querySelector("[data-ohw-floating-panel]");
16129
+ if (!panel) return false;
16130
+ const rect = panel.getBoundingClientRect();
16131
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
16132
+ };
17202
16133
  const handleMouseMove = (e) => {
17203
16134
  const { clientX, clientY } = e;
17204
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17205
- hoveredItemElRef.current = null;
17206
- setHoveredItemRect(null);
17207
- hoveredNavContainerRef.current = null;
17208
- setHoveredNavContainerRect(null);
17209
- siblingHintElRef.current = null;
17210
- setSiblingHintRect(null);
17211
- setSiblingHintRects([]);
17212
- dismissImageHover();
17213
- clearImageHover();
17214
- setSectionGap(null);
17215
- return;
17216
- }
16135
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17217
16136
  probeSectionGapAt(clientX, clientY);
17218
16137
  probeImageAt(clientX, clientY);
17219
16138
  probeHoverCardsAt(clientX, clientY);
@@ -17222,11 +16141,7 @@ function OhhwellsBridge() {
17222
16141
  if (e.data?.type !== "ow:pointer-sync") return;
17223
16142
  const { clientX, clientY } = e.data;
17224
16143
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
17225
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17226
- dismissImageHover();
17227
- clearImageHover();
17228
- return;
17229
- }
16144
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17230
16145
  probeSectionGapAt(clientX, clientY);
17231
16146
  probeImageAt(clientX, clientY);
17232
16147
  probeHoverCardsAt(clientX, clientY);
@@ -17476,15 +16391,6 @@ function OhhwellsBridge() {
17476
16391
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
17477
16392
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
17478
16393
  }
17479
- if (typeof content[BRAND_KIT_KEY] === "string") {
17480
- brandKitRef.current = content[BRAND_KIT_KEY];
17481
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
17482
- }
17483
- if (typeof content[STYLE_STORE_KEY] === "string") {
17484
- stylesRef.current = content[STYLE_STORE_KEY];
17485
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17486
- }
17487
- applyBrandChrome(content);
17488
16394
  let sectionsJson = null;
17489
16395
  for (const [key, val] of Object.entries(content)) {
17490
16396
  if (key === "__ohw_sections") {
@@ -17492,11 +16398,6 @@ function OhhwellsBridge() {
17492
16398
  continue;
17493
16399
  }
17494
16400
  if (key === AI_SECTIONS_KEY) continue;
17495
- if (key === LOGO_PLACEHOLDER_KEY) continue;
17496
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
17497
- if (key === BRAND_KIT_KEY) continue;
17498
- if (key === STYLE_STORE_KEY) continue;
17499
- if (BRAND_CHROME_KEYS.has(key)) continue;
17500
16401
  if (applyVideoSettingNode(key, val)) continue;
17501
16402
  if (applyCarouselNode(key, val)) continue;
17502
16403
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -17516,8 +16417,6 @@ function OhhwellsBridge() {
17516
16417
  });
17517
16418
  applyLinkByKey(key, val);
17518
16419
  }
17519
- applyLogoFromContent(content);
17520
- applyLogoSizes(content);
17521
16420
  if (sectionsJson) {
17522
16421
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
17523
16422
  sectionsLoadedRef.current = true;
@@ -17533,58 +16432,6 @@ function OhhwellsBridge() {
17533
16432
  if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
17534
16433
  postToParentRef.current({ type: "ow:hydrate-done" });
17535
16434
  };
17536
- const handleUpdateLogoIdentity = (e) => {
17537
- if (e.data?.type !== "ow:update-logo-identity") return;
17538
- const rawText = typeof e.data.text === "string" ? e.data.text : "";
17539
- const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
17540
- const href = typeof e.data.href === "string" ? e.data.href : void 0;
17541
- const imageProvided = "image" in e.data;
17542
- const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
17543
- let isPlaceholder = e.data.isPlaceholder !== false;
17544
- if (imageUrl) isPlaceholder = false;
17545
- else if (imageProvided && imageUrl === null) {
17546
- isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
17547
- }
17548
- const display = applyLogoIdentity(rawText, isPlaceholder);
17549
- const displayAlt = resolveLogoDisplayText(alt || display);
17550
- if (imageUrl !== void 0) {
17551
- applyLogoImage(imageUrl, displayAlt);
17552
- } else {
17553
- for (const key of LOGO_IMAGE_KEYS) {
17554
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
17555
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
17556
- if (img) img.alt = displayAlt;
17557
- });
17558
- }
17559
- }
17560
- if (href !== void 0) {
17561
- applyLogoHref(href);
17562
- applyLinkByKey("nav-logo-href", href);
17563
- applyLinkByKey("footer-logo-href", href);
17564
- applyLinkByKey("logo-href", href);
17565
- }
17566
- const nodes = [
17567
- ...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
17568
- { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
17569
- { key: LOGO_ALT_KEY, text: displayAlt }
17570
- ];
17571
- if (imageUrl !== void 0) {
17572
- if (imageUrl) {
17573
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
17574
- } else {
17575
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
17576
- }
17577
- }
17578
- if (href !== void 0) {
17579
- for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
17580
- }
17581
- editContentRef.current = {
17582
- ...editContentRef.current,
17583
- ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
17584
- };
17585
- applyLogoSizes(editContentRef.current);
17586
- postToParentRef.current({ type: "ow:change", nodes });
17587
- };
17588
16435
  window.addEventListener("message", handleHydrate);
17589
16436
  const postAiSectionsChanged = () => {
17590
16437
  postToParentRef.current({
@@ -17598,10 +16445,7 @@ function OhhwellsBridge() {
17598
16445
  const payload = e.data.payload;
17599
16446
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
17600
16447
  const previous = aiSectionsRef.current;
17601
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
17602
- ...payload,
17603
- path: payload.path ?? window.location.pathname
17604
- });
16448
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
17605
16449
  const nextValue = serializeAiSectionsState(nextState);
17606
16450
  aiSectionsRef.current = nextValue;
17607
16451
  applyAiSectionsToDom(nextState);
@@ -17638,42 +16482,12 @@ function OhhwellsBridge() {
17638
16482
  const value = typeof e.data.value === "string" ? e.data.value : "";
17639
16483
  aiSectionsRef.current = value;
17640
16484
  applyAiSectionsToDom(parseAiSectionsState(value));
17641
- applyStylesToDom(parseStyleStore(stylesRef.current));
17642
16485
  const restoredHeight = document.documentElement.scrollHeight;
17643
16486
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
17644
16487
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
17645
16488
  postAiSectionsChanged();
17646
16489
  };
17647
16490
  window.addEventListener("message", handleAiSetSections);
17648
- const handleAiSetBrand = (e) => {
17649
- if (e.data?.type !== "ow:ai-set-brand") return;
17650
- const value = typeof e.data.value === "string" ? e.data.value : "";
17651
- const previous = brandKitRef.current;
17652
- brandKitRef.current = value;
17653
- applyBrandToDom(parseBrandKit(value));
17654
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
17655
- applyStylesToDom(parseStyleStore(stylesRef.current));
17656
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
17657
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
17658
- };
17659
- window.addEventListener("message", handleAiSetBrand);
17660
- const handleAiSetStyles = (e) => {
17661
- if (e.data?.type !== "ow:ai-set-styles") return;
17662
- const value = typeof e.data.value === "string" ? e.data.value : "";
17663
- const previous = stylesRef.current;
17664
- stylesRef.current = value;
17665
- applyStylesToDom(parseStyleStore(value));
17666
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
17667
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
17668
- };
17669
- window.addEventListener("message", handleAiSetStyles);
17670
- const handleGetBrand = (e) => {
17671
- if (e.data?.type !== "ow:get-brand") return;
17672
- const template = deriveTemplateBrand();
17673
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
17674
- postToParentRef.current({ type: "ow:brand-value", value });
17675
- };
17676
- window.addEventListener("message", handleGetBrand);
17677
16491
  const handleDeactivate = (e) => {
17678
16492
  if (e.data?.type !== "ow:deactivate") return;
17679
16493
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -17682,12 +16496,6 @@ function OhhwellsBridge() {
17682
16496
  closeLinkPopoverRef.current();
17683
16497
  return;
17684
16498
  }
17685
- if (floatingPanelOpenRef.current) {
17686
- setFloatingPanelRef.current(null);
17687
- deselectRef.current();
17688
- deactivateRef.current();
17689
- return;
17690
- }
17691
16499
  deselectRef.current();
17692
16500
  deactivateRef.current();
17693
16501
  };
@@ -17741,10 +16549,6 @@ function OhhwellsBridge() {
17741
16549
  return;
17742
16550
  }
17743
16551
  if (selectedElRef.current) {
17744
- if (toolbarVariantRef.current === "logo") {
17745
- deselectRef.current();
17746
- return;
17747
- }
17748
16552
  if (toolbarVariantRef.current === "select-frame") {
17749
16553
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
17750
16554
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -17784,10 +16588,6 @@ function OhhwellsBridge() {
17784
16588
  return;
17785
16589
  }
17786
16590
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
17787
- if (toolbarVariantRef.current === "logo") {
17788
- deselectRef.current();
17789
- return;
17790
- }
17791
16591
  if (toolbarVariantRef.current === "select-frame") {
17792
16592
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
17793
16593
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -17865,8 +16665,7 @@ function OhhwellsBridge() {
17865
16665
  const handleScroll = () => {
17866
16666
  const focusEl = activeElRef.current ?? selectedElRef.current;
17867
16667
  if (focusEl) {
17868
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
17869
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
16668
+ const r2 = activeElRef.current ? getEditMeasureEl(activeElRef.current).getBoundingClientRect() : focusEl.getBoundingClientRect();
17870
16669
  applyToolbarPos(r2);
17871
16670
  setToolbarRect(r2);
17872
16671
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -17876,9 +16675,7 @@ function OhhwellsBridge() {
17876
16675
  setToggleState((prev) => prev ? { ...prev, rect } : null);
17877
16676
  }
17878
16677
  if (hoveredItemElRef.current) {
17879
- const hoverEl = hoveredItemElRef.current;
17880
- const logo = getLogoElement(hoverEl);
17881
- setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
16678
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
17882
16679
  }
17883
16680
  if (hoveredNavContainerRef.current) {
17884
16681
  setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
@@ -17922,12 +16719,6 @@ function OhhwellsBridge() {
17922
16719
  if (aiSectionsRef.current) {
17923
16720
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
17924
16721
  }
17925
- if (stylesRef.current) {
17926
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
17927
- }
17928
- if (brandKitRef.current) {
17929
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
17930
- }
17931
16722
  postToParentRef.current({ type: "ow:save-result", nodes });
17932
16723
  };
17933
16724
  const handleInsertSection = (e) => {
@@ -17938,12 +16729,8 @@ function OhhwellsBridge() {
17938
16729
  if (inserted) {
17939
16730
  const tracker = getSectionsTracker();
17940
16731
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
17941
- const reportHeight = () => {
17942
- const h = document.body.scrollHeight;
17943
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17944
- };
17945
- reportHeight();
17946
- setTimeout(reportHeight, 500);
16732
+ const h = document.documentElement.scrollHeight;
16733
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17947
16734
  }
17948
16735
  };
17949
16736
  const handleSwitchSchedule = (e) => {
@@ -18136,17 +16923,13 @@ function OhhwellsBridge() {
18136
16923
  if (e.data?.type !== "ow:parent-scroll") return;
18137
16924
  const { iframeOffsetTop, headerH, canvasH } = e.data;
18138
16925
  parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
18139
- if (floatingPanelOpenRef.current) {
18140
- setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
18141
- }
18142
16926
  if (visibleViewportRef.current) {
18143
16927
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
18144
16928
  }
18145
16929
  const focusEl = activeElRef.current ?? selectedElRef.current;
18146
16930
  if (focusEl) {
18147
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
18148
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
18149
- applyToolbarPos(r2);
16931
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
16932
+ applyToolbarPos(measureEl.getBoundingClientRect());
18150
16933
  }
18151
16934
  };
18152
16935
  const handleClickAt = (e) => {
@@ -18171,25 +16954,6 @@ function OhhwellsBridge() {
18171
16954
  postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "", elementType: stateCardImage.dataset.ohwEditable ?? "image" });
18172
16955
  return;
18173
16956
  }
18174
- const logoAtPoint = Array.from(
18175
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]')
18176
- ).map((el) => getLogoElement(el)).find((logo) => {
18177
- if (!logo) return false;
18178
- const r2 = logo.getBoundingClientRect();
18179
- return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
18180
- });
18181
- if (logoAtPoint) {
18182
- if (!logoHasUploadedImage(logoAtPoint)) {
18183
- deselectRef.current();
18184
- deactivateRef.current();
18185
- const identity = readLogoIdentityFromDom();
18186
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
18187
- return;
18188
- }
18189
- selectLogoRef.current(logoAtPoint);
18190
- openLogoSizePanelRef.current(logoAtPoint);
18191
- return;
18192
- }
18193
16957
  const textEditable = Array.from(
18194
16958
  document.querySelectorAll(NON_MEDIA_SELECTOR)
18195
16959
  ).find((el) => {
@@ -18261,14 +17025,6 @@ function OhhwellsBridge() {
18261
17025
  window.addEventListener("message", handleParentScroll);
18262
17026
  window.addEventListener("message", handlePointerSync);
18263
17027
  window.addEventListener("message", handleClickAt);
18264
- window.addEventListener("message", handleUpdateLogoIdentity);
18265
- const handleViewMode = (e) => {
18266
- if (e.data?.type !== "ow:view-mode") return;
18267
- const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
18268
- setEditorViewport(mode);
18269
- applyLogoSizes(editContentRef.current);
18270
- };
18271
- window.addEventListener("message", handleViewMode);
18272
17028
  const handleViewportResize = () => {
18273
17029
  if (visibleViewportRef.current) {
18274
17030
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
@@ -18324,15 +17080,10 @@ function OhhwellsBridge() {
18324
17080
  window.removeEventListener("resize", handleViewportResize);
18325
17081
  window.removeEventListener("message", handlePointerSync);
18326
17082
  window.removeEventListener("message", handleClickAt);
18327
- window.removeEventListener("message", handleUpdateLogoIdentity);
18328
- window.removeEventListener("message", handleViewMode);
18329
17083
  window.removeEventListener("message", handleHydrate);
18330
17084
  window.removeEventListener("message", handleAiApplyTree);
18331
17085
  window.removeEventListener("message", handleAiDeleteSection);
18332
17086
  window.removeEventListener("message", handleAiSetSections);
18333
- window.removeEventListener("message", handleAiSetBrand);
18334
- window.removeEventListener("message", handleAiSetStyles);
18335
- window.removeEventListener("message", handleGetBrand);
18336
17087
  window.removeEventListener("message", handleDeactivate);
18337
17088
  window.removeEventListener("message", handleToastAction);
18338
17089
  window.removeEventListener("message", handleUiEscape);
@@ -18536,7 +17287,7 @@ function OhhwellsBridge() {
18536
17287
  postToParent2({
18537
17288
  type: "ow:ready",
18538
17289
  version: "1",
18539
- bridgeVersion: "0.1.61",
17290
+ bridgeVersion: "0.1.60",
18540
17291
  path: pathname,
18541
17292
  nodes: collectEditableNodes(editContentRef.current),
18542
17293
  sections
@@ -18931,10 +17682,10 @@ function OhhwellsBridge() {
18931
17682
  [postToParent2]
18932
17683
  );
18933
17684
  return bridgeRoot ? (0, import_react_dom4.createPortal)(
18934
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
18935
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
18936
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
18937
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17685
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
17686
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
17687
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
17688
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18938
17689
  MediaOverlay,
18939
17690
  {
18940
17691
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -18945,7 +17696,7 @@ function OhhwellsBridge() {
18945
17696
  },
18946
17697
  `uploading-${key}`
18947
17698
  )),
18948
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17699
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18949
17700
  MediaOverlay,
18950
17701
  {
18951
17702
  hover: mediaHover,
@@ -18954,11 +17705,11 @@ function OhhwellsBridge() {
18954
17705
  onVideoSettingsChange: handleVideoSettingsChange
18955
17706
  }
18956
17707
  ),
18957
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
18958
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
18959
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
18960
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
18961
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17708
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
17709
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
17710
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
17711
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
17712
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18962
17713
  "div",
18963
17714
  {
18964
17715
  className: "pointer-events-none fixed z-2147483646",
@@ -18968,7 +17719,7 @@ function OhhwellsBridge() {
18968
17719
  width: slot.width,
18969
17720
  height: slot.height
18970
17721
  },
18971
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17722
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18972
17723
  DropIndicator,
18973
17724
  {
18974
17725
  direction: slot.direction,
@@ -18979,7 +17730,7 @@ function OhhwellsBridge() {
18979
17730
  },
18980
17731
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
18981
17732
  )),
18982
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17733
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18983
17734
  "div",
18984
17735
  {
18985
17736
  className: "pointer-events-none fixed z-2147483646",
@@ -18989,7 +17740,7 @@ function OhhwellsBridge() {
18989
17740
  width: slot.width,
18990
17741
  height: slot.height
18991
17742
  },
18992
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17743
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18993
17744
  DropIndicator,
18994
17745
  {
18995
17746
  direction: slot.direction,
@@ -19000,11 +17751,11 @@ function OhhwellsBridge() {
19000
17751
  },
19001
17752
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
19002
17753
  )),
19003
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19004
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19005
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19006
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19007
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17754
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
17755
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
17756
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
17757
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
17758
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19008
17759
  FooterContainerChrome,
19009
17760
  {
19010
17761
  rect: toolbarRect,
@@ -19012,7 +17763,7 @@ function OhhwellsBridge() {
19012
17763
  addDisabled: !canAddFooterColumn()
19013
17764
  }
19014
17765
  ),
19015
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17766
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19016
17767
  ItemInteractionLayer,
19017
17768
  {
19018
17769
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -19024,10 +17775,10 @@ function OhhwellsBridge() {
19024
17775
  dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
19025
17776
  onDragHandleDragStart: handleItemDragStart,
19026
17777
  onDragHandleDragEnd: handleItemDragEnd,
19027
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
19028
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
19029
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
19030
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17778
+ onItemPointerDown: handleItemChromePointerDown,
17779
+ onItemClick: handleItemChromeClick,
17780
+ itemDragSurface: !isFooterFrameSelection,
17781
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19031
17782
  ItemActionToolbar,
19032
17783
  {
19033
17784
  onEditLink: openLinkPopoverForSelected,
@@ -19063,8 +17814,8 @@ function OhhwellsBridge() {
19063
17814
  ) : void 0
19064
17815
  }
19065
17816
  ),
19066
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19067
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17817
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
17818
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19068
17819
  EditGlowChrome,
19069
17820
  {
19070
17821
  rect: toolbarRect,
@@ -19074,7 +17825,7 @@ function OhhwellsBridge() {
19074
17825
  hideHandle: isItemDragging
19075
17826
  }
19076
17827
  ),
19077
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17828
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19078
17829
  FloatingToolbar,
19079
17830
  {
19080
17831
  rect: toolbarRect,
@@ -19087,7 +17838,7 @@ function OhhwellsBridge() {
19087
17838
  }
19088
17839
  )
19089
17840
  ] }),
19090
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
17841
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
19091
17842
  "div",
19092
17843
  {
19093
17844
  "data-ohw-max-badge": "",
@@ -19113,7 +17864,7 @@ function OhhwellsBridge() {
19113
17864
  ]
19114
17865
  }
19115
17866
  ),
19116
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17867
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19117
17868
  StateToggle,
19118
17869
  {
19119
17870
  rect: toggleState.rect,
@@ -19122,15 +17873,15 @@ function OhhwellsBridge() {
19122
17873
  onStateChange: handleStateChange
19123
17874
  }
19124
17875
  ),
19125
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
17876
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
19126
17877
  "div",
19127
17878
  {
19128
17879
  "data-ohw-section-insert-line": "",
19129
17880
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
19130
17881
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
19131
17882
  children: [
19132
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19133
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17883
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
17884
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19134
17885
  Badge,
19135
17886
  {
19136
17887
  className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
@@ -19147,11 +17898,11 @@ function OhhwellsBridge() {
19147
17898
  children: "Add Section"
19148
17899
  }
19149
17900
  ),
19150
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
17901
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19151
17902
  ]
19152
17903
  }
19153
17904
  ),
19154
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17905
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19155
17906
  LinkPopover,
19156
17907
  {
19157
17908
  panelRef: linkPopoverPanelRef,
@@ -19168,7 +17919,7 @@ function OhhwellsBridge() {
19168
17919
  },
19169
17920
  linkPopover.key
19170
17921
  ) : null,
19171
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17922
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19172
17923
  FloatingPanel,
19173
17924
  {
19174
17925
  open: true,
@@ -19178,7 +17929,7 @@ function OhhwellsBridge() {
19178
17929
  onPositionChange: setFloatingPanelPos,
19179
17930
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
19180
17931
  onClose: closeFloatingPanelOnly,
19181
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17932
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
19182
17933
  SocialsDisplayPanel,
19183
17934
  {
19184
17935
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -19189,115 +17940,11 @@ function OhhwellsBridge() {
19189
17940
  }
19190
17941
  )
19191
17942
  }
19192
- ) : null,
19193
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19194
- FloatingPanel,
19195
- {
19196
- open: true,
19197
- title: floatingPanel.title,
19198
- context: floatingPanel.context,
19199
- position: floatingPanelPos,
19200
- onPositionChange: setFloatingPanelPos,
19201
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
19202
- onClose: closeFloatingPanelAndDeselect,
19203
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19204
- LogoSizePanel,
19205
- {
19206
- viewport: editorViewport,
19207
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
19208
- mobileFollowing: logoSizeDraft.mobileFollowing,
19209
- onSizeChange: (px) => {
19210
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
19211
- ...logoSizeDraft,
19212
- desktopPx: px,
19213
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
19214
- };
19215
- setLogoSizeDraft(next);
19216
- persistLogoSizeDraft(floatingPanel.placement, next);
19217
- },
19218
- onCustomizeMobile: () => {
19219
- const next = {
19220
- ...logoSizeDraft,
19221
- mobileFollowing: false,
19222
- mobilePx: logoSizeDraft.desktopPx
19223
- };
19224
- setLogoSizeDraft(next);
19225
- persistLogoSizeDraft(floatingPanel.placement, next);
19226
- },
19227
- onResetMobile: () => {
19228
- const next = {
19229
- ...logoSizeDraft,
19230
- mobileFollowing: true,
19231
- mobilePx: logoSizeDraft.desktopPx
19232
- };
19233
- setLogoSizeDraft(next);
19234
- persistLogoSizeDraft(floatingPanel.placement, next);
19235
- },
19236
- onUpdateEverywhere: () => {
19237
- const identity = readLogoIdentityFromDom();
19238
- postToParent2({ type: "ow:open-logo-settings", ...identity });
19239
- }
19240
- }
19241
- )
19242
- }
19243
17943
  ) : null
19244
17944
  ] }),
19245
17945
  bridgeRoot
19246
17946
  ) : null;
19247
17947
  }
19248
-
19249
- // src/ui/EmptySection.tsx
19250
- var import_link = __toESM(require("next/link"), 1);
19251
- var import_jsx_runtime34 = require("react/jsx-runtime");
19252
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
19253
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
19254
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19255
- "p",
19256
- {
19257
- style: {
19258
- fontFamily: "var(--brand-font-body)",
19259
- fontSize: "0.75rem",
19260
- fontWeight: 500,
19261
- letterSpacing: "0.15em",
19262
- textTransform: "uppercase",
19263
- color: "var(--brand-accent)",
19264
- marginBottom: "1.5rem"
19265
- },
19266
- 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" }) })
19267
- }
19268
- ),
19269
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19270
- "h1",
19271
- {
19272
- style: {
19273
- fontFamily: "var(--brand-font-heading)",
19274
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
19275
- lineHeight: 1.1,
19276
- letterSpacing: "-0.025em",
19277
- color: "var(--brand-text)",
19278
- marginBottom: "1rem"
19279
- },
19280
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
19281
- children: title
19282
- }
19283
- ),
19284
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19285
- "p",
19286
- {
19287
- style: {
19288
- fontFamily: "var(--brand-font-body)",
19289
- fontSize: "1rem",
19290
- lineHeight: 1.7,
19291
- fontWeight: 300,
19292
- color: "var(--brand-text-muted)",
19293
- maxWidth: "340px"
19294
- },
19295
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
19296
- children: "This page doesn't have any content yet."
19297
- }
19298
- )
19299
- ] });
19300
- }
19301
17948
  // Annotate the CommonJS export names for ESM import in node:
19302
17949
  0 && (module.exports = {
19303
17950
  AI_DEFAULT_BRAND,
@@ -19315,7 +17962,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
19315
17962
  DropdownMenuItem,
19316
17963
  DropdownMenuSeparator,
19317
17964
  DropdownMenuTrigger,
19318
- EmptySection,
19319
17965
  ItemActionToolbar,
19320
17966
  ItemInteractionLayer,
19321
17967
  LinkEditorPanel,