@ohhwells/bridge 0.1.65-next.189 → 0.1.65

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,
@@ -157,12 +156,7 @@ function parseAiSectionsState(raw) {
157
156
  media: entry.media && typeof entry.media === "object" ? entry.media : {}
158
157
  }));
159
158
  const removed = Array.isArray(parsed.removed) ? parsed.removed.filter((id) => typeof id === "string" && id.length > 0) : [];
160
- return {
161
- v: 1,
162
- sections,
163
- ...removed.length ? { removed } : {},
164
- ...parsed.hideTemplate === true ? { hideTemplate: true } : {}
165
- };
159
+ return { v: 1, sections, ...removed.length ? { removed } : {} };
166
160
  } catch {
167
161
  return EMPTY_AI_SECTIONS;
168
162
  }
@@ -175,7 +169,6 @@ function applyTreeToState(state, payload) {
175
169
  const entry = {
176
170
  id: payload.id,
177
171
  label: payload.label ?? "Generated section",
178
- ...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
179
172
  afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
180
173
  ...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
181
174
  ...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
@@ -198,317 +191,6 @@ function deleteSectionFromState(state, sectionId) {
198
191
  return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
199
192
  }
200
193
 
201
- // src/lib/brand-chrome.ts
202
- var BRAND_NAME_KEY = "__ohw_brand_name";
203
- var BRAND_TITLE_KEY = "__ohw_site_title";
204
- var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
205
- var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
206
- BRAND_NAME_KEY,
207
- BRAND_TITLE_KEY,
208
- BRAND_FAVICON_LETTER_KEY
209
- ]);
210
- function upsertMeta(selector, attr, token, value) {
211
- let el = document.head.querySelector(selector);
212
- if (!el) {
213
- el = document.createElement("meta");
214
- el.setAttribute(attr, token);
215
- document.head.appendChild(el);
216
- }
217
- if (el.getAttribute("content") !== value) el.setAttribute("content", value);
218
- }
219
- function escapeXml(value) {
220
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
221
- }
222
- function applyLetterFavicon(letter) {
223
- 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>`;
224
- const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
225
- let link = document.head.querySelector('link[rel="icon"]');
226
- if (!link) {
227
- link = document.createElement("link");
228
- link.rel = "icon";
229
- document.head.appendChild(link);
230
- }
231
- link.type = "image/svg+xml";
232
- if (link.href !== href) link.href = href;
233
- }
234
- function applyBrandChrome(content) {
235
- const name = content[BRAND_NAME_KEY];
236
- if (typeof name === "string" && name.length > 0) {
237
- document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
238
- if (el.textContent !== name) el.textContent = name;
239
- if (el.getAttribute("title") !== name) el.setAttribute("title", name);
240
- });
241
- }
242
- const title = content[BRAND_TITLE_KEY];
243
- if (typeof title === "string" && title.length > 0) {
244
- if (document.title !== title) document.title = title;
245
- upsertMeta('meta[property="og:title"]', "property", "og:title", title);
246
- upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
247
- }
248
- const letter = content[BRAND_FAVICON_LETTER_KEY];
249
- if (typeof letter === "string" && letter.length > 0) {
250
- applyLetterFavicon(letter);
251
- }
252
- }
253
-
254
- // src/lib/brand-kit.ts
255
- var BRAND_KIT_KEY = "__ohw_brand";
256
- var BRAND_VAR_PREFIX = "--ohw-brand-";
257
- var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
258
- (role) => `${BRAND_VAR_PREFIX}${role}`
259
- );
260
- var FONT_VARS = {
261
- heading: ["--font-heading", "--font-display", "--brand-font-heading"],
262
- body: ["--font-body", "--brand-font-body"]
263
- };
264
- var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
265
- function brandColorVars(kit) {
266
- const { dark, primary, accent, light } = kit.palette;
267
- const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
268
- return {
269
- [`${BRAND_VAR_PREFIX}primary`]: primary,
270
- [`${BRAND_VAR_PREFIX}accent`]: accent,
271
- [`${BRAND_VAR_PREFIX}light`]: light,
272
- [`${BRAND_VAR_PREFIX}dark`]: dark,
273
- [`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
274
- [`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
275
- [`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
276
- };
277
- }
278
- function parseBrandKit(raw) {
279
- if (!raw) return null;
280
- try {
281
- const parsed = JSON.parse(raw);
282
- const p = parsed?.palette;
283
- const f = parsed?.fonts;
284
- 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") {
285
- return null;
286
- }
287
- return {
288
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
289
- fonts: { heading: f.heading, body: f.body }
290
- };
291
- } catch {
292
- return null;
293
- }
294
- }
295
- function familyOf(stack) {
296
- const first = stack.split(",")[0]?.trim() ?? "";
297
- return first.replace(/^['"]|['"]$/g, "");
298
- }
299
- function loadBrandFonts(families) {
300
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
301
- if (unique.length === 0) return;
302
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
303
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
304
- let link = document.getElementById(BRAND_FONT_LINK_ID);
305
- if (!link) {
306
- link = document.createElement("link");
307
- link.id = BRAND_FONT_LINK_ID;
308
- link.rel = "stylesheet";
309
- document.head.appendChild(link);
310
- }
311
- if (link.href !== href) link.href = href;
312
- }
313
- function applyBrandToDom(kit) {
314
- const root = document.documentElement;
315
- if (!kit) {
316
- for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
317
- for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
318
- document.getElementById(BRAND_FONT_LINK_ID)?.remove();
319
- return;
320
- }
321
- for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
322
- for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
323
- for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
324
- loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
325
- }
326
-
327
- // src/lib/section-styles.ts
328
- var STYLE_STORE_KEY = "__ohw_styles";
329
- var STYLE_SHEET_ID = "ohw-section-styles";
330
- function parseStyleStore(raw) {
331
- if (!raw) return null;
332
- try {
333
- const parsed = JSON.parse(raw);
334
- if (parsed?.v !== 1) return null;
335
- return {
336
- v: 1,
337
- sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
338
- nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
339
- };
340
- } catch {
341
- return null;
342
- }
343
- }
344
- var BG_VALUES = {
345
- surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
346
- accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
347
- "accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
348
- };
349
- var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
350
- function styleSheetCss() {
351
- const rules = [];
352
- for (const [tone, value] of Object.entries(BG_VALUES)) {
353
- rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
354
- }
355
- rules.push(
356
- `[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
357
- );
358
- rules.push(
359
- `[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
360
- `[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
361
- );
362
- for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
363
- rules.push(
364
- `[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
365
- );
366
- }
367
- rules.push(
368
- `[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
369
- );
370
- for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
371
- rules.push(
372
- `[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
373
- );
374
- }
375
- const pad = { tight: 40, balanced: 64, airy: 96 };
376
- for (const [spacing, px] of Object.entries(pad)) {
377
- rules.push(
378
- `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
379
- );
380
- }
381
- return rules.join("\n");
382
- }
383
- var STYLE_FONT_LINK_ID = "ohw-style-fonts";
384
- function loadStyleFonts(families) {
385
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
386
- const existing = document.getElementById(STYLE_FONT_LINK_ID);
387
- if (unique.length === 0) {
388
- existing?.remove();
389
- return;
390
- }
391
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
392
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
393
- let link = existing;
394
- if (!link) {
395
- link = document.createElement("link");
396
- link.id = STYLE_FONT_LINK_ID;
397
- link.rel = "stylesheet";
398
- document.head.appendChild(link);
399
- }
400
- if (link.href !== href) link.href = href;
401
- }
402
- var SECTION_ATTRS = {
403
- sectionBackground: "data-ohw-style-bg",
404
- textDistribution: "data-ohw-style-distribution",
405
- headlineScale: "data-ohw-style-headline",
406
- imageAspect: "data-ohw-style-aspect",
407
- spacing: "data-ohw-style-spacing"
408
- };
409
- var NODE_WROTE_ATTR = "data-ohw-style-node";
410
- var NODE_PROPS = ["color", "font-family", "font-size", "background"];
411
- function saveInline(el, prop) {
412
- const attr = `data-ohw-style-prev-${prop}`;
413
- if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
414
- }
415
- function restoreInline(el, prop) {
416
- const attr = `data-ohw-style-prev-${prop}`;
417
- if (!el.hasAttribute(attr)) return;
418
- const prev = el.getAttribute(attr) ?? "";
419
- if (prev) el.style.setProperty(prop, prev);
420
- else el.style.removeProperty(prop);
421
- el.removeAttribute(attr);
422
- }
423
- function ensureStyleSheet() {
424
- let el = document.getElementById(STYLE_SHEET_ID);
425
- if (!el) {
426
- el = document.createElement("style");
427
- el.id = STYLE_SHEET_ID;
428
- document.head.appendChild(el);
429
- }
430
- const css = styleSheetCss();
431
- if (el.textContent !== css) el.textContent = css;
432
- }
433
- function clearSectionAttrs(root) {
434
- for (const attr of Object.values(SECTION_ATTRS)) {
435
- for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
436
- }
437
- for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
438
- restoreInline(el, "background");
439
- el.removeAttribute("data-ohw-style-bgcolor");
440
- }
441
- }
442
- function clearNodeProps(root) {
443
- for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
444
- const h = el;
445
- for (const prop of NODE_PROPS) restoreInline(h, prop);
446
- h.removeAttribute(NODE_WROTE_ATTR);
447
- }
448
- }
449
- function buttonSurfaceOf(el) {
450
- return el.closest("a, button") ?? el;
451
- }
452
- function applyStylesToDom(store) {
453
- ensureStyleSheet();
454
- clearSectionAttrs(document);
455
- clearNodeProps(document);
456
- loadStyleFonts(
457
- store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
458
- );
459
- if (!store) return;
460
- for (const [sectionId, override] of Object.entries(store.sections)) {
461
- const sections = document.querySelectorAll(
462
- `[data-ohw-section="${CSS.escape(sectionId)}"]`
463
- );
464
- for (const section of Array.from(sections)) {
465
- for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
466
- const value = override[prop];
467
- if (value === void 0) continue;
468
- if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
469
- section.setAttribute(attr, String(value).replace(":", "-"));
470
- }
471
- if (override.sectionBackgroundColor !== void 0) {
472
- saveInline(section, "background");
473
- section.style.setProperty("background", override.sectionBackgroundColor, "important");
474
- section.setAttribute("data-ohw-style-bgcolor", "");
475
- }
476
- }
477
- }
478
- for (const [key, override] of Object.entries(store.nodes)) {
479
- const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
480
- for (const el of Array.from(nodes)) {
481
- if (override.color !== void 0) {
482
- saveInline(el, "color");
483
- el.style.setProperty("color", override.color, "important");
484
- el.setAttribute(NODE_WROTE_ATTR, "");
485
- }
486
- if (override.fontFamily !== void 0) {
487
- saveInline(el, "font-family");
488
- el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
489
- el.setAttribute(NODE_WROTE_ATTR, "");
490
- }
491
- if (override.fontSize !== void 0) {
492
- saveInline(el, "font-size");
493
- el.style.setProperty("font-size", `${override.fontSize}px`, "important");
494
- el.setAttribute(NODE_WROTE_ATTR, "");
495
- }
496
- if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
497
- const surface = buttonSurfaceOf(el);
498
- if (override.buttonBackground !== void 0) {
499
- saveInline(surface, "background");
500
- surface.style.setProperty("background", override.buttonBackground, "important");
501
- }
502
- if (override.buttonText !== void 0) {
503
- saveInline(surface, "color");
504
- surface.style.setProperty("color", override.buttonText, "important");
505
- }
506
- surface.setAttribute(NODE_WROTE_ATTR, "");
507
- }
508
- }
509
- }
510
- }
511
-
512
194
  // src/ui/ai-tree/aiSectionsManager.tsx
513
195
  var import_react_dom = require("react-dom");
514
196
  var import_client = require("react-dom/client");
@@ -523,8 +205,7 @@ function lucideByName(name) {
523
205
  }
524
206
  var typeStyle = (spec, font) => ({
525
207
  fontFamily: font,
526
- // Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
527
- 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,
528
209
  lineHeight: spec.line,
529
210
  fontWeight: spec.weight
530
211
  });
@@ -539,36 +220,6 @@ var FEATURE_LINE_CSS = [
539
220
  `background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
540
221
  `mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
541
222
  ].join("");
542
- function hexLuminance(color) {
543
- const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
544
- if (!m) return null;
545
- const [r2, g, b] = [0, 2, 4].map((i) => {
546
- const c = parseInt(m[1].slice(i, i + 2), 16) / 255;
547
- return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
548
- });
549
- return 0.2126 * r2 + 0.7152 * g + 0.0722 * b;
550
- }
551
- function hexContrast(a, b) {
552
- const la = hexLuminance(a);
553
- const lb = hexLuminance(b);
554
- if (la === null || lb === null) return null;
555
- const [hi, lo] = la > lb ? [la, lb] : [lb, la];
556
- return (hi + 0.05) / (lo + 0.05);
557
- }
558
- function accentBandContext(brand) {
559
- const p = brand.palette;
560
- const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
561
- if (lightWins) {
562
- return {
563
- brand: { ...brand, palette: { dark: p.light, primary: p.light, accent: p.light, light: p.primary } },
564
- buttonLabel: p.primary
565
- };
566
- }
567
- return {
568
- brand: { ...brand, palette: { dark: p.dark, primary: p.dark, accent: p.dark, light: p.light } },
569
- buttonLabel: p.light
570
- };
571
- }
572
223
  function textAttrs(ctx, path) {
573
224
  return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
574
225
  }
@@ -581,8 +232,6 @@ var AI_RESPONSIVE_CSS = [
581
232
  " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
582
233
  " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
583
234
  " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
584
- " [data-ai-responsive] { overflow-x: hidden; }",
585
- " [data-ai-responsive] img { max-width: 100%; }",
586
235
  "}"
587
236
  ].join("\n");
588
237
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
@@ -676,7 +325,7 @@ function ButtonEl({
676
325
  textDecoration: "none",
677
326
  cursor: "pointer",
678
327
  ...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body),
679
- ...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? AI_TREE_TOKENS.textPrimaryForeground }
328
+ ...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: AI_TREE_TOKENS.textPrimaryForeground }
680
329
  },
681
330
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
682
331
  }
@@ -1578,14 +1227,11 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1578
1227
  return null;
1579
1228
  }
1580
1229
  const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
1581
- const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
1582
- const blockBrand = band?.brand ?? resolvedBrand;
1583
1230
  const ctx = {
1584
- brand: blockBrand,
1231
+ brand: resolvedBrand,
1585
1232
  resolveMedia: resolveMedia ?? (() => null),
1586
- cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
1587
- keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
1588
- ...band ? { buttonLabel: band.buttonLabel } : {}
1233
+ cardSurface: resolvedBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${resolvedBrand.palette.light} 90%, ${resolvedBrand.palette.dark})`,
1234
+ keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null
1589
1235
  };
1590
1236
  const settings = tree.settings ?? {};
1591
1237
  const pad = AI_TREE_TOKENS.sectionPadding[settings.spacing ?? "balanced"];
@@ -1593,20 +1239,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1593
1239
  const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
1594
1240
  const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
1595
1241
  const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
1596
- const toneBackground = (() => {
1597
- const { dark, primary, light } = resolvedBrand.palette;
1598
- switch (settings.sectionBackground) {
1599
- case "surface":
1600
- return `color-mix(in srgb, ${light} 94%, ${dark})`;
1601
- case "accent":
1602
- return primary;
1603
- case "accent-soft":
1604
- return `color-mix(in srgb, ${primary} 12%, ${light})`;
1605
- default:
1606
- return void 0;
1607
- }
1608
- })();
1609
- const distributed = !isOverlay && settings.textDistribution;
1610
1242
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1611
1243
  "section",
1612
1244
  {
@@ -1616,11 +1248,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1616
1248
  style: {
1617
1249
  position: "relative",
1618
1250
  padding: `${pad}px 0`,
1619
- background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
1251
+ background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
1620
1252
  backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
1621
1253
  backgroundSize: "cover",
1622
- backgroundPosition: "center",
1623
- color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
1254
+ backgroundPosition: "center"
1624
1255
  },
1625
1256
  children: [
1626
1257
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
@@ -1644,24 +1275,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1644
1275
  display: "grid",
1645
1276
  gridTemplateColumns: "repeat(12, 1fr)",
1646
1277
  gap: AI_TREE_TOKENS.spacing6,
1647
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1278
+ alignItems: settings.verticalPosition === "top" ? "start" : "center",
1648
1279
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1649
1280
  },
1650
- children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1651
- "div",
1652
- {
1653
- "data-ai-cell": "",
1654
- style: {
1655
- gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1656
- minWidth: 0,
1657
- // space-between: each column becomes a flex column whose content spreads over
1658
- // the full row height instead of clumping at the top.
1659
- ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
1660
- },
1661
- children: renderNode(block, ctx, `r${r2}.b${b}`)
1662
- },
1663
- b
1664
- ))
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))
1665
1282
  },
1666
1283
  r2
1667
1284
  ))
