@ohhwells/bridge 0.1.66-next.190 → 0.1.66

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";
@@ -660,7 +309,7 @@ function ButtonEl({
660
309
  }) {
661
310
  const secondary = slots.variant === "secondary";
662
311
  const href = str(slots.href);
663
- const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
312
+ const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`) } : {};
664
313
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
665
314
  "a",
666
315
  {
@@ -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]");
@@ -14407,6 +13807,13 @@ function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
14407
13807
  if (isPointOverNavItem(column, clientX, clientY)) return null;
14408
13808
  return column;
14409
13809
  }
13810
+ function isPointOverLogo(x, y) {
13811
+ for (const root of document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]')) {
13812
+ const r2 = root.getBoundingClientRect();
13813
+ if (r2.width > 0 && r2.height > 0 && x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
13814
+ }
13815
+ return false;
13816
+ }
14410
13817
  function isPointOverNavigation(x, y) {
14411
13818
  const roots = /* @__PURE__ */ new Set();
14412
13819
  const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
@@ -14495,7 +13902,7 @@ function getNavigationSelectionParent(el) {
14495
13902
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
14496
13903
  return getFooterLinksContainer();
14497
13904
  }
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)) {
13905
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
14499
13906
  return getNavigationRoot(el);
14500
13907
  }
14501
13908
  return null;
@@ -14741,7 +14148,7 @@ function EditGlowChrome({
14741
14148
  hideHandle = false
14742
14149
  }) {
14743
14150
  const GAP = SELECTION_CHROME_GAP2;
14744
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
14151
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
14745
14152
  "div",
14746
14153
  {
14747
14154
  ref: elRef,
@@ -14756,7 +14163,7 @@ function EditGlowChrome({
14756
14163
  zIndex: 2147483646
14757
14164
  },
14758
14165
  children: [
14759
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14166
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14760
14167
  "div",
14761
14168
  {
14762
14169
  style: {
@@ -14769,7 +14176,7 @@ function EditGlowChrome({
14769
14176
  }
14770
14177
  }
14771
14178
  ),
14772
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14179
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14773
14180
  "div",
14774
14181
  {
14775
14182
  "data-ohw-drag-handle-container": "",
@@ -14781,7 +14188,7 @@ function EditGlowChrome({
14781
14188
  transform: "translate(calc(-100% - 7px), -50%)",
14782
14189
  pointerEvents: dragDisabled ? "none" : "auto"
14783
14190
  },
14784
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14191
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14785
14192
  DragHandle,
14786
14193
  {
14787
14194
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -14991,7 +14398,7 @@ function FloatingToolbar({
14991
14398
  return () => ro.disconnect();
14992
14399
  }, [showEditLink, activeCommands]);
14993
14400
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
14994
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14401
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14995
14402
  "div",
14996
14403
  {
14997
14404
  ref: setRefs,
@@ -15003,12 +14410,12 @@ function FloatingToolbar({
15003
14410
  zIndex: 2147483647,
15004
14411
  pointerEvents: "auto"
15005
14412
  },
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, {}),
14413
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
14414
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
14415
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
15009
14416
  btns.map((btn) => {
15010
14417
  const isActive = activeCommands.has(btn.cmd);
15011
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14418
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15012
14419
  CustomToolbarButton,
15013
14420
  {
15014
14421
  title: btn.title,
@@ -15017,7 +14424,7 @@ function FloatingToolbar({
15017
14424
  e.preventDefault();
15018
14425
  onCommand(btn.cmd);
15019
14426
  },
15020
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14427
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15021
14428
  "svg",
15022
14429
  {
15023
14430
  width: "16",
@@ -15038,7 +14445,7 @@ function FloatingToolbar({
15038
14445
  );
15039
14446
  })
15040
14447
  ] }, gi)),
15041
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14448
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15042
14449
  CustomToolbarButton,
15043
14450
  {
15044
14451
  type: "button",
@@ -15052,7 +14459,7 @@ function FloatingToolbar({
15052
14459
  e.preventDefault();
15053
14460
  e.stopPropagation();
15054
14461
  },
15055
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Link, { className: "size-4 shrink-0", "aria-hidden": true })
14462
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
15056
14463
  }
15057
14464
  ) : null
15058
14465
  ] })
@@ -15069,7 +14476,7 @@ function StateToggle({
15069
14476
  states,
15070
14477
  onStateChange
15071
14478
  }) {
15072
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14479
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15073
14480
  ToggleGroup,
15074
14481
  {
15075
14482
  "data-ohw-state-toggle": "",
@@ -15083,12 +14490,11 @@ function StateToggle({
15083
14490
  left: rect.right - 8,
15084
14491
  transform: "translateX(-100%)"
15085
14492
  },
15086
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14493
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
15087
14494
  }
15088
14495
  );
15089
14496
  }
15090
14497
  var contentCache = /* @__PURE__ */ new Map();
15091
- var fetchedContentPaths = /* @__PURE__ */ new Set();
15092
14498
  function resolveSubdomain(subdomainFromQuery) {
15093
14499
  if (subdomainFromQuery) return subdomainFromQuery;
15094
14500
  if (typeof window !== "undefined") {
@@ -15427,6 +14833,13 @@ function OhhwellsBridge() {
15427
14833
  const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
15428
14834
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
15429
14835
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
14836
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
14837
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
14838
+ floatingPanelOpenRef.current = floatingPanel !== null;
14839
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
14840
+ const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
14841
+ const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
14842
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
15430
14843
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
15431
14844
  const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
15432
14845
  const footerDragRef = (0, import_react16.useRef)(null);
@@ -15441,16 +14854,7 @@ function OhhwellsBridge() {
15441
14854
  const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
15442
14855
  const editContentRef = (0, import_react16.useRef)({});
15443
14856
  const aiSectionsRef = (0, import_react16.useRef)("");
15444
- const brandKitRef = (0, import_react16.useRef)("");
15445
- const stylesRef = (0, import_react16.useRef)("");
15446
14857
  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
14858
  const [sitePages, setSitePages] = (0, import_react16.useState)([]);
15455
14859
  const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
15456
14860
  const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
@@ -15459,18 +14863,7 @@ function OhhwellsBridge() {
15459
14863
  const linkPopoverOpenRef = (0, import_react16.useRef)(false);
15460
14864
  const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
15461
14865
  setLinkPopoverRef.current = setLinkPopover;
15462
- setFloatingPanelRef.current = setFloatingPanel;
15463
14866
  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
14867
  const {
15475
14868
  navDragRef,
15476
14869
  navDropSlots,
@@ -16555,6 +15948,25 @@ function OhhwellsBridge() {
16555
15948
  setLogoSizeDraft(null);
16556
15949
  deselectRef.current();
16557
15950
  }, []);
15951
+ (0, import_react16.useEffect)(() => {
15952
+ const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
15953
+ if (!session || !logoSizeDraft) {
15954
+ postToParentRef.current({ type: "ow:logo-size-panel", open: false });
15955
+ return;
15956
+ }
15957
+ postToParentRef.current({
15958
+ type: "ow:logo-size-panel",
15959
+ open: true,
15960
+ title: session.title,
15961
+ context: session.context ?? "",
15962
+ placement: session.placement,
15963
+ viewport: editorViewport,
15964
+ mobileFollowing: logoSizeDraft.mobileFollowing,
15965
+ sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
15966
+ min: LOGO_SIZE_MIN,
15967
+ max: LOGO_SIZE_MAX
15968
+ });
15969
+ }, [floatingPanel, logoSizeDraft, editorViewport]);
16558
15970
  const persistLogoSizeDraft = (0, import_react16.useCallback)(
16559
15971
  (placement, draft) => {
16560
15972
  const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
@@ -16713,27 +16125,15 @@ function OhhwellsBridge() {
16713
16125
  }
16714
16126
  const applyContent = (content) => {
16715
16127
  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
16128
  if (typeof content[AI_SECTIONS_KEY] === "string") {
16721
16129
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
16722
16130
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
16723
16131
  }
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
16132
  for (const [key, val] of Object.entries(content)) {
16730
16133
  if (key === "__ohw_sections") continue;
16731
16134
  if (key === AI_SECTIONS_KEY) continue;
16732
16135
  if (key === LOGO_PLACEHOLDER_KEY) continue;
16733
16136
  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
16137
  if (applyVideoSettingNode(key, val)) continue;
16738
16138
  if (applyCarouselNode(key, val)) continue;
16739
16139
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16791,9 +16191,7 @@ function OhhwellsBridge() {
16791
16191
  let cancelled = false;
16792
16192
  setFetchState("loading");
16793
16193
  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) => {
16194
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16797
16195
  if (cancelled) return;
16798
16196
  const content = data?.content ?? {};
16799
16197
  contentCache.set(subdomain, content);
@@ -16913,21 +16311,10 @@ function OhhwellsBridge() {
16913
16311
  initSectionInstancesFromContent(content, window.location.pathname);
16914
16312
  observer?.disconnect();
16915
16313
  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
16314
  for (const [key, val] of Object.entries(content)) {
16924
16315
  if (key === "__ohw_sections") continue;
16925
16316
  if (key === LOGO_PLACEHOLDER_KEY) continue;
16926
16317
  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
16318
  if (applyVideoSettingNode(key, val)) continue;
16932
16319
  if (applyCarouselNode(key, val)) continue;
16933
16320
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16970,17 +16357,6 @@ function OhhwellsBridge() {
16970
16357
  debounceTimer = setTimeout(applyFromCache, 150);
16971
16358
  };
16972
16359
  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
16360
  observer = new MutationObserver(scheduleApply);
16985
16361
  observer.observe(document.body, { childList: true, subtree: true });
16986
16362
  return () => {
@@ -17074,31 +16450,26 @@ function OhhwellsBridge() {
17074
16450
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
17075
16451
  (0, import_react16.useEffect)(() => {
17076
16452
  if (!isEditMode) return;
17077
- let lastPosted = 0;
17078
16453
  const measure = () => {
17079
16454
  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
- });
16455
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
17092
16456
  };
17093
16457
  const t1 = setTimeout(measure, 50);
17094
16458
  const t2 = setTimeout(measure, 500);
17095
- const ro = new ResizeObserver(schedule);
17096
- ro.observe(document.body);
16459
+ let lastWidth = window.innerWidth;
16460
+ let resizeTimer = null;
16461
+ const handleResize = () => {
16462
+ if (window.innerWidth === lastWidth) return;
16463
+ lastWidth = window.innerWidth;
16464
+ if (resizeTimer) clearTimeout(resizeTimer);
16465
+ resizeTimer = setTimeout(measure, 150);
16466
+ };
16467
+ window.addEventListener("resize", handleResize);
17097
16468
  return () => {
17098
16469
  clearTimeout(t1);
17099
16470
  clearTimeout(t2);
17100
- if (raf != null) cancelAnimationFrame(raf);
17101
- ro.disconnect();
16471
+ if (resizeTimer) clearTimeout(resizeTimer);
16472
+ window.removeEventListener("resize", handleResize);
17102
16473
  };
17103
16474
  }, [pathname, isEditMode, postToParent2]);
17104
16475
  (0, import_react16.useEffect)(() => {
@@ -17279,12 +16650,10 @@ function OhhwellsBridge() {
17279
16650
  return;
17280
16651
  }
17281
16652
  const target = e.target;
17282
- if (target.closest("[data-ohw-ai-review]")) return;
17283
16653
  if (target.closest("[data-ohw-toolbar]")) return;
17284
16654
  if (target.closest("[data-ohw-state-toggle]")) return;
17285
16655
  if (target.closest("[data-ohw-max-badge]")) return;
17286
16656
  if (isInsideLinkEditor(target)) return;
17287
- if (isInsideFloatingPanel(target)) return;
17288
16657
  if (target.closest("[data-ohw-form-toolbar]")) return;
17289
16658
  if (target.closest(
17290
16659
  '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
@@ -17558,12 +16927,10 @@ function OhhwellsBridge() {
17558
16927
  };
17559
16928
  const handleDblClick = (e) => {
17560
16929
  const target = e.target;
17561
- if (target.closest("[data-ohw-ai-review]")) return;
17562
16930
  if (target.closest("[data-ohw-toolbar]")) return;
17563
16931
  if (target.closest("[data-ohw-state-toggle]")) return;
17564
16932
  if (target.closest("[data-ohw-max-badge]")) return;
17565
16933
  if (isInsideLinkEditor(target)) return;
17566
- if (isInsideFloatingPanel(target)) return;
17567
16934
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
17568
16935
  return;
17569
16936
  }
@@ -17604,14 +16971,11 @@ function OhhwellsBridge() {
17604
16971
  setSiblingHintRects([]);
17605
16972
  return;
17606
16973
  }
17607
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
16974
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
17608
16975
  hoveredItemElRef.current = null;
17609
16976
  setHoveredItemRect(null);
17610
16977
  hoveredNavContainerRef.current = null;
17611
16978
  setHoveredNavContainerRect(null);
17612
- siblingHintElRef.current = null;
17613
- setSiblingHintRect(null);
17614
- setSiblingHintRects([]);
17615
16979
  return;
17616
16980
  }
17617
16981
  {
@@ -17720,6 +17084,7 @@ function OhhwellsBridge() {
17720
17084
  hoveredNavContainerRef.current = null;
17721
17085
  setHoveredNavContainerRect(null);
17722
17086
  hoveredItemElRef.current = editable;
17087
+ setHoveredItemRect(editable.getBoundingClientRect());
17723
17088
  }
17724
17089
  }
17725
17090
  }
@@ -18016,7 +17381,7 @@ function OhhwellsBridge() {
18016
17381
  }
18017
17382
  };
18018
17383
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
18019
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17384
+ if (linkPopoverOpenRef.current) {
18020
17385
  if (hoveredImageRef.current) {
18021
17386
  hoveredImageRef.current = null;
18022
17387
  hoveredImageHasTextOverlapRef.current = false;
@@ -18032,6 +17397,11 @@ function OhhwellsBridge() {
18032
17397
  probeNavigationHoverAt(x, y);
18033
17398
  return;
18034
17399
  }
17400
+ if (isPointOverLogo(x, y)) {
17401
+ dismissImageHover();
17402
+ probeNavigationHoverAt(x, y);
17403
+ return;
17404
+ }
18035
17405
  const overMoreMenu = document.elementFromPoint(x, y)?.closest?.(
18036
17406
  '[data-ohw-more-menu], [data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]'
18037
17407
  );
@@ -18270,7 +17640,7 @@ function OhhwellsBridge() {
18270
17640
  }
18271
17641
  };
18272
17642
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
18273
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17643
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
18274
17644
  if (activeStateElRef.current) {
18275
17645
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
18276
17646
  activeStateElRef.current = null;
@@ -18345,7 +17715,8 @@ function OhhwellsBridge() {
18345
17715
  };
18346
17716
  const handleMouseMove = (e) => {
18347
17717
  const { clientX, clientY } = e;
18348
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
17718
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17719
+ if (isOverEditorChrome(clientX, clientY)) {
18349
17720
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
18350
17721
  formHoverElRef.current = null;
18351
17722
  setFormHoverRect(null);
@@ -18353,12 +17724,6 @@ function OhhwellsBridge() {
18353
17724
  setHoveredItemRect(null);
18354
17725
  hoveredNavContainerRef.current = null;
18355
17726
  setHoveredNavContainerRect(null);
18356
- siblingHintElRef.current = null;
18357
- setSiblingHintRect(null);
18358
- setSiblingHintRects([]);
18359
- dismissImageHover();
18360
- clearImageHover();
18361
- setSectionGap(null);
18362
17727
  return;
18363
17728
  }
18364
17729
  probeSectionGapAt(clientX, clientY);
@@ -18369,11 +17734,7 @@ function OhhwellsBridge() {
18369
17734
  if (e.data?.type !== "ow:pointer-sync") return;
18370
17735
  const { clientX, clientY } = e.data;
18371
17736
  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
- }
17737
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
18377
17738
  probeSectionGapAt(clientX, clientY);
18378
17739
  probeImageAt(clientX, clientY);
18379
17740
  probeHoverCardsAt(clientX, clientY);
@@ -18619,19 +17980,10 @@ function OhhwellsBridge() {
18619
17980
  if (e.data?.type !== "ow:hydrate") return;
18620
17981
  const content = e.data.content;
18621
17982
  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
17983
  if (typeof content[AI_SECTIONS_KEY] === "string") {
18627
17984
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
18628
17985
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
18629
17986
  }
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
17987
  let sectionsJson = null;
18636
17988
  for (const [key, val] of Object.entries(content)) {
18637
17989
  if (key === "__ohw_sections") {
@@ -18641,9 +17993,6 @@ function OhhwellsBridge() {
18641
17993
  if (key === AI_SECTIONS_KEY) continue;
18642
17994
  if (key === LOGO_PLACEHOLDER_KEY) continue;
18643
17995
  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
17996
  if (applyVideoSettingNode(key, val)) continue;
18648
17997
  if (applyCarouselNode(key, val)) continue;
18649
17998
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -18745,10 +18094,7 @@ function OhhwellsBridge() {
18745
18094
  const payload = e.data.payload;
18746
18095
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
18747
18096
  const previous = aiSectionsRef.current;
18748
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
18749
- ...payload,
18750
- path: payload.path ?? window.location.pathname
18751
- });
18097
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
18752
18098
  const nextValue = serializeAiSectionsState(nextState);
18753
18099
  aiSectionsRef.current = nextValue;
18754
18100
  applyAiSectionsToDom(nextState);
@@ -18785,42 +18131,12 @@ function OhhwellsBridge() {
18785
18131
  const value = typeof e.data.value === "string" ? e.data.value : "";
18786
18132
  aiSectionsRef.current = value;
18787
18133
  applyAiSectionsToDom(parseAiSectionsState(value));
18788
- applyStylesToDom(parseStyleStore(stylesRef.current));
18789
18134
  const restoredHeight = document.documentElement.scrollHeight;
18790
18135
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
18791
18136
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
18792
18137
  postAiSectionsChanged();
18793
18138
  };
18794
18139
  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
18140
  const handleDeactivate = (e) => {
18825
18141
  if (e.data?.type !== "ow:deactivate") return;
18826
18142
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -18829,12 +18145,6 @@ function OhhwellsBridge() {
18829
18145
  closeLinkPopoverRef.current();
18830
18146
  return;
18831
18147
  }
18832
- if (floatingPanelOpenRef.current) {
18833
- setFloatingPanelRef.current(null);
18834
- deselectRef.current();
18835
- deactivateRef.current();
18836
- return;
18837
- }
18838
18148
  deselectRef.current();
18839
18149
  deactivateRef.current();
18840
18150
  };
@@ -19081,12 +18391,6 @@ function OhhwellsBridge() {
19081
18391
  if (aiSectionsRef.current) {
19082
18392
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
19083
18393
  }
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
18394
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
19091
18395
  const formKey = formKeyOf(form);
19092
18396
  if (!formKey) return;
@@ -19104,12 +18408,8 @@ function OhhwellsBridge() {
19104
18408
  if (inserted) {
19105
18409
  const tracker = getSectionsTracker();
19106
18410
  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);
18411
+ const h = document.documentElement.scrollHeight;
18412
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19113
18413
  }
19114
18414
  };
19115
18415
  const handleSwitchSchedule = (e) => {
@@ -19496,9 +18796,6 @@ function OhhwellsBridge() {
19496
18796
  window.removeEventListener("message", handleAiApplyTree);
19497
18797
  window.removeEventListener("message", handleAiDeleteSection);
19498
18798
  window.removeEventListener("message", handleAiSetSections);
19499
- window.removeEventListener("message", handleAiSetBrand);
19500
- window.removeEventListener("message", handleAiSetStyles);
19501
- window.removeEventListener("message", handleGetBrand);
19502
18799
  window.removeEventListener("message", handleDeactivate);
19503
18800
  window.removeEventListener("message", handleToastAction);
19504
18801
  window.removeEventListener("message", handleFormCount);
@@ -19705,7 +19002,7 @@ function OhhwellsBridge() {
19705
19002
  postToParent2({
19706
19003
  type: "ow:ready",
19707
19004
  version: "1",
19708
- bridgeVersion: "0.1.66",
19005
+ bridgeVersion: "0.1.65",
19709
19006
  path: pathname,
19710
19007
  nodes: collectEditableNodes(editContentRef.current),
19711
19008
  sections
@@ -19759,6 +19056,44 @@ function OhhwellsBridge() {
19759
19056
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
19760
19057
  refreshActiveCommandsRef.current();
19761
19058
  }, []);
19059
+ (0, import_react16.useEffect)(() => {
19060
+ const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
19061
+ if (!session || !logoSizeDraft) return;
19062
+ const onPanelAction = (e) => {
19063
+ const type = e.data?.type;
19064
+ if (type === "ow:logo-size-close") {
19065
+ closeFloatingPanelAndDeselect();
19066
+ return;
19067
+ }
19068
+ if (type === "ow:logo-size-update-everywhere") {
19069
+ postToParentRef.current({ type: "ow:open-logo-settings", ...readLogoIdentityFromDom() });
19070
+ return;
19071
+ }
19072
+ if (type === "ow:logo-size-customize-mobile" || type === "ow:logo-size-reset-mobile") {
19073
+ const following = type === "ow:logo-size-reset-mobile";
19074
+ const next2 = {
19075
+ ...logoSizeDraft,
19076
+ mobileFollowing: following,
19077
+ mobilePx: logoSizeDraft.desktopPx
19078
+ };
19079
+ setLogoSizeDraft(next2);
19080
+ persistLogoSizeDraft(session.placement, next2);
19081
+ return;
19082
+ }
19083
+ if (type !== "ow:logo-size-set") return;
19084
+ const px = Number(e.data.px);
19085
+ if (!Number.isFinite(px)) return;
19086
+ const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
19087
+ ...logoSizeDraft,
19088
+ desktopPx: px,
19089
+ mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
19090
+ };
19091
+ setLogoSizeDraft(next);
19092
+ persistLogoSizeDraft(session.placement, next);
19093
+ };
19094
+ window.addEventListener("message", onPanelAction);
19095
+ return () => window.removeEventListener("message", onPanelAction);
19096
+ }, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
19762
19097
  const handleStateChange = (0, import_react16.useCallback)((state) => {
19763
19098
  if (!activeStateElRef.current) return;
19764
19099
  const el = activeStateElRef.current;
@@ -20100,10 +19435,10 @@ function OhhwellsBridge() {
20100
19435
  [postToParent2]
20101
19436
  );
20102
19437
  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)(
19438
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19439
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
19440
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
19441
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20107
19442
  MediaOverlay,
20108
19443
  {
20109
19444
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -20114,7 +19449,7 @@ function OhhwellsBridge() {
20114
19449
  },
20115
19450
  `uploading-${key}`
20116
19451
  )),
20117
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19452
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20118
19453
  MediaOverlay,
20119
19454
  {
20120
19455
  hover: mediaHover,
@@ -20123,11 +19458,11 @@ function OhhwellsBridge() {
20123
19458
  onVideoSettingsChange: handleVideoSettingsChange
20124
19459
  }
20125
19460
  ),
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)(
19461
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
19462
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
19463
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
19464
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
19465
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20131
19466
  "div",
20132
19467
  {
20133
19468
  className: "pointer-events-none fixed z-2147483646",
@@ -20137,7 +19472,7 @@ function OhhwellsBridge() {
20137
19472
  width: slot.width,
20138
19473
  height: slot.height
20139
19474
  },
20140
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19475
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20141
19476
  DropIndicator,
20142
19477
  {
20143
19478
  direction: slot.direction,
@@ -20148,7 +19483,7 @@ function OhhwellsBridge() {
20148
19483
  },
20149
19484
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
20150
19485
  )),
20151
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19486
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20152
19487
  "div",
20153
19488
  {
20154
19489
  className: "pointer-events-none fixed z-2147483646",
@@ -20158,7 +19493,7 @@ function OhhwellsBridge() {
20158
19493
  width: slot.width,
20159
19494
  height: slot.height
20160
19495
  },
20161
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19496
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20162
19497
  DropIndicator,
20163
19498
  {
20164
19499
  direction: slot.direction,
@@ -20169,10 +19504,10 @@ function OhhwellsBridge() {
20169
19504
  },
20170
19505
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
20171
19506
  )),
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)(
19507
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19508
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19509
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19510
+ formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20176
19511
  ItemInteractionLayer,
20177
19512
  {
20178
19513
  rect: formPickRect,
@@ -20180,13 +19515,13 @@ function OhhwellsBridge() {
20180
19515
  itemDragSurface: false,
20181
19516
  toolbarAlign: "left",
20182
19517
  chromeGap: 24,
20183
- toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19518
+ toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20184
19519
  "div",
20185
19520
  {
20186
19521
  "data-ohw-form-toolbar": "",
20187
19522
  className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
20188
19523
  children: [
20189
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19524
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20190
19525
  "button",
20191
19526
  {
20192
19527
  type: "button",
@@ -20194,11 +19529,11 @@ function OhhwellsBridge() {
20194
19529
  className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
20195
19530
  onClick: () => setFieldTypePickerOpen((open) => !open),
20196
19531
  "data-ohw-add-field": "",
20197
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Plus, { size: 15, "aria-hidden": true })
19532
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
20198
19533
  }
20199
19534
  ),
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)(
19535
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19536
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20202
19537
  "button",
20203
19538
  {
20204
19539
  type: "button",
@@ -20213,11 +19548,11 @@ function OhhwellsBridge() {
20213
19548
  });
20214
19549
  },
20215
19550
  children: [
20216
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Settings, { size: 14, "aria-hidden": true }),
19551
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
20217
19552
  "Form settings",
20218
19553
  formPickCount ? (
20219
19554
  // Counter pill, per the design — not a text suffix.
20220
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19555
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20221
19556
  "span",
20222
19557
  {
20223
19558
  "data-ohw-form-count": "",
@@ -20229,8 +19564,8 @@ function OhhwellsBridge() {
20229
19564
  ]
20230
19565
  }
20231
19566
  ),
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)(
19567
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19568
+ /* @__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
19569
  "button",
20235
19570
  {
20236
19571
  type: "button",
@@ -20260,7 +19595,7 @@ function OhhwellsBridge() {
20260
19595
  )
20261
19596
  }
20262
19597
  ),
20263
- formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19598
+ formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20264
19599
  ItemInteractionLayer,
20265
19600
  {
20266
19601
  rect: formHoverRect,
@@ -20268,7 +19603,7 @@ function OhhwellsBridge() {
20268
19603
  chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20269
19604
  }
20270
19605
  ),
20271
- fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19606
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20272
19607
  ItemInteractionLayer,
20273
19608
  {
20274
19609
  rect: fieldPickRect,
@@ -20280,7 +19615,7 @@ function OhhwellsBridge() {
20280
19615
  dragHandleLabel: "Reorder field",
20281
19616
  onDragHandleDragStart: handleFieldDragStart,
20282
19617
  onDragHandleDragEnd: handleFieldDragEnd,
20283
- toolbar: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19618
+ toolbar: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20284
19619
  FormFieldToolbar,
20285
19620
  {
20286
19621
  type: fieldPickState.type,
@@ -20293,12 +19628,12 @@ function OhhwellsBridge() {
20293
19628
  )
20294
19629
  }
20295
19630
  ),
20296
- fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19631
+ fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20297
19632
  "div",
20298
19633
  {
20299
19634
  className: "pointer-events-none fixed z-[2147483644]",
20300
19635
  style: { top: slot.top, left: slot.left, width: slot.width },
20301
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19636
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20302
19637
  DropIndicator,
20303
19638
  {
20304
19639
  direction: "horizontal",
@@ -20309,16 +19644,16 @@ function OhhwellsBridge() {
20309
19644
  },
20310
19645
  `field-drop-${i}`
20311
19646
  )) : null,
20312
- fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19647
+ fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20313
19648
  "div",
20314
19649
  {
20315
19650
  className: "pointer-events-none fixed z-[2147483645]",
20316
19651
  style: { top: formPickRect.top + 16, left: formPickRect.left + 24 },
20317
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(FieldTypePicker, { onPick: handleAddField })
19652
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldTypePicker, { onPick: handleAddField })
20318
19653
  }
20319
19654
  ),
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)(
19655
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19656
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20322
19657
  FooterContainerChrome,
20323
19658
  {
20324
19659
  rect: toolbarRect,
@@ -20326,7 +19661,7 @@ function OhhwellsBridge() {
20326
19661
  addDisabled: !canAddFooterColumn()
20327
19662
  }
20328
19663
  ),
20329
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19664
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20330
19665
  ItemInteractionLayer,
20331
19666
  {
20332
19667
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -20341,7 +19676,7 @@ function OhhwellsBridge() {
20341
19676
  onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
20342
19677
  onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
20343
19678
  itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
20344
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19679
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20345
19680
  ItemActionToolbar,
20346
19681
  {
20347
19682
  onEditLink: openLinkPopoverForSelected,
@@ -20377,8 +19712,8 @@ function OhhwellsBridge() {
20377
19712
  ) : void 0
20378
19713
  }
20379
19714
  ),
20380
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20381
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19715
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19716
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20382
19717
  EditGlowChrome,
20383
19718
  {
20384
19719
  rect: toolbarRect,
@@ -20388,7 +19723,7 @@ function OhhwellsBridge() {
20388
19723
  hideHandle: isItemDragging
20389
19724
  }
20390
19725
  ),
20391
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19726
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20392
19727
  FloatingToolbar,
20393
19728
  {
20394
19729
  rect: toolbarRect,
@@ -20401,7 +19736,7 @@ function OhhwellsBridge() {
20401
19736
  }
20402
19737
  )
20403
19738
  ] }),
20404
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19739
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20405
19740
  "div",
20406
19741
  {
20407
19742
  "data-ohw-max-badge": "",
@@ -20427,7 +19762,7 @@ function OhhwellsBridge() {
20427
19762
  ]
20428
19763
  }
20429
19764
  ),
20430
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19765
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20431
19766
  StateToggle,
20432
19767
  {
20433
19768
  rect: toggleState.rect,
@@ -20436,15 +19771,15 @@ function OhhwellsBridge() {
20436
19771
  onStateChange: handleStateChange
20437
19772
  }
20438
19773
  ),
20439
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19774
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20440
19775
  "div",
20441
19776
  {
20442
19777
  "data-ohw-section-insert-line": "",
20443
19778
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
20444
19779
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
20445
19780
  children: [
20446
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
20447
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19781
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19782
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20448
19783
  Badge,
20449
19784
  {
20450
19785
  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 +19796,11 @@ function OhhwellsBridge() {
20461
19796
  children: "Add Section"
20462
19797
  }
20463
19798
  ),
20464
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19799
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
20465
19800
  ]
20466
19801
  }
20467
19802
  ),
20468
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19803
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20469
19804
  LinkPopover,
20470
19805
  {
20471
19806
  panelRef: linkPopoverPanelRef,
@@ -20482,7 +19817,7 @@ function OhhwellsBridge() {
20482
19817
  },
20483
19818
  linkPopover.key
20484
19819
  ) : null,
20485
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19820
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20486
19821
  FloatingPanel,
20487
19822
  {
20488
19823
  open: true,
@@ -20492,7 +19827,7 @@ function OhhwellsBridge() {
20492
19827
  onPositionChange: setFloatingPanelPos,
20493
19828
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
20494
19829
  onClose: closeFloatingPanelOnly,
20495
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19830
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20496
19831
  SocialsDisplayPanel,
20497
19832
  {
20498
19833
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -20503,115 +19838,11 @@ function OhhwellsBridge() {
20503
19838
  }
20504
19839
  )
20505
19840
  }
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
19841
  ) : null
20558
19842
  ] }),
20559
19843
  bridgeRoot
20560
19844
  ) : null;
20561
19845
  }
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
19846
  // Annotate the CommonJS export names for ESM import in node:
20616
19847
  0 && (module.exports = {
20617
19848
  AI_DEFAULT_BRAND,
@@ -20629,7 +19860,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
20629
19860
  DropdownMenuItem,
20630
19861
  DropdownMenuSeparator,
20631
19862
  DropdownMenuTrigger,
20632
- EmptySection,
20633
19863
  ItemActionToolbar,
20634
19864
  ItemInteractionLayer,
20635
19865
  LinkEditorPanel,