@ohhwells/bridge 0.1.112-next.291 → 0.1.112

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
@@ -279,17 +279,16 @@ var LEGACY_BRAND_VAR_NAMES = [
279
279
  "text-muted",
280
280
  "surface",
281
281
  "border",
282
- "on-primary"
282
+ "on-primary",
283
+ "navbar-background"
283
284
  ].map((role) => `--brand-${role}`);
284
285
  var FONT_VARS = {
285
286
  heading: ["--font-heading", "--font-display", "--brand-font-heading"],
286
287
  body: ["--font-body", "--brand-font-body"]
287
288
  };
288
289
  var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
289
- var CUSTOM_FONT_STYLE_ID = "ohw-brand-custom-fonts";
290
- var CUSTOM_FONT_FORMATS = /* @__PURE__ */ new Set(["woff2", "woff", "truetype", "opentype"]);
291
- function brandColorVars(palette) {
292
- const { dark, primary, accent, light } = palette;
290
+ function brandColorVars(kit) {
291
+ const { dark, primary, accent, light } = kit.palette;
293
292
  const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
294
293
  const surface = mix(light, 95, dark);
295
294
  const border = mix(light, 85, dark);
@@ -312,42 +311,22 @@ function brandColorVars(palette) {
312
311
  "--brand-border": border,
313
312
  // Buttons/bands painted in the primary colour assume it's dark/saturated enough to need
314
313
  // light text on top — the same assumption LOGO_IMAGE's light-on-dark navbar mark makes.
315
- "--brand-on-primary": light
314
+ "--brand-on-primary": light,
315
+ "--brand-navbar-background": dark
316
316
  };
317
317
  }
318
- function parseCustomFontWeight(raw) {
319
- if (typeof raw !== "object" || raw === null) return null;
320
- const w = raw;
321
- if (typeof w.weight !== "number" || !Number.isFinite(w.weight)) return null;
322
- if (typeof w.url !== "string" || !w.url) return null;
323
- if (typeof w.format !== "string" || !CUSTOM_FONT_FORMATS.has(w.format)) return null;
324
- const weightEnd = typeof w.weightEnd === "number" && Number.isFinite(w.weightEnd) && w.weightEnd > w.weight ? w.weightEnd : void 0;
325
- return { weight: w.weight, ...weightEnd !== void 0 ? { weightEnd } : {}, url: w.url, format: w.format };
326
- }
327
- function parseCustomFont(raw) {
328
- if (typeof raw !== "object" || raw === null) return null;
329
- const f = raw;
330
- if (typeof f.family !== "string" || !f.family) return null;
331
- if (typeof f.label !== "string" || !f.label) return null;
332
- if (!Array.isArray(f.weights)) return null;
333
- const weights = f.weights.map(parseCustomFontWeight).filter((w) => w !== null);
334
- if (weights.length === 0) return null;
335
- return { family: f.family, label: f.label, weights };
336
- }
337
318
  function parseBrandKit(raw) {
338
319
  if (!raw) return null;
339
320
  try {
340
321
  const parsed = JSON.parse(raw);
341
322
  const p = parsed?.palette;
342
323
  const f = parsed?.fonts;
343
- const palette = p && typeof p.dark === "string" && typeof p.primary === "string" && typeof p.accent === "string" && typeof p.light === "string" ? { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light } : void 0;
344
- const fonts = f && typeof f.heading === "string" && typeof f.body === "string" ? { heading: f.heading, body: f.body } : void 0;
345
- const customFonts = Array.isArray(parsed?.customFonts) ? parsed.customFonts.map(parseCustomFont).filter((c) => c !== null) : void 0;
346
- if (!palette && !fonts && !customFonts) return null;
324
+ 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") {
325
+ return null;
326
+ }
347
327
  return {
348
- ...palette ? { palette } : {},
349
- ...fonts ? { fonts } : {},
350
- ...customFonts ? { customFonts } : {}
328
+ palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
329
+ fonts: { heading: f.heading, body: f.body }
351
330
  };
352
331
  } catch {
353
332
  return null;
@@ -357,16 +336,11 @@ function familyOf(stack) {
357
336
  const first = stack.split(",")[0]?.trim() ?? "";
358
337
  return first.replace(/^['"]|['"]$/g, "");
359
338
  }
360
- function quoteFamily(family) {
361
- return `'${family.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
362
- }
363
- var WEIGHT_SCALE = [100, 200, 300, 400, 500, 600, 700, 800, 900];
364
339
  function loadBrandFonts(families) {
365
340
  const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
366
341
  if (unique.length === 0) return;
367
- const weights = WEIGHT_SCALE.join(";");
368
- const spec = unique.map((f) => `family=${f.replace(/ /g, "+")}:wght@${weights}`).join("&");
369
- const href = `https://fonts.googleapis.com/css2?${spec}&display=swap`;
342
+ const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
343
+ const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
370
344
  let link = document.getElementById(BRAND_FONT_LINK_ID);
371
345
  if (!link) {
372
346
  link = document.createElement("link");
@@ -376,54 +350,18 @@ function loadBrandFonts(families) {
376
350
  }
377
351
  if (link.href !== href) link.href = href;
378
352
  }
379
- function escapeCssString(value) {
380
- return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
381
- }
382
- function loadCustomFonts(fonts) {
383
- const list = fonts ?? [];
384
- let style = document.getElementById(CUSTOM_FONT_STYLE_ID);
385
- if (list.length === 0) {
386
- style?.remove();
387
- return;
388
- }
389
- if (!style) {
390
- style = document.createElement("style");
391
- style.id = CUSTOM_FONT_STYLE_ID;
392
- document.head.appendChild(style);
393
- }
394
- style.textContent = list.flatMap(
395
- (font) => font.weights.map((w) => {
396
- const weightDescriptor = w.weightEnd ? `${w.weight} ${w.weightEnd}` : `${w.weight}`;
397
- return `@font-face { font-family: '${escapeCssString(font.family)}'; src: url('${escapeCssString(w.url)}') format('${w.format}'); font-weight: ${weightDescriptor}; font-display: swap; }`;
398
- })
399
- ).join("\n");
400
- }
401
353
  function applyBrandToDom(kit) {
402
354
  const root = document.documentElement;
403
355
  if (!kit) {
404
356
  for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
405
357
  for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
406
358
  document.getElementById(BRAND_FONT_LINK_ID)?.remove();
407
- document.getElementById(CUSTOM_FONT_STYLE_ID)?.remove();
408
359
  return;
409
360
  }
410
- if (kit.palette) {
411
- for (const [name, value] of Object.entries(brandColorVars(kit.palette))) root.style.setProperty(name, value);
412
- }
413
- if (kit.customFonts) {
414
- loadCustomFonts(kit.customFonts);
415
- }
416
- if (kit.fonts) {
417
- const heading = quoteFamily(kit.fonts.heading);
418
- const body = quoteFamily(kit.fonts.body);
419
- for (const name of FONT_VARS.heading) root.style.setProperty(name, heading);
420
- for (const name of FONT_VARS.body) root.style.setProperty(name, body);
421
- const customFamilies = new Set((kit.customFonts ?? []).map((f) => f.family));
422
- const googleFamilies = [familyOf(kit.fonts.heading), familyOf(kit.fonts.body)].filter(
423
- (f) => !customFamilies.has(f)
424
- );
425
- loadBrandFonts(googleFamilies);
426
- }
361
+ for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
362
+ for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
363
+ for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
364
+ loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
427
365
  }
428
366
 
429
367
  // src/lib/section-styles.ts
@@ -448,20 +386,6 @@ var BG_VALUES = {
448
386
  accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
449
387
  "accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
450
388
  };
451
- var NAVBAR_COLOR_TOKENS = ["dark", "primary", "accent", "light"];
452
- function navbarColorVar(token) {
453
- const fallback = {
454
- dark: "#0C0A09",
455
- primary: "#0078E5",
456
- accent: "#0078E5",
457
- light: "#FFFFFF"
458
- };
459
- return `var(--ohw-brand-${token}, var(--color-${token}, ${fallback[token]}))`;
460
- }
461
- function resolveNavbarValue(value) {
462
- if (value === void 0) return void 0;
463
- return NAVBAR_COLOR_TOKENS.includes(value) ? navbarColorVar(value) : value;
464
- }
465
389
  var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
466
390
  function styleSheetCss() {
467
391
  const rules = [];
@@ -631,16 +555,8 @@ function applyStylesToDom(store) {
631
555
  for (const [sectionId, override] of Object.entries(store.sections)) {
632
556
  const escaped = CSS.escape(sectionId);
633
557
  const byInstance = document.querySelectorAll(`[data-ohw-instance="${escaped}"]`);
634
- const sections = Array.from(
635
- byInstance.length ? byInstance : document.querySelectorAll(`[data-ohw-section="${escaped}"]`)
636
- );
637
- const isNavbar = sectionId === "navbar";
638
- if (isNavbar) {
639
- const drawer = document.querySelector("[data-ohw-nav-drawer]");
640
- if (drawer && !sections.includes(drawer)) sections.push(drawer);
641
- }
558
+ const sections = byInstance.length ? byInstance : document.querySelectorAll(`[data-ohw-section="${escaped}"]`);
642
559
  for (const marker of Array.from(sections)) {
643
- const isDrawerMarker = isNavbar && marker.hasAttribute("data-ohw-nav-drawer");
644
560
  const section = marker.querySelector(":scope > [data-ai-section]") ?? marker;
645
561
  for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
646
562
  const value = override[prop];
@@ -648,23 +564,19 @@ function applyStylesToDom(store) {
648
564
  if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
649
565
  section.setAttribute(attr, String(value).replace(":", "-"));
650
566
  }
651
- const bgOverride = isDrawerMarker ? override.navbarMobileBackground ?? override.sectionBackgroundColor : override.sectionBackgroundColor;
652
- const textOverride = isDrawerMarker ? override.navbarMobileTextColor ?? override.textColor : override.textColor;
653
- const bgValue = isNavbar ? resolveNavbarValue(bgOverride) : bgOverride;
654
- const textValue = isNavbar ? resolveNavbarValue(textOverride) : textOverride;
655
- if (bgValue !== void 0) {
567
+ if (override.sectionBackgroundColor !== void 0) {
656
568
  saveInline(section, "background");
657
- section.style.setProperty("background", bgValue, "important");
569
+ section.style.setProperty("background", override.sectionBackgroundColor, "important");
658
570
  section.setAttribute("data-ohw-style-bgcolor", "");
659
571
  }
660
- if (textValue !== void 0 || override.fontFamily !== void 0) {
572
+ if (override.textColor !== void 0 || override.fontFamily !== void 0) {
661
573
  const textEls = marker.querySelectorAll(
662
574
  '[data-ohw-editable="text"], [data-ohw-editable="plain"], [data-ohw-field-label]'
663
575
  );
664
576
  for (const el of Array.from(textEls)) {
665
- if (textValue !== void 0) {
577
+ if (override.textColor !== void 0) {
666
578
  saveInline(el, "color");
667
- el.style.setProperty("color", textValue, "important");
579
+ el.style.setProperty("color", override.textColor, "important");
668
580
  el.setAttribute(NODE_WROTE_ATTR, "");
669
581
  }
670
582
  if (override.fontFamily !== void 0) {
@@ -1370,22 +1282,6 @@ function accentBandContext(brand) {
1370
1282
  function textAttrs(ctx, path) {
1371
1283
  return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
1372
1284
  }
1373
- var AI_RESPONSIVE_CSS = [
1374
- "@media (max-width: 960px) {",
1375
- " [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
1376
- ' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
1377
- "}",
1378
- "@media (max-width: 640px) {",
1379
- " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
1380
- " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
1381
- // Group containers flatten to a column on phones; span placements come along for free.
1382
- " [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
1383
- " [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
1384
- " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
1385
- " [data-ai-responsive] { overflow-x: hidden; }",
1386
- " [data-ai-responsive] img { max-width: 100%; }",
1387
- "}"
1388
- ].join("\n");
1389
1285
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
1390
1286
  function MediaBox({
1391
1287
  refValue,
@@ -1398,17 +1294,13 @@ function MediaBox({
1398
1294
  const url = refValue ? ctx.resolveMedia(refValue) : null;
1399
1295
  const isIcon = /^(lucide|simple):/.test(refValue);
1400
1296
  const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
1401
- const editAttrs = ctx.keyFor && editPath ? {
1402
- "data-ohw-key": ctx.keyFor(editPath),
1403
- "data-ohw-editable": isIcon ? "icon" : "image"
1404
- } : {};
1297
+ const editAttrs = ctx.keyFor && editPath && !isIcon ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "image" } : {};
1405
1298
  if (isIcon) {
1406
1299
  const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
1407
1300
  return /* @__PURE__ */ jsx(
1408
1301
  "span",
1409
1302
  {
1410
1303
  "data-ai-icon": refValue,
1411
- ...editAttrs,
1412
1304
  style: {
1413
1305
  display: "inline-flex",
1414
1306
  width: 48,
@@ -2301,7 +2193,7 @@ function CollectionBlock({ node, ctx, path }) {
2301
2193
  return /* @__PURE__ */ jsx(
2302
2194
  "div",
2303
2195
  {
2304
- "data-ai-grid": String(itemsPerRow),
2196
+ "data-ai-grid": "",
2305
2197
  style: {
2306
2198
  display: "grid",
2307
2199
  gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`,
@@ -2654,7 +2546,6 @@ function AiTreeRenderer({
2654
2546
  {
2655
2547
  "data-ai-section": tree.tag ?? "",
2656
2548
  ...bgAttrs,
2657
- "data-ai-responsive": "",
2658
2549
  style: {
2659
2550
  position: "relative",
2660
2551
  padding: `${pad}px 0`,
@@ -2665,13 +2556,12 @@ function AiTreeRenderer({
2665
2556
  color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
2666
2557
  },
2667
2558
  children: [
2668
- /* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
2669
- /* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
2670
2559
  isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
2560
+ /* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
2671
2561
  /* @__PURE__ */ jsx(
2672
2562
  "div",
2673
2563
  {
2674
- "data-ai-section-inner": "",
2564
+ "data-ai-container": "",
2675
2565
  style: {
2676
2566
  position: "relative",
2677
2567
  maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
@@ -2682,7 +2572,7 @@ function AiTreeRenderer({
2682
2572
  children: tree.rows.map((row, r2) => /* @__PURE__ */ jsx(
2683
2573
  "div",
2684
2574
  {
2685
- "data-ai-columns": "",
2575
+ "data-ai-row": "",
2686
2576
  style: {
2687
2577
  display: "grid",
2688
2578
  gridTemplateColumns: "repeat(12, 1fr)",
@@ -2732,52 +2622,14 @@ function readRootVar(name) {
2732
2622
  if (typeof document === "undefined") return "";
2733
2623
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
2734
2624
  }
2735
- function normalizeColorToHex(value) {
2736
- if (!value || typeof document === "undefined") return value;
2737
- const canvas = document.createElement("canvas");
2738
- canvas.width = 1;
2739
- canvas.height = 1;
2740
- const ctx = canvas.getContext("2d");
2741
- if (!ctx) return value;
2742
- ctx.fillStyle = value;
2743
- ctx.fillRect(0, 0, 1, 1);
2744
- const [r2, g, b] = ctx.getImageData(0, 0, 1, 1).data;
2745
- const toHex = (n) => n.toString(16).padStart(2, "0");
2746
- return `#${toHex(r2)}${toHex(g)}${toHex(b)}`;
2747
- }
2748
- var GENERIC_FONT_KEYWORDS = /* @__PURE__ */ new Set([
2749
- "serif",
2750
- "sans-serif",
2751
- "monospace",
2752
- "cursive",
2753
- "fantasy",
2754
- "system-ui",
2755
- "ui-serif",
2756
- "ui-sans-serif",
2757
- "ui-monospace",
2758
- "ui-rounded",
2759
- "math",
2760
- "emoji",
2761
- "fangsong"
2762
- ]);
2763
- function primaryFontFamily(stack) {
2764
- const first = stack.split(",").map((part) => part.trim().replace(/^["']|["']$/g, "")).find((part) => part && !GENERIC_FONT_KEYWORDS.has(part.toLowerCase()));
2765
- return first ?? "";
2766
- }
2767
- function humanizeFontFamily(name) {
2768
- return name.replace(/^__/, "").replace(/_[0-9a-f]{6}$/i, "").replace(/_/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").trim().replace(/\s+/g, " ").replace(/(^|\s)([a-z])/g, (_, sep, c) => sep + c.toUpperCase());
2769
- }
2770
- function readFontVar(name) {
2771
- return humanizeFontFamily(primaryFontFamily(readRootVar(name)));
2772
- }
2773
2625
  function deriveBrandOverride() {
2774
2626
  const dark = readRootVar("--ohw-brand-dark");
2775
2627
  const primary = readRootVar("--ohw-brand-primary");
2776
2628
  const light = readRootVar("--ohw-brand-light");
2777
2629
  if (!dark || !primary || !light) return null;
2778
2630
  const accent = readRootVar("--ohw-brand-accent");
2779
- const heading = readFontVar("--font-heading") || readFontVar("--font-display");
2780
- const body = readFontVar("--font-body");
2631
+ const heading = readRootVar("--font-heading") || readRootVar("--font-display");
2632
+ const body = readRootVar("--font-body");
2781
2633
  return {
2782
2634
  palette: { dark, primary, accent: accent || dark, light },
2783
2635
  fonts: {
@@ -2786,55 +2638,22 @@ function deriveBrandOverride() {
2786
2638
  }
2787
2639
  };
2788
2640
  }
2789
- function deriveTemplateBrandLive() {
2641
+ function deriveTemplateBrand() {
2790
2642
  const primary = readRootVar("--brand-primary") || readRootVar("--color-primary");
2791
2643
  const dark = readRootVar("--brand-text") || readRootVar("--color-dark");
2792
2644
  const light = readRootVar("--brand-background") || readRootVar("--color-light");
2793
2645
  if (!dark || !primary || !light) return null;
2794
2646
  const accent = readRootVar("--brand-accent") || readRootVar("--color-accent");
2795
- const heading = readFontVar("--brand-font-heading") || readFontVar("--font-heading") || readFontVar("--font-display");
2796
- const body = readFontVar("--brand-font-body") || readFontVar("--font-body");
2647
+ const heading = readRootVar("--brand-font-heading") || readRootVar("--font-heading") || readRootVar("--font-display");
2648
+ const body = readRootVar("--brand-font-body") || readRootVar("--font-body");
2797
2649
  return {
2798
- palette: {
2799
- dark: normalizeColorToHex(dark),
2800
- primary: normalizeColorToHex(primary),
2801
- accent: normalizeColorToHex(accent || dark),
2802
- light: normalizeColorToHex(light)
2803
- },
2650
+ palette: { dark, primary, accent: accent || dark, light },
2804
2651
  fonts: {
2805
2652
  heading: heading || AI_DEFAULT_BRAND.fonts.heading,
2806
2653
  body: body || AI_DEFAULT_BRAND.fonts.body
2807
2654
  }
2808
2655
  };
2809
2656
  }
2810
- function deriveTemplateFontsLive() {
2811
- const heading = readFontVar("--brand-font-heading") || readFontVar("--font-heading") || readFontVar("--font-display");
2812
- const body = readFontVar("--brand-font-body") || readFontVar("--font-body");
2813
- if (!heading && !body) return null;
2814
- return {
2815
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
2816
- body: body || AI_DEFAULT_BRAND.fonts.body
2817
- };
2818
- }
2819
- var OVERRIDE_VAR_NAMES = [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...FONT_VARS.heading, ...FONT_VARS.body];
2820
- function withOverrideStripped(read) {
2821
- const root = document.documentElement;
2822
- const restore = OVERRIDE_VAR_NAMES.map((name) => [name, root.style.getPropertyValue(name)]);
2823
- for (const name of OVERRIDE_VAR_NAMES) root.style.removeProperty(name);
2824
- try {
2825
- return read();
2826
- } finally {
2827
- for (const [name, value] of restore) if (value) root.style.setProperty(name, value);
2828
- }
2829
- }
2830
- var TEMPLATE_BRAND_SNAPSHOT = typeof document === "undefined" ? null : withOverrideStripped(deriveTemplateBrandLive);
2831
- var TEMPLATE_FONTS_SNAPSHOT = typeof document === "undefined" ? null : withOverrideStripped(deriveTemplateFontsLive);
2832
- function deriveTemplateBrand() {
2833
- return TEMPLATE_BRAND_SNAPSHOT;
2834
- }
2835
- function deriveTemplateFonts() {
2836
- return TEMPLATE_FONTS_SNAPSHOT;
2837
- }
2838
2657
  function deriveTemplateButtonStyle() {
2839
2658
  if (typeof document === "undefined") return null;
2840
2659
  const candidates = Array.from(
@@ -7332,12 +7151,12 @@ var cva = (base, config) => (props) => {
7332
7151
  import { Toggle as TogglePrimitive } from "radix-ui";
7333
7152
  import { jsx as jsx5 } from "react/jsx-runtime";
7334
7153
  var toggleVariants = cva(
7335
- "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-bridge-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
7154
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
7336
7155
  {
7337
7156
  variants: {
7338
7157
  variant: {
7339
7158
  default: "bg-transparent border-0",
7340
- outline: "border border-input bg-transparent shadow-xs hover:bg-bridge-accent hover:text-accent-foreground"
7159
+ outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
7341
7160
  },
7342
7161
  size: {
7343
7162
  default: "px-2 py-1",
@@ -7430,10 +7249,10 @@ var DragHandle = React4.forwardRef(
7430
7249
  type,
7431
7250
  "data-slot": "drag-handle",
7432
7251
  className: cn(
7433
- "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-7.5",
7252
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
7434
7253
  "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
7435
7254
  "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
7436
- "enabled:active:border enabled:active:border-bridge-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
7255
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
7437
7256
  "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
7438
7257
  className
7439
7258
  ),
@@ -7455,7 +7274,7 @@ var CustomToolbar = React5.forwardRef(({ className, onMouseDown, ...props }, ref
7455
7274
  "data-ohw-toolbar": "",
7456
7275
  className: cn(
7457
7276
  // Figma: bg background, radius 8, gap-1, p-0.5, shadow-md — no border
7458
- "inline-flex h-8 items-center gap-1 rounded-(--radius,0.5rem) bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
7277
+ "inline-flex h-8 items-center gap-1 rounded-[var(--radius,0.5rem)] bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
7459
7278
  className
7460
7279
  ),
7461
7280
  onMouseDown: (e) => {
@@ -7484,7 +7303,7 @@ var CustomToolbarButton = React5.forwardRef(
7484
7303
  type,
7485
7304
  className: cn(
7486
7305
  "inline-flex size-7 shrink-0 items-center justify-center rounded-[calc(var(--radius,0.5rem)-2px)] text-foreground transition-colors",
7487
- active ? "bg-bridge-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
7306
+ active ? "bg-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
7488
7307
  className
7489
7308
  ),
7490
7309
  ...props
@@ -8748,13 +8567,13 @@ function FormFieldToolbar({
8748
8567
  ]
8749
8568
  }
8750
8569
  ) }),
8751
- /* @__PURE__ */ jsx13(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-47.5 p-1", children: FIELD_TYPES.map((entry) => {
8570
+ /* @__PURE__ */ jsx13(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-[190px] p-1", children: FIELD_TYPES.map((entry) => {
8752
8571
  const Icon = TYPE_ICONS[entry.type];
8753
8572
  return /* @__PURE__ */ jsxs6(
8754
8573
  DropdownMenuItem,
8755
8574
  {
8756
8575
  onSelect: () => onTypeChange(entry.type),
8757
- className: "rounded-md py-2 text-[13px] " + (entry.type === type ? "bg-bridge-primary/10" : ""),
8576
+ className: "rounded-md py-2 text-[13px] " + (entry.type === type ? "bg-primary/10" : ""),
8758
8577
  children: [
8759
8578
  /* @__PURE__ */ jsx13(Icon, { size: 14, strokeWidth: 1.75, className: "shrink-0", "aria-hidden": true }),
8760
8579
  entry.label
@@ -8771,7 +8590,7 @@ function FormFieldToolbar({
8771
8590
  type: "button",
8772
8591
  "aria-pressed": required,
8773
8592
  onClick: onRequiredToggle,
8774
- className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-medium transition-colors " + (required ? "bg-bridge-primary/10 text-bridge-primary" : "text-foreground hover:bg-muted/70"),
8593
+ className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-medium transition-colors " + (required ? "bg-primary/10 text-primary" : "text-foreground hover:bg-muted/70"),
8775
8594
  "data-ohw-field-required-toggle": "",
8776
8595
  children: [
8777
8596
  /* @__PURE__ */ jsx13(Asterisk, { size: 14, strokeWidth: 2, "aria-hidden": true }),
@@ -8791,7 +8610,7 @@ function FormFieldToolbar({
8791
8610
  children: /* @__PURE__ */ jsx13(MoreHorizontal2, { size: 15, "aria-hidden": true })
8792
8611
  }
8793
8612
  ) }),
8794
- /* @__PURE__ */ jsxs6(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-42.5 p-1", children: [
8613
+ /* @__PURE__ */ jsxs6(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-[170px] p-1", children: [
8795
8614
  /* @__PURE__ */ jsxs6(DropdownMenuItem, { onSelect: onDuplicate, className: "rounded-md py-2 text-[13px]", children: [
8796
8615
  /* @__PURE__ */ jsx13(Copy2, { size: 14, strokeWidth: 1.75, className: "shrink-0", "aria-hidden": true }),
8797
8616
  "Duplicate"
@@ -8819,7 +8638,7 @@ function FieldTypePicker({ onPick }) {
8819
8638
  {
8820
8639
  type: "button",
8821
8640
  onClick: () => onPick(entry.type),
8822
- className: "flex h-[76px] flex-col items-center justify-center gap-2 rounded-xl border border-border text-[15px] font-medium text-foreground transition-colors hover:border-bridge-primary hover:bg-bridge-primary/5",
8641
+ className: "flex h-[76px] flex-col items-center justify-center gap-2 rounded-xl border border-border text-[15px] font-medium text-foreground transition-colors hover:border-primary hover:bg-primary/5",
8823
8642
  children: [
8824
8643
  /* @__PURE__ */ jsx13(Icon, { size: 26, strokeWidth: 1.5, "aria-hidden": true }),
8825
8644
  entry.label
@@ -8845,7 +8664,7 @@ var buttonVariants = cva(
8845
8664
  {
8846
8665
  variants: {
8847
8666
  variant: {
8848
- default: "bg-bridge-primary text-primary-foreground hover:opacity-90",
8667
+ default: "bg-primary text-primary-foreground hover:opacity-90",
8849
8668
  outline: "border border-border bg-background text-foreground shadow-sm hover:bg-muted/80",
8850
8669
  ghost: "min-w-0 px-3 py-2 text-foreground hover:bg-muted/50"
8851
8670
  },
@@ -8940,7 +8759,6 @@ function MediaOverlay({
8940
8759
  (prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
8941
8760
  );
8942
8761
  }, [isVideo]);
8943
- const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
8944
8762
  const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
8945
8763
  const box = {
8946
8764
  position: "fixed",
@@ -9046,8 +8864,8 @@ function MediaOverlay({
9046
8864
  pointerEvents: hover.hasTextOverlap ? "none" : "auto",
9047
8865
  // Selected: a firm component ring with no wash, so the image reads as chosen rather
9048
8866
  // than hovered. Hover keeps the existing tinted preview.
9049
- boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
9050
- background: selected ? "transparent" : "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
8867
+ boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
8868
+ background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
9051
8869
  },
9052
8870
  onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
9053
8871
  children: [
@@ -9070,17 +8888,17 @@ function MediaOverlay({
9070
8888
  },
9071
8889
  children: [
9072
8890
  isVideo ? /* @__PURE__ */ jsx15(Film, { size: 14 }) : /* @__PURE__ */ jsx15(ImageIcon, { size: 14 }),
9073
- replaceLabel
8891
+ isVideo ? "Replace video" : "Replace image"
9074
8892
  ]
9075
8893
  }
9076
8894
  ),
9077
- showChrome && replaceMode !== "none" && /* @__PURE__ */ jsxs7(
8895
+ replaceMode === "none" ? null : /* @__PURE__ */ jsxs7(
9078
8896
  Button,
9079
8897
  {
9080
8898
  "data-ohw-media-overlay": "",
9081
8899
  variant: "outline",
9082
8900
  size: "sm",
9083
- "aria-label": replaceLabel,
8901
+ "aria-label": isVideo ? "Replace video" : "Replace image",
9084
8902
  className: "gap-1.5 cursor-pointer hover:bg-background",
9085
8903
  style: {
9086
8904
  ...OVERLAY_BUTTON_STYLE,
@@ -9103,7 +8921,7 @@ function MediaOverlay({
9103
8921
  },
9104
8922
  children: [
9105
8923
  isVideo ? /* @__PURE__ */ jsx15(Film, { size: 14 }) : /* @__PURE__ */ jsx15(ImageIcon, { size: 14 }),
9106
- replaceMode === "full" ? replaceLabel : null
8924
+ replaceMode === "full" ? isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image" : null
9107
8925
  ]
9108
8926
  }
9109
8927
  )
@@ -9141,8 +8959,8 @@ function CarouselOverlay({
9141
8959
  height: rect.height,
9142
8960
  zIndex: 2147483646,
9143
8961
  pointerEvents: "auto",
9144
- boxShadow: "inset 0 0 0 1.5px var(--color-bridge-primary)",
9145
- background: "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
8962
+ boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
8963
+ background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
9146
8964
  },
9147
8965
  onClick: () => onEdit(hover.key),
9148
8966
  children: /* @__PURE__ */ jsxs8(
@@ -9995,7 +9813,7 @@ function SectionTreeItem({
9995
9813
  /* @__PURE__ */ jsx20(
9996
9814
  "div",
9997
9815
  {
9998
- className: "-mr-px h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
9816
+ className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
9999
9817
  "aria-hidden": true
10000
9818
  }
10001
9819
  ),
@@ -10014,7 +9832,7 @@ function SectionTreeItem({
10014
9832
  className: cn(
10015
9833
  "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-md border border-border bg-background p-3",
10016
9834
  interactive && "cursor-pointer hover:bg-muted/30",
10017
- interactive && selected && "border-bridge-primary"
9835
+ interactive && selected && "border-primary"
10018
9836
  ),
10019
9837
  children: [
10020
9838
  /* @__PURE__ */ jsx20(
@@ -10144,7 +9962,7 @@ function UrlOrPageInput({
10144
9962
  };
10145
9963
  const fieldClassName = cn(
10146
9964
  "data-ohw-link-field flex h-[36px] w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
10147
- urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-bridge-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
9965
+ urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
10148
9966
  );
10149
9967
  return /* @__PURE__ */ jsxs13("div", { className: "flex w-full flex-col gap-2 p-0", children: [
10150
9968
  /* @__PURE__ */ jsx23(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
@@ -14051,7 +13869,6 @@ function readLogoSizeState(content, placement) {
14051
13869
  function getLogoElement(el) {
14052
13870
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
14053
13871
  if (marked) return marked;
14054
- if (el.closest('[data-ohw-editable="icon"]')) return null;
14055
13872
  const root = el.closest("nav, [data-ohw-nav-root], footer");
14056
13873
  if (!root) return null;
14057
13874
  const anchor = el.closest("a");
@@ -14345,7 +14162,7 @@ function DisplaySwitch({
14345
14162
  onClick: () => onChange(!checked),
14346
14163
  className: cn(
14347
14164
  "relative h-5 w-9 shrink-0 rounded-full transition-colors",
14348
- checked ? "bg-bridge-primary" : "bg-primary-50",
14165
+ checked ? "bg-primary" : "bg-primary-50",
14349
14166
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
14350
14167
  ),
14351
14168
  children: /* @__PURE__ */ jsx28(
@@ -14353,7 +14170,7 @@ function DisplaySwitch({
14353
14170
  {
14354
14171
  className: cn(
14355
14172
  "absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all",
14356
- checked ? "left-4.5" : "left-0.5"
14173
+ checked ? "left-[1.125rem]" : "left-0.5"
14357
14174
  )
14358
14175
  }
14359
14176
  )
@@ -15988,7 +15805,7 @@ var badgeVariants = cva(
15988
15805
  {
15989
15806
  variants: {
15990
15807
  variant: {
15991
- default: "border-transparent bg-bridge-primary text-primary-foreground",
15808
+ default: "border-transparent bg-primary text-primary-foreground",
15992
15809
  secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15993
15810
  destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
15994
15811
  outline: "text-foreground"
@@ -16170,10 +15987,21 @@ function parseSchedulingInsertAfter(insertAfter) {
16170
15987
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
16171
15988
  };
16172
15989
  }
16173
- function resolveEntryAnchor(entry) {
16174
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
16175
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
16176
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
15990
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
15991
+ const parsed = parseSchedulingInsertAfter(insertAfter);
15992
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
15993
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
15994
+ return { effectiveInsertAfter, insertBefore };
15995
+ }
15996
+ function getSchedulingMountPoint(insertAfter) {
15997
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
15998
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
15999
+ if (!anchorEl && anchor === "scheduling") {
16000
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
16001
+ anchorEl = widgets.at(-1) ?? null;
16002
+ }
16003
+ if (!anchorEl) return null;
16004
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
16177
16005
  }
16178
16006
  function schedulingMountDepth(insertAfter) {
16179
16007
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -16190,7 +16018,8 @@ function getPageSchedulingEntries(raw) {
16190
16018
  }
16191
16019
  }
16192
16020
  function isSchedulingWidgetMissing(entry) {
16193
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
16021
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
16022
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
16194
16023
  }
16195
16024
  function hasMissingSchedulingWidgets(entries) {
16196
16025
  return entries.some(isSchedulingWidgetMissing);
@@ -16228,18 +16057,17 @@ function initSectionsFromContent(content, removeExisting = false, currentPath =
16228
16057
  } catch {
16229
16058
  }
16230
16059
  }
16231
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
16232
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
16233
- const sectionId = schedulingSectionId(widgetId);
16060
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
16061
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
16062
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
16234
16063
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
16235
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
16236
- if (!anchorEl) return false;
16237
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
16064
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
16065
+ if (!mountPoint) return false;
16238
16066
  const container = document.createElement("div");
16239
16067
  container.dataset.ohwSectionContainer = "scheduling";
16240
16068
  container.dataset.ohwInstance = sectionId;
16241
- if (beforeId) {
16242
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
16069
+ if (insertBefore) {
16070
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
16243
16071
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
16244
16072
  if (!beforePoint) return false;
16245
16073
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -16250,26 +16078,20 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
16250
16078
  }
16251
16079
  tail.insertAdjacentElement("afterend", container);
16252
16080
  }
16253
- try {
16254
- const root = createRoot2(container);
16255
- schedulingRoots.set(container, root);
16256
- flushSync2(() => {
16257
- root.render(
16258
- /* @__PURE__ */ jsx33(
16259
- SchedulingWidget,
16260
- {
16261
- notifyOnConnect,
16262
- initialScheduleId: scheduleId,
16263
- insertAfter: widgetId
16264
- }
16265
- )
16266
- );
16267
- });
16268
- } catch (err) {
16269
- console.error("[ow:scheduling] render threw", err);
16270
- container.remove();
16271
- return false;
16272
- }
16081
+ const root = createRoot2(container);
16082
+ schedulingRoots.set(container, root);
16083
+ flushSync2(() => {
16084
+ root.render(
16085
+ /* @__PURE__ */ jsx33(
16086
+ SchedulingWidget,
16087
+ {
16088
+ notifyOnConnect,
16089
+ initialScheduleId: scheduleId,
16090
+ insertAfter: effectiveInsertAfter
16091
+ }
16092
+ )
16093
+ );
16094
+ });
16273
16095
  const tracker = getSectionsTracker();
16274
16096
  let sections = [];
16275
16097
  try {
@@ -16277,12 +16099,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
16277
16099
  } catch {
16278
16100
  }
16279
16101
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
16280
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
16102
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
16281
16103
  sections.push({
16282
16104
  type: "scheduling",
16283
- insertAfter: widgetId,
16284
- anchorId,
16285
- beforeId: beforeId ?? null,
16105
+ insertAfter: effectiveInsertAfter,
16286
16106
  pagePath: window.location.pathname,
16287
16107
  ...scheduleId ? { scheduleId } : {}
16288
16108
  });
@@ -16296,8 +16116,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
16296
16116
  for (let i = pending.length - 1; i >= 0; i--) {
16297
16117
  const entry = pending[i];
16298
16118
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
16299
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
16300
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
16119
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId ?? null)) {
16301
16120
  pending.splice(i, 1);
16302
16121
  }
16303
16122
  }
@@ -16461,11 +16280,6 @@ function applyLinkByKey(key, val) {
16461
16280
  hrefAnchors.forEach((el) => applyLinkHref(el, val));
16462
16281
  }
16463
16282
  }
16464
- function isInsideLinkEditor(target) {
16465
- return Boolean(
16466
- 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"]')
16467
- );
16468
- }
16469
16283
  function isInsideFloatingPanel(target) {
16470
16284
  return Boolean(target.closest("[data-ohw-floating-panel]"));
16471
16285
  }
@@ -16473,6 +16287,11 @@ function isPointOverFloatingPanel(clientX, clientY) {
16473
16287
  const el = document.elementFromPoint(clientX, clientY);
16474
16288
  return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
16475
16289
  }
16290
+ function isInsideLinkEditor(target) {
16291
+ return Boolean(
16292
+ 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"]')
16293
+ );
16294
+ }
16476
16295
  function getHrefKeyFromElement(el) {
16477
16296
  if (!el) return null;
16478
16297
  const anchor = el.closest("[data-ohw-href-key]");
@@ -16632,7 +16451,6 @@ function isFooterAddItemDisabled(selected) {
16632
16451
  }
16633
16452
  function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
16634
16453
  if (getNavigationItemAnchor(target)) return null;
16635
- if (target.closest("[data-ohw-editable]")) return null;
16636
16454
  const column = getFooterColumn(target);
16637
16455
  if (!column) return null;
16638
16456
  if (isPointOverNavItem(column, clientX, clientY)) return null;
@@ -16742,7 +16560,7 @@ function getNavigationSelectionParent(el) {
16742
16560
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
16743
16561
  return getFooterLinksContainer();
16744
16562
  }
16745
- 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)) {
16563
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
16746
16564
  return getNavigationRoot(el);
16747
16565
  }
16748
16566
  return null;
@@ -16774,12 +16592,6 @@ function collectNavigationItemSiblingHintRects(selected) {
16774
16592
  return [];
16775
16593
  }).filter((el) => isNavigationItem2(el) && el !== selected).map((el) => el.getBoundingClientRect());
16776
16594
  }
16777
- if (selected.closest('footer, [data-ohw-section="footer"]')) {
16778
- const group = findFooterItemGroup2(selected);
16779
- if (group) {
16780
- return Array.from(group.querySelectorAll("[data-ohw-href-key]")).filter((el) => isNavigationItem2(el) && el !== selected).map((el) => el.getBoundingClientRect());
16781
- }
16782
- }
16783
16595
  return listNavigationItems().filter((el) => el !== selected && !el.closest("[data-ohw-nav-children]")).map((el) => el.getBoundingClientRect());
16784
16596
  }
16785
16597
  function placeCaretAtPoint(el, x, y) {
@@ -16964,6 +16776,7 @@ var ICONS = {
16964
16776
  insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
16965
16777
  insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
16966
16778
  };
16779
+ var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
16967
16780
  var SELECTION_CHROME_GAP2 = 4;
16968
16781
  var TOOLBAR_STROKE_GAP2 = 4;
16969
16782
  var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
@@ -17347,7 +17160,6 @@ function StateToggle({
17347
17160
  );
17348
17161
  }
17349
17162
  var contentCache = /* @__PURE__ */ new Map();
17350
- var fetchedContentPaths = /* @__PURE__ */ new Set();
17351
17163
  var brandingCache = /* @__PURE__ */ new Map();
17352
17164
  var OHW_LOADER_STYLE = {
17353
17165
  position: "fixed",
@@ -17896,6 +17708,13 @@ function OhhwellsBridge() {
17896
17708
  const [isItemDragging, setIsItemDragging] = useState14(false);
17897
17709
  const [isFooterFrameSelection, setIsFooterFrameSelection] = useState14(false);
17898
17710
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
17711
+ const [floatingPanel, setFloatingPanel] = useState14(null);
17712
+ const floatingPanelOpenRef = useRef10(false);
17713
+ floatingPanelOpenRef.current = floatingPanel !== null;
17714
+ const [floatingPanelPos, setFloatingPanelPos] = useState14(null);
17715
+ const [logoSizeDraft, setLogoSizeDraft] = useState14(null);
17716
+ const [editorViewport, setEditorViewport] = useState14("desktop");
17717
+ const [parentScrollSnap, setParentScrollSnap] = useState14(null);
17899
17718
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState14(null);
17900
17719
  const [footerHeadingVisible, setFooterHeadingVisible] = useState14(null);
17901
17720
  const footerDragRef = useRef10(null);
@@ -17912,15 +17731,7 @@ function OhhwellsBridge() {
17912
17731
  const aiSectionsRef = useRef10("");
17913
17732
  const brandKitRef = useRef10("");
17914
17733
  const stylesRef = useRef10("");
17915
- const appliedDrawerRef = useRef10(null);
17916
17734
  const pendingDeleteUndoRef = useRef10(null);
17917
- const [floatingPanel, setFloatingPanel] = useState14(null);
17918
- const floatingPanelOpenRef = useRef10(false);
17919
- const setFloatingPanelRef = useRef10(setFloatingPanel);
17920
- const [floatingPanelPos, setFloatingPanelPos] = useState14(null);
17921
- const [logoSizeDraft, setLogoSizeDraft] = useState14(null);
17922
- const [editorViewport, setEditorViewport] = useState14("desktop");
17923
- const [parentScrollSnap, setParentScrollSnap] = useState14(null);
17924
17735
  const [sitePages, setSitePages] = useState14([]);
17925
17736
  const [sectionsByPath, setSectionsByPath] = useState14({});
17926
17737
  const sectionsPrefetchGenRef = useRef10(0);
@@ -17929,18 +17740,7 @@ function OhhwellsBridge() {
17929
17740
  const linkPopoverOpenRef = useRef10(false);
17930
17741
  const linkPopoverGraceUntilRef = useRef10(0);
17931
17742
  setLinkPopoverRef.current = setLinkPopover;
17932
- setFloatingPanelRef.current = setFloatingPanel;
17933
17743
  linkPopoverSessionRef.current = linkPopover;
17934
- floatingPanelOpenRef.current = Boolean(floatingPanel);
17935
- useEffect13(() => {
17936
- const syncViewport = () => {
17937
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
17938
- setEditorViewport((prev) => prev === next ? prev : next);
17939
- };
17940
- syncViewport();
17941
- window.addEventListener("resize", syncViewport);
17942
- return () => window.removeEventListener("resize", syncViewport);
17943
- }, []);
17944
17744
  const {
17945
17745
  navDragRef,
17946
17746
  navPointerDragRef,
@@ -19276,7 +19076,6 @@ function OhhwellsBridge() {
19276
19076
  }
19277
19077
  if (typeof content[STYLE_STORE_KEY] === "string") {
19278
19078
  stylesRef.current = content[STYLE_STORE_KEY];
19279
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
19280
19079
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
19281
19080
  }
19282
19081
  applyBrandChrome(content);
@@ -19284,11 +19083,11 @@ function OhhwellsBridge() {
19284
19083
  for (const [key, val] of Object.entries(content)) {
19285
19084
  if (key === "__ohw_sections") continue;
19286
19085
  if (key === AI_SECTIONS_KEY) continue;
19287
- if (key === LOGO_PLACEHOLDER_KEY) continue;
19288
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
19289
19086
  if (key === BRAND_KIT_KEY) continue;
19290
19087
  if (key === STYLE_STORE_KEY) continue;
19291
19088
  if (BRAND_CHROME_KEYS.has(key)) continue;
19089
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
19090
+ if (LOGO_IMAGE_KEYS.includes(key)) continue;
19292
19091
  if (applyVideoSettingNode(key, val)) continue;
19293
19092
  if (applyCarouselNode(key, val)) continue;
19294
19093
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -19359,9 +19158,7 @@ function OhhwellsBridge() {
19359
19158
  let cancelled = false;
19360
19159
  setFetchState("loading");
19361
19160
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
19362
- const initialPath = pathname;
19363
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
19364
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
19161
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
19365
19162
  if (cancelled) return;
19366
19163
  const content = data?.content ?? {};
19367
19164
  const branding = Boolean(data?.showBranding);
@@ -19470,9 +19267,7 @@ function OhhwellsBridge() {
19470
19267
  }, [isEditMode]);
19471
19268
  useEffect13(() => {
19472
19269
  if (isEditMode || fetchState !== "done") return;
19473
- console.log("env", process.env.NEXT_PUBLIC_FLOWOPS_API_URL);
19474
19270
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
19475
- console.log({ apiUrl, subdomain });
19476
19271
  bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
19477
19272
  }, [isEditMode, fetchState, subdomain]);
19478
19273
  useEffect13(() => {
@@ -19497,17 +19292,16 @@ function OhhwellsBridge() {
19497
19292
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
19498
19293
  }
19499
19294
  if (typeof content[STYLE_STORE_KEY] === "string") {
19500
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
19501
19295
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
19502
19296
  }
19503
19297
  for (const [key, val] of Object.entries(content)) {
19504
19298
  if (key === "__ohw_sections") continue;
19505
19299
  if (key === AI_SECTIONS_KEY) continue;
19506
- if (key === LOGO_PLACEHOLDER_KEY) continue;
19507
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
19508
19300
  if (key === BRAND_KIT_KEY) continue;
19509
19301
  if (key === STYLE_STORE_KEY) continue;
19510
19302
  if (BRAND_CHROME_KEYS.has(key)) continue;
19303
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
19304
+ if (LOGO_IMAGE_KEYS.includes(key)) continue;
19511
19305
  if (applyVideoSettingNode(key, val)) continue;
19512
19306
  if (applyCarouselNode(key, val)) continue;
19513
19307
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -19558,17 +19352,6 @@ function OhhwellsBridge() {
19558
19352
  debounceTimer = setTimeout(applyFromCache, 150);
19559
19353
  };
19560
19354
  applyFromCache();
19561
- const pathCacheKey = `${subdomain}::${pathname}`;
19562
- if (!fetchedContentPaths.has(pathCacheKey)) {
19563
- fetchedContentPaths.add(pathCacheKey);
19564
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
19565
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
19566
- if (!data?.content) return;
19567
- contentCache.set(subdomain, data.content);
19568
- applyFromCache();
19569
- }).catch(() => {
19570
- });
19571
- }
19572
19355
  observer = new MutationObserver(scheduleApply);
19573
19356
  observer.observe(document.body, { childList: true, subtree: true });
19574
19357
  return () => {
@@ -19613,17 +19396,6 @@ function OhhwellsBridge() {
19613
19396
  if (!isEditMode) return;
19614
19397
  initSectionInstancesFromContent(editContentRef.current, pathname);
19615
19398
  }, [pathname, isEditMode]);
19616
- useEffect13(() => {
19617
- if (!isEditMode) return;
19618
- const observer = new MutationObserver(() => {
19619
- const drawer = document.querySelector("[data-ohw-nav-drawer]");
19620
- if (!drawer || drawer === appliedDrawerRef.current) return;
19621
- appliedDrawerRef.current = drawer;
19622
- applyStylesToDom(parseStyleStore(stylesRef.current));
19623
- });
19624
- observer.observe(document.body, { childList: true, subtree: true });
19625
- return () => observer.disconnect();
19626
- }, [isEditMode, pathname]);
19627
19399
  useEffect13(() => {
19628
19400
  const contentForNav = () => {
19629
19401
  if (isEditMode) return editContentRef.current;
@@ -19715,11 +19487,26 @@ function OhhwellsBridge() {
19715
19487
  const t2 = setTimeout(measure, 500);
19716
19488
  const ro = new ResizeObserver(schedule);
19717
19489
  ro.observe(document.body);
19490
+ let lastWidth = window.innerWidth;
19491
+ let resizeTimers = [];
19492
+ const clearResizeTimers = () => {
19493
+ resizeTimers.forEach(clearTimeout);
19494
+ resizeTimers = [];
19495
+ };
19496
+ const handleResize = () => {
19497
+ if (window.innerWidth === lastWidth) return;
19498
+ lastWidth = window.innerWidth;
19499
+ clearResizeTimers();
19500
+ resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
19501
+ };
19502
+ window.addEventListener("resize", handleResize);
19718
19503
  return () => {
19719
19504
  clearTimeout(t1);
19720
19505
  clearTimeout(t2);
19721
19506
  if (raf != null) cancelAnimationFrame(raf);
19722
19507
  ro.disconnect();
19508
+ clearResizeTimers();
19509
+ window.removeEventListener("resize", handleResize);
19723
19510
  };
19724
19511
  }, [pathname, isEditMode, postToParent2]);
19725
19512
  useEffect13(() => {
@@ -20014,6 +19801,9 @@ function OhhwellsBridge() {
20014
19801
  if (target.closest("[data-ohw-state-toggle]")) return;
20015
19802
  if (target.closest("[data-ohw-max-badge]")) return;
20016
19803
  if (isInsideLinkEditor(target)) return;
19804
+ if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
19805
+ clearMediaSelectionRef.current();
19806
+ }
20017
19807
  if (isInsideFloatingPanel(target)) return;
20018
19808
  if (target.closest("[data-ohw-form-toolbar]")) return;
20019
19809
  if (target.closest(
@@ -20021,9 +19811,6 @@ function OhhwellsBridge() {
20021
19811
  )) {
20022
19812
  return;
20023
19813
  }
20024
- if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
20025
- clearMediaSelectionRef.current();
20026
- }
20027
19814
  {
20028
19815
  const formEl = getFormElement(target);
20029
19816
  const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
@@ -20187,6 +19974,14 @@ function OhhwellsBridge() {
20187
19974
  }
20188
19975
  const clickedButton = findClosestButtonLike(target);
20189
19976
  const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
19977
+ console.log("[click-debug]", {
19978
+ editableType: editable.dataset.ohwEditable,
19979
+ editableTag: editable.tagName,
19980
+ targetTag: target.tagName,
19981
+ clickedButtonTag: clickedButton?.tagName ?? null,
19982
+ buttonOnMedia,
19983
+ isMediaEditableEditable: isMediaEditable(editable)
19984
+ });
20190
19985
  if (isMediaEditable(editable) && !buttonOnMedia) {
20191
19986
  e.preventDefault();
20192
19987
  e.stopPropagation();
@@ -20213,6 +20008,11 @@ function OhhwellsBridge() {
20213
20008
  const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
20214
20009
  const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
20215
20010
  const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
20011
+ console.log("[click-debug 2]", {
20012
+ hrefLookupTargetTag: hrefLookupTarget.tagName,
20013
+ hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
20014
+ navAnchorTag: navAnchor?.tagName ?? null
20015
+ });
20216
20016
  if (navAnchor) {
20217
20017
  e.preventDefault();
20218
20018
  e.stopPropagation();
@@ -20254,7 +20054,7 @@ function OhhwellsBridge() {
20254
20054
  return;
20255
20055
  }
20256
20056
  const footerColClick = target.closest("[data-ohw-footer-col]");
20257
- if (footerColClick && !target.closest("[data-ohw-editable]")) {
20057
+ if (footerColClick) {
20258
20058
  e.preventDefault();
20259
20059
  e.stopPropagation();
20260
20060
  selectFrameRef.current(footerColClick);
@@ -20382,9 +20182,6 @@ function OhhwellsBridge() {
20382
20182
  setHoveredItemRect(null);
20383
20183
  hoveredNavContainerRef.current = null;
20384
20184
  setHoveredNavContainerRect(null);
20385
- siblingHintElRef.current = null;
20386
- setSiblingHintRect(null);
20387
- setSiblingHintRects([]);
20388
20185
  return;
20389
20186
  }
20390
20187
  {
@@ -20416,7 +20213,7 @@ function OhhwellsBridge() {
20416
20213
  const navContainer = target.closest("[data-ohw-nav-container]");
20417
20214
  if (!navContainer) {
20418
20215
  const footerLinks = target.closest("[data-ohw-footer-links], .rb-footer-links") ?? null;
20419
- if (footerLinks && selected2 !== footerLinks && !getNavigationItemAnchor(target) && !target.closest("[data-ohw-footer-col], [data-ohw-footer-column]") && !target.closest("[data-ohw-editable]")) {
20216
+ if (footerLinks && selected2 !== footerLinks && !getNavigationItemAnchor(target) && !target.closest("[data-ohw-footer-col], [data-ohw-footer-column]")) {
20420
20217
  hoveredNavContainerRef.current = footerLinks;
20421
20218
  setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
20422
20219
  hoveredItemElRef.current = null;
@@ -20454,7 +20251,7 @@ function OhhwellsBridge() {
20454
20251
  return;
20455
20252
  }
20456
20253
  const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
20457
- if (footerCol && !target.closest("[data-ohw-editable]")) {
20254
+ if (footerCol) {
20458
20255
  hoveredNavContainerRef.current = null;
20459
20256
  setHoveredNavContainerRect(null);
20460
20257
  if (selectedElRef.current === footerCol) return;
@@ -20505,6 +20302,7 @@ function OhhwellsBridge() {
20505
20302
  hoveredNavContainerRef.current = null;
20506
20303
  setHoveredNavContainerRect(null);
20507
20304
  hoveredItemElRef.current = editable;
20305
+ setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
20508
20306
  }
20509
20307
  }
20510
20308
  }
@@ -20801,7 +20599,7 @@ function OhhwellsBridge() {
20801
20599
  }
20802
20600
  };
20803
20601
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
20804
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
20602
+ if (linkPopoverOpenRef.current) {
20805
20603
  if (hoveredImageRef.current) {
20806
20604
  hoveredImageRef.current = null;
20807
20605
  hoveredImageHasTextOverlapRef.current = false;
@@ -21174,7 +20972,8 @@ function OhhwellsBridge() {
21174
20972
  };
21175
20973
  const handleMouseMove = (e) => {
21176
20974
  const { clientX, clientY } = e;
21177
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
20975
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
20976
+ if (isOverEditorChrome(clientX, clientY)) {
21178
20977
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
21179
20978
  formHoverElRef.current = null;
21180
20979
  setFormHoverRect(null);
@@ -21182,12 +20981,7 @@ function OhhwellsBridge() {
21182
20981
  setHoveredItemRect(null);
21183
20982
  hoveredNavContainerRef.current = null;
21184
20983
  setHoveredNavContainerRect(null);
21185
- siblingHintElRef.current = null;
21186
- setSiblingHintRect(null);
21187
- setSiblingHintRects([]);
21188
20984
  dismissImageHover();
21189
- clearImageHover();
21190
- setSectionGap(null);
21191
20985
  return;
21192
20986
  }
21193
20987
  if (probeSocialsRowAt(clientX, clientY)) return;
@@ -21199,11 +20993,7 @@ function OhhwellsBridge() {
21199
20993
  if (e.data?.type !== "ow:pointer-sync") return;
21200
20994
  const { clientX, clientY } = e.data;
21201
20995
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
21202
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
21203
- dismissImageHover();
21204
- clearImageHover();
21205
- return;
21206
- }
20996
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
21207
20997
  if (probeSocialsRowAt(clientX, clientY)) return;
21208
20998
  probeSectionGapAt(clientX, clientY);
21209
20999
  probeImageAt(clientX, clientY);
@@ -21542,7 +21332,6 @@ function OhhwellsBridge() {
21542
21332
  }
21543
21333
  if (typeof content[STYLE_STORE_KEY] === "string") {
21544
21334
  stylesRef.current = content[STYLE_STORE_KEY];
21545
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
21546
21335
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
21547
21336
  }
21548
21337
  applyBrandChrome(content);
@@ -21554,11 +21343,11 @@ function OhhwellsBridge() {
21554
21343
  continue;
21555
21344
  }
21556
21345
  if (key === AI_SECTIONS_KEY) continue;
21557
- if (key === LOGO_PLACEHOLDER_KEY) continue;
21558
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
21559
21346
  if (key === BRAND_KIT_KEY) continue;
21560
21347
  if (key === STYLE_STORE_KEY) continue;
21561
21348
  if (BRAND_CHROME_KEYS.has(key)) continue;
21349
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
21350
+ if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
21562
21351
  if (applyVideoSettingNode(key, val)) continue;
21563
21352
  if (applyCarouselNode(key, val)) continue;
21564
21353
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -21783,26 +21572,10 @@ function OhhwellsBridge() {
21783
21572
  const handleGetBrand = (e) => {
21784
21573
  if (e.data?.type !== "ow:get-brand") return;
21785
21574
  const template = deriveTemplateBrand();
21786
- const fallback = template ?? (() => {
21787
- const fonts = deriveTemplateFonts();
21788
- return fonts ? { palette: AI_DEFAULT_BRAND.palette, fonts } : null;
21789
- })();
21790
- const value = brandKitRef.current || (fallback ? JSON.stringify(fallback) : "");
21575
+ const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
21791
21576
  postToParentRef.current({ type: "ow:brand-value", value });
21792
21577
  };
21793
21578
  window.addEventListener("message", handleGetBrand);
21794
- const handleGetTemplateFonts = (e) => {
21795
- if (e.data?.type !== "ow:get-template-fonts") return;
21796
- const fonts = deriveTemplateFonts();
21797
- postToParentRef.current({ type: "ow:template-fonts-value", value: fonts ? JSON.stringify(fonts) : "" });
21798
- };
21799
- window.addEventListener("message", handleGetTemplateFonts);
21800
- const handleGetTemplateBrand = (e) => {
21801
- if (e.data?.type !== "ow:get-template-brand") return;
21802
- const brand = deriveTemplateBrand();
21803
- postToParentRef.current({ type: "ow:template-brand-value", value: brand ? JSON.stringify(brand) : "" });
21804
- };
21805
- window.addEventListener("message", handleGetTemplateBrand);
21806
21579
  const handleMoveSection = (e) => {
21807
21580
  if (e.data?.type !== "ow:move-section") return;
21808
21581
  const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
@@ -21995,12 +21768,6 @@ function OhhwellsBridge() {
21995
21768
  closeLinkPopoverRef.current();
21996
21769
  return;
21997
21770
  }
21998
- if (floatingPanelOpenRef.current) {
21999
- setFloatingPanelRef.current(null);
22000
- deselectRef.current();
22001
- deactivateRef.current();
22002
- return;
22003
- }
22004
21771
  deselectRef.current();
22005
21772
  deactivateRef.current();
22006
21773
  clearMediaSelectionRef.current();
@@ -22289,12 +22056,8 @@ function OhhwellsBridge() {
22289
22056
  if (inserted) {
22290
22057
  const tracker = getSectionsTracker();
22291
22058
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
22292
- const reportHeight = () => {
22293
- const h = document.body.scrollHeight;
22294
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
22295
- };
22296
- reportHeight();
22297
- setTimeout(reportHeight, 500);
22059
+ const h = document.body.scrollHeight;
22060
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
22298
22061
  }
22299
22062
  };
22300
22063
  const handleSwitchSchedule = (e) => {
@@ -22715,17 +22478,15 @@ function OhhwellsBridge() {
22715
22478
  window.removeEventListener("message", handleAiSetBrand);
22716
22479
  window.removeEventListener("message", handleAiSetStyles);
22717
22480
  window.removeEventListener("message", handleGetBrand);
22718
- window.removeEventListener("message", handleGetTemplateFonts);
22719
- window.removeEventListener("message", handleGetTemplateBrand);
22720
22481
  window.removeEventListener("message", handleMoveSection);
22721
22482
  window.removeEventListener("message", handlePanelDragging);
22722
22483
  window.removeEventListener("message", handleDeleteSection);
22723
22484
  window.removeEventListener("message", handleDuplicateSection);
22724
22485
  window.removeEventListener("message", handleDeactivate);
22486
+ document.documentElement.removeAttribute("data-ohw-panel-dragging");
22725
22487
  window.removeEventListener("message", handleToastAction);
22726
22488
  window.removeEventListener("message", handleFormCount);
22727
22489
  window.removeEventListener("message", handleUiEscape);
22728
- document.documentElement.removeAttribute("data-ohw-panel-dragging");
22729
22490
  autoSaveTimers.current.forEach(clearTimeout);
22730
22491
  autoSaveTimers.current.clear();
22731
22492
  if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
@@ -22928,7 +22689,7 @@ function OhhwellsBridge() {
22928
22689
  postToParent2({
22929
22690
  type: "ow:ready",
22930
22691
  version: "1",
22931
- bridgeVersion: "0.1.112",
22692
+ bridgeVersion: "0.1.111",
22932
22693
  path: pathname,
22933
22694
  nodes: collectEditableNodes(editContentRef.current),
22934
22695
  sections
@@ -23544,7 +23305,7 @@ function OhhwellsBridge() {
23544
23305
  "span",
23545
23306
  {
23546
23307
  "data-ohw-form-count": "",
23547
- className: "ml-0.5 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-bridge-primary px-1.5 text-[11px] font-semibold text-primary-foreground",
23308
+ className: "ml-0.5 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground",
23548
23309
  children: formPickCount
23549
23310
  }
23550
23311
  )
@@ -23782,11 +23543,11 @@ function OhhwellsBridge() {
23782
23543
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
23783
23544
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
23784
23545
  children: [
23785
- /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
23546
+ /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
23786
23547
  /* @__PURE__ */ jsx33(
23787
23548
  Badge,
23788
23549
  {
23789
- className: "px-8 py-1 bg-bridge-primary hover:bg-bridge-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
23550
+ 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",
23790
23551
  onClick: () => {
23791
23552
  window.parent.postMessage(
23792
23553
  {
@@ -23800,7 +23561,7 @@ function OhhwellsBridge() {
23800
23561
  children: "Add Section"
23801
23562
  }
23802
23563
  ),
23803
- /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
23564
+ /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
23804
23565
  ]
23805
23566
  }
23806
23567
  ),
@@ -23848,59 +23609,6 @@ function OhhwellsBridge() {
23848
23609
  ) : null
23849
23610
  ] });
23850
23611
  }
23851
-
23852
- // src/ui/EmptySection.tsx
23853
- import Link3 from "next/link";
23854
- import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
23855
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
23856
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
23857
- /* @__PURE__ */ jsx34(
23858
- "p",
23859
- {
23860
- style: {
23861
- fontFamily: "var(--brand-font-body)",
23862
- fontSize: "0.75rem",
23863
- fontWeight: 500,
23864
- letterSpacing: "0.15em",
23865
- textTransform: "uppercase",
23866
- color: "var(--brand-accent)",
23867
- marginBottom: "1.5rem"
23868
- },
23869
- children: /* @__PURE__ */ jsx34(Link3, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx34("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
23870
- }
23871
- ),
23872
- /* @__PURE__ */ jsx34(
23873
- "h1",
23874
- {
23875
- style: {
23876
- fontFamily: "var(--brand-font-heading)",
23877
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
23878
- lineHeight: 1.1,
23879
- letterSpacing: "-0.025em",
23880
- color: "var(--brand-text)",
23881
- marginBottom: "1rem"
23882
- },
23883
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
23884
- children: title
23885
- }
23886
- ),
23887
- /* @__PURE__ */ jsx34(
23888
- "p",
23889
- {
23890
- style: {
23891
- fontFamily: "var(--brand-font-body)",
23892
- fontSize: "1rem",
23893
- lineHeight: 1.7,
23894
- fontWeight: 300,
23895
- color: "var(--brand-text-muted)",
23896
- maxWidth: "340px"
23897
- },
23898
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
23899
- children: "This page doesn't have any content yet."
23900
- }
23901
- )
23902
- ] });
23903
- }
23904
23612
  export {
23905
23613
  AI_DEFAULT_BRAND,
23906
23614
  AI_TREE_SCHEMA_VERSIONS,
@@ -23917,7 +23625,6 @@ export {
23917
23625
  DropdownMenuItem,
23918
23626
  DropdownMenuSeparator,
23919
23627
  DropdownMenuTrigger,
23920
- EmptySection,
23921
23628
  ItemActionToolbar,
23922
23629
  ItemInteractionLayer,
23923
23630
  LinkEditorPanel,