@@ -1677,36 +1294,17 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
1677
1294
  var CONTAINER_ATTR = "data-ohw-ai-generated";
1678
1295
  var REPLACED_ATTR = "data-ohw-ai-replaced-by";
1679
1296
  var REMOVED_ATTR = "data-ohw-ai-removed";
1680
- var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
1681
- var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
1682
- function readRootVar(name) {
1683
- if (typeof document === "undefined") return "";
1684
- return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1685
- }
1686
- function deriveBrandOverride() {
1687
- const dark = readRootVar("--ohw-brand-dark");
1688
- const primary = readRootVar("--ohw-brand-primary");
1689
- const light = readRootVar("--ohw-brand-light");
1690
- if (!dark || !primary || !light) return null;
1691
- const accent = readRootVar("--ohw-brand-accent");
1692
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1693
- const body = readRootVar("--font-body");
1694
- return {
1695
- palette: { dark, primary, accent: accent || dark, light },
1696
- fonts: {
1697
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
1698
- body: body || AI_DEFAULT_BRAND.fonts.body
1699
- }
1700
- };
1701
- }
1702
1297
  function deriveTemplateBrand() {
1703
- const dark = readRootVar("--color-dark");
1704
- const primary = readRootVar("--color-primary");
1705
- 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");
1706
1304
  if (!dark || !primary || !light) return null;
1707
- const accent = readRootVar("--color-accent");
1708
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1709
- 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");
1710
1308
  return {
1711
1309
  palette: { dark, primary, accent: accent || dark, light },
1712
1310
  fonts: {
@@ -1778,24 +1376,6 @@ function syncRemovedSections(state) {
1778
1376
  }
1779
1377
  }
1780
1378
  }
1781
- function syncTemplateHidden(state, pageHasSections) {
1782
- const hide = state.hideTemplate === true && pageHasSections;
1783
- for (const el of Array.from(document.querySelectorAll(`[${TEMPLATE_HIDDEN_ATTR}]`))) {
1784
- if (!hide) {
1785
- el.style.removeProperty("display");
1786
- el.removeAttribute(TEMPLATE_HIDDEN_ATTR);
1787
- }
1788
- }
1789
- if (!hide) return;
1790
- for (const el of Array.from(document.querySelectorAll("[data-ohw-section]"))) {
1791
- if (el.hasAttribute(CONTAINER_ATTR)) continue;
1792
- if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
1793
- if (el.parentElement?.closest("[data-ohw-section]")) continue;
1794
- if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR)) continue;
1795
- el.style.display = "none";
1796
- el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
1797
- }
1798
- }
1799
1379
  function syncReplacedOriginals(state) {
1800
1380
  for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
1801
1381
  const byId = el.getAttribute(REPLACED_ATTR) ?? "";
@@ -1816,12 +1396,8 @@ function syncReplacedOriginals(state) {
1816
1396
  }
1817
1397
  function applyAiSectionsToDom(state, options) {
1818
1398
  if (typeof document === "undefined") return;
1819
- const brandOverride = deriveBrandOverride();
1820
1399
  const templateBrand = deriveTemplateBrand();
1821
- const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
1822
- const pagePath = window.location.pathname;
1823
- const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
1824
- const activeIds = new Set(pageSections.map((entry) => entry.id));
1400
+ const activeIds = new Set(state.sections.map((entry) => entry.id));
1825
1401
  for (const [id, section] of mounted) {
1826
1402
  if (!activeIds.has(id)) {
1827
1403
  section.root.unmount();
@@ -1829,8 +1405,8 @@ function applyAiSectionsToDom(state, options) {
1829
1405
  mounted.delete(id);
1830
1406
  }
1831
1407
  }
1832
- for (const entry of pageSections) {
1833
- const serialized = JSON.stringify(entry) + brandKey;
1408
+ for (const entry of state.sections) {
1409
+ const serialized = JSON.stringify(entry);
1834
1410
  const existing = mounted.get(entry.id);
1835
1411
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
1836
1412
  continue;
@@ -1844,7 +1420,6 @@ function applyAiSectionsToDom(state, options) {
1844
1420
  mounted.delete(entry.id);
1845
1421
  }
1846
1422
  container.setAttribute("data-ohw-section", entry.id);
1847
- container.setAttribute("data-ohw-instance", entry.id);
1848
1423
  container.setAttribute("data-ohw-section-label", entry.label);
1849
1424
  placeContainer(container, entry);
1850
1425
  const root = mounted.get(entry.id)?.root ?? (0, import_client.createRoot)(container);
@@ -1855,7 +1430,7 @@ function applyAiSectionsToDom(state, options) {
1855
1430
  AiTreeRenderer,
1856
1431
  {
1857
1432
  tree: entry.tree,
1858
- brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1433
+ brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1859
1434
  resolveMedia,
1860
1435
  editKeyPrefix: `ai.${entry.id}`
1861
1436
  }
@@ -1866,7 +1441,6 @@ function applyAiSectionsToDom(state, options) {
1866
1441
  }
1867
1442
  syncReplacedOriginals(state);
1868
1443
  syncRemovedSections(state);
1869
- syncTemplateHidden(state, pageSections.length > 0);
1870
1444
  }
1871
1445
 
1872
1446
  // src/useLinkHrefGuardian.ts
@@ -2473,7 +2047,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2473
2047
  const autoId = (0, import_react5.useId)();
2474
2048
  const insertAfter = insertAfterProp ?? autoId;
2475
2049
  const [schedule, setSchedule] = (0, import_react5.useState)(null);
2476
- const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
2050
+ const [loading, setLoading] = (0, import_react5.useState)(true);
2477
2051
  const [inEditor, setInEditor] = (0, import_react5.useState)(false);
2478
2052
  const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
2479
2053
  const [modalState, setModalState] = (0, import_react5.useState)(null);
@@ -2647,10 +2221,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2647
2221
  "*"
2648
2222
  );
2649
2223
  };
2224
+ if (!inEditor && !loading && !schedule) return null;
2650
2225
  const sectionId = `scheduling-${insertAfter}`;
2651
- if (!inEditor && !loading && !schedule) {
2652
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2653
- }
2654
2226
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2655
2227
  "section",
2656
2228
  {
@@ -7755,9 +7327,6 @@ var import_lucide_react7 = require("lucide-react");
7755
7327
 
7756
7328
  // src/lib/sections.ts
7757
7329
  var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
7758
- function isChromeSection(el) {
7759
- return el.matches("header, nav, footer, aside");
7760
- }
7761
7330
  function titleCaseSectionId(id) {
7762
7331
  return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
7763
7332
  }
@@ -7768,8 +7337,6 @@ function parseSectionsFromRoot(root) {
7768
7337
  const id = el.getAttribute("data-ohw-section") ?? "";
7769
7338
  if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
7770
7339
  if (el.parentElement?.closest("[data-ohw-section]")) continue;
7771
- if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
7772
- continue;
7773
7340
  seen.add(id);
7774
7341
  const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
7775
7342
  sections.push({ id, label });
@@ -7787,12 +7354,8 @@ function parseSectionsFromHtml(html) {
7787
7354
 
7788
7355
  // src/ui/ai-section/AiSectionOverlay.tsx
7789
7356
  var import_jsx_runtime17 = require("react/jsx-runtime");
7790
- function findSectionElement(instanceId) {
7791
- const escaped = CSS.escape(instanceId);
7792
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7793
- }
7794
- function readRect(instanceId) {
7795
- const el = findSectionElement(instanceId);
7357
+ function readRect(sectionId) {
7358
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7796
7359
  if (!el) return null;
7797
7360
  const r2 = el.getBoundingClientRect();
7798
7361
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7815,7 +7378,7 @@ function useLiveSectionRect(sectionId) {
7815
7378
  const opts = { capture: true, passive: true };
7816
7379
  window.addEventListener("scroll", update, opts);
7817
7380
  window.addEventListener("resize", update);
7818
- const el = findSectionElement(sectionId);
7381
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7819
7382
  const ro = el ? new ResizeObserver(update) : null;
7820
7383
  if (el && ro) ro.observe(el);
7821
7384
  const interval = setInterval(update, 500);
@@ -7828,14 +7391,6 @@ function useLiveSectionRect(sectionId) {
7828
7391
  }, [sectionId]);
7829
7392
  return rect;
7830
7393
  }
7831
- function computeSectionBoundaryFlags(instanceId) {
7832
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7833
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
7834
- );
7835
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7836
- if (index === -1) return { isFirst: true, isLast: true };
7837
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7838
- }
7839
7394
  var PRIMARY2 = "#0885FE";
7840
7395
  function edgeAwareRadius(rect) {
7841
7396
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7909,7 +7464,6 @@ function AiSectionOverlay({
7909
7464
  }) {
7910
7465
  const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
7911
7466
  const [reviewId, setReviewId] = (0, import_react8.useState)(null);
7912
- const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
7913
7467
  const reviewIdRef = (0, import_react8.useRef)(null);
7914
7468
  reviewIdRef.current = reviewId;
7915
7469
  const selectedIdRef = (0, import_react8.useRef)(null);
@@ -7918,7 +7472,7 @@ function AiSectionOverlay({
7918
7472
  (el) => {
7919
7473
  postToParent2({
7920
7474
  type: "ow:section-selected",
7921
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
7475
+ sectionId: el?.dataset.ohwSection ?? null,
7922
7476
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7923
7477
  });
7924
7478
  },
@@ -7927,7 +7481,7 @@ function AiSectionOverlay({
7927
7481
  const selectFromElement = (0, import_react8.useCallback)(
7928
7482
  (el, options) => {
7929
7483
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7930
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
7484
+ const id = sectionEl?.dataset.ohwSection ?? null;
7931
7485
  if (id === selectedIdRef.current) return;
7932
7486
  setSelectedId(id);
7933
7487
  if (options?.report !== false) report(sectionEl);
@@ -7968,10 +7522,9 @@ function AiSectionOverlay({
7968
7522
  }
7969
7523
  const found = readRect(sectionId) != null;
7970
7524
  setReviewId(found ? sectionId : null);
7971
- setReviewButtonsHidden(e.data.hideButtons === true);
7972
7525
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7973
7526
  if (found) {
7974
- document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7527
+ document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7975
7528
  }
7976
7529
  }
7977
7530
  };
@@ -7990,7 +7543,7 @@ function AiSectionOverlay({
7990
7543
  return;
7991
7544
  }
7992
7545
  const sec = t.closest("[data-ohw-section]");
7993
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
7546
+ setHoveredId(sec?.dataset.ohwSection ?? null);
7994
7547
  };
7995
7548
  const onLeave = () => setHoveredId(null);
7996
7549
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -8022,30 +7575,9 @@ function AiSectionOverlay({
8022
7575
  },
8023
7576
  [postToParent2]
8024
7577
  );
8025
- const activeSelectionId = reviewId ? null : selectedId;
8026
- const selectionRect = useLiveSectionRect(activeSelectionId);
7578
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
8027
7579
  const reviewRect = useLiveSectionRect(reviewId);
8028
7580
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
8029
- (0, import_react8.useEffect)(() => {
8030
- const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
8031
- if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
8032
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
8033
- return;
8034
- }
8035
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
8036
- postToParent2({
8037
- type: "ow:section-rect",
8038
- instanceId: activeSelectionId,
8039
- rect: {
8040
- top: selectionRect.top + window.scrollY,
8041
- left: selectionRect.left + window.scrollX,
8042
- width: selectionRect.width,
8043
- height: selectionRect.height
8044
- },
8045
- isFirst,
8046
- isLast
8047
- });
8048
- }, [activeSelectionId, selectionRect, postToParent2]);
8049
7581
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
8050
7582
  hoverRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
8051
7583
  "div",
@@ -8096,16 +7628,13 @@ function AiSectionOverlay({
8096
7628
  border: `2px solid ${PRIMARY2}`,
8097
7629
  borderRadius: edgeAwareRadius(reviewRect),
8098
7630
  zIndex: 2147483200,
8099
- // The veil itself: swallows clicks so the section stays locked until decided. This
8100
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
8101
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
8102
- // Accept/Discard resolves to the media beneath and opens the file picker.
7631
+ // The veil itself: swallows clicks so the section stays locked until decided.
8103
7632
  background: "rgba(8, 133, 254, 0.04)",
8104
7633
  pointerEvents: "auto",
8105
7634
  cursor: "default"
8106
7635
  },
8107
7636
  onClick: (e) => e.stopPropagation(),
8108
- children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7637
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
8109
7638
  "div",
8110
7639
  {
8111
7640
  style: {
@@ -12299,7 +11828,6 @@ function readLogoSizeState(content, placement) {
12299
11828
  function getLogoElement(el) {
12300
11829
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
12301
11830
  if (marked) return marked;
12302
- if (el.closest('[data-ohw-editable="icon"]')) return null;
12303
11831
  const root = el.closest("nav, [data-ohw-nav-root], footer");
12304
11832
  if (!root) return null;
12305
11833
  const anchor = el.closest("a");
@@ -12548,127 +12076,16 @@ function FloatingPanel({
12548
12076
  );
12549
12077
  }
12550
12078
 
12551
- // src/ui/logo-size-panel.tsx
12552
- var import_lucide_react15 = require("lucide-react");
12553
- var import_jsx_runtime28 = require("react/jsx-runtime");
12554
- function SizeSlider({
12555
- value,
12556
- onChange
12557
- }) {
12558
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
12559
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full flex-col gap-3", children: [
12560
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
12561
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
12562
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
12563
- value,
12564
- " px"
12565
- ] })
12566
- ] }),
12567
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
12568
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12569
- "div",
12570
- {
12571
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
12572
- style: { width: `${pct}%` }
12573
- }
12574
- ),
12575
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12576
- "input",
12577
- {
12578
- type: "range",
12579
- min: LOGO_SIZE_MIN,
12580
- max: LOGO_SIZE_MAX,
12581
- step: 1,
12582
- value,
12583
- "aria-label": "Logo size",
12584
- className: cn(
12585
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
12586
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
12587
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
12588
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
12589
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
12590
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
12591
- "[&::-moz-range-thumb]:bg-background"
12592
- ),
12593
- onChange: (e) => onChange(Number(e.target.value))
12594
- }
12595
- )
12596
- ] })
12597
- ] });
12598
- }
12599
- function LogoSizePanel({
12600
- viewport,
12601
- sizePx,
12602
- mobileFollowing = true,
12603
- onSizeChange,
12604
- onCustomizeMobile,
12605
- onResetMobile,
12606
- onUpdateEverywhere,
12607
- className
12608
- }) {
12609
- const showFollowing = viewport === "mobile" && mobileFollowing;
12610
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
12611
- const showDesktopSlider = viewport === "desktop";
12612
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-4", className), children: [
12613
- showFollowing ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
12614
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-start gap-1", children: [
12615
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react15.Link, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
12616
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
12617
- ] }),
12618
- /* @__PURE__ */ (0, import_jsx_runtime28.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." }),
12619
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12620
- Button,
12621
- {
12622
- type: "button",
12623
- variant: "outline",
12624
- size: "sm",
12625
- className: "h-9 w-full min-w-0 cursor-pointer",
12626
- onClick: onCustomizeMobile,
12627
- children: "Customize for mobile"
12628
- }
12629
- )
12630
- ] }) : null,
12631
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
12632
- showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12633
- Button,
12634
- {
12635
- type: "button",
12636
- variant: "outline",
12637
- size: "sm",
12638
- className: "h-9 w-full min-w-0 cursor-pointer",
12639
- onClick: onResetMobile,
12640
- children: "Reset to desktop size"
12641
- }
12642
- ) : null,
12643
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "h-px w-full bg-border", role: "separator" }),
12644
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
12645
- Button,
12646
- {
12647
- type: "button",
12648
- variant: "outline",
12649
- size: "sm",
12650
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
12651
- onClick: onUpdateEverywhere,
12652
- children: [
12653
- "Update logo everywhere",
12654
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react15.ArrowUpRight, { size: 16, "aria-hidden": true })
12655
- ]
12656
- }
12657
- ),
12658
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
12659
- ] });
12660
- }
12661
-
12662
12079
  // src/ui/socials-display-panel.tsx
12663
- var import_jsx_runtime29 = require("react/jsx-runtime");
12080
+ var import_jsx_runtime28 = require("react/jsx-runtime");
12664
12081
  function DisplaySwitch({
12665
12082
  label,
12666
12083
  checked,
12667
12084
  disabled,
12668
12085
  onChange
12669
12086
  }) {
12670
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
12671
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12087
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
12088
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12672
12089
  "span",
12673
12090
  {
12674
12091
  className: cn(
@@ -12678,7 +12095,7 @@ function DisplaySwitch({
12678
12095
  children: label
12679
12096
  }
12680
12097
  ),
12681
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12098
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12682
12099
  "button",
12683
12100
  {
12684
12101
  type: "button",
@@ -12692,7 +12109,7 @@ function DisplaySwitch({
12692
12109
  checked ? "bg-primary" : "bg-primary-50",
12693
12110
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
12694
12111
  ),
12695
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12112
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12696
12113
  "span",
12697
12114
  {
12698
12115
  className: cn(
@@ -12706,8 +12123,8 @@ function DisplaySwitch({
12706
12123
  ] });
12707
12124
  }
12708
12125
  function SocialsDisplayPanel({ display, onChange, className }) {
12709
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
12710
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12126
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
12127
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12711
12128
  DisplaySwitch,
12712
12129
  {
12713
12130
  label: "Text",
@@ -12716,7 +12133,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
12716
12133
  onChange: (text) => onChange({ ...display, text })
12717
12134
  }
12718
12135
  ),
12719
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12136
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12720
12137
  DisplaySwitch,
12721
12138
  {
12722
12139
  label: "Icon",
@@ -13276,8 +12693,8 @@ function useNavItemDrag({
13276
12693
  }
13277
12694
 
13278
12695
  // src/ui/footer-container-chrome.tsx
13279
- var import_lucide_react16 = require("lucide-react");
13280
- var import_jsx_runtime30 = require("react/jsx-runtime");
12696
+ var import_lucide_react15 = require("lucide-react");
12697
+ var import_jsx_runtime29 = require("react/jsx-runtime");
13281
12698
  function FooterContainerChrome({
13282
12699
  rect,
13283
12700
  onAdd,
@@ -13285,7 +12702,7 @@ function FooterContainerChrome({
13285
12702
  }) {
13286
12703
  const chromeGap = 6;
13287
12704
  const buttonMargin = 7;
13288
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12705
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13289
12706
  "div",
13290
12707
  {
13291
12708
  "data-ohw-footer-container-chrome": "",
@@ -13297,8 +12714,8 @@ function FooterContainerChrome({
13297
12714
  width: rect.width + chromeGap * 2,
13298
12715
  height: rect.height + chromeGap * 2
13299
12716
  },
13300
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { children: [
13301
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12717
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
12718
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13302
12719
  "button",
13303
12720
  {
13304
12721
  type: "button",
@@ -13317,10 +12734,10 @@ function FooterContainerChrome({
13317
12734
  if (addDisabled) return;
13318
12735
  onAdd();
13319
12736
  },
13320
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12737
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13321
12738
  }
13322
12739
  ) }),
13323
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12740
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
13324
12741
  ] })
13325
12742
  }
13326
12743
  ) });
@@ -13505,18 +12922,6 @@ function collectEditableNodes(extraContent, root = document) {
13505
12922
  }
13506
12923
  if (extraContent && !isScoped) {
13507
12924
  applyNavFooterDeleteOverrides(byKey, extraContent);
13508
- for (const key of LOGO_IMAGE_KEYS) {
13509
- if (!(key in extraContent)) continue;
13510
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
13511
- }
13512
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
13513
- if (!(key in extraContent)) continue;
13514
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13515
- }
13516
- for (const key of LOGO_SIZE_KEYS) {
13517
- if (!(key in extraContent)) continue;
13518
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13519
- }
13520
12925
  }
13521
12926
  return Array.from(byKey.values());
13522
12927
  }
@@ -13782,14 +13187,14 @@ function deleteSelectedNavFooterItem(deps) {
13782
13187
  }
13783
13188
 
13784
13189
  // src/ui/navbar-container-chrome.tsx
13785
- var import_lucide_react17 = require("lucide-react");
13786
- var import_jsx_runtime31 = require("react/jsx-runtime");
13190
+ var import_lucide_react16 = require("lucide-react");
13191
+ var import_jsx_runtime30 = require("react/jsx-runtime");
13787
13192
  function NavbarContainerChrome({
13788
13193
  rect,
13789
13194
  onAdd
13790
13195
  }) {
13791
13196
  const chromeGap = 6;
13792
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
13197
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13793
13198
  "div",
13794
13199
  {
13795
13200
  "data-ohw-navbar-container-chrome": "",
@@ -13801,7 +13206,7 @@ function NavbarContainerChrome({
13801
13206
  width: rect.width + chromeGap * 2,
13802
13207
  height: rect.height + chromeGap * 2
13803
13208
  },
13804
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
13209
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13805
13210
  "button",
13806
13211
  {
13807
13212
  type: "button",
@@ -13818,7 +13223,7 @@ function NavbarContainerChrome({
13818
13223
  e.stopPropagation();
13819
13224
  onAdd();
13820
13225
  },
13821
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react17.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13226
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13822
13227
  }
13823
13228
  )
13824
13229
  }
@@ -13827,7 +13232,7 @@ function NavbarContainerChrome({
13827
13232
 
13828
13233
  // src/ui/drop-indicator.tsx
13829
13234
  var React10 = __toESM(require("react"), 1);
13830
- var import_jsx_runtime32 = require("react/jsx-runtime");
13235
+ var import_jsx_runtime31 = require("react/jsx-runtime");
13831
13236
  var dropIndicatorVariants = cva(
13832
13237
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
13833
13238
  {
@@ -13851,7 +13256,7 @@ var dropIndicatorVariants = cva(
13851
13256
  );
13852
13257
  var DropIndicator = React10.forwardRef(
13853
13258
  ({ className, direction, state, ...props }, ref) => {
13854
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
13259
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
13855
13260
  "div",
13856
13261
  {
13857
13262
  ref,
@@ -13868,7 +13273,7 @@ var DropIndicator = React10.forwardRef(
13868
13273
  DropIndicator.displayName = "DropIndicator";
13869
13274
 
13870
13275
  // src/ui/badge.tsx
13871
- var import_jsx_runtime33 = require("react/jsx-runtime");
13276
+ var import_jsx_runtime32 = require("react/jsx-runtime");
13872
13277
  var badgeVariants = cva(
13873
13278
  "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",
13874
13279
  {
@@ -13886,12 +13291,12 @@ var badgeVariants = cva(
13886
13291
  }
13887
13292
  );
13888
13293
  function Badge({ className, variant, ...props }) {
13889
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
13294
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
13890
13295
  }
13891
13296
 
13892
13297
  // src/OhhwellsBridge.tsx
13893
- var import_lucide_react18 = require("lucide-react");
13894
- var import_jsx_runtime34 = require("react/jsx-runtime");
13298
+ var import_lucide_react17 = require("lucide-react");
13299
+ var import_jsx_runtime33 = require("react/jsx-runtime");
13895
13300
  var PRIMARY3 = "#0885FE";
13896
13301
  var IMAGE_FADE_MS = 300;
13897
13302
  function runOpacityFade(el, onDone) {
@@ -13985,10 +13390,21 @@ function parseSchedulingInsertAfter(insertAfter) {
13985
13390
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
13986
13391
  };
13987
13392
  }
13988
- function resolveEntryAnchor(entry) {
13989
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
13990
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
13991
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
13393
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
13394
+ const parsed = parseSchedulingInsertAfter(insertAfter);
13395
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
13396
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
13397
+ return { effectiveInsertAfter, insertBefore };
13398
+ }
13399
+ function getSchedulingMountPoint(insertAfter) {
13400
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
13401
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
13402
+ if (!anchorEl && anchor === "scheduling") {
13403
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
13404
+ anchorEl = widgets.at(-1) ?? null;
13405
+ }
13406
+ if (!anchorEl) return null;
13407
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13992
13408
  }
13993
13409
  function schedulingMountDepth(insertAfter) {
13994
13410
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -14005,7 +13421,8 @@ function getPageSchedulingEntries(raw) {
14005
13421
  }
14006
13422
  }
14007
13423
  function isSchedulingWidgetMissing(entry) {
14008
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
13424
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
13425
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
14009
13426
  }
14010
13427
  function hasMissingSchedulingWidgets(entries) {
14011
13428
  return entries.some(isSchedulingWidgetMissing);
@@ -14035,17 +13452,16 @@ function initSectionsFromContent(content, removeExisting = false) {
14035
13452
  } catch {
14036
13453
  }
14037
13454
  }
14038
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
14039
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
14040
- const sectionId = schedulingSectionId(widgetId);
13455
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
13456
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
13457
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
14041
13458
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
14042
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
14043
- if (!anchorEl) return false;
14044
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13459
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
13460
+ if (!mountPoint) return false;
14045
13461
  const container = document.createElement("div");
14046
13462
  container.dataset.ohwSectionContainer = "scheduling";
14047
- if (beforeId) {
14048
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
13463
+ if (insertBefore) {
13464
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
14049
13465
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
14050
13466
  if (!beforePoint) return false;
14051
13467
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -14056,25 +13472,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
14056
13472
  }
14057
13473
  tail.insertAdjacentElement("afterend", container);
14058
13474
  }
14059
- try {
14060
- const root = (0, import_client2.createRoot)(container);
14061
- (0, import_react_dom3.flushSync)(() => {
14062
- root.render(
14063
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14064
- SchedulingWidget,
14065
- {
14066
- notifyOnConnect,
14067
- initialScheduleId: scheduleId,
14068
- insertAfter: widgetId
14069
- }
14070
- )
14071
- );
14072
- });
14073
- } catch (err) {
14074
- console.error("[ow:scheduling] render threw", err);
14075
- container.remove();
14076
- return false;
14077
- }
13475
+ const root = (0, import_client2.createRoot)(container);
13476
+ (0, import_react_dom3.flushSync)(() => {
13477
+ root.render(
13478
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13479
+ SchedulingWidget,
13480
+ {
13481
+ notifyOnConnect,
13482
+ initialScheduleId: scheduleId,
13483
+ insertAfter: effectiveInsertAfter
13484
+ }
13485
+ )
13486
+ );
13487
+ });
14078
13488
  const tracker = getSectionsTracker();
14079
13489
  let sections = [];
14080
13490
  try {
@@ -14082,12 +13492,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
14082
13492
  } catch {
14083
13493
  }
14084
13494
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
14085
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
13495
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
14086
13496
  sections.push({
14087
13497
  type: "scheduling",
14088
- insertAfter: widgetId,
14089
- anchorId,
14090
- beforeId: beforeId ?? null,
13498
+ insertAfter: effectiveInsertAfter,
14091
13499
  pagePath: window.location.pathname,
14092
13500
  ...scheduleId ? { scheduleId } : {}
14093
13501
  });
@@ -14101,8 +13509,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
14101
13509
  for (let i = pending.length - 1; i >= 0; i--) {
14102
13510
  const entry = pending[i];
14103
13511
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
14104
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
14105
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
13512
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
14106
13513
  pending.splice(i, 1);
14107
13514
  }
14108
13515
  }
@@ -14250,13 +13657,6 @@ function isInsideLinkEditor(target) {
14250
13657
  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"]')
14251
13658
  );
14252
13659
  }
14253
- function isInsideFloatingPanel(target) {
14254
- return Boolean(target.closest("[data-ohw-floating-panel]"));
14255
- }
14256
- function isPointOverFloatingPanel(clientX, clientY) {
14257
- const el = document.elementFromPoint(clientX, clientY);
14258
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
14259
- }
14260
13660
  function getHrefKeyFromElement(el) {
14261
13661
  if (!el) return null;
14262
13662
  const anchor = el.closest("[data-ohw-href-key]");
@@ -14495,7 +13895,7 @@ function getNavigationSelectionParent(el) {
14495
13895
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
14496
13896
  return getFooterLinksContainer();
14497
13897
  }
14498
- 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)) {
13898
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
14499
13899
  return getNavigationRoot(el);
14500
13900
  }
14501
13901
  return null;
@@ -14741,7 +14141,7 @@ function EditGlowChrome({
14741
14141
  hideHandle = false
14742
14142
  }) {
14743
14143
  const GAP = SELECTION_CHROME_GAP2;
14744
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
14144
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
14745
14145
  "div",
14746
14146
  {
14747
14147
  ref: elRef,
@@ -14756,7 +14156,7 @@ function EditGlowChrome({
14756
14156
  zIndex: 2147483646
14757
14157
  },
14758
14158
  children: [
14759
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14159
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14760
14160
  "div",
14761
14161
  {
14762
14162
  style: {
@@ -14769,7 +14169,7 @@ function EditGlowChrome({
14769
14169
  }
14770
14170
  }
14771
14171
  ),
14772
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14172
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14773
14173
  "div",
14774
14174
  {
14775
14175
  "data-ohw-drag-handle-container": "",
@@ -14781,7 +14181,7 @@ function EditGlowChrome({
14781
14181
  transform: "translate(calc(-100% - 7px), -50%)",
14782
14182
  pointerEvents: dragDisabled ? "none" : "auto"
14783
14183
  },
14784
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14184
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14785
14185
  DragHandle,
14786
14186
  {
14787
14187
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -14991,7 +14391,7 @@ function FloatingToolbar({
14991
14391
  return () => ro.disconnect();
14992
14392
  }, [showEditLink, activeCommands]);
14993
14393
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
14994
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14394
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14995
14395
  "div",
14996
14396
  {
14997
14397
  ref: setRefs,
@@ -15003,12 +14403,12 @@ function FloatingToolbar({
15003
14403
  zIndex: 2147483647,
15004
14404
  pointerEvents: "auto"
15005
14405
  },
15006
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(CustomToolbar, { children: [
15007
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react16.default.Fragment, { children: [
15008
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CustomToolbarDivider, {}),
14406
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
14407
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
14408
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
15009
14409
  btns.map((btn) => {
15010
14410
  const isActive = activeCommands.has(btn.cmd);
15011
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14411
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15012
14412
  CustomToolbarButton,
15013
14413
  {
15014
14414
  title: btn.title,
@@ -15017,7 +14417,7 @@ function FloatingToolbar({
15017
14417
  e.preventDefault();
15018
14418
  onCommand(btn.cmd);
15019
14419
  },
15020
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14420
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15021
14421
  "svg",
15022
14422
  {
15023
14423
  width: "16",
@@ -15038,7 +14438,7 @@ function FloatingToolbar({
15038
14438
  );
15039
14439
  })
15040
14440
  ] }, gi)),
15041
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14441
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15042
14442
  CustomToolbarButton,
15043
14443
  {
15044
14444
  type: "button",
@@ -15052,7 +14452,7 @@ function FloatingToolbar({
15052
14452
  e.preventDefault();
15053
14453
  e.stopPropagation();
15054
14454
  },
15055
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Link, { className: "size-4 shrink-0", "aria-hidden": true })
14455
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
15056
14456
  }
15057
14457
  ) : null
15058
14458
  ] })
@@ -15069,7 +14469,7 @@ function StateToggle({
15069
14469
  states,
15070
14470
  onStateChange
15071
14471
  }) {
15072
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14472
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15073
14473
  ToggleGroup,
15074
14474
  {
15075
14475
  "data-ohw-state-toggle": "",
@@ -15083,12 +14483,11 @@ function StateToggle({
15083
14483
  left: rect.right - 8,
15084
14484
  transform: "translateX(-100%)"
15085
14485
  },
15086
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14486
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
15087
14487
  }
15088
14488
  );
15089
14489
  }
15090
14490
  var contentCache = /* @__PURE__ */ new Map();
15091
- var fetchedContentPaths = /* @__PURE__ */ new Set();
15092
14491
  function resolveSubdomain(subdomainFromQuery) {
15093
14492
  if (subdomainFromQuery) return subdomainFromQuery;
15094
14493
  if (typeof window !== "undefined") {
@@ -15427,6 +14826,13 @@ function OhhwellsBridge() {
15427
14826
  const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
15428
14827
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
15429
14828
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
14829
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
14830
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
14831
+ floatingPanelOpenRef.current = floatingPanel !== null;
14832
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
14833
+ const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
14834
+ const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
14835
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
15430
14836
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
15431
14837
  const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
15432
14838
  const footerDragRef = (0, import_react16.useRef)(null);
@@ -15441,16 +14847,7 @@ function OhhwellsBridge() {
15441
14847
  const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
15442
14848
  const editContentRef = (0, import_react16.useRef)({});
15443
14849
  const aiSectionsRef = (0, import_react16.useRef)("");
15444
- const brandKitRef = (0, import_react16.useRef)("");
15445
- const stylesRef = (0, import_react16.useRef)("");
15446
14850
  const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
15447
- const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
15448
- const floatingPanelOpenRef = (0, import_react16.useRef)(false);
15449
- const setFloatingPanelRef = (0, import_react16.useRef)(setFloatingPanel);
15450
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
15451
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
15452
- const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
15453
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
15454
14851
  const [sitePages, setSitePages] = (0, import_react16.useState)([]);
15455
14852
  const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
15456
14853
  const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
@@ -15459,18 +14856,7 @@ function OhhwellsBridge() {
15459
14856
  const linkPopoverOpenRef = (0, import_react16.useRef)(false);
15460
14857
  const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
15461
14858
  setLinkPopoverRef.current = setLinkPopover;
15462
- setFloatingPanelRef.current = setFloatingPanel;
15463
14859
  linkPopoverSessionRef.current = linkPopover;
15464
- floatingPanelOpenRef.current = Boolean(floatingPanel);
15465
- (0, import_react16.useEffect)(() => {
15466
- const syncViewport = () => {
15467
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
15468
- setEditorViewport((prev) => prev === next ? prev : next);
15469
- };
15470
- syncViewport();
15471
- window.addEventListener("resize", syncViewport);
15472
- return () => window.removeEventListener("resize", syncViewport);
15473
- }, []);
15474
14860
  const {
15475
14861
  navDragRef,
15476
14862
  navDropSlots,
@@ -16555,6 +15941,25 @@ function OhhwellsBridge() {
16555
15941
  setLogoSizeDraft(null);
16556
15942
  deselectRef.current();
16557
15943
  }, []);
15944
+ (0, import_react16.useEffect)(() => {
15945
+ const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
15946
+ if (!session || !logoSizeDraft) {
15947
+ postToParentRef.current({ type: "ow:logo-size-panel", open: false });
15948
+ return;
15949
+ }
15950
+ postToParentRef.current({
15951
+ type: "ow:logo-size-panel",
15952
+ open: true,
15953
+ title: session.title,
15954
+ context: session.context ?? "",
15955
+ placement: session.placement,
15956
+ viewport: editorViewport,
15957
+ mobileFollowing: logoSizeDraft.mobileFollowing,
15958
+ sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
15959
+ min: LOGO_SIZE_MIN,
15960
+ max: LOGO_SIZE_MAX
15961
+ });
15962
+ }, [floatingPanel, logoSizeDraft, editorViewport]);
16558
15963
  const persistLogoSizeDraft = (0, import_react16.useCallback)(
16559
15964
  (placement, draft) => {
16560
15965
  const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
@@ -16713,27 +16118,15 @@ function OhhwellsBridge() {
16713
16118
  }
16714
16119
  const applyContent = (content) => {
16715
16120
  const imageLoads = [];
16716
- if (typeof content[BRAND_KIT_KEY] === "string") {
16717
- brandKitRef.current = content[BRAND_KIT_KEY];
16718
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
16719
- }
16720
16121
  if (typeof content[AI_SECTIONS_KEY] === "string") {
16721
16122
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
16722
16123
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
16723
16124
  }
16724
- if (typeof content[STYLE_STORE_KEY] === "string") {
16725
- stylesRef.current = content[STYLE_STORE_KEY];
16726
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
16727
- }
16728
- applyBrandChrome(content);
16729
16125
  for (const [key, val] of Object.entries(content)) {
16730
16126
  if (key === "__ohw_sections") continue;
16731
16127
  if (key === AI_SECTIONS_KEY) continue;
16732
16128
  if (key === LOGO_PLACEHOLDER_KEY) continue;
16733
16129
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
16734
- if (key === BRAND_KIT_KEY) continue;
16735
- if (key === STYLE_STORE_KEY) continue;
16736
- if (BRAND_CHROME_KEYS.has(key)) continue;
16737
16130
  if (applyVideoSettingNode(key, val)) continue;
16738
16131
  if (applyCarouselNode(key, val)) continue;
16739
16132
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16791,9 +16184,7 @@ function OhhwellsBridge() {
16791
16184
  let cancelled = false;
16792
16185
  setFetchState("loading");
16793
16186
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
16794
- const initialPath = pathname;
16795
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
16796
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16187
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16797
16188
  if (cancelled) return;
16798
16189
  const content = data?.content ?? {};
16799
16190
  contentCache.set(subdomain, content);
@@ -16913,21 +16304,10 @@ function OhhwellsBridge() {
16913
16304
  initSectionInstancesFromContent(content, window.location.pathname);
16914
16305
  observer?.disconnect();
16915
16306
  try {
16916
- applyBrandChrome(content);
16917
- if (typeof content[BRAND_KIT_KEY] === "string") {
16918
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
16919
- }
16920
- if (typeof content[STYLE_STORE_KEY] === "string") {
16921
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
16922
- }
16923
16307
  for (const [key, val] of Object.entries(content)) {
16924
16308
  if (key === "__ohw_sections") continue;
16925
16309
  if (key === LOGO_PLACEHOLDER_KEY) continue;
16926
16310
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
16927
- if (key === BRAND_KIT_KEY) continue;
16928
- if (key === STYLE_STORE_KEY) continue;
16929
- if (key === STYLE_STORE_KEY) continue;
16930
- if (BRAND_CHROME_KEYS.has(key)) continue;
16931
16311
  if (applyVideoSettingNode(key, val)) continue;
16932
16312
  if (applyCarouselNode(key, val)) continue;
16933
16313
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16970,17 +16350,6 @@ function OhhwellsBridge() {
16970
16350
  debounceTimer = setTimeout(applyFromCache, 150);
16971
16351
  };
16972
16352
  applyFromCache();
16973
- const pathCacheKey = `${subdomain}::${pathname}`;
16974
- if (!fetchedContentPaths.has(pathCacheKey)) {
16975
- fetchedContentPaths.add(pathCacheKey);
16976
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
16977
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16978
- if (!data?.content) return;
16979
- contentCache.set(subdomain, data.content);
16980
- applyFromCache();
16981
- }).catch(() => {
16982
- });
16983
- }
16984
16353
  observer = new MutationObserver(scheduleApply);
16985
16354
  observer.observe(document.body, { childList: true, subtree: true });
16986
16355
  return () => {
@@ -17074,31 +16443,26 @@ function OhhwellsBridge() {
17074
16443
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
17075
16444
  (0, import_react16.useEffect)(() => {
17076
16445
  if (!isEditMode) return;
17077
- let lastPosted = 0;
17078
16446
  const measure = () => {
17079
16447
  const h = document.body.scrollHeight;
17080
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
17081
- lastPosted = h;
17082
- postToParent2({ type: "ow:height", height: h });
17083
- }
17084
- };
17085
- let raf = null;
17086
- const schedule = () => {
17087
- if (raf != null) return;
17088
- raf = requestAnimationFrame(() => {
17089
- raf = null;
17090
- measure();
17091
- });
16448
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
17092
16449
  };
17093
16450
  const t1 = setTimeout(measure, 50);
17094
16451
  const t2 = setTimeout(measure, 500);
17095
- const ro = new ResizeObserver(schedule);
17096
- ro.observe(document.body);
16452
+ let lastWidth = window.innerWidth;
16453
+ let resizeTimer = null;
16454
+ const handleResize = () => {
16455
+ if (window.innerWidth === lastWidth) return;
16456
+ lastWidth = window.innerWidth;
16457
+ if (resizeTimer) clearTimeout(resizeTimer);
16458
+ resizeTimer = setTimeout(measure, 150);
16459
+ };
16460
+ window.addEventListener("resize", handleResize);
17097
16461
  return () => {
17098
16462
  clearTimeout(t1);
17099
16463
  clearTimeout(t2);
17100
- if (raf != null) cancelAnimationFrame(raf);
17101
- ro.disconnect();
16464
+ if (resizeTimer) clearTimeout(resizeTimer);
16465
+ window.removeEventListener("resize", handleResize);
17102
16466
  };
17103
16467
  }, [pathname, isEditMode, postToParent2]);
17104
16468
  (0, import_react16.useEffect)(() => {
@@ -17279,12 +16643,10 @@ function OhhwellsBridge() {
17279
16643
  return;
17280
16644
  }
17281
16645
  const target = e.target;
17282
- if (target.closest("[data-ohw-ai-review]")) return;
17283
16646
  if (target.closest("[data-ohw-toolbar]")) return;
17284
16647
  if (target.closest("[data-ohw-state-toggle]")) return;
17285
16648
  if (target.closest("[data-ohw-max-badge]")) return;
17286
16649
  if (isInsideLinkEditor(target)) return;
17287
- if (isInsideFloatingPanel(target)) return;
17288
16650
  if (target.closest("[data-ohw-form-toolbar]")) return;
17289
16651
  if (target.closest(
17290
16652
  '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
@@ -17558,12 +16920,10 @@ function OhhwellsBridge() {
17558
16920
  };
17559
16921
  const handleDblClick = (e) => {
17560
16922
  const target = e.target;
17561
- if (target.closest("[data-ohw-ai-review]")) return;
17562
16923
  if (target.closest("[data-ohw-toolbar]")) return;
17563
16924
  if (target.closest("[data-ohw-state-toggle]")) return;
17564
16925
  if (target.closest("[data-ohw-max-badge]")) return;
17565
16926
  if (isInsideLinkEditor(target)) return;
17566
- if (isInsideFloatingPanel(target)) return;
17567
16927
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
17568
16928
  return;
17569
16929
  }
@@ -17604,14 +16964,11 @@ function OhhwellsBridge() {
17604
16964
  setSiblingHintRects([]);
17605
16965
  return;
17606
16966
  }
17607
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
16967
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
17608
16968
  hoveredItemElRef.current = null;
17609
16969
  setHoveredItemRect(null);
17610
16970
  hoveredNavContainerRef.current = null;
17611
16971
  setHoveredNavContainerRect(null);
17612
- siblingHintElRef.current = null;
17613
- setSiblingHintRect(null);
17614
- setSiblingHintRects([]);
17615
16972
  return;
17616
16973
  }
17617
16974
  {
@@ -17720,6 +17077,7 @@ function OhhwellsBridge() {
17720
17077
  hoveredNavContainerRef.current = null;
17721
17078
  setHoveredNavContainerRect(null);
17722
17079
  hoveredItemElRef.current = editable;
17080
+ setHoveredItemRect(editable.getBoundingClientRect());
17723
17081
  }
17724
17082
  }
17725
17083
  }
@@ -18016,7 +17374,7 @@ function OhhwellsBridge() {
18016
17374
  }
18017
17375
  };
18018
17376
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
18019
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17377
+ if (linkPopoverOpenRef.current) {
18020
17378
  if (hoveredImageRef.current) {
18021
17379
  hoveredImageRef.current = null;
18022
17380
  hoveredImageHasTextOverlapRef.current = false;
@@ -18270,7 +17628,7 @@ function OhhwellsBridge() {
18270
17628
  }
18271
17629
  };
18272
17630
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
18273
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17631
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
18274
17632
  if (activeStateElRef.current) {
18275
17633
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
18276
17634
  activeStateElRef.current = null;
@@ -18345,7 +17703,8 @@ function OhhwellsBridge() {
18345
17703
  };
18346
17704
  const handleMouseMove = (e) => {
18347
17705
  const { clientX, clientY } = e;
18348
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
17706
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17707
+ if (isOverEditorChrome(clientX, clientY)) {
18349
17708
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
18350
17709
  formHoverElRef.current = null;
18351
17710
  setFormHoverRect(null);
@@ -18353,12 +17712,6 @@ function OhhwellsBridge() {
18353
17712
  setHoveredItemRect(null);
18354
17713
  hoveredNavContainerRef.current = null;
18355
17714
  setHoveredNavContainerRect(null);
18356
- siblingHintElRef.current = null;
18357
- setSiblingHintRect(null);
18358
- setSiblingHintRects([]);
18359
- dismissImageHover();
18360
- clearImageHover();
18361
- setSectionGap(null);
18362
17715
  return;
18363
17716
  }
18364
17717
  probeSectionGapAt(clientX, clientY);
@@ -18369,11 +17722,7 @@ function OhhwellsBridge() {
18369
17722
  if (e.data?.type !== "ow:pointer-sync") return;
18370
17723
  const { clientX, clientY } = e.data;
18371
17724
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
18372
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
18373
- dismissImageHover();
18374
- clearImageHover();
18375
- return;
18376
- }
17725
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
18377
17726
  probeSectionGapAt(clientX, clientY);
18378
17727
  probeImageAt(clientX, clientY);
18379
17728
  probeHoverCardsAt(clientX, clientY);
@@ -18619,19 +17968,10 @@ function OhhwellsBridge() {
18619
17968
  if (e.data?.type !== "ow:hydrate") return;
18620
17969
  const content = e.data.content;
18621
17970
  if (!content) return;
18622
- if (typeof content[BRAND_KIT_KEY] === "string") {
18623
- brandKitRef.current = content[BRAND_KIT_KEY];
18624
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
18625
- }
18626
17971
  if (typeof content[AI_SECTIONS_KEY] === "string") {
18627
17972
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
18628
17973
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
18629
17974
  }
18630
- if (typeof content[STYLE_STORE_KEY] === "string") {
18631
- stylesRef.current = content[STYLE_STORE_KEY];
18632
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
18633
- }
18634
- applyBrandChrome(content);
18635
17975
  let sectionsJson = null;
18636
17976
  for (const [key, val] of Object.entries(content)) {
18637
17977
  if (key === "__ohw_sections") {
@@ -18641,9 +17981,6 @@ function OhhwellsBridge() {
18641
17981
  if (key === AI_SECTIONS_KEY) continue;
18642
17982
  if (key === LOGO_PLACEHOLDER_KEY) continue;
18643
17983
  if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
18644
- if (key === BRAND_KIT_KEY) continue;
18645
- if (key === STYLE_STORE_KEY) continue;
18646
- if (BRAND_CHROME_KEYS.has(key)) continue;
18647
17984
  if (applyVideoSettingNode(key, val)) continue;
18648
17985
  if (applyCarouselNode(key, val)) continue;
18649
17986
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -18745,10 +18082,7 @@ function OhhwellsBridge() {
18745
18082
  const payload = e.data.payload;
18746
18083
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
18747
18084
  const previous = aiSectionsRef.current;
18748
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
18749
- ...payload,
18750
- path: payload.path ?? window.location.pathname
18751
- });
18085
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
18752
18086
  const nextValue = serializeAiSectionsState(nextState);
18753
18087
  aiSectionsRef.current = nextValue;
18754
18088
  applyAiSectionsToDom(nextState);
@@ -18785,42 +18119,12 @@ function OhhwellsBridge() {
18785
18119
  const value = typeof e.data.value === "string" ? e.data.value : "";
18786
18120
  aiSectionsRef.current = value;
18787
18121
  applyAiSectionsToDom(parseAiSectionsState(value));
18788
- applyStylesToDom(parseStyleStore(stylesRef.current));
18789
18122
  const restoredHeight = document.documentElement.scrollHeight;
18790
18123
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
18791
18124
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
18792
18125
  postAiSectionsChanged();
18793
18126
  };
18794
18127
  window.addEventListener("message", handleAiSetSections);
18795
- const handleAiSetBrand = (e) => {
18796
- if (e.data?.type !== "ow:ai-set-brand") return;
18797
- const value = typeof e.data.value === "string" ? e.data.value : "";
18798
- const previous = brandKitRef.current;
18799
- brandKitRef.current = value;
18800
- applyBrandToDom(parseBrandKit(value));
18801
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
18802
- applyStylesToDom(parseStyleStore(stylesRef.current));
18803
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
18804
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
18805
- };
18806
- window.addEventListener("message", handleAiSetBrand);
18807
- const handleAiSetStyles = (e) => {
18808
- if (e.data?.type !== "ow:ai-set-styles") return;
18809
- const value = typeof e.data.value === "string" ? e.data.value : "";
18810
- const previous = stylesRef.current;
18811
- stylesRef.current = value;
18812
- applyStylesToDom(parseStyleStore(value));
18813
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
18814
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
18815
- };
18816
- window.addEventListener("message", handleAiSetStyles);
18817
- const handleGetBrand = (e) => {
18818
- if (e.data?.type !== "ow:get-brand") return;
18819
- const template = deriveTemplateBrand();
18820
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
18821
- postToParentRef.current({ type: "ow:brand-value", value });
18822
- };
18823
- window.addEventListener("message", handleGetBrand);
18824
18128
  const handleDeactivate = (e) => {
18825
18129
  if (e.data?.type !== "ow:deactivate") return;
18826
18130
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -18829,12 +18133,6 @@ function OhhwellsBridge() {
18829
18133
  closeLinkPopoverRef.current();
18830
18134
  return;
18831
18135
  }
18832
- if (floatingPanelOpenRef.current) {
18833
- setFloatingPanelRef.current(null);
18834
- deselectRef.current();
18835
- deactivateRef.current();
18836
- return;
18837
- }
18838
18136
  deselectRef.current();
18839
18137
  deactivateRef.current();
18840
18138
  };
@@ -19081,12 +18379,6 @@ function OhhwellsBridge() {
19081
18379
  if (aiSectionsRef.current) {
19082
18380
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
19083
18381
  }
19084
- if (stylesRef.current) {
19085
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
19086
- }
19087
- if (brandKitRef.current) {
19088
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
19089
- }
19090
18382
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
19091
18383
  const formKey = formKeyOf(form);
19092
18384
  if (!formKey) return;
@@ -19104,12 +18396,8 @@ function OhhwellsBridge() {
19104
18396
  if (inserted) {
19105
18397
  const tracker = getSectionsTracker();
19106
18398
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
19107
- const reportHeight = () => {
19108
- const h = document.body.scrollHeight;
19109
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19110
- };
19111
- reportHeight();
19112
- setTimeout(reportHeight, 500);
18399
+ const h = document.documentElement.scrollHeight;
18400
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19113
18401
  }
19114
18402
  };
19115
18403
  const handleSwitchSchedule = (e) => {
@@ -19496,9 +18784,6 @@ function OhhwellsBridge() {
19496
18784
  window.removeEventListener("message", handleAiApplyTree);
19497
18785
  window.removeEventListener("message", handleAiDeleteSection);
19498
18786
  window.removeEventListener("message", handleAiSetSections);
19499
- window.removeEventListener("message", handleAiSetBrand);
19500
- window.removeEventListener("message", handleAiSetStyles);
19501
- window.removeEventListener("message", handleGetBrand);
19502
18787
  window.removeEventListener("message", handleDeactivate);
19503
18788
  window.removeEventListener("message", handleToastAction);
19504
18789
  window.removeEventListener("message", handleFormCount);
@@ -19705,7 +18990,7 @@ function OhhwellsBridge() {
19705
18990
  postToParent2({
19706
18991
  type: "ow:ready",
19707
18992
  version: "1",
19708
- bridgeVersion: "0.1.65",
18993
+ bridgeVersion: "0.1.64",
19709
18994
  path: pathname,
19710
18995
  nodes: collectEditableNodes(editContentRef.current),
19711
18996
  sections
@@ -19759,6 +19044,44 @@ function OhhwellsBridge() {
19759
19044
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
19760
19045
  refreshActiveCommandsRef.current();
19761
19046
  }, []);
19047
+ (0, import_react16.useEffect)(() => {
19048
+ const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
19049
+ if (!session || !logoSizeDraft) return;
19050
+ const onPanelAction = (e) => {
19051
+ const type = e.data?.type;
19052
+ if (type === "ow:logo-size-close") {
19053
+ closeFloatingPanelAndDeselect();
19054
+ return;
19055
+ }
19056
+ if (type === "ow:logo-size-update-everywhere") {
19057
+ postToParentRef.current({ type: "ow:open-logo-settings", ...readLogoIdentityFromDom() });
19058
+ return;
19059
+ }
19060
+ if (type === "ow:logo-size-customize-mobile" || type === "ow:logo-size-reset-mobile") {
19061
+ const following = type === "ow:logo-size-reset-mobile";
19062
+ const next2 = {
19063
+ ...logoSizeDraft,
19064
+ mobileFollowing: following,
19065
+ mobilePx: logoSizeDraft.desktopPx
19066
+ };
19067
+ setLogoSizeDraft(next2);
19068
+ persistLogoSizeDraft(session.placement, next2);
19069
+ return;
19070
+ }
19071
+ if (type !== "ow:logo-size-set") return;
19072
+ const px = Number(e.data.px);
19073
+ if (!Number.isFinite(px)) return;
19074
+ const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
19075
+ ...logoSizeDraft,
19076
+ desktopPx: px,
19077
+ mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
19078
+ };
19079
+ setLogoSizeDraft(next);
19080
+ persistLogoSizeDraft(session.placement, next);
19081
+ };
19082
+ window.addEventListener("message", onPanelAction);
19083
+ return () => window.removeEventListener("message", onPanelAction);
19084
+ }, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
19762
19085
  const handleStateChange = (0, import_react16.useCallback)((state) => {
19763
19086
  if (!activeStateElRef.current) return;
19764
19087
  const el = activeStateElRef.current;
@@ -20100,10 +19423,10 @@ function OhhwellsBridge() {
20100
19423
  [postToParent2]
20101
19424
  );
20102
19425
  return bridgeRoot ? (0, import_react_dom4.createPortal)(
20103
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20104
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
20105
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
20106
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19426
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19427
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
19428
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
19429
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20107
19430
  MediaOverlay,
20108
19431
  {
20109
19432
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -20114,7 +19437,7 @@ function OhhwellsBridge() {
20114
19437
  },
20115
19438
  `uploading-${key}`
20116
19439
  )),
20117
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19440
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20118
19441
  MediaOverlay,
20119
19442
  {
20120
19443
  hover: mediaHover,
@@ -20123,11 +19446,11 @@ function OhhwellsBridge() {
20123
19446
  onVideoSettingsChange: handleVideoSettingsChange
20124
19447
  }
20125
19448
  ),
20126
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
20127
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
20128
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
20129
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
20130
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19449
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
19450
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
19451
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
19452
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
19453
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20131
19454
  "div",
20132
19455
  {
20133
19456
  className: "pointer-events-none fixed z-2147483646",
@@ -20137,7 +19460,7 @@ function OhhwellsBridge() {
20137
19460
  width: slot.width,
20138
19461
  height: slot.height
20139
19462
  },
20140
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19463
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20141
19464
  DropIndicator,
20142
19465
  {
20143
19466
  direction: slot.direction,
@@ -20148,7 +19471,7 @@ function OhhwellsBridge() {
20148
19471
  },
20149
19472
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
20150
19473
  )),
20151
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19474
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20152
19475
  "div",
20153
19476
  {
20154
19477
  className: "pointer-events-none fixed z-2147483646",
@@ -20158,7 +19481,7 @@ function OhhwellsBridge() {
20158
19481
  width: slot.width,
20159
19482
  height: slot.height
20160
19483
  },
20161
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19484
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20162
19485
  DropIndicator,
20163
19486
  {
20164
19487
  direction: slot.direction,
@@ -20169,10 +19492,10 @@ function OhhwellsBridge() {
20169
19492
  },
20170
19493
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
20171
19494
  )),
20172
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
20173
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
20174
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
20175
- formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19495
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19496
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19497
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19498
+ formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20176
19499
  ItemInteractionLayer,
20177
19500
  {
20178
19501
  rect: formPickRect,
@@ -20180,13 +19503,13 @@ function OhhwellsBridge() {
20180
19503
  itemDragSurface: false,
20181
19504
  toolbarAlign: "left",
20182
19505
  chromeGap: 24,
20183
- toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19506
+ toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20184
19507
  "div",
20185
19508
  {
20186
19509
  "data-ohw-form-toolbar": "",
20187
19510
  className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
20188
19511
  children: [
20189
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19512
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20190
19513
  "button",
20191
19514
  {
20192
19515
  type: "button",
@@ -20194,11 +19517,11 @@ function OhhwellsBridge() {
20194
19517
  className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
20195
19518
  onClick: () => setFieldTypePickerOpen((open) => !open),
20196
19519
  "data-ohw-add-field": "",
20197
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Plus, { size: 15, "aria-hidden": true })
19520
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
20198
19521
  }
20199
19522
  ),
20200
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20201
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19523
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19524
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20202
19525
  "button",
20203
19526
  {
20204
19527
  type: "button",
@@ -20213,11 +19536,11 @@ function OhhwellsBridge() {
20213
19536
  });
20214
19537
  },
20215
19538
  children: [
20216
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Settings, { size: 14, "aria-hidden": true }),
19539
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
20217
19540
  "Form settings",
20218
19541
  formPickCount ? (
20219
19542
  // Counter pill, per the design — not a text suffix.
20220
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19543
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20221
19544
  "span",
20222
19545
  {
20223
19546
  "data-ohw-form-count": "",
@@ -20229,8 +19552,8 @@ function OhhwellsBridge() {
20229
19552
  ]
20230
19553
  }
20231
19554
  ),
20232
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20233
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19555
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19556
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20234
19557
  "button",
20235
19558
  {
20236
19559
  type: "button",
@@ -20260,7 +19583,7 @@ function OhhwellsBridge() {
20260
19583
  )
20261
19584
  }
20262
19585
  ),
20263
- formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19586
+ formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20264
19587
  ItemInteractionLayer,
20265
19588
  {
20266
19589
  rect: formHoverRect,
@@ -20268,7 +19591,7 @@ function OhhwellsBridge() {
20268
19591
  chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20269
19592
  }
20270
19593
  ),
20271
- fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19594
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20272
19595
  ItemInteractionLayer,
20273
19596
  {
20274
19597
  rect: fieldPickRect,
@@ -20280,7 +19603,7 @@ function OhhwellsBridge() {
20280
19603
  dragHandleLabel: "Reorder field",
20281
19604
  onDragHandleDragStart: handleFieldDragStart,
20282
19605
  onDragHandleDragEnd: handleFieldDragEnd,
20283
- toolbar: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19606
+ toolbar: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20284
19607
  FormFieldToolbar,
20285
19608
  {
20286
19609
  type: fieldPickState.type,
@@ -20293,12 +19616,12 @@ function OhhwellsBridge() {
20293
19616
  )
20294
19617
  }
20295
19618
  ),
20296
- fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19619
+ fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20297
19620
  "div",
20298
19621
  {
20299
19622
  className: "pointer-events-none fixed z-[2147483644]",
20300
19623
  style: { top: slot.top, left: slot.left, width: slot.width },
20301
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19624
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20302
19625
  DropIndicator,
20303
19626
  {
20304
19627
  direction: "horizontal",
@@ -20309,16 +19632,16 @@ function OhhwellsBridge() {
20309
19632
  },
20310
19633
  `field-drop-${i}`
20311
19634
  )) : null,
20312
- fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19635
+ fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20313
19636
  "div",
20314
19637
  {
20315
19638
  className: "pointer-events-none fixed z-[2147483645]",
20316
19639
  style: { top: formPickRect.top + 16, left: formPickRect.left + 24 },
20317
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(FieldTypePicker, { onPick: handleAddField })
19640
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldTypePicker, { onPick: handleAddField })
20318
19641
  }
20319
19642
  ),
20320
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
20321
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19643
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19644
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20322
19645
  FooterContainerChrome,
20323
19646
  {
20324
19647
  rect: toolbarRect,
@@ -20326,7 +19649,7 @@ function OhhwellsBridge() {
20326
19649
  addDisabled: !canAddFooterColumn()
20327
19650
  }
20328
19651
  ),
20329
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19652
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20330
19653
  ItemInteractionLayer,
20331
19654
  {
20332
19655
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -20341,7 +19664,7 @@ function OhhwellsBridge() {
20341
19664
  onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
20342
19665
  onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
20343
19666
  itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
20344
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19667
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20345
19668
  ItemActionToolbar,
20346
19669
  {
20347
19670
  onEditLink: openLinkPopoverForSelected,
@@ -20377,8 +19700,8 @@ function OhhwellsBridge() {
20377
19700
  ) : void 0
20378
19701
  }
20379
19702
  ),
20380
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20381
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19703
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19704
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20382
19705
  EditGlowChrome,
20383
19706
  {
20384
19707
  rect: toolbarRect,
@@ -20388,7 +19711,7 @@ function OhhwellsBridge() {
20388
19711
  hideHandle: isItemDragging
20389
19712
  }
20390
19713
  ),
20391
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19714
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20392
19715
  FloatingToolbar,
20393
19716
  {
20394
19717
  rect: toolbarRect,
@@ -20401,7 +19724,7 @@ function OhhwellsBridge() {
20401
19724
  }
20402
19725
  )
20403
19726
  ] }),
20404
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19727
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20405
19728
  "div",
20406
19729
  {
20407
19730
  "data-ohw-max-badge": "",
@@ -20427,7 +19750,7 @@ function OhhwellsBridge() {
20427
19750
  ]
20428
19751
  }
20429
19752
  ),
20430
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19753
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20431
19754
  StateToggle,
20432
19755
  {
20433
19756
  rect: toggleState.rect,
@@ -20436,15 +19759,15 @@ function OhhwellsBridge() {
20436
19759
  onStateChange: handleStateChange
20437
19760
  }
20438
19761
  ),
20439
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19762
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20440
19763
  "div",
20441
19764
  {
20442
19765
  "data-ohw-section-insert-line": "",
20443
19766
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
20444
19767
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
20445
19768
  children: [
20446
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
20447
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19769
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19770
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20448
19771
  Badge,
20449
19772
  {
20450
19773
  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",
@@ -20461,11 +19784,11 @@ function OhhwellsBridge() {
20461
19784
  children: "Add Section"
20462
19785
  }
20463
19786
  ),
20464
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19787
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
20465
19788
  ]
20466
19789
  }
20467
19790
  ),
20468
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19791
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20469
19792
  LinkPopover,
20470
19793
  {
20471
19794
  panelRef: linkPopoverPanelRef,
@@ -20482,7 +19805,7 @@ function OhhwellsBridge() {
20482
19805
  },
20483
19806
  linkPopover.key
20484
19807
  ) : null,
20485
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19808
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20486
19809
  FloatingPanel,
20487
19810
  {
20488
19811
  open: true,
@@ -20492,7 +19815,7 @@ function OhhwellsBridge() {
20492
19815
  onPositionChange: setFloatingPanelPos,
20493
19816
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
20494
19817
  onClose: closeFloatingPanelOnly,
20495
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19818
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20496
19819
  SocialsDisplayPanel,
20497
19820
  {
20498
19821
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -20503,115 +19826,11 @@ function OhhwellsBridge() {
20503
19826
  }
20504
19827
  )
20505
19828
  }
20506
- ) : null,
20507
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20508
- FloatingPanel,
20509
- {
20510
- open: true,
20511
- title: floatingPanel.title,
20512
- context: floatingPanel.context,
20513
- position: floatingPanelPos,
20514
- onPositionChange: setFloatingPanelPos,
20515
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
20516
- onClose: closeFloatingPanelAndDeselect,
20517
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20518
- LogoSizePanel,
20519
- {
20520
- viewport: editorViewport,
20521
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
20522
- mobileFollowing: logoSizeDraft.mobileFollowing,
20523
- onSizeChange: (px) => {
20524
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
20525
- ...logoSizeDraft,
20526
- desktopPx: px,
20527
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
20528
- };
20529
- setLogoSizeDraft(next);
20530
- persistLogoSizeDraft(floatingPanel.placement, next);
20531
- },
20532
- onCustomizeMobile: () => {
20533
- const next = {
20534
- ...logoSizeDraft,
20535
- mobileFollowing: false,
20536
- mobilePx: logoSizeDraft.desktopPx
20537
- };
20538
- setLogoSizeDraft(next);
20539
- persistLogoSizeDraft(floatingPanel.placement, next);
20540
- },
20541
- onResetMobile: () => {
20542
- const next = {
20543
- ...logoSizeDraft,
20544
- mobileFollowing: true,
20545
- mobilePx: logoSizeDraft.desktopPx
20546
- };
20547
- setLogoSizeDraft(next);
20548
- persistLogoSizeDraft(floatingPanel.placement, next);
20549
- },
20550
- onUpdateEverywhere: () => {
20551
- const identity = readLogoIdentityFromDom();
20552
- postToParent2({ type: "ow:open-logo-settings", ...identity });
20553
- }
20554
- }
20555
- )
20556
- }
20557
19829
  ) : null
20558
19830
  ] }),
20559
19831
  bridgeRoot
20560
19832
  ) : null;
20561
19833
  }
20562
-
20563
- // src/ui/EmptySection.tsx
20564
- var import_link = __toESM(require("next/link"), 1);
20565
- var import_jsx_runtime35 = require("react/jsx-runtime");
20566
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
20567
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
20568
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
20569
- "p",
20570
- {
20571
- style: {
20572
- fontFamily: "var(--brand-font-body)",
20573
- fontSize: "0.75rem",
20574
- fontWeight: 500,
20575
- letterSpacing: "0.15em",
20576
- textTransform: "uppercase",
20577
- color: "var(--brand-accent)",
20578
- marginBottom: "1.5rem"
20579
- },
20580
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
20581
- }
20582
- ),
20583
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
20584
- "h1",
20585
- {
20586
- style: {
20587
- fontFamily: "var(--brand-font-heading)",
20588
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
20589
- lineHeight: 1.1,
20590
- letterSpacing: "-0.025em",
20591
- color: "var(--brand-text)",
20592
- marginBottom: "1rem"
20593
- },
20594
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
20595
- children: title
20596
- }
20597
- ),
20598
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
20599
- "p",
20600
- {
20601
- style: {
20602
- fontFamily: "var(--brand-font-body)",
20603
- fontSize: "1rem",
20604
- lineHeight: 1.7,
20605
- fontWeight: 300,
20606
- color: "var(--brand-text-muted)",
20607
- maxWidth: "340px"
20608
- },
20609
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
20610
- children: "This page doesn't have any content yet."
20611
- }
20612
- )
20613
- ] });
20614
- }
20615
19834
  // Annotate the CommonJS export names for ESM import in node:
20616
19835
  0 && (module.exports = {
20617
19836
  AI_DEFAULT_BRAND,
@@ -20629,7 +19848,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
20629
19848
  DropdownMenuItem,
20630
19849
  DropdownMenuSeparator,
20631
19850
  DropdownMenuTrigger,
20632
- EmptySection,
20633
19851
  ItemActionToolbar,
20634
19852
  ItemInteractionLayer,
20635
19853
  LinkEditorPanel,