@ohhwells/bridge 0.1.65-next.189 → 0.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -83,12 +83,7 @@ function parseAiSectionsState(raw) {
83
83
  media: entry.media && typeof entry.media === "object" ? entry.media : {}
84
84
  }));
85
85
  const removed = Array.isArray(parsed.removed) ? parsed.removed.filter((id) => typeof id === "string" && id.length > 0) : [];
86
- return {
87
- v: 1,
88
- sections,
89
- ...removed.length ? { removed } : {},
90
- ...parsed.hideTemplate === true ? { hideTemplate: true } : {}
91
- };
86
+ return { v: 1, sections, ...removed.length ? { removed } : {} };
92
87
  } catch {
93
88
  return EMPTY_AI_SECTIONS;
94
89
  }
@@ -101,7 +96,6 @@ function applyTreeToState(state, payload) {
101
96
  const entry = {
102
97
  id: payload.id,
103
98
  label: payload.label ?? "Generated section",
104
- ...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
105
99
  afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
106
100
  ...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
107
101
  ...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
@@ -124,317 +118,6 @@ function deleteSectionFromState(state, sectionId) {
124
118
  return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
125
119
  }
126
120
 
127
- // src/lib/brand-chrome.ts
128
- var BRAND_NAME_KEY = "__ohw_brand_name";
129
- var BRAND_TITLE_KEY = "__ohw_site_title";
130
- var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
131
- var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
132
- BRAND_NAME_KEY,
133
- BRAND_TITLE_KEY,
134
- BRAND_FAVICON_LETTER_KEY
135
- ]);
136
- function upsertMeta(selector, attr, token, value) {
137
- let el = document.head.querySelector(selector);
138
- if (!el) {
139
- el = document.createElement("meta");
140
- el.setAttribute(attr, token);
141
- document.head.appendChild(el);
142
- }
143
- if (el.getAttribute("content") !== value) el.setAttribute("content", value);
144
- }
145
- function escapeXml(value) {
146
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
147
- }
148
- function applyLetterFavicon(letter) {
149
- 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>`;
150
- const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
151
- let link = document.head.querySelector('link[rel="icon"]');
152
- if (!link) {
153
- link = document.createElement("link");
154
- link.rel = "icon";
155
- document.head.appendChild(link);
156
- }
157
- link.type = "image/svg+xml";
158
- if (link.href !== href) link.href = href;
159
- }
160
- function applyBrandChrome(content) {
161
- const name = content[BRAND_NAME_KEY];
162
- if (typeof name === "string" && name.length > 0) {
163
- document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
164
- if (el.textContent !== name) el.textContent = name;
165
- if (el.getAttribute("title") !== name) el.setAttribute("title", name);
166
- });
167
- }
168
- const title = content[BRAND_TITLE_KEY];
169
- if (typeof title === "string" && title.length > 0) {
170
- if (document.title !== title) document.title = title;
171
- upsertMeta('meta[property="og:title"]', "property", "og:title", title);
172
- upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
173
- }
174
- const letter = content[BRAND_FAVICON_LETTER_KEY];
175
- if (typeof letter === "string" && letter.length > 0) {
176
- applyLetterFavicon(letter);
177
- }
178
- }
179
-
180
- // src/lib/brand-kit.ts
181
- var BRAND_KIT_KEY = "__ohw_brand";
182
- var BRAND_VAR_PREFIX = "--ohw-brand-";
183
- var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
184
- (role) => `${BRAND_VAR_PREFIX}${role}`
185
- );
186
- var FONT_VARS = {
187
- heading: ["--font-heading", "--font-display", "--brand-font-heading"],
188
- body: ["--font-body", "--brand-font-body"]
189
- };
190
- var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
191
- function brandColorVars(kit) {
192
- const { dark, primary, accent, light } = kit.palette;
193
- const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
194
- return {
195
- [`${BRAND_VAR_PREFIX}primary`]: primary,
196
- [`${BRAND_VAR_PREFIX}accent`]: accent,
197
- [`${BRAND_VAR_PREFIX}light`]: light,
198
- [`${BRAND_VAR_PREFIX}dark`]: dark,
199
- [`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
200
- [`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
201
- [`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
202
- };
203
- }
204
- function parseBrandKit(raw) {
205
- if (!raw) return null;
206
- try {
207
- const parsed = JSON.parse(raw);
208
- const p = parsed?.palette;
209
- const f = parsed?.fonts;
210
- 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") {
211
- return null;
212
- }
213
- return {
214
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
215
- fonts: { heading: f.heading, body: f.body }
216
- };
217
- } catch {
218
- return null;
219
- }
220
- }
221
- function familyOf(stack) {
222
- const first = stack.split(",")[0]?.trim() ?? "";
223
- return first.replace(/^['"]|['"]$/g, "");
224
- }
225
- function loadBrandFonts(families) {
226
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
227
- if (unique.length === 0) return;
228
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
229
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
230
- let link = document.getElementById(BRAND_FONT_LINK_ID);
231
- if (!link) {
232
- link = document.createElement("link");
233
- link.id = BRAND_FONT_LINK_ID;
234
- link.rel = "stylesheet";
235
- document.head.appendChild(link);
236
- }
237
- if (link.href !== href) link.href = href;
238
- }
239
- function applyBrandToDom(kit) {
240
- const root = document.documentElement;
241
- if (!kit) {
242
- for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
243
- for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
244
- document.getElementById(BRAND_FONT_LINK_ID)?.remove();
245
- return;
246
- }
247
- for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
248
- for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
249
- for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
250
- loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
251
- }
252
-
253
- // src/lib/section-styles.ts
254
- var STYLE_STORE_KEY = "__ohw_styles";
255
- var STYLE_SHEET_ID = "ohw-section-styles";
256
- function parseStyleStore(raw) {
257
- if (!raw) return null;
258
- try {
259
- const parsed = JSON.parse(raw);
260
- if (parsed?.v !== 1) return null;
261
- return {
262
- v: 1,
263
- sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
264
- nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
265
- };
266
- } catch {
267
- return null;
268
- }
269
- }
270
- var BG_VALUES = {
271
- surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
272
- accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
273
- "accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
274
- };
275
- var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
276
- function styleSheetCss() {
277
- const rules = [];
278
- for (const [tone, value] of Object.entries(BG_VALUES)) {
279
- rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
280
- }
281
- rules.push(
282
- `[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
283
- );
284
- rules.push(
285
- `[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
286
- `[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
287
- );
288
- for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
289
- rules.push(
290
- `[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
291
- );
292
- }
293
- rules.push(
294
- `[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
295
- );
296
- for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
297
- rules.push(
298
- `[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
299
- );
300
- }
301
- const pad = { tight: 40, balanced: 64, airy: 96 };
302
- for (const [spacing, px] of Object.entries(pad)) {
303
- rules.push(
304
- `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
305
- );
306
- }
307
- return rules.join("\n");
308
- }
309
- var STYLE_FONT_LINK_ID = "ohw-style-fonts";
310
- function loadStyleFonts(families) {
311
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
312
- const existing = document.getElementById(STYLE_FONT_LINK_ID);
313
- if (unique.length === 0) {
314
- existing?.remove();
315
- return;
316
- }
317
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
318
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
319
- let link = existing;
320
- if (!link) {
321
- link = document.createElement("link");
322
- link.id = STYLE_FONT_LINK_ID;
323
- link.rel = "stylesheet";
324
- document.head.appendChild(link);
325
- }
326
- if (link.href !== href) link.href = href;
327
- }
328
- var SECTION_ATTRS = {
329
- sectionBackground: "data-ohw-style-bg",
330
- textDistribution: "data-ohw-style-distribution",
331
- headlineScale: "data-ohw-style-headline",
332
- imageAspect: "data-ohw-style-aspect",
333
- spacing: "data-ohw-style-spacing"
334
- };
335
- var NODE_WROTE_ATTR = "data-ohw-style-node";
336
- var NODE_PROPS = ["color", "font-family", "font-size", "background"];
337
- function saveInline(el, prop) {
338
- const attr = `data-ohw-style-prev-${prop}`;
339
- if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
340
- }
341
- function restoreInline(el, prop) {
342
- const attr = `data-ohw-style-prev-${prop}`;
343
- if (!el.hasAttribute(attr)) return;
344
- const prev = el.getAttribute(attr) ?? "";
345
- if (prev) el.style.setProperty(prop, prev);
346
- else el.style.removeProperty(prop);
347
- el.removeAttribute(attr);
348
- }
349
- function ensureStyleSheet() {
350
- let el = document.getElementById(STYLE_SHEET_ID);
351
- if (!el) {
352
- el = document.createElement("style");
353
- el.id = STYLE_SHEET_ID;
354
- document.head.appendChild(el);
355
- }
356
- const css = styleSheetCss();
357
- if (el.textContent !== css) el.textContent = css;
358
- }
359
- function clearSectionAttrs(root) {
360
- for (const attr of Object.values(SECTION_ATTRS)) {
361
- for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
362
- }
363
- for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
364
- restoreInline(el, "background");
365
- el.removeAttribute("data-ohw-style-bgcolor");
366
- }
367
- }
368
- function clearNodeProps(root) {
369
- for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
370
- const h = el;
371
- for (const prop of NODE_PROPS) restoreInline(h, prop);
372
- h.removeAttribute(NODE_WROTE_ATTR);
373
- }
374
- }
375
- function buttonSurfaceOf(el) {
376
- return el.closest("a, button") ?? el;
377
- }
378
- function applyStylesToDom(store) {
379
- ensureStyleSheet();
380
- clearSectionAttrs(document);
381
- clearNodeProps(document);
382
- loadStyleFonts(
383
- store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
384
- );
385
- if (!store) return;
386
- for (const [sectionId, override] of Object.entries(store.sections)) {
387
- const sections = document.querySelectorAll(
388
- `[data-ohw-section="${CSS.escape(sectionId)}"]`
389
- );
390
- for (const section of Array.from(sections)) {
391
- for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
392
- const value = override[prop];
393
- if (value === void 0) continue;
394
- if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
395
- section.setAttribute(attr, String(value).replace(":", "-"));
396
- }
397
- if (override.sectionBackgroundColor !== void 0) {
398
- saveInline(section, "background");
399
- section.style.setProperty("background", override.sectionBackgroundColor, "important");
400
- section.setAttribute("data-ohw-style-bgcolor", "");
401
- }
402
- }
403
- }
404
- for (const [key, override] of Object.entries(store.nodes)) {
405
- const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
406
- for (const el of Array.from(nodes)) {
407
- if (override.color !== void 0) {
408
- saveInline(el, "color");
409
- el.style.setProperty("color", override.color, "important");
410
- el.setAttribute(NODE_WROTE_ATTR, "");
411
- }
412
- if (override.fontFamily !== void 0) {
413
- saveInline(el, "font-family");
414
- el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
415
- el.setAttribute(NODE_WROTE_ATTR, "");
416
- }
417
- if (override.fontSize !== void 0) {
418
- saveInline(el, "font-size");
419
- el.style.setProperty("font-size", `${override.fontSize}px`, "important");
420
- el.setAttribute(NODE_WROTE_ATTR, "");
421
- }
422
- if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
423
- const surface = buttonSurfaceOf(el);
424
- if (override.buttonBackground !== void 0) {
425
- saveInline(surface, "background");
426
- surface.style.setProperty("background", override.buttonBackground, "important");
427
- }
428
- if (override.buttonText !== void 0) {
429
- saveInline(surface, "color");
430
- surface.style.setProperty("color", override.buttonText, "important");
431
- }
432
- surface.setAttribute(NODE_WROTE_ATTR, "");
433
- }
434
- }
435
- }
436
- }
437
-
438
121
  // src/ui/ai-tree/aiSectionsManager.tsx
439
122
  import { flushSync } from "react-dom";
440
123
  import { createRoot } from "react-dom/client";
@@ -449,8 +132,7 @@ function lucideByName(name) {
449
132
  }
450
133
  var typeStyle = (spec, font) => ({
451
134
  fontFamily: font,
452
- // Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
453
- 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,
135
+ fontSize: spec.size,
454
136
  lineHeight: spec.line,
455
137
  fontWeight: spec.weight
456
138
  });
@@ -465,36 +147,6 @@ var FEATURE_LINE_CSS = [
465
147
  `background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
466
148
  `mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
467
149
  ].join("");
468
- function hexLuminance(color) {
469
- const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
470
- if (!m) return null;
471
- const [r2, g, b] = [0, 2, 4].map((i) => {
472
- const c = parseInt(m[1].slice(i, i + 2), 16) / 255;
473
- return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
474
- });
475
- return 0.2126 * r2 + 0.7152 * g + 0.0722 * b;
476
- }
477
- function hexContrast(a, b) {
478
- const la = hexLuminance(a);
479
- const lb = hexLuminance(b);
480
- if (la === null || lb === null) return null;
481
- const [hi, lo] = la > lb ? [la, lb] : [lb, la];
482
- return (hi + 0.05) / (lo + 0.05);
483
- }
484
- function accentBandContext(brand) {
485
- const p = brand.palette;
486
- const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
487
- if (lightWins) {
488
- return {
489
- brand: { ...brand, palette: { dark: p.light, primary: p.light, accent: p.light, light: p.primary } },
490
- buttonLabel: p.primary
491
- };
492
- }
493
- return {
494
- brand: { ...brand, palette: { dark: p.dark, primary: p.dark, accent: p.dark, light: p.light } },
495
- buttonLabel: p.light
496
- };
497
- }
498
150
  function textAttrs(ctx, path) {
499
151
  return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
500
152
  }
@@ -507,8 +159,6 @@ var AI_RESPONSIVE_CSS = [
507
159
  " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
508
160
  " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
509
161
  " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
510
- " [data-ai-responsive] { overflow-x: hidden; }",
511
- " [data-ai-responsive] img { max-width: 100%; }",
512
162
  "}"
513
163
  ].join("\n");
514
164
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
@@ -602,7 +252,7 @@ function ButtonEl({
602
252
  textDecoration: "none",
603
253
  cursor: "pointer",
604
254
  ...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body),
605
- ...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 }
255
+ ...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: AI_TREE_TOKENS.textPrimaryForeground }
606
256
  },
607
257
  children: /* @__PURE__ */ jsx("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
608
258
  }
@@ -1504,14 +1154,11 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1504
1154
  return null;
1505
1155
  }
1506
1156
  const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
1507
- const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
1508
- const blockBrand = band?.brand ?? resolvedBrand;
1509
1157
  const ctx = {
1510
- brand: blockBrand,
1158
+ brand: resolvedBrand,
1511
1159
  resolveMedia: resolveMedia ?? (() => null),
1512
- cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
1513
- keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
1514
- ...band ? { buttonLabel: band.buttonLabel } : {}
1160
+ cardSurface: resolvedBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${resolvedBrand.palette.light} 90%, ${resolvedBrand.palette.dark})`,
1161
+ keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null
1515
1162
  };
1516
1163
  const settings = tree.settings ?? {};
1517
1164
  const pad = AI_TREE_TOKENS.sectionPadding[settings.spacing ?? "balanced"];
@@ -1519,20 +1166,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1519
1166
  const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
1520
1167
  const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
1521
1168
  const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
1522
- const toneBackground = (() => {
1523
- const { dark, primary, light } = resolvedBrand.palette;
1524
- switch (settings.sectionBackground) {
1525
- case "surface":
1526
- return `color-mix(in srgb, ${light} 94%, ${dark})`;
1527
- case "accent":
1528
- return primary;
1529
- case "accent-soft":
1530
- return `color-mix(in srgb, ${primary} 12%, ${light})`;
1531
- default:
1532
- return void 0;
1533
- }
1534
- })();
1535
- const distributed = !isOverlay && settings.textDistribution;
1536
1169
  return /* @__PURE__ */ jsxs(
1537
1170
  "section",
1538
1171
  {
@@ -1542,11 +1175,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1542
1175
  style: {
1543
1176
  position: "relative",
1544
1177
  padding: `${pad}px 0`,
1545
- background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
1178
+ background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
1546
1179
  backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
1547
1180
  backgroundSize: "cover",
1548
- backgroundPosition: "center",
1549
- color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
1181
+ backgroundPosition: "center"
1550
1182
  },
1551
1183
  children: [
1552
1184
  /* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
@@ -1570,24 +1202,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1570
1202
  display: "grid",
1571
1203
  gridTemplateColumns: "repeat(12, 1fr)",
1572
1204
  gap: AI_TREE_TOKENS.spacing6,
1573
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1205
+ alignItems: settings.verticalPosition === "top" ? "start" : "center",
1574
1206
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1575
1207
  },
1576
- children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx(
1577
- "div",
1578
- {
1579
- "data-ai-cell": "",
1580
- style: {
1581
- gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1582
- minWidth: 0,
1583
- // space-between: each column becomes a flex column whose content spreads over
1584
- // the full row height instead of clumping at the top.
1585
- ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
1586
- },
1587
- children: renderNode(block, ctx, `r${r2}.b${b}`)
1588
- },
1589
- b
1590
- ))
1208
+ children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx("div", { style: { gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`, minWidth: 0 }, children: renderNode(block, ctx, `r${r2}.b${b}`) }, b))
1591
1209
  },
1592
1210
  r2
1593
1211
  ))
@@ -1603,36 +1221,17 @@ import { jsx as jsx2 } from "react/jsx-runtime";
1603
1221
  var CONTAINER_ATTR = "data-ohw-ai-generated";
1604
1222
  var REPLACED_ATTR = "data-ohw-ai-replaced-by";
1605
1223
  var REMOVED_ATTR = "data-ohw-ai-removed";
1606
- var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
1607
- var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
1608
- function readRootVar(name) {
1609
- if (typeof document === "undefined") return "";
1610
- return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1611
- }
1612
- function deriveBrandOverride() {
1613
- const dark = readRootVar("--ohw-brand-dark");
1614
- const primary = readRootVar("--ohw-brand-primary");
1615
- const light = readRootVar("--ohw-brand-light");
1616
- if (!dark || !primary || !light) return null;
1617
- const accent = readRootVar("--ohw-brand-accent");
1618
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1619
- const body = readRootVar("--font-body");
1620
- return {
1621
- palette: { dark, primary, accent: accent || dark, light },
1622
- fonts: {
1623
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
1624
- body: body || AI_DEFAULT_BRAND.fonts.body
1625
- }
1626
- };
1627
- }
1628
1224
  function deriveTemplateBrand() {
1629
- const dark = readRootVar("--color-dark");
1630
- const primary = readRootVar("--color-primary");
1631
- const light = readRootVar("--color-light");
1225
+ if (typeof document === "undefined") return null;
1226
+ const cs = getComputedStyle(document.documentElement);
1227
+ const read = (name) => cs.getPropertyValue(name).trim();
1228
+ const dark = read("--color-dark");
1229
+ const primary = read("--color-primary");
1230
+ const light = read("--color-light");
1632
1231
  if (!dark || !primary || !light) return null;
1633
- const accent = readRootVar("--color-accent");
1634
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1635
- const body = readRootVar("--font-body");
1232
+ const accent = read("--color-accent");
1233
+ const heading = read("--font-heading") || read("--font-display");
1234
+ const body = read("--font-body");
1636
1235
  return {
1637
1236
  palette: { dark, primary, accent: accent || dark, light },
1638
1237
  fonts: {
@@ -1704,24 +1303,6 @@ function syncRemovedSections(state) {
1704
1303
  }
1705
1304
  }
1706
1305
  }
1707
- function syncTemplateHidden(state, pageHasSections) {
1708
- const hide = state.hideTemplate === true && pageHasSections;
1709
- for (const el of Array.from(document.querySelectorAll(`[${TEMPLATE_HIDDEN_ATTR}]`))) {
1710
- if (!hide) {
1711
- el.style.removeProperty("display");
1712
- el.removeAttribute(TEMPLATE_HIDDEN_ATTR);
1713
- }
1714
- }
1715
- if (!hide) return;
1716
- for (const el of Array.from(document.querySelectorAll("[data-ohw-section]"))) {
1717
- if (el.hasAttribute(CONTAINER_ATTR)) continue;
1718
- if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
1719
- if (el.parentElement?.closest("[data-ohw-section]")) continue;
1720
- if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR)) continue;
1721
- el.style.display = "none";
1722
- el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
1723
- }
1724
- }
1725
1306
  function syncReplacedOriginals(state) {
1726
1307
  for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
1727
1308
  const byId = el.getAttribute(REPLACED_ATTR) ?? "";
@@ -1742,12 +1323,8 @@ function syncReplacedOriginals(state) {
1742
1323
  }
1743
1324
  function applyAiSectionsToDom(state, options) {
1744
1325
  if (typeof document === "undefined") return;
1745
- const brandOverride = deriveBrandOverride();
1746
1326
  const templateBrand = deriveTemplateBrand();
1747
- const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
1748
- const pagePath = window.location.pathname;
1749
- const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
1750
- const activeIds = new Set(pageSections.map((entry) => entry.id));
1327
+ const activeIds = new Set(state.sections.map((entry) => entry.id));
1751
1328
  for (const [id, section] of mounted) {
1752
1329
  if (!activeIds.has(id)) {
1753
1330
  section.root.unmount();
@@ -1755,8 +1332,8 @@ function applyAiSectionsToDom(state, options) {
1755
1332
  mounted.delete(id);
1756
1333
  }
1757
1334
  }
1758
- for (const entry of pageSections) {
1759
- const serialized = JSON.stringify(entry) + brandKey;
1335
+ for (const entry of state.sections) {
1336
+ const serialized = JSON.stringify(entry);
1760
1337
  const existing = mounted.get(entry.id);
1761
1338
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
1762
1339
  continue;
@@ -1770,7 +1347,6 @@ function applyAiSectionsToDom(state, options) {
1770
1347
  mounted.delete(entry.id);
1771
1348
  }
1772
1349
  container.setAttribute("data-ohw-section", entry.id);
1773
- container.setAttribute("data-ohw-instance", entry.id);
1774
1350
  container.setAttribute("data-ohw-section-label", entry.label);
1775
1351
  placeContainer(container, entry);
1776
1352
  const root = mounted.get(entry.id)?.root ?? createRoot(container);
@@ -1781,7 +1357,7 @@ function applyAiSectionsToDom(state, options) {
1781
1357
  AiTreeRenderer,
1782
1358
  {
1783
1359
  tree: entry.tree,
1784
- brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1360
+ brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1785
1361
  resolveMedia,
1786
1362
  editKeyPrefix: `ai.${entry.id}`
1787
1363
  }
@@ -1792,7 +1368,6 @@ function applyAiSectionsToDom(state, options) {
1792
1368
  }
1793
1369
  syncReplacedOriginals(state);
1794
1370
  syncRemovedSections(state);
1795
- syncTemplateHidden(state, pageSections.length > 0);
1796
1371
  }
1797
1372
 
1798
1373
  // src/useLinkHrefGuardian.ts
@@ -2399,7 +1974,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2399
1974
  const autoId = useId();
2400
1975
  const insertAfter = insertAfterProp ?? autoId;
2401
1976
  const [schedule, setSchedule] = useState2(null);
2402
- const [loading, setLoading] = useState2(initialScheduleId !== null);
1977
+ const [loading, setLoading] = useState2(true);
2403
1978
  const [inEditor, setInEditor] = useState2(false);
2404
1979
  const [isHovered, setIsHovered] = useState2(false);
2405
1980
  const [modalState, setModalState] = useState2(null);
@@ -2573,10 +2148,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2573
2148
  "*"
2574
2149
  );
2575
2150
  };
2151
+ if (!inEditor && !loading && !schedule) return null;
2576
2152
  const sectionId = `scheduling-${insertAfter}`;
2577
- if (!inEditor && !loading && !schedule) {
2578
- return /* @__PURE__ */ jsx4("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2579
- }
2580
2153
  return /* @__PURE__ */ jsxs3(
2581
2154
  "section",
2582
2155
  {
@@ -7681,9 +7254,6 @@ import { Check, X } from "lucide-react";
7681
7254
 
7682
7255
  // src/lib/sections.ts
7683
7256
  var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
7684
- function isChromeSection(el) {
7685
- return el.matches("header, nav, footer, aside");
7686
- }
7687
7257
  function titleCaseSectionId(id) {
7688
7258
  return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
7689
7259
  }
@@ -7694,8 +7264,6 @@ function parseSectionsFromRoot(root) {
7694
7264
  const id = el.getAttribute("data-ohw-section") ?? "";
7695
7265
  if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
7696
7266
  if (el.parentElement?.closest("[data-ohw-section]")) continue;
7697
- if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
7698
- continue;
7699
7267
  seen.add(id);
7700
7268
  const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
7701
7269
  sections.push({ id, label });
@@ -7713,12 +7281,8 @@ function parseSectionsFromHtml(html) {
7713
7281
 
7714
7282
  // src/ui/ai-section/AiSectionOverlay.tsx
7715
7283
  import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
7716
- function findSectionElement(instanceId) {
7717
- const escaped = CSS.escape(instanceId);
7718
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7719
- }
7720
- function readRect(instanceId) {
7721
- const el = findSectionElement(instanceId);
7284
+ function readRect(sectionId) {
7285
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7722
7286
  if (!el) return null;
7723
7287
  const r2 = el.getBoundingClientRect();
7724
7288
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7741,7 +7305,7 @@ function useLiveSectionRect(sectionId) {
7741
7305
  const opts = { capture: true, passive: true };
7742
7306
  window.addEventListener("scroll", update, opts);
7743
7307
  window.addEventListener("resize", update);
7744
- const el = findSectionElement(sectionId);
7308
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7745
7309
  const ro = el ? new ResizeObserver(update) : null;
7746
7310
  if (el && ro) ro.observe(el);
7747
7311
  const interval = setInterval(update, 500);
@@ -7754,14 +7318,6 @@ function useLiveSectionRect(sectionId) {
7754
7318
  }, [sectionId]);
7755
7319
  return rect;
7756
7320
  }
7757
- function computeSectionBoundaryFlags(instanceId) {
7758
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7759
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
7760
- );
7761
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7762
- if (index === -1) return { isFirst: true, isLast: true };
7763
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7764
- }
7765
7321
  var PRIMARY2 = "#0885FE";
7766
7322
  function edgeAwareRadius(rect) {
7767
7323
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7835,7 +7391,6 @@ function AiSectionOverlay({
7835
7391
  }) {
7836
7392
  const [selectedId, setSelectedId] = useState4(null);
7837
7393
  const [reviewId, setReviewId] = useState4(null);
7838
- const [reviewButtonsHidden, setReviewButtonsHidden] = useState4(false);
7839
7394
  const reviewIdRef = useRef4(null);
7840
7395
  reviewIdRef.current = reviewId;
7841
7396
  const selectedIdRef = useRef4(null);
@@ -7844,7 +7399,7 @@ function AiSectionOverlay({
7844
7399
  (el) => {
7845
7400
  postToParent2({
7846
7401
  type: "ow:section-selected",
7847
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
7402
+ sectionId: el?.dataset.ohwSection ?? null,
7848
7403
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7849
7404
  });
7850
7405
  },
@@ -7853,7 +7408,7 @@ function AiSectionOverlay({
7853
7408
  const selectFromElement = useCallback2(
7854
7409
  (el, options) => {
7855
7410
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7856
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
7411
+ const id = sectionEl?.dataset.ohwSection ?? null;
7857
7412
  if (id === selectedIdRef.current) return;
7858
7413
  setSelectedId(id);
7859
7414
  if (options?.report !== false) report(sectionEl);
@@ -7894,10 +7449,9 @@ function AiSectionOverlay({
7894
7449
  }
7895
7450
  const found = readRect(sectionId) != null;
7896
7451
  setReviewId(found ? sectionId : null);
7897
- setReviewButtonsHidden(e.data.hideButtons === true);
7898
7452
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7899
7453
  if (found) {
7900
- document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7454
+ document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7901
7455
  }
7902
7456
  }
7903
7457
  };
@@ -7916,7 +7470,7 @@ function AiSectionOverlay({
7916
7470
  return;
7917
7471
  }
7918
7472
  const sec = t.closest("[data-ohw-section]");
7919
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
7473
+ setHoveredId(sec?.dataset.ohwSection ?? null);
7920
7474
  };
7921
7475
  const onLeave = () => setHoveredId(null);
7922
7476
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -7948,30 +7502,9 @@ function AiSectionOverlay({
7948
7502
  },
7949
7503
  [postToParent2]
7950
7504
  );
7951
- const activeSelectionId = reviewId ? null : selectedId;
7952
- const selectionRect = useLiveSectionRect(activeSelectionId);
7505
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
7953
7506
  const reviewRect = useLiveSectionRect(reviewId);
7954
7507
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
7955
- useEffect4(() => {
7956
- const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
7957
- if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
7958
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
7959
- return;
7960
- }
7961
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
7962
- postToParent2({
7963
- type: "ow:section-rect",
7964
- instanceId: activeSelectionId,
7965
- rect: {
7966
- top: selectionRect.top + window.scrollY,
7967
- left: selectionRect.left + window.scrollX,
7968
- width: selectionRect.width,
7969
- height: selectionRect.height
7970
- },
7971
- isFirst,
7972
- isLast
7973
- });
7974
- }, [activeSelectionId, selectionRect, postToParent2]);
7975
7508
  return /* @__PURE__ */ jsxs9(Fragment5, { children: [
7976
7509
  hoverRect && /* @__PURE__ */ jsx17(
7977
7510
  "div",
@@ -8022,16 +7555,13 @@ function AiSectionOverlay({
8022
7555
  border: `2px solid ${PRIMARY2}`,
8023
7556
  borderRadius: edgeAwareRadius(reviewRect),
8024
7557
  zIndex: 2147483200,
8025
- // The veil itself: swallows clicks so the section stays locked until decided. This
8026
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
8027
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
8028
- // Accept/Discard resolves to the media beneath and opens the file picker.
7558
+ // The veil itself: swallows clicks so the section stays locked until decided.
8029
7559
  background: "rgba(8, 133, 254, 0.04)",
8030
7560
  pointerEvents: "auto",
8031
7561
  cursor: "default"
8032
7562
  },
8033
7563
  onClick: (e) => e.stopPropagation(),
8034
- children: !reviewButtonsHidden && /* @__PURE__ */ jsxs9(
7564
+ children: /* @__PURE__ */ jsxs9(
8035
7565
  "div",
8036
7566
  {
8037
7567
  style: {
@@ -12225,7 +11755,6 @@ function readLogoSizeState(content, placement) {
12225
11755
  function getLogoElement(el) {
12226
11756
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
12227
11757
  if (marked) return marked;
12228
- if (el.closest('[data-ohw-editable="icon"]')) return null;
12229
11758
  const root = el.closest("nav, [data-ohw-nav-root], footer");
12230
11759
  if (!root) return null;
12231
11760
  const anchor = el.closest("a");
@@ -12480,127 +12009,16 @@ function FloatingPanel({
12480
12009
  );
12481
12010
  }
12482
12011
 
12483
- // src/ui/logo-size-panel.tsx
12484
- import { ArrowUpRight, Link as Link2 } from "lucide-react";
12485
- import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
12486
- function SizeSlider({
12487
- value,
12488
- onChange
12489
- }) {
12490
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
12491
- return /* @__PURE__ */ jsxs18("div", { className: "flex w-full flex-col gap-3", children: [
12492
- /* @__PURE__ */ jsxs18("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
12493
- /* @__PURE__ */ jsx28("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
12494
- /* @__PURE__ */ jsxs18("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
12495
- value,
12496
- " px"
12497
- ] })
12498
- ] }),
12499
- /* @__PURE__ */ jsxs18("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
12500
- /* @__PURE__ */ jsx28(
12501
- "div",
12502
- {
12503
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
12504
- style: { width: `${pct}%` }
12505
- }
12506
- ),
12507
- /* @__PURE__ */ jsx28(
12508
- "input",
12509
- {
12510
- type: "range",
12511
- min: LOGO_SIZE_MIN,
12512
- max: LOGO_SIZE_MAX,
12513
- step: 1,
12514
- value,
12515
- "aria-label": "Logo size",
12516
- className: cn(
12517
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
12518
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
12519
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
12520
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
12521
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
12522
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
12523
- "[&::-moz-range-thumb]:bg-background"
12524
- ),
12525
- onChange: (e) => onChange(Number(e.target.value))
12526
- }
12527
- )
12528
- ] })
12529
- ] });
12530
- }
12531
- function LogoSizePanel({
12532
- viewport,
12533
- sizePx,
12534
- mobileFollowing = true,
12535
- onSizeChange,
12536
- onCustomizeMobile,
12537
- onResetMobile,
12538
- onUpdateEverywhere,
12539
- className
12540
- }) {
12541
- const showFollowing = viewport === "mobile" && mobileFollowing;
12542
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
12543
- const showDesktopSlider = viewport === "desktop";
12544
- return /* @__PURE__ */ jsxs18("div", { className: cn("flex w-full flex-col gap-4", className), children: [
12545
- showFollowing ? /* @__PURE__ */ jsxs18("div", { className: "flex w-full flex-col gap-2", children: [
12546
- /* @__PURE__ */ jsxs18("div", { className: "flex items-start gap-1", children: [
12547
- /* @__PURE__ */ jsx28(Link2, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
12548
- /* @__PURE__ */ jsx28("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
12549
- ] }),
12550
- /* @__PURE__ */ jsx28("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." }),
12551
- /* @__PURE__ */ jsx28(
12552
- Button,
12553
- {
12554
- type: "button",
12555
- variant: "outline",
12556
- size: "sm",
12557
- className: "h-9 w-full min-w-0 cursor-pointer",
12558
- onClick: onCustomizeMobile,
12559
- children: "Customize for mobile"
12560
- }
12561
- )
12562
- ] }) : null,
12563
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ jsx28(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
12564
- showMobileSlider ? /* @__PURE__ */ jsx28(
12565
- Button,
12566
- {
12567
- type: "button",
12568
- variant: "outline",
12569
- size: "sm",
12570
- className: "h-9 w-full min-w-0 cursor-pointer",
12571
- onClick: onResetMobile,
12572
- children: "Reset to desktop size"
12573
- }
12574
- ) : null,
12575
- /* @__PURE__ */ jsx28("div", { className: "h-px w-full bg-border", role: "separator" }),
12576
- /* @__PURE__ */ jsxs18(
12577
- Button,
12578
- {
12579
- type: "button",
12580
- variant: "outline",
12581
- size: "sm",
12582
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
12583
- onClick: onUpdateEverywhere,
12584
- children: [
12585
- "Update logo everywhere",
12586
- /* @__PURE__ */ jsx28(ArrowUpRight, { size: 16, "aria-hidden": true })
12587
- ]
12588
- }
12589
- ),
12590
- /* @__PURE__ */ jsx28("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
12591
- ] });
12592
- }
12593
-
12594
12012
  // src/ui/socials-display-panel.tsx
12595
- import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
12013
+ import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
12596
12014
  function DisplaySwitch({
12597
12015
  label,
12598
12016
  checked,
12599
12017
  disabled,
12600
12018
  onChange
12601
12019
  }) {
12602
- return /* @__PURE__ */ jsxs19("div", { className: "flex w-full items-center gap-2", children: [
12603
- /* @__PURE__ */ jsx29(
12020
+ return /* @__PURE__ */ jsxs18("div", { className: "flex w-full items-center gap-2", children: [
12021
+ /* @__PURE__ */ jsx28(
12604
12022
  "span",
12605
12023
  {
12606
12024
  className: cn(
@@ -12610,7 +12028,7 @@ function DisplaySwitch({
12610
12028
  children: label
12611
12029
  }
12612
12030
  ),
12613
- /* @__PURE__ */ jsx29(
12031
+ /* @__PURE__ */ jsx28(
12614
12032
  "button",
12615
12033
  {
12616
12034
  type: "button",
@@ -12624,7 +12042,7 @@ function DisplaySwitch({
12624
12042
  checked ? "bg-primary" : "bg-primary-50",
12625
12043
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
12626
12044
  ),
12627
- children: /* @__PURE__ */ jsx29(
12045
+ children: /* @__PURE__ */ jsx28(
12628
12046
  "span",
12629
12047
  {
12630
12048
  className: cn(
@@ -12638,8 +12056,8 @@ function DisplaySwitch({
12638
12056
  ] });
12639
12057
  }
12640
12058
  function SocialsDisplayPanel({ display, onChange, className }) {
12641
- return /* @__PURE__ */ jsxs19("div", { className: cn("flex w-full flex-col gap-3", className), children: [
12642
- /* @__PURE__ */ jsx29(
12059
+ return /* @__PURE__ */ jsxs18("div", { className: cn("flex w-full flex-col gap-3", className), children: [
12060
+ /* @__PURE__ */ jsx28(
12643
12061
  DisplaySwitch,
12644
12062
  {
12645
12063
  label: "Text",
@@ -12648,7 +12066,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
12648
12066
  onChange: (text) => onChange({ ...display, text })
12649
12067
  }
12650
12068
  ),
12651
- /* @__PURE__ */ jsx29(
12069
+ /* @__PURE__ */ jsx28(
12652
12070
  DisplaySwitch,
12653
12071
  {
12654
12072
  label: "Icon",
@@ -13209,7 +12627,7 @@ function useNavItemDrag({
13209
12627
 
13210
12628
  // src/ui/footer-container-chrome.tsx
13211
12629
  import { Plus as Plus2 } from "lucide-react";
13212
- import { jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
12630
+ import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
13213
12631
  function FooterContainerChrome({
13214
12632
  rect,
13215
12633
  onAdd,
@@ -13217,7 +12635,7 @@ function FooterContainerChrome({
13217
12635
  }) {
13218
12636
  const chromeGap = 6;
13219
12637
  const buttonMargin = 7;
13220
- return /* @__PURE__ */ jsx30(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx30(
12638
+ return /* @__PURE__ */ jsx29(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx29(
13221
12639
  "div",
13222
12640
  {
13223
12641
  "data-ohw-footer-container-chrome": "",
@@ -13229,8 +12647,8 @@ function FooterContainerChrome({
13229
12647
  width: rect.width + chromeGap * 2,
13230
12648
  height: rect.height + chromeGap * 2
13231
12649
  },
13232
- children: /* @__PURE__ */ jsxs20(Tooltip, { children: [
13233
- /* @__PURE__ */ jsx30(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx30(
12650
+ children: /* @__PURE__ */ jsxs19(Tooltip, { children: [
12651
+ /* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
13234
12652
  "button",
13235
12653
  {
13236
12654
  type: "button",
@@ -13249,10 +12667,10 @@ function FooterContainerChrome({
13249
12667
  if (addDisabled) return;
13250
12668
  onAdd();
13251
12669
  },
13252
- children: /* @__PURE__ */ jsx30(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12670
+ children: /* @__PURE__ */ jsx29(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13253
12671
  }
13254
12672
  ) }),
13255
- /* @__PURE__ */ jsx30(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12673
+ /* @__PURE__ */ jsx29(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
13256
12674
  ] })
13257
12675
  }
13258
12676
  ) });
@@ -13437,18 +12855,6 @@ function collectEditableNodes(extraContent, root = document) {
13437
12855
  }
13438
12856
  if (extraContent && !isScoped) {
13439
12857
  applyNavFooterDeleteOverrides(byKey, extraContent);
13440
- for (const key of LOGO_IMAGE_KEYS) {
13441
- if (!(key in extraContent)) continue;
13442
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
13443
- }
13444
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
13445
- if (!(key in extraContent)) continue;
13446
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13447
- }
13448
- for (const key of LOGO_SIZE_KEYS) {
13449
- if (!(key in extraContent)) continue;
13450
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13451
- }
13452
12858
  }
13453
12859
  return Array.from(byKey.values());
13454
12860
  }
@@ -13715,13 +13121,13 @@ function deleteSelectedNavFooterItem(deps) {
13715
13121
 
13716
13122
  // src/ui/navbar-container-chrome.tsx
13717
13123
  import { Plus as Plus3 } from "lucide-react";
13718
- import { jsx as jsx31 } from "react/jsx-runtime";
13124
+ import { jsx as jsx30 } from "react/jsx-runtime";
13719
13125
  function NavbarContainerChrome({
13720
13126
  rect,
13721
13127
  onAdd
13722
13128
  }) {
13723
13129
  const chromeGap = 6;
13724
- return /* @__PURE__ */ jsx31(
13130
+ return /* @__PURE__ */ jsx30(
13725
13131
  "div",
13726
13132
  {
13727
13133
  "data-ohw-navbar-container-chrome": "",
@@ -13733,7 +13139,7 @@ function NavbarContainerChrome({
13733
13139
  width: rect.width + chromeGap * 2,
13734
13140
  height: rect.height + chromeGap * 2
13735
13141
  },
13736
- children: /* @__PURE__ */ jsx31(
13142
+ children: /* @__PURE__ */ jsx30(
13737
13143
  "button",
13738
13144
  {
13739
13145
  type: "button",
@@ -13750,7 +13156,7 @@ function NavbarContainerChrome({
13750
13156
  e.stopPropagation();
13751
13157
  onAdd();
13752
13158
  },
13753
- children: /* @__PURE__ */ jsx31(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13159
+ children: /* @__PURE__ */ jsx30(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13754
13160
  }
13755
13161
  )
13756
13162
  }
@@ -13759,7 +13165,7 @@ function NavbarContainerChrome({
13759
13165
 
13760
13166
  // src/ui/drop-indicator.tsx
13761
13167
  import * as React10 from "react";
13762
- import { jsx as jsx32 } from "react/jsx-runtime";
13168
+ import { jsx as jsx31 } from "react/jsx-runtime";
13763
13169
  var dropIndicatorVariants = cva(
13764
13170
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
13765
13171
  {
@@ -13783,7 +13189,7 @@ var dropIndicatorVariants = cva(
13783
13189
  );
13784
13190
  var DropIndicator = React10.forwardRef(
13785
13191
  ({ className, direction, state, ...props }, ref) => {
13786
- return /* @__PURE__ */ jsx32(
13192
+ return /* @__PURE__ */ jsx31(
13787
13193
  "div",
13788
13194
  {
13789
13195
  ref,
@@ -13800,7 +13206,7 @@ var DropIndicator = React10.forwardRef(
13800
13206
  DropIndicator.displayName = "DropIndicator";
13801
13207
 
13802
13208
  // src/ui/badge.tsx
13803
- import { jsx as jsx33 } from "react/jsx-runtime";
13209
+ import { jsx as jsx32 } from "react/jsx-runtime";
13804
13210
  var badgeVariants = cva(
13805
13211
  "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",
13806
13212
  {
@@ -13818,12 +13224,12 @@ var badgeVariants = cva(
13818
13224
  }
13819
13225
  );
13820
13226
  function Badge({ className, variant, ...props }) {
13821
- return /* @__PURE__ */ jsx33("div", { className: cn(badgeVariants({ variant }), className), ...props });
13227
+ return /* @__PURE__ */ jsx32("div", { className: cn(badgeVariants({ variant }), className), ...props });
13822
13228
  }
13823
13229
 
13824
13230
  // src/OhhwellsBridge.tsx
13825
- import { Link as Link3, Plus as Plus4, Settings } from "lucide-react";
13826
- import { Fragment as Fragment8, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
13231
+ import { Link as Link2, Plus as Plus4, Settings } from "lucide-react";
13232
+ import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
13827
13233
  var PRIMARY3 = "#0885FE";
13828
13234
  var IMAGE_FADE_MS = 300;
13829
13235
  function runOpacityFade(el, onDone) {
@@ -13917,10 +13323,21 @@ function parseSchedulingInsertAfter(insertAfter) {
13917
13323
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
13918
13324
  };
13919
13325
  }
13920
- function resolveEntryAnchor(entry) {
13921
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
13922
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
13923
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
13326
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
13327
+ const parsed = parseSchedulingInsertAfter(insertAfter);
13328
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
13329
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
13330
+ return { effectiveInsertAfter, insertBefore };
13331
+ }
13332
+ function getSchedulingMountPoint(insertAfter) {
13333
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
13334
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
13335
+ if (!anchorEl && anchor === "scheduling") {
13336
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
13337
+ anchorEl = widgets.at(-1) ?? null;
13338
+ }
13339
+ if (!anchorEl) return null;
13340
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13924
13341
  }
13925
13342
  function schedulingMountDepth(insertAfter) {
13926
13343
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -13937,7 +13354,8 @@ function getPageSchedulingEntries(raw) {
13937
13354
  }
13938
13355
  }
13939
13356
  function isSchedulingWidgetMissing(entry) {
13940
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
13357
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
13358
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
13941
13359
  }
13942
13360
  function hasMissingSchedulingWidgets(entries) {
13943
13361
  return entries.some(isSchedulingWidgetMissing);
@@ -13967,17 +13385,16 @@ function initSectionsFromContent(content, removeExisting = false) {
13967
13385
  } catch {
13968
13386
  }
13969
13387
  }
13970
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
13971
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
13972
- const sectionId = schedulingSectionId(widgetId);
13388
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
13389
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
13390
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
13973
13391
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
13974
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
13975
- if (!anchorEl) return false;
13976
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13392
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
13393
+ if (!mountPoint) return false;
13977
13394
  const container = document.createElement("div");
13978
13395
  container.dataset.ohwSectionContainer = "scheduling";
13979
- if (beforeId) {
13980
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
13396
+ if (insertBefore) {
13397
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
13981
13398
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
13982
13399
  if (!beforePoint) return false;
13983
13400
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -13988,25 +13405,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13988
13405
  }
13989
13406
  tail.insertAdjacentElement("afterend", container);
13990
13407
  }
13991
- try {
13992
- const root = createRoot2(container);
13993
- flushSync2(() => {
13994
- root.render(
13995
- /* @__PURE__ */ jsx34(
13996
- SchedulingWidget,
13997
- {
13998
- notifyOnConnect,
13999
- initialScheduleId: scheduleId,
14000
- insertAfter: widgetId
14001
- }
14002
- )
14003
- );
14004
- });
14005
- } catch (err) {
14006
- console.error("[ow:scheduling] render threw", err);
14007
- container.remove();
14008
- return false;
14009
- }
13408
+ const root = createRoot2(container);
13409
+ flushSync2(() => {
13410
+ root.render(
13411
+ /* @__PURE__ */ jsx33(
13412
+ SchedulingWidget,
13413
+ {
13414
+ notifyOnConnect,
13415
+ initialScheduleId: scheduleId,
13416
+ insertAfter: effectiveInsertAfter
13417
+ }
13418
+ )
13419
+ );
13420
+ });
14010
13421
  const tracker = getSectionsTracker();
14011
13422
  let sections = [];
14012
13423
  try {
@@ -14014,12 +13425,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
14014
13425
  } catch {
14015
13426
  }
14016
13427
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
14017
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
13428
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
14018
13429
  sections.push({
14019
13430
  type: "scheduling",
14020
- insertAfter: widgetId,
14021
- anchorId,
14022
- beforeId: beforeId ?? null,
13431
+ insertAfter: effectiveInsertAfter,
14023
13432
  pagePath: window.location.pathname,
14024
13433
  ...scheduleId ? { scheduleId } : {}
14025
13434
  });
@@ -14033,8 +13442,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
14033
13442
  for (let i = pending.length - 1; i >= 0; i--) {
14034
13443
  const entry = pending[i];
14035
13444
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
14036
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
14037
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
13445
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
14038
13446
  pending.splice(i, 1);
14039
13447
  }
14040
13448
  }
@@ -14182,13 +13590,6 @@ function isInsideLinkEditor(target) {
14182
13590
  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"]')
14183
13591
  );
14184
13592
  }
14185
- function isInsideFloatingPanel(target) {
14186
- return Boolean(target.closest("[data-ohw-floating-panel]"));
14187
- }
14188
- function isPointOverFloatingPanel(clientX, clientY) {
14189
- const el = document.elementFromPoint(clientX, clientY);
14190
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
14191
- }
14192
13593
  function getHrefKeyFromElement(el) {
14193
13594
  if (!el) return null;
14194
13595
  const anchor = el.closest("[data-ohw-href-key]");
@@ -14427,7 +13828,7 @@ function getNavigationSelectionParent(el) {
14427
13828
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
14428
13829
  return getFooterLinksContainer();
14429
13830
  }
14430
- 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)) {
13831
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
14431
13832
  return getNavigationRoot(el);
14432
13833
  }
14433
13834
  return null;
@@ -14673,7 +14074,7 @@ function EditGlowChrome({
14673
14074
  hideHandle = false
14674
14075
  }) {
14675
14076
  const GAP = SELECTION_CHROME_GAP2;
14676
- return /* @__PURE__ */ jsxs21(
14077
+ return /* @__PURE__ */ jsxs20(
14677
14078
  "div",
14678
14079
  {
14679
14080
  ref: elRef,
@@ -14688,7 +14089,7 @@ function EditGlowChrome({
14688
14089
  zIndex: 2147483646
14689
14090
  },
14690
14091
  children: [
14691
- /* @__PURE__ */ jsx34(
14092
+ /* @__PURE__ */ jsx33(
14692
14093
  "div",
14693
14094
  {
14694
14095
  style: {
@@ -14701,7 +14102,7 @@ function EditGlowChrome({
14701
14102
  }
14702
14103
  }
14703
14104
  ),
14704
- reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx34(
14105
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx33(
14705
14106
  "div",
14706
14107
  {
14707
14108
  "data-ohw-drag-handle-container": "",
@@ -14713,7 +14114,7 @@ function EditGlowChrome({
14713
14114
  transform: "translate(calc(-100% - 7px), -50%)",
14714
14115
  pointerEvents: dragDisabled ? "none" : "auto"
14715
14116
  },
14716
- children: /* @__PURE__ */ jsx34(
14117
+ children: /* @__PURE__ */ jsx33(
14717
14118
  DragHandle,
14718
14119
  {
14719
14120
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -14923,7 +14324,7 @@ function FloatingToolbar({
14923
14324
  return () => ro.disconnect();
14924
14325
  }, [showEditLink, activeCommands]);
14925
14326
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
14926
- return /* @__PURE__ */ jsx34(
14327
+ return /* @__PURE__ */ jsx33(
14927
14328
  "div",
14928
14329
  {
14929
14330
  ref: setRefs,
@@ -14935,12 +14336,12 @@ function FloatingToolbar({
14935
14336
  zIndex: 2147483647,
14936
14337
  pointerEvents: "auto"
14937
14338
  },
14938
- children: /* @__PURE__ */ jsxs21(CustomToolbar, { children: [
14939
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs21(React11.Fragment, { children: [
14940
- gi > 0 && /* @__PURE__ */ jsx34(CustomToolbarDivider, {}),
14339
+ children: /* @__PURE__ */ jsxs20(CustomToolbar, { children: [
14340
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs20(React11.Fragment, { children: [
14341
+ gi > 0 && /* @__PURE__ */ jsx33(CustomToolbarDivider, {}),
14941
14342
  btns.map((btn) => {
14942
14343
  const isActive = activeCommands.has(btn.cmd);
14943
- return /* @__PURE__ */ jsx34(
14344
+ return /* @__PURE__ */ jsx33(
14944
14345
  CustomToolbarButton,
14945
14346
  {
14946
14347
  title: btn.title,
@@ -14949,7 +14350,7 @@ function FloatingToolbar({
14949
14350
  e.preventDefault();
14950
14351
  onCommand(btn.cmd);
14951
14352
  },
14952
- children: /* @__PURE__ */ jsx34(
14353
+ children: /* @__PURE__ */ jsx33(
14953
14354
  "svg",
14954
14355
  {
14955
14356
  width: "16",
@@ -14970,7 +14371,7 @@ function FloatingToolbar({
14970
14371
  );
14971
14372
  })
14972
14373
  ] }, gi)),
14973
- showEditLink ? /* @__PURE__ */ jsx34(
14374
+ showEditLink ? /* @__PURE__ */ jsx33(
14974
14375
  CustomToolbarButton,
14975
14376
  {
14976
14377
  type: "button",
@@ -14984,7 +14385,7 @@ function FloatingToolbar({
14984
14385
  e.preventDefault();
14985
14386
  e.stopPropagation();
14986
14387
  },
14987
- children: /* @__PURE__ */ jsx34(Link3, { className: "size-4 shrink-0", "aria-hidden": true })
14388
+ children: /* @__PURE__ */ jsx33(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
14988
14389
  }
14989
14390
  ) : null
14990
14391
  ] })
@@ -15001,7 +14402,7 @@ function StateToggle({
15001
14402
  states,
15002
14403
  onStateChange
15003
14404
  }) {
15004
- return /* @__PURE__ */ jsx34(
14405
+ return /* @__PURE__ */ jsx33(
15005
14406
  ToggleGroup,
15006
14407
  {
15007
14408
  "data-ohw-state-toggle": "",
@@ -15015,12 +14416,11 @@ function StateToggle({
15015
14416
  left: rect.right - 8,
15016
14417
  transform: "translateX(-100%)"
15017
14418
  },
15018
- children: states.map((state) => /* @__PURE__ */ jsx34(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14419
+ children: states.map((state) => /* @__PURE__ */ jsx33(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
15019
14420
  }
15020
14421
  );
15021
14422
  }
15022
14423
  var contentCache = /* @__PURE__ */ new Map();
15023
- var fetchedContentPaths = /* @__PURE__ */ new Set();
15024
14424
  function resolveSubdomain(subdomainFromQuery) {
15025
14425
  if (subdomainFromQuery) return subdomainFromQuery;
15026
14426
  if (typeof window !== "undefined") {
@@ -15359,6 +14759,13 @@ function OhhwellsBridge() {
15359
14759
  const [isItemDragging, setIsItemDragging] = useState11(false);
15360
14760
  const [isFooterFrameSelection, setIsFooterFrameSelection] = useState11(false);
15361
14761
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
14762
+ const [floatingPanel, setFloatingPanel] = useState11(null);
14763
+ const floatingPanelOpenRef = useRef9(false);
14764
+ floatingPanelOpenRef.current = floatingPanel !== null;
14765
+ const [floatingPanelPos, setFloatingPanelPos] = useState11(null);
14766
+ const [logoSizeDraft, setLogoSizeDraft] = useState11(null);
14767
+ const [editorViewport, setEditorViewport] = useState11("desktop");
14768
+ const [parentScrollSnap, setParentScrollSnap] = useState11(null);
15362
14769
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState11(null);
15363
14770
  const [footerHeadingVisible, setFooterHeadingVisible] = useState11(null);
15364
14771
  const footerDragRef = useRef9(null);
@@ -15373,16 +14780,7 @@ function OhhwellsBridge() {
15373
14780
  const addNavAfterAnchorRef = useRef9(null);
15374
14781
  const editContentRef = useRef9({});
15375
14782
  const aiSectionsRef = useRef9("");
15376
- const brandKitRef = useRef9("");
15377
- const stylesRef = useRef9("");
15378
14783
  const pendingDeleteUndoRef = useRef9(null);
15379
- const [floatingPanel, setFloatingPanel] = useState11(null);
15380
- const floatingPanelOpenRef = useRef9(false);
15381
- const setFloatingPanelRef = useRef9(setFloatingPanel);
15382
- const [floatingPanelPos, setFloatingPanelPos] = useState11(null);
15383
- const [logoSizeDraft, setLogoSizeDraft] = useState11(null);
15384
- const [editorViewport, setEditorViewport] = useState11("desktop");
15385
- const [parentScrollSnap, setParentScrollSnap] = useState11(null);
15386
14784
  const [sitePages, setSitePages] = useState11([]);
15387
14785
  const [sectionsByPath, setSectionsByPath] = useState11({});
15388
14786
  const sectionsPrefetchGenRef = useRef9(0);
@@ -15391,18 +14789,7 @@ function OhhwellsBridge() {
15391
14789
  const linkPopoverOpenRef = useRef9(false);
15392
14790
  const linkPopoverGraceUntilRef = useRef9(0);
15393
14791
  setLinkPopoverRef.current = setLinkPopover;
15394
- setFloatingPanelRef.current = setFloatingPanel;
15395
14792
  linkPopoverSessionRef.current = linkPopover;
15396
- floatingPanelOpenRef.current = Boolean(floatingPanel);
15397
- useEffect12(() => {
15398
- const syncViewport = () => {
15399
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
15400
- setEditorViewport((prev) => prev === next ? prev : next);
15401
- };
15402
- syncViewport();
15403
- window.addEventListener("resize", syncViewport);
15404
- return () => window.removeEventListener("resize", syncViewport);
15405
- }, []);
15406
14793
  const {
15407
14794
  navDragRef,
15408
14795
  navDropSlots,
@@ -16487,6 +15874,25 @@ function OhhwellsBridge() {
16487
15874
  setLogoSizeDraft(null);
16488
15875
  deselectRef.current();
16489
15876
  }, []);
15877
+ useEffect12(() => {
15878
+ const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
15879
+ if (!session || !logoSizeDraft) {
15880
+ postToParentRef.current({ type: "ow:logo-size-panel", open: false });
15881
+ return;
15882
+ }
15883
+ postToParentRef.current({
15884
+ type: "ow:logo-size-panel",
15885
+ open: true,
15886
+ title: session.title,
15887
+ context: session.context ?? "",
15888
+ placement: session.placement,
15889
+ viewport: editorViewport,
15890
+ mobileFollowing: logoSizeDraft.mobileFollowing,
15891
+ sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
15892
+ min: LOGO_SIZE_MIN,
15893
+ max: LOGO_SIZE_MAX
15894
+ });
15895
+ }, [floatingPanel, logoSizeDraft, editorViewport]);
16490
15896
  const persistLogoSizeDraft = useCallback7(
16491
15897
  (placement, draft) => {
16492
15898
  const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
@@ -16645,27 +16051,15 @@ function OhhwellsBridge() {
16645
16051
  }
16646
16052
  const applyContent = (content) => {
16647
16053
  const imageLoads = [];
16648
- if (typeof content[BRAND_KIT_KEY] === "string") {
16649
- brandKitRef.current = content[BRAND_KIT_KEY];
16650
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
16651
- }
16652
16054
  if (typeof content[AI_SECTIONS_KEY] === "string") {
16653
16055
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
16654
16056
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
16655
16057
  }
16656
- if (typeof content[STYLE_STORE_KEY] === "string") {
16657
- stylesRef.current = content[STYLE_STORE_KEY];
16658
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
16659
- }
16660
- applyBrandChrome(content);
16661
16058
  for (const [key, val] of Object.entries(content)) {
16662
16059
  if (key === "__ohw_sections") continue;
16663
16060
  if (key === AI_SECTIONS_KEY) continue;
16664
16061
  if (key === LOGO_PLACEHOLDER_KEY) continue;
16665
16062
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
16666
- if (key === BRAND_KIT_KEY) continue;
16667
- if (key === STYLE_STORE_KEY) continue;
16668
- if (BRAND_CHROME_KEYS.has(key)) continue;
16669
16063
  if (applyVideoSettingNode(key, val)) continue;
16670
16064
  if (applyCarouselNode(key, val)) continue;
16671
16065
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16723,9 +16117,7 @@ function OhhwellsBridge() {
16723
16117
  let cancelled = false;
16724
16118
  setFetchState("loading");
16725
16119
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
16726
- const initialPath = pathname;
16727
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
16728
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16120
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16729
16121
  if (cancelled) return;
16730
16122
  const content = data?.content ?? {};
16731
16123
  contentCache.set(subdomain, content);
@@ -16845,21 +16237,10 @@ function OhhwellsBridge() {
16845
16237
  initSectionInstancesFromContent(content, window.location.pathname);
16846
16238
  observer?.disconnect();
16847
16239
  try {
16848
- applyBrandChrome(content);
16849
- if (typeof content[BRAND_KIT_KEY] === "string") {
16850
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
16851
- }
16852
- if (typeof content[STYLE_STORE_KEY] === "string") {
16853
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
16854
- }
16855
16240
  for (const [key, val] of Object.entries(content)) {
16856
16241
  if (key === "__ohw_sections") continue;
16857
16242
  if (key === LOGO_PLACEHOLDER_KEY) continue;
16858
16243
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
16859
- if (key === BRAND_KIT_KEY) continue;
16860
- if (key === STYLE_STORE_KEY) continue;
16861
- if (key === STYLE_STORE_KEY) continue;
16862
- if (BRAND_CHROME_KEYS.has(key)) continue;
16863
16244
  if (applyVideoSettingNode(key, val)) continue;
16864
16245
  if (applyCarouselNode(key, val)) continue;
16865
16246
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16902,17 +16283,6 @@ function OhhwellsBridge() {
16902
16283
  debounceTimer = setTimeout(applyFromCache, 150);
16903
16284
  };
16904
16285
  applyFromCache();
16905
- const pathCacheKey = `${subdomain}::${pathname}`;
16906
- if (!fetchedContentPaths.has(pathCacheKey)) {
16907
- fetchedContentPaths.add(pathCacheKey);
16908
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
16909
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16910
- if (!data?.content) return;
16911
- contentCache.set(subdomain, data.content);
16912
- applyFromCache();
16913
- }).catch(() => {
16914
- });
16915
- }
16916
16286
  observer = new MutationObserver(scheduleApply);
16917
16287
  observer.observe(document.body, { childList: true, subtree: true });
16918
16288
  return () => {
@@ -17006,31 +16376,26 @@ function OhhwellsBridge() {
17006
16376
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
17007
16377
  useEffect12(() => {
17008
16378
  if (!isEditMode) return;
17009
- let lastPosted = 0;
17010
16379
  const measure = () => {
17011
16380
  const h = document.body.scrollHeight;
17012
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
17013
- lastPosted = h;
17014
- postToParent2({ type: "ow:height", height: h });
17015
- }
17016
- };
17017
- let raf = null;
17018
- const schedule = () => {
17019
- if (raf != null) return;
17020
- raf = requestAnimationFrame(() => {
17021
- raf = null;
17022
- measure();
17023
- });
16381
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
17024
16382
  };
17025
16383
  const t1 = setTimeout(measure, 50);
17026
16384
  const t2 = setTimeout(measure, 500);
17027
- const ro = new ResizeObserver(schedule);
17028
- ro.observe(document.body);
16385
+ let lastWidth = window.innerWidth;
16386
+ let resizeTimer = null;
16387
+ const handleResize = () => {
16388
+ if (window.innerWidth === lastWidth) return;
16389
+ lastWidth = window.innerWidth;
16390
+ if (resizeTimer) clearTimeout(resizeTimer);
16391
+ resizeTimer = setTimeout(measure, 150);
16392
+ };
16393
+ window.addEventListener("resize", handleResize);
17029
16394
  return () => {
17030
16395
  clearTimeout(t1);
17031
16396
  clearTimeout(t2);
17032
- if (raf != null) cancelAnimationFrame(raf);
17033
- ro.disconnect();
16397
+ if (resizeTimer) clearTimeout(resizeTimer);
16398
+ window.removeEventListener("resize", handleResize);
17034
16399
  };
17035
16400
  }, [pathname, isEditMode, postToParent2]);
17036
16401
  useEffect12(() => {
@@ -17211,12 +16576,10 @@ function OhhwellsBridge() {
17211
16576
  return;
17212
16577
  }
17213
16578
  const target = e.target;
17214
- if (target.closest("[data-ohw-ai-review]")) return;
17215
16579
  if (target.closest("[data-ohw-toolbar]")) return;
17216
16580
  if (target.closest("[data-ohw-state-toggle]")) return;
17217
16581
  if (target.closest("[data-ohw-max-badge]")) return;
17218
16582
  if (isInsideLinkEditor(target)) return;
17219
- if (isInsideFloatingPanel(target)) return;
17220
16583
  if (target.closest("[data-ohw-form-toolbar]")) return;
17221
16584
  if (target.closest(
17222
16585
  '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
@@ -17490,12 +16853,10 @@ function OhhwellsBridge() {
17490
16853
  };
17491
16854
  const handleDblClick = (e) => {
17492
16855
  const target = e.target;
17493
- if (target.closest("[data-ohw-ai-review]")) return;
17494
16856
  if (target.closest("[data-ohw-toolbar]")) return;
17495
16857
  if (target.closest("[data-ohw-state-toggle]")) return;
17496
16858
  if (target.closest("[data-ohw-max-badge]")) return;
17497
16859
  if (isInsideLinkEditor(target)) return;
17498
- if (isInsideFloatingPanel(target)) return;
17499
16860
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
17500
16861
  return;
17501
16862
  }
@@ -17536,14 +16897,11 @@ function OhhwellsBridge() {
17536
16897
  setSiblingHintRects([]);
17537
16898
  return;
17538
16899
  }
17539
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
16900
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
17540
16901
  hoveredItemElRef.current = null;
17541
16902
  setHoveredItemRect(null);
17542
16903
  hoveredNavContainerRef.current = null;
17543
16904
  setHoveredNavContainerRect(null);
17544
- siblingHintElRef.current = null;
17545
- setSiblingHintRect(null);
17546
- setSiblingHintRects([]);
17547
16905
  return;
17548
16906
  }
17549
16907
  {
@@ -17652,6 +17010,7 @@ function OhhwellsBridge() {
17652
17010
  hoveredNavContainerRef.current = null;
17653
17011
  setHoveredNavContainerRect(null);
17654
17012
  hoveredItemElRef.current = editable;
17013
+ setHoveredItemRect(editable.getBoundingClientRect());
17655
17014
  }
17656
17015
  }
17657
17016
  }
@@ -17948,7 +17307,7 @@ function OhhwellsBridge() {
17948
17307
  }
17949
17308
  };
17950
17309
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
17951
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17310
+ if (linkPopoverOpenRef.current) {
17952
17311
  if (hoveredImageRef.current) {
17953
17312
  hoveredImageRef.current = null;
17954
17313
  hoveredImageHasTextOverlapRef.current = false;
@@ -18202,7 +17561,7 @@ function OhhwellsBridge() {
18202
17561
  }
18203
17562
  };
18204
17563
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
18205
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17564
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
18206
17565
  if (activeStateElRef.current) {
18207
17566
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
18208
17567
  activeStateElRef.current = null;
@@ -18277,7 +17636,8 @@ function OhhwellsBridge() {
18277
17636
  };
18278
17637
  const handleMouseMove = (e) => {
18279
17638
  const { clientX, clientY } = e;
18280
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
17639
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17640
+ if (isOverEditorChrome(clientX, clientY)) {
18281
17641
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
18282
17642
  formHoverElRef.current = null;
18283
17643
  setFormHoverRect(null);
@@ -18285,12 +17645,6 @@ function OhhwellsBridge() {
18285
17645
  setHoveredItemRect(null);
18286
17646
  hoveredNavContainerRef.current = null;
18287
17647
  setHoveredNavContainerRect(null);
18288
- siblingHintElRef.current = null;
18289
- setSiblingHintRect(null);
18290
- setSiblingHintRects([]);
18291
- dismissImageHover();
18292
- clearImageHover();
18293
- setSectionGap(null);
18294
17648
  return;
18295
17649
  }
18296
17650
  probeSectionGapAt(clientX, clientY);
@@ -18301,11 +17655,7 @@ function OhhwellsBridge() {
18301
17655
  if (e.data?.type !== "ow:pointer-sync") return;
18302
17656
  const { clientX, clientY } = e.data;
18303
17657
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
18304
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
18305
- dismissImageHover();
18306
- clearImageHover();
18307
- return;
18308
- }
17658
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
18309
17659
  probeSectionGapAt(clientX, clientY);
18310
17660
  probeImageAt(clientX, clientY);
18311
17661
  probeHoverCardsAt(clientX, clientY);
@@ -18551,19 +17901,10 @@ function OhhwellsBridge() {
18551
17901
  if (e.data?.type !== "ow:hydrate") return;
18552
17902
  const content = e.data.content;
18553
17903
  if (!content) return;
18554
- if (typeof content[BRAND_KIT_KEY] === "string") {
18555
- brandKitRef.current = content[BRAND_KIT_KEY];
18556
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
18557
- }
18558
17904
  if (typeof content[AI_SECTIONS_KEY] === "string") {
18559
17905
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
18560
17906
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
18561
17907
  }
18562
- if (typeof content[STYLE_STORE_KEY] === "string") {
18563
- stylesRef.current = content[STYLE_STORE_KEY];
18564
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
18565
- }
18566
- applyBrandChrome(content);
18567
17908
  let sectionsJson = null;
18568
17909
  for (const [key, val] of Object.entries(content)) {
18569
17910
  if (key === "__ohw_sections") {
@@ -18573,9 +17914,6 @@ function OhhwellsBridge() {
18573
17914
  if (key === AI_SECTIONS_KEY) continue;
18574
17915
  if (key === LOGO_PLACEHOLDER_KEY) continue;
18575
17916
  if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
18576
- if (key === BRAND_KIT_KEY) continue;
18577
- if (key === STYLE_STORE_KEY) continue;
18578
- if (BRAND_CHROME_KEYS.has(key)) continue;
18579
17917
  if (applyVideoSettingNode(key, val)) continue;
18580
17918
  if (applyCarouselNode(key, val)) continue;
18581
17919
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -18677,10 +18015,7 @@ function OhhwellsBridge() {
18677
18015
  const payload = e.data.payload;
18678
18016
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
18679
18017
  const previous = aiSectionsRef.current;
18680
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
18681
- ...payload,
18682
- path: payload.path ?? window.location.pathname
18683
- });
18018
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
18684
18019
  const nextValue = serializeAiSectionsState(nextState);
18685
18020
  aiSectionsRef.current = nextValue;
18686
18021
  applyAiSectionsToDom(nextState);
@@ -18717,42 +18052,12 @@ function OhhwellsBridge() {
18717
18052
  const value = typeof e.data.value === "string" ? e.data.value : "";
18718
18053
  aiSectionsRef.current = value;
18719
18054
  applyAiSectionsToDom(parseAiSectionsState(value));
18720
- applyStylesToDom(parseStyleStore(stylesRef.current));
18721
18055
  const restoredHeight = document.documentElement.scrollHeight;
18722
18056
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
18723
18057
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
18724
18058
  postAiSectionsChanged();
18725
18059
  };
18726
18060
  window.addEventListener("message", handleAiSetSections);
18727
- const handleAiSetBrand = (e) => {
18728
- if (e.data?.type !== "ow:ai-set-brand") return;
18729
- const value = typeof e.data.value === "string" ? e.data.value : "";
18730
- const previous = brandKitRef.current;
18731
- brandKitRef.current = value;
18732
- applyBrandToDom(parseBrandKit(value));
18733
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
18734
- applyStylesToDom(parseStyleStore(stylesRef.current));
18735
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
18736
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
18737
- };
18738
- window.addEventListener("message", handleAiSetBrand);
18739
- const handleAiSetStyles = (e) => {
18740
- if (e.data?.type !== "ow:ai-set-styles") return;
18741
- const value = typeof e.data.value === "string" ? e.data.value : "";
18742
- const previous = stylesRef.current;
18743
- stylesRef.current = value;
18744
- applyStylesToDom(parseStyleStore(value));
18745
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
18746
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
18747
- };
18748
- window.addEventListener("message", handleAiSetStyles);
18749
- const handleGetBrand = (e) => {
18750
- if (e.data?.type !== "ow:get-brand") return;
18751
- const template = deriveTemplateBrand();
18752
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
18753
- postToParentRef.current({ type: "ow:brand-value", value });
18754
- };
18755
- window.addEventListener("message", handleGetBrand);
18756
18061
  const handleDeactivate = (e) => {
18757
18062
  if (e.data?.type !== "ow:deactivate") return;
18758
18063
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -18761,12 +18066,6 @@ function OhhwellsBridge() {
18761
18066
  closeLinkPopoverRef.current();
18762
18067
  return;
18763
18068
  }
18764
- if (floatingPanelOpenRef.current) {
18765
- setFloatingPanelRef.current(null);
18766
- deselectRef.current();
18767
- deactivateRef.current();
18768
- return;
18769
- }
18770
18069
  deselectRef.current();
18771
18070
  deactivateRef.current();
18772
18071
  };
@@ -19013,12 +18312,6 @@ function OhhwellsBridge() {
19013
18312
  if (aiSectionsRef.current) {
19014
18313
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
19015
18314
  }
19016
- if (stylesRef.current) {
19017
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
19018
- }
19019
- if (brandKitRef.current) {
19020
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
19021
- }
19022
18315
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
19023
18316
  const formKey = formKeyOf(form);
19024
18317
  if (!formKey) return;
@@ -19036,12 +18329,8 @@ function OhhwellsBridge() {
19036
18329
  if (inserted) {
19037
18330
  const tracker = getSectionsTracker();
19038
18331
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
19039
- const reportHeight = () => {
19040
- const h = document.body.scrollHeight;
19041
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19042
- };
19043
- reportHeight();
19044
- setTimeout(reportHeight, 500);
18332
+ const h = document.documentElement.scrollHeight;
18333
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19045
18334
  }
19046
18335
  };
19047
18336
  const handleSwitchSchedule = (e) => {
@@ -19428,9 +18717,6 @@ function OhhwellsBridge() {
19428
18717
  window.removeEventListener("message", handleAiApplyTree);
19429
18718
  window.removeEventListener("message", handleAiDeleteSection);
19430
18719
  window.removeEventListener("message", handleAiSetSections);
19431
- window.removeEventListener("message", handleAiSetBrand);
19432
- window.removeEventListener("message", handleAiSetStyles);
19433
- window.removeEventListener("message", handleGetBrand);
19434
18720
  window.removeEventListener("message", handleDeactivate);
19435
18721
  window.removeEventListener("message", handleToastAction);
19436
18722
  window.removeEventListener("message", handleFormCount);
@@ -19637,7 +18923,7 @@ function OhhwellsBridge() {
19637
18923
  postToParent2({
19638
18924
  type: "ow:ready",
19639
18925
  version: "1",
19640
- bridgeVersion: "0.1.65",
18926
+ bridgeVersion: "0.1.64",
19641
18927
  path: pathname,
19642
18928
  nodes: collectEditableNodes(editContentRef.current),
19643
18929
  sections
@@ -19691,6 +18977,44 @@ function OhhwellsBridge() {
19691
18977
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
19692
18978
  refreshActiveCommandsRef.current();
19693
18979
  }, []);
18980
+ useEffect12(() => {
18981
+ const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
18982
+ if (!session || !logoSizeDraft) return;
18983
+ const onPanelAction = (e) => {
18984
+ const type = e.data?.type;
18985
+ if (type === "ow:logo-size-close") {
18986
+ closeFloatingPanelAndDeselect();
18987
+ return;
18988
+ }
18989
+ if (type === "ow:logo-size-update-everywhere") {
18990
+ postToParentRef.current({ type: "ow:open-logo-settings", ...readLogoIdentityFromDom() });
18991
+ return;
18992
+ }
18993
+ if (type === "ow:logo-size-customize-mobile" || type === "ow:logo-size-reset-mobile") {
18994
+ const following = type === "ow:logo-size-reset-mobile";
18995
+ const next2 = {
18996
+ ...logoSizeDraft,
18997
+ mobileFollowing: following,
18998
+ mobilePx: logoSizeDraft.desktopPx
18999
+ };
19000
+ setLogoSizeDraft(next2);
19001
+ persistLogoSizeDraft(session.placement, next2);
19002
+ return;
19003
+ }
19004
+ if (type !== "ow:logo-size-set") return;
19005
+ const px = Number(e.data.px);
19006
+ if (!Number.isFinite(px)) return;
19007
+ const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
19008
+ ...logoSizeDraft,
19009
+ desktopPx: px,
19010
+ mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
19011
+ };
19012
+ setLogoSizeDraft(next);
19013
+ persistLogoSizeDraft(session.placement, next);
19014
+ };
19015
+ window.addEventListener("message", onPanelAction);
19016
+ return () => window.removeEventListener("message", onPanelAction);
19017
+ }, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
19694
19018
  const handleStateChange = useCallback7((state) => {
19695
19019
  if (!activeStateElRef.current) return;
19696
19020
  const el = activeStateElRef.current;
@@ -20032,10 +19356,10 @@ function OhhwellsBridge() {
20032
19356
  [postToParent2]
20033
19357
  );
20034
19358
  return bridgeRoot ? createPortal2(
20035
- /* @__PURE__ */ jsxs21(Fragment8, { children: [
20036
- /* @__PURE__ */ jsx34("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
20037
- isEditMode && /* @__PURE__ */ jsx34(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
20038
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx34(
19359
+ /* @__PURE__ */ jsxs20(Fragment8, { children: [
19360
+ /* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
19361
+ isEditMode && /* @__PURE__ */ jsx33(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
19362
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx33(
20039
19363
  MediaOverlay,
20040
19364
  {
20041
19365
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -20046,7 +19370,7 @@ function OhhwellsBridge() {
20046
19370
  },
20047
19371
  `uploading-${key}`
20048
19372
  )),
20049
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx34(
19373
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx33(
20050
19374
  MediaOverlay,
20051
19375
  {
20052
19376
  hover: mediaHover,
@@ -20055,11 +19379,11 @@ function OhhwellsBridge() {
20055
19379
  onVideoSettingsChange: handleVideoSettingsChange
20056
19380
  }
20057
19381
  ),
20058
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx34(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
20059
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx34(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
20060
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx34(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
20061
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx34(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
20062
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx34(
19382
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
19383
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
19384
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
19385
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
19386
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
20063
19387
  "div",
20064
19388
  {
20065
19389
  className: "pointer-events-none fixed z-2147483646",
@@ -20069,7 +19393,7 @@ function OhhwellsBridge() {
20069
19393
  width: slot.width,
20070
19394
  height: slot.height
20071
19395
  },
20072
- children: /* @__PURE__ */ jsx34(
19396
+ children: /* @__PURE__ */ jsx33(
20073
19397
  DropIndicator,
20074
19398
  {
20075
19399
  direction: slot.direction,
@@ -20080,7 +19404,7 @@ function OhhwellsBridge() {
20080
19404
  },
20081
19405
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
20082
19406
  )),
20083
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx34(
19407
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
20084
19408
  "div",
20085
19409
  {
20086
19410
  className: "pointer-events-none fixed z-2147483646",
@@ -20090,7 +19414,7 @@ function OhhwellsBridge() {
20090
19414
  width: slot.width,
20091
19415
  height: slot.height
20092
19416
  },
20093
- children: /* @__PURE__ */ jsx34(
19417
+ children: /* @__PURE__ */ jsx33(
20094
19418
  DropIndicator,
20095
19419
  {
20096
19420
  direction: slot.direction,
@@ -20101,10 +19425,10 @@ function OhhwellsBridge() {
20101
19425
  },
20102
19426
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
20103
19427
  )),
20104
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx34(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
20105
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx34(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
20106
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx34(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
20107
- formPickRect && !isItemDragging && /* @__PURE__ */ jsx34(
19428
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19429
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19430
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19431
+ formPickRect && !isItemDragging && /* @__PURE__ */ jsx33(
20108
19432
  ItemInteractionLayer,
20109
19433
  {
20110
19434
  rect: formPickRect,
@@ -20112,13 +19436,13 @@ function OhhwellsBridge() {
20112
19436
  itemDragSurface: false,
20113
19437
  toolbarAlign: "left",
20114
19438
  chromeGap: 24,
20115
- toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ jsxs21(
19439
+ toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ jsxs20(
20116
19440
  "div",
20117
19441
  {
20118
19442
  "data-ohw-form-toolbar": "",
20119
19443
  className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
20120
19444
  children: [
20121
- /* @__PURE__ */ jsx34(
19445
+ /* @__PURE__ */ jsx33(
20122
19446
  "button",
20123
19447
  {
20124
19448
  type: "button",
@@ -20126,11 +19450,11 @@ function OhhwellsBridge() {
20126
19450
  className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
20127
19451
  onClick: () => setFieldTypePickerOpen((open) => !open),
20128
19452
  "data-ohw-add-field": "",
20129
- children: /* @__PURE__ */ jsx34(Plus4, { size: 15, "aria-hidden": true })
19453
+ children: /* @__PURE__ */ jsx33(Plus4, { size: 15, "aria-hidden": true })
20130
19454
  }
20131
19455
  ),
20132
- /* @__PURE__ */ jsx34("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20133
- /* @__PURE__ */ jsxs21(
19456
+ /* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19457
+ /* @__PURE__ */ jsxs20(
20134
19458
  "button",
20135
19459
  {
20136
19460
  type: "button",
@@ -20145,11 +19469,11 @@ function OhhwellsBridge() {
20145
19469
  });
20146
19470
  },
20147
19471
  children: [
20148
- /* @__PURE__ */ jsx34(Settings, { size: 14, "aria-hidden": true }),
19472
+ /* @__PURE__ */ jsx33(Settings, { size: 14, "aria-hidden": true }),
20149
19473
  "Form settings",
20150
19474
  formPickCount ? (
20151
19475
  // Counter pill, per the design — not a text suffix.
20152
- /* @__PURE__ */ jsx34(
19476
+ /* @__PURE__ */ jsx33(
20153
19477
  "span",
20154
19478
  {
20155
19479
  "data-ohw-form-count": "",
@@ -20161,8 +19485,8 @@ function OhhwellsBridge() {
20161
19485
  ]
20162
19486
  }
20163
19487
  ),
20164
- /* @__PURE__ */ jsx34("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20165
- /* @__PURE__ */ jsx34("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx34(
19488
+ /* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19489
+ /* @__PURE__ */ jsx33("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx33(
20166
19490
  "button",
20167
19491
  {
20168
19492
  type: "button",
@@ -20192,7 +19516,7 @@ function OhhwellsBridge() {
20192
19516
  )
20193
19517
  }
20194
19518
  ),
20195
- formHoverRect && !isItemDragging && /* @__PURE__ */ jsx34(
19519
+ formHoverRect && !isItemDragging && /* @__PURE__ */ jsx33(
20196
19520
  ItemInteractionLayer,
20197
19521
  {
20198
19522
  rect: formHoverRect,
@@ -20200,7 +19524,7 @@ function OhhwellsBridge() {
20200
19524
  chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20201
19525
  }
20202
19526
  ),
20203
- fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx34(
19527
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(
20204
19528
  ItemInteractionLayer,
20205
19529
  {
20206
19530
  rect: fieldPickRect,
@@ -20212,7 +19536,7 @@ function OhhwellsBridge() {
20212
19536
  dragHandleLabel: "Reorder field",
20213
19537
  onDragHandleDragStart: handleFieldDragStart,
20214
19538
  onDragHandleDragEnd: handleFieldDragEnd,
20215
- toolbar: /* @__PURE__ */ jsx34(
19539
+ toolbar: /* @__PURE__ */ jsx33(
20216
19540
  FormFieldToolbar,
20217
19541
  {
20218
19542
  type: fieldPickState.type,
@@ -20225,12 +19549,12 @@ function OhhwellsBridge() {
20225
19549
  )
20226
19550
  }
20227
19551
  ),
20228
- fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx34(
19552
+ fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
20229
19553
  "div",
20230
19554
  {
20231
19555
  className: "pointer-events-none fixed z-[2147483644]",
20232
19556
  style: { top: slot.top, left: slot.left, width: slot.width },
20233
- children: /* @__PURE__ */ jsx34(
19557
+ children: /* @__PURE__ */ jsx33(
20234
19558
  DropIndicator,
20235
19559
  {
20236
19560
  direction: "horizontal",
@@ -20241,16 +19565,16 @@ function OhhwellsBridge() {
20241
19565
  },
20242
19566
  `field-drop-${i}`
20243
19567
  )) : null,
20244
- fieldTypePickerOpen && formPickRect && /* @__PURE__ */ jsx34(
19568
+ fieldTypePickerOpen && formPickRect && /* @__PURE__ */ jsx33(
20245
19569
  "div",
20246
19570
  {
20247
19571
  className: "pointer-events-none fixed z-[2147483645]",
20248
19572
  style: { top: formPickRect.top + 16, left: formPickRect.left + 24 },
20249
- children: /* @__PURE__ */ jsx34(FieldTypePicker, { onPick: handleAddField })
19573
+ children: /* @__PURE__ */ jsx33(FieldTypePicker, { onPick: handleAddField })
20250
19574
  }
20251
19575
  ),
20252
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx34(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
20253
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx34(
19576
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx33(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19577
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
20254
19578
  FooterContainerChrome,
20255
19579
  {
20256
19580
  rect: toolbarRect,
@@ -20258,7 +19582,7 @@ function OhhwellsBridge() {
20258
19582
  addDisabled: !canAddFooterColumn()
20259
19583
  }
20260
19584
  ),
20261
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx34(
19585
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
20262
19586
  ItemInteractionLayer,
20263
19587
  {
20264
19588
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -20273,7 +19597,7 @@ function OhhwellsBridge() {
20273
19597
  onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
20274
19598
  onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
20275
19599
  itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
20276
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx34(
19600
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
20277
19601
  ItemActionToolbar,
20278
19602
  {
20279
19603
  onEditLink: openLinkPopoverForSelected,
@@ -20309,8 +19633,8 @@ function OhhwellsBridge() {
20309
19633
  ) : void 0
20310
19634
  }
20311
19635
  ),
20312
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs21(Fragment8, { children: [
20313
- /* @__PURE__ */ jsx34(
19636
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
19637
+ /* @__PURE__ */ jsx33(
20314
19638
  EditGlowChrome,
20315
19639
  {
20316
19640
  rect: toolbarRect,
@@ -20320,7 +19644,7 @@ function OhhwellsBridge() {
20320
19644
  hideHandle: isItemDragging
20321
19645
  }
20322
19646
  ),
20323
- /* @__PURE__ */ jsx34(
19647
+ /* @__PURE__ */ jsx33(
20324
19648
  FloatingToolbar,
20325
19649
  {
20326
19650
  rect: toolbarRect,
@@ -20333,7 +19657,7 @@ function OhhwellsBridge() {
20333
19657
  }
20334
19658
  )
20335
19659
  ] }),
20336
- maxBadge && /* @__PURE__ */ jsxs21(
19660
+ maxBadge && /* @__PURE__ */ jsxs20(
20337
19661
  "div",
20338
19662
  {
20339
19663
  "data-ohw-max-badge": "",
@@ -20359,7 +19683,7 @@ function OhhwellsBridge() {
20359
19683
  ]
20360
19684
  }
20361
19685
  ),
20362
- toggleState && !linkPopover && /* @__PURE__ */ jsx34(
19686
+ toggleState && !linkPopover && /* @__PURE__ */ jsx33(
20363
19687
  StateToggle,
20364
19688
  {
20365
19689
  rect: toggleState.rect,
@@ -20368,15 +19692,15 @@ function OhhwellsBridge() {
20368
19692
  onStateChange: handleStateChange
20369
19693
  }
20370
19694
  ),
20371
- sectionGap && !linkPopover && /* @__PURE__ */ jsxs21(
19695
+ sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
20372
19696
  "div",
20373
19697
  {
20374
19698
  "data-ohw-section-insert-line": "",
20375
19699
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
20376
19700
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
20377
19701
  children: [
20378
- /* @__PURE__ */ jsx34("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
20379
- /* @__PURE__ */ jsx34(
19702
+ /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19703
+ /* @__PURE__ */ jsx33(
20380
19704
  Badge,
20381
19705
  {
20382
19706
  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",
@@ -20393,11 +19717,11 @@ function OhhwellsBridge() {
20393
19717
  children: "Add Section"
20394
19718
  }
20395
19719
  ),
20396
- /* @__PURE__ */ jsx34("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19720
+ /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
20397
19721
  ]
20398
19722
  }
20399
19723
  ),
20400
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx34(
19724
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx33(
20401
19725
  LinkPopover,
20402
19726
  {
20403
19727
  panelRef: linkPopoverPanelRef,
@@ -20414,7 +19738,7 @@ function OhhwellsBridge() {
20414
19738
  },
20415
19739
  linkPopover.key
20416
19740
  ) : null,
20417
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx34(
19741
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx33(
20418
19742
  FloatingPanel,
20419
19743
  {
20420
19744
  open: true,
@@ -20424,7 +19748,7 @@ function OhhwellsBridge() {
20424
19748
  onPositionChange: setFloatingPanelPos,
20425
19749
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
20426
19750
  onClose: closeFloatingPanelOnly,
20427
- children: /* @__PURE__ */ jsx34(
19751
+ children: /* @__PURE__ */ jsx33(
20428
19752
  SocialsDisplayPanel,
20429
19753
  {
20430
19754
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -20435,115 +19759,11 @@ function OhhwellsBridge() {
20435
19759
  }
20436
19760
  )
20437
19761
  }
20438
- ) : null,
20439
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ jsx34(
20440
- FloatingPanel,
20441
- {
20442
- open: true,
20443
- title: floatingPanel.title,
20444
- context: floatingPanel.context,
20445
- position: floatingPanelPos,
20446
- onPositionChange: setFloatingPanelPos,
20447
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
20448
- onClose: closeFloatingPanelAndDeselect,
20449
- children: /* @__PURE__ */ jsx34(
20450
- LogoSizePanel,
20451
- {
20452
- viewport: editorViewport,
20453
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
20454
- mobileFollowing: logoSizeDraft.mobileFollowing,
20455
- onSizeChange: (px) => {
20456
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
20457
- ...logoSizeDraft,
20458
- desktopPx: px,
20459
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
20460
- };
20461
- setLogoSizeDraft(next);
20462
- persistLogoSizeDraft(floatingPanel.placement, next);
20463
- },
20464
- onCustomizeMobile: () => {
20465
- const next = {
20466
- ...logoSizeDraft,
20467
- mobileFollowing: false,
20468
- mobilePx: logoSizeDraft.desktopPx
20469
- };
20470
- setLogoSizeDraft(next);
20471
- persistLogoSizeDraft(floatingPanel.placement, next);
20472
- },
20473
- onResetMobile: () => {
20474
- const next = {
20475
- ...logoSizeDraft,
20476
- mobileFollowing: true,
20477
- mobilePx: logoSizeDraft.desktopPx
20478
- };
20479
- setLogoSizeDraft(next);
20480
- persistLogoSizeDraft(floatingPanel.placement, next);
20481
- },
20482
- onUpdateEverywhere: () => {
20483
- const identity = readLogoIdentityFromDom();
20484
- postToParent2({ type: "ow:open-logo-settings", ...identity });
20485
- }
20486
- }
20487
- )
20488
- }
20489
19762
  ) : null
20490
19763
  ] }),
20491
19764
  bridgeRoot
20492
19765
  ) : null;
20493
19766
  }
20494
-
20495
- // src/ui/EmptySection.tsx
20496
- import Link4 from "next/link";
20497
- import { Fragment as Fragment9, jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
20498
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
20499
- return /* @__PURE__ */ jsxs22(Fragment9, { children: [
20500
- /* @__PURE__ */ jsx35(
20501
- "p",
20502
- {
20503
- style: {
20504
- fontFamily: "var(--brand-font-body)",
20505
- fontSize: "0.75rem",
20506
- fontWeight: 500,
20507
- letterSpacing: "0.15em",
20508
- textTransform: "uppercase",
20509
- color: "var(--brand-accent)",
20510
- marginBottom: "1.5rem"
20511
- },
20512
- children: /* @__PURE__ */ jsx35(Link4, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx35("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
20513
- }
20514
- ),
20515
- /* @__PURE__ */ jsx35(
20516
- "h1",
20517
- {
20518
- style: {
20519
- fontFamily: "var(--brand-font-heading)",
20520
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
20521
- lineHeight: 1.1,
20522
- letterSpacing: "-0.025em",
20523
- color: "var(--brand-text)",
20524
- marginBottom: "1rem"
20525
- },
20526
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
20527
- children: title
20528
- }
20529
- ),
20530
- /* @__PURE__ */ jsx35(
20531
- "p",
20532
- {
20533
- style: {
20534
- fontFamily: "var(--brand-font-body)",
20535
- fontSize: "1rem",
20536
- lineHeight: 1.7,
20537
- fontWeight: 300,
20538
- color: "var(--brand-text-muted)",
20539
- maxWidth: "340px"
20540
- },
20541
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
20542
- children: "This page doesn't have any content yet."
20543
- }
20544
- )
20545
- ] });
20546
- }
20547
19767
  export {
20548
19768
  AI_DEFAULT_BRAND,
20549
19769
  AI_TREE_SCHEMA_VERSIONS,
@@ -20560,7 +19780,6 @@ export {
20560
19780
  DropdownMenuItem,
20561
19781
  DropdownMenuSeparator,
20562
19782
  DropdownMenuTrigger,
20563
- EmptySection,
20564
19783
  ItemActionToolbar,
20565
19784
  ItemInteractionLayer,
20566
19785
  LinkEditorPanel,