@ohhwells/bridge 0.1.115 → 0.1.117

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,16 +279,17 @@ var LEGACY_BRAND_VAR_NAMES = [
279
279
  "text-muted",
280
280
  "surface",
281
281
  "border",
282
- "on-primary",
283
- "navbar-background"
282
+ "on-primary"
284
283
  ].map((role) => `--brand-${role}`);
285
284
  var FONT_VARS = {
286
285
  heading: ["--font-heading", "--font-display", "--brand-font-heading"],
287
286
  body: ["--font-body", "--brand-font-body"]
288
287
  };
289
288
  var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
290
- function brandColorVars(kit) {
291
- const { dark, primary, accent, light } = kit.palette;
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;
292
293
  const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
293
294
  const surface = mix(light, 95, dark);
294
295
  const border = mix(light, 85, dark);
@@ -311,22 +312,42 @@ function brandColorVars(kit) {
311
312
  "--brand-border": border,
312
313
  // Buttons/bands painted in the primary colour assume it's dark/saturated enough to need
313
314
  // light text on top — the same assumption LOGO_IMAGE's light-on-dark navbar mark makes.
314
- "--brand-on-primary": light,
315
- "--brand-navbar-background": dark
315
+ "--brand-on-primary": light
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
+ }
318
337
  function parseBrandKit(raw) {
319
338
  if (!raw) return null;
320
339
  try {
321
340
  const parsed = JSON.parse(raw);
322
341
  const p = parsed?.palette;
323
342
  const f = parsed?.fonts;
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
- }
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;
327
347
  return {
328
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
329
- fonts: { heading: f.heading, body: f.body }
348
+ ...palette ? { palette } : {},
349
+ ...fonts ? { fonts } : {},
350
+ ...customFonts ? { customFonts } : {}
330
351
  };
331
352
  } catch {
332
353
  return null;
@@ -336,11 +357,16 @@ function familyOf(stack) {
336
357
  const first = stack.split(",")[0]?.trim() ?? "";
337
358
  return first.replace(/^['"]|['"]$/g, "");
338
359
  }
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];
339
364
  function loadBrandFonts(families) {
340
365
  const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
341
366
  if (unique.length === 0) return;
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`;
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`;
344
370
  let link = document.getElementById(BRAND_FONT_LINK_ID);
345
371
  if (!link) {
346
372
  link = document.createElement("link");
@@ -350,18 +376,54 @@ function loadBrandFonts(families) {
350
376
  }
351
377
  if (link.href !== href) link.href = href;
352
378
  }
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
+ }
353
401
  function applyBrandToDom(kit) {
354
402
  const root = document.documentElement;
355
403
  if (!kit) {
356
404
  for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
357
405
  for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
358
406
  document.getElementById(BRAND_FONT_LINK_ID)?.remove();
407
+ document.getElementById(CUSTOM_FONT_STYLE_ID)?.remove();
359
408
  return;
360
409
  }
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)]);
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
+ }
365
427
  }
366
428
 
367
429
  // src/lib/section-styles.ts
@@ -2650,14 +2712,52 @@ function readRootVar(name) {
2650
2712
  if (typeof document === "undefined") return "";
2651
2713
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
2652
2714
  }
2715
+ function normalizeColorToHex(value) {
2716
+ if (!value || typeof document === "undefined") return value;
2717
+ const canvas = document.createElement("canvas");
2718
+ canvas.width = 1;
2719
+ canvas.height = 1;
2720
+ const ctx = canvas.getContext("2d");
2721
+ if (!ctx) return value;
2722
+ ctx.fillStyle = value;
2723
+ ctx.fillRect(0, 0, 1, 1);
2724
+ const [r2, g, b] = ctx.getImageData(0, 0, 1, 1).data;
2725
+ const toHex = (n) => n.toString(16).padStart(2, "0");
2726
+ return `#${toHex(r2)}${toHex(g)}${toHex(b)}`;
2727
+ }
2728
+ var GENERIC_FONT_KEYWORDS = /* @__PURE__ */ new Set([
2729
+ "serif",
2730
+ "sans-serif",
2731
+ "monospace",
2732
+ "cursive",
2733
+ "fantasy",
2734
+ "system-ui",
2735
+ "ui-serif",
2736
+ "ui-sans-serif",
2737
+ "ui-monospace",
2738
+ "ui-rounded",
2739
+ "math",
2740
+ "emoji",
2741
+ "fangsong"
2742
+ ]);
2743
+ function primaryFontFamily(stack) {
2744
+ const first = stack.split(",").map((part) => part.trim().replace(/^["']|["']$/g, "")).find((part) => part && !GENERIC_FONT_KEYWORDS.has(part.toLowerCase()));
2745
+ return first ?? "";
2746
+ }
2747
+ function humanizeFontFamily(name) {
2748
+ 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());
2749
+ }
2750
+ function readFontVar(name) {
2751
+ return humanizeFontFamily(primaryFontFamily(readRootVar(name)));
2752
+ }
2653
2753
  function deriveBrandOverride() {
2654
2754
  const dark = readRootVar("--ohw-brand-dark");
2655
2755
  const primary = readRootVar("--ohw-brand-primary");
2656
2756
  const light = readRootVar("--ohw-brand-light");
2657
2757
  if (!dark || !primary || !light) return null;
2658
2758
  const accent = readRootVar("--ohw-brand-accent");
2659
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
2660
- const body = readRootVar("--font-body");
2759
+ const heading = readFontVar("--font-heading") || readFontVar("--font-display");
2760
+ const body = readFontVar("--font-body");
2661
2761
  return {
2662
2762
  palette: { dark, primary, accent: accent || dark, light },
2663
2763
  fonts: {
@@ -2666,22 +2766,55 @@ function deriveBrandOverride() {
2666
2766
  }
2667
2767
  };
2668
2768
  }
2669
- function deriveTemplateBrand() {
2769
+ function deriveTemplateBrandLive() {
2670
2770
  const primary = readRootVar("--brand-primary") || readRootVar("--color-primary");
2671
2771
  const dark = readRootVar("--brand-text") || readRootVar("--color-dark");
2672
2772
  const light = readRootVar("--brand-background") || readRootVar("--color-light");
2673
2773
  if (!dark || !primary || !light) return null;
2674
2774
  const accent = readRootVar("--brand-accent") || readRootVar("--color-accent");
2675
- const heading = readRootVar("--brand-font-heading") || readRootVar("--font-heading") || readRootVar("--font-display");
2676
- const body = readRootVar("--brand-font-body") || readRootVar("--font-body");
2775
+ const heading = readFontVar("--brand-font-heading") || readFontVar("--font-heading") || readFontVar("--font-display");
2776
+ const body = readFontVar("--brand-font-body") || readFontVar("--font-body");
2677
2777
  return {
2678
- palette: { dark, primary, accent: accent || dark, light },
2778
+ palette: {
2779
+ dark: normalizeColorToHex(dark),
2780
+ primary: normalizeColorToHex(primary),
2781
+ accent: normalizeColorToHex(accent || dark),
2782
+ light: normalizeColorToHex(light)
2783
+ },
2679
2784
  fonts: {
2680
2785
  heading: heading || AI_DEFAULT_BRAND.fonts.heading,
2681
2786
  body: body || AI_DEFAULT_BRAND.fonts.body
2682
2787
  }
2683
2788
  };
2684
2789
  }
2790
+ function deriveTemplateFontsLive() {
2791
+ const heading = readFontVar("--brand-font-heading") || readFontVar("--font-heading") || readFontVar("--font-display");
2792
+ const body = readFontVar("--brand-font-body") || readFontVar("--font-body");
2793
+ if (!heading && !body) return null;
2794
+ return {
2795
+ heading: heading || AI_DEFAULT_BRAND.fonts.heading,
2796
+ body: body || AI_DEFAULT_BRAND.fonts.body
2797
+ };
2798
+ }
2799
+ var OVERRIDE_VAR_NAMES = [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...FONT_VARS.heading, ...FONT_VARS.body];
2800
+ function withOverrideStripped(read) {
2801
+ const root = document.documentElement;
2802
+ const restore = OVERRIDE_VAR_NAMES.map((name) => [name, root.style.getPropertyValue(name)]);
2803
+ for (const name of OVERRIDE_VAR_NAMES) root.style.removeProperty(name);
2804
+ try {
2805
+ return read();
2806
+ } finally {
2807
+ for (const [name, value] of restore) if (value) root.style.setProperty(name, value);
2808
+ }
2809
+ }
2810
+ var TEMPLATE_BRAND_SNAPSHOT = typeof document === "undefined" ? null : withOverrideStripped(deriveTemplateBrandLive);
2811
+ var TEMPLATE_FONTS_SNAPSHOT = typeof document === "undefined" ? null : withOverrideStripped(deriveTemplateFontsLive);
2812
+ function deriveTemplateBrand() {
2813
+ return TEMPLATE_BRAND_SNAPSHOT;
2814
+ }
2815
+ function deriveTemplateFonts() {
2816
+ return TEMPLATE_FONTS_SNAPSHOT;
2817
+ }
2685
2818
  function deriveTemplateButtonStyle() {
2686
2819
  if (typeof document === "undefined") return null;
2687
2820
  const candidates = Array.from(
@@ -7179,12 +7312,12 @@ var cva = (base, config) => (props) => {
7179
7312
  import { Toggle as TogglePrimitive } from "radix-ui";
7180
7313
  import { jsx as jsx5 } from "react/jsx-runtime";
7181
7314
  var toggleVariants = cva(
7182
- "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",
7315
+ "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",
7183
7316
  {
7184
7317
  variants: {
7185
7318
  variant: {
7186
7319
  default: "bg-transparent border-0",
7187
- outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
7320
+ outline: "border border-input bg-transparent shadow-xs hover:bg-bridge-accent hover:text-accent-foreground"
7188
7321
  },
7189
7322
  size: {
7190
7323
  default: "px-2 py-1",
@@ -7277,10 +7410,10 @@ var DragHandle = React4.forwardRef(
7277
7410
  type,
7278
7411
  "data-slot": "drag-handle",
7279
7412
  className: cn(
7280
- "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
7413
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-7.5",
7281
7414
  "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
7282
7415
  "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
7283
- "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
7416
+ "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",
7284
7417
  "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
7285
7418
  className
7286
7419
  ),
@@ -7302,7 +7435,7 @@ var CustomToolbar = React5.forwardRef(({ className, onMouseDown, ...props }, ref
7302
7435
  "data-ohw-toolbar": "",
7303
7436
  className: cn(
7304
7437
  // Figma: bg background, radius 8, gap-1, p-0.5, shadow-md — no border
7305
- "inline-flex h-8 items-center gap-1 rounded-[var(--radius,0.5rem)] bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
7438
+ "inline-flex h-8 items-center gap-1 rounded-(--radius,0.5rem) bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
7306
7439
  className
7307
7440
  ),
7308
7441
  onMouseDown: (e) => {
@@ -7331,7 +7464,7 @@ var CustomToolbarButton = React5.forwardRef(
7331
7464
  type,
7332
7465
  className: cn(
7333
7466
  "inline-flex size-7 shrink-0 items-center justify-center rounded-[calc(var(--radius,0.5rem)-2px)] text-foreground transition-colors",
7334
- active ? "bg-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
7467
+ active ? "bg-bridge-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
7335
7468
  className
7336
7469
  ),
7337
7470
  ...props
@@ -8595,13 +8728,13 @@ function FormFieldToolbar({
8595
8728
  ]
8596
8729
  }
8597
8730
  ) }),
8598
- /* @__PURE__ */ jsx13(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-[190px] p-1", children: FIELD_TYPES.map((entry) => {
8731
+ /* @__PURE__ */ jsx13(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-47.5 p-1", children: FIELD_TYPES.map((entry) => {
8599
8732
  const Icon = TYPE_ICONS[entry.type];
8600
8733
  return /* @__PURE__ */ jsxs6(
8601
8734
  DropdownMenuItem,
8602
8735
  {
8603
8736
  onSelect: () => onTypeChange(entry.type),
8604
- className: "rounded-md py-2 text-[13px] " + (entry.type === type ? "bg-primary/10" : ""),
8737
+ className: "rounded-md py-2 text-[13px] " + (entry.type === type ? "bg-bridge-primary/10" : ""),
8605
8738
  children: [
8606
8739
  /* @__PURE__ */ jsx13(Icon, { size: 14, strokeWidth: 1.75, className: "shrink-0", "aria-hidden": true }),
8607
8740
  entry.label
@@ -8618,7 +8751,7 @@ function FormFieldToolbar({
8618
8751
  type: "button",
8619
8752
  "aria-pressed": required,
8620
8753
  onClick: onRequiredToggle,
8621
- 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"),
8754
+ 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"),
8622
8755
  "data-ohw-field-required-toggle": "",
8623
8756
  children: [
8624
8757
  /* @__PURE__ */ jsx13(Asterisk, { size: 14, strokeWidth: 2, "aria-hidden": true }),
@@ -8638,7 +8771,7 @@ function FormFieldToolbar({
8638
8771
  children: /* @__PURE__ */ jsx13(MoreHorizontal2, { size: 15, "aria-hidden": true })
8639
8772
  }
8640
8773
  ) }),
8641
- /* @__PURE__ */ jsxs6(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-[170px] p-1", children: [
8774
+ /* @__PURE__ */ jsxs6(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-42.5 p-1", children: [
8642
8775
  /* @__PURE__ */ jsxs6(DropdownMenuItem, { onSelect: onDuplicate, className: "rounded-md py-2 text-[13px]", children: [
8643
8776
  /* @__PURE__ */ jsx13(Copy2, { size: 14, strokeWidth: 1.75, className: "shrink-0", "aria-hidden": true }),
8644
8777
  "Duplicate"
@@ -8666,7 +8799,7 @@ function FieldTypePicker({ onPick }) {
8666
8799
  {
8667
8800
  type: "button",
8668
8801
  onClick: () => onPick(entry.type),
8669
- 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",
8802
+ 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",
8670
8803
  children: [
8671
8804
  /* @__PURE__ */ jsx13(Icon, { size: 26, strokeWidth: 1.5, "aria-hidden": true }),
8672
8805
  entry.label
@@ -8692,7 +8825,7 @@ var buttonVariants = cva(
8692
8825
  {
8693
8826
  variants: {
8694
8827
  variant: {
8695
- default: "bg-primary text-primary-foreground hover:opacity-90",
8828
+ default: "bg-bridge-primary text-primary-foreground hover:opacity-90",
8696
8829
  outline: "border border-border bg-background text-foreground shadow-sm hover:bg-muted/80",
8697
8830
  ghost: "min-w-0 px-3 py-2 text-foreground hover:bg-muted/50"
8698
8831
  },
@@ -8765,6 +8898,7 @@ function MediaOverlay({
8765
8898
  fadingOut = false,
8766
8899
  selected = false,
8767
8900
  hovered = false,
8901
+ cueOnly = false,
8768
8902
  onFadeOutComplete,
8769
8903
  onReplace,
8770
8904
  onSelect,
@@ -8773,7 +8907,7 @@ function MediaOverlay({
8773
8907
  const { rect } = hover;
8774
8908
  const skeletonRef = React8.useRef(null);
8775
8909
  const isVideo = hover.elementType === "video";
8776
- const showChrome = !selected || hovered;
8910
+ const showChrome = (!selected || hovered) && !cueOnly;
8777
8911
  const autoplay = hover.videoAutoplay ?? true;
8778
8912
  const muted = hover.videoMuted ?? true;
8779
8913
  const probeRef = React8.useRef(null);
@@ -8889,11 +9023,11 @@ function MediaOverlay({
8889
9023
  // parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
8890
9024
  // in-document, pointer-events does it natively. The button below opts back in, so
8891
9025
  // Replace still works.
8892
- pointerEvents: hover.hasTextOverlap ? "none" : "auto",
9026
+ pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
8893
9027
  // Selected: a firm component ring with no wash, so the image reads as chosen rather
8894
9028
  // than hovered. Hover keeps the existing tinted preview.
8895
- boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
8896
- background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
9029
+ boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
9030
+ background: selected ? "transparent" : "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
8897
9031
  },
8898
9032
  onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
8899
9033
  children: [
@@ -8920,7 +9054,7 @@ function MediaOverlay({
8920
9054
  ]
8921
9055
  }
8922
9056
  ),
8923
- replaceMode === "none" ? null : /* @__PURE__ */ jsxs7(
9057
+ replaceMode === "none" || cueOnly ? null : /* @__PURE__ */ jsxs7(
8924
9058
  Button,
8925
9059
  {
8926
9060
  "data-ohw-media-overlay": "",
@@ -8940,7 +9074,7 @@ function MediaOverlay({
8940
9074
  justifyContent: "center"
8941
9075
  } : null,
8942
9076
  // Don't let Replace steal clicks when text (e.g. nav) sits on top of this media.
8943
- pointerEvents: hover.hasTextOverlap ? "none" : "auto"
9077
+ pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto"
8944
9078
  },
8945
9079
  onMouseDown: (e) => e.preventDefault(),
8946
9080
  onClick: (e) => {
@@ -8970,7 +9104,8 @@ var OVERLAY_BUTTON_STYLE2 = {
8970
9104
  };
8971
9105
  function CarouselOverlay({
8972
9106
  hover,
8973
- onEdit
9107
+ onEdit,
9108
+ cueOnly = false
8974
9109
  }) {
8975
9110
  const { rect } = hover;
8976
9111
  return /* @__PURE__ */ jsx16(
@@ -8986,12 +9121,12 @@ function CarouselOverlay({
8986
9121
  width: rect.width,
8987
9122
  height: rect.height,
8988
9123
  zIndex: 2147483646,
8989
- pointerEvents: "auto",
8990
- boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
8991
- background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
9124
+ pointerEvents: cueOnly ? "none" : "auto",
9125
+ boxShadow: "inset 0 0 0 1.5px var(--color-bridge-primary)",
9126
+ background: "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
8992
9127
  },
8993
9128
  onClick: () => onEdit(hover.key),
8994
- children: /* @__PURE__ */ jsxs8(
9129
+ children: cueOnly ? null : /* @__PURE__ */ jsxs8(
8995
9130
  Button,
8996
9131
  {
8997
9132
  "data-ohw-carousel-overlay": "",
@@ -9182,7 +9317,8 @@ function ReviewButton({
9182
9317
  }
9183
9318
  function AiSectionOverlay({
9184
9319
  postToParent: postToParent2,
9185
- apiRef
9320
+ apiRef,
9321
+ onSelectionChange
9186
9322
  }) {
9187
9323
  const [selectedId, setSelectedId] = useState6(null);
9188
9324
  const [reviewId, setReviewId] = useState6(null);
@@ -9191,6 +9327,9 @@ function AiSectionOverlay({
9191
9327
  reviewIdRef.current = reviewId;
9192
9328
  const selectedIdRef = useRef4(null);
9193
9329
  selectedIdRef.current = selectedId;
9330
+ useEffect4(() => {
9331
+ onSelectionChange?.(selectedId);
9332
+ }, [selectedId, onSelectionChange]);
9194
9333
  const report = useCallback2(
9195
9334
  (el) => {
9196
9335
  const labelSrc = el ? sectionElementOf(el) : null;
@@ -9208,6 +9347,7 @@ function AiSectionOverlay({
9208
9347
  const sectionEl = inner ? movableUnit(inner) : null;
9209
9348
  const id = sectionEl ? instanceIdOf(sectionEl) || null : null;
9210
9349
  if (id === selectedIdRef.current) return;
9350
+ selectedIdRef.current = id;
9211
9351
  setSelectedId(id);
9212
9352
  if (options?.report !== false) report(sectionEl);
9213
9353
  },
@@ -9228,9 +9368,11 @@ function AiSectionOverlay({
9228
9368
  return sectionEl != null;
9229
9369
  },
9230
9370
  clear: () => {
9371
+ selectedIdRef.current = null;
9231
9372
  setSelectedId(null);
9232
9373
  report(null);
9233
- }
9374
+ },
9375
+ getSelectedId: () => selectedIdRef.current
9234
9376
  };
9235
9377
  return () => {
9236
9378
  apiRef.current = null;
@@ -9239,6 +9381,7 @@ function AiSectionOverlay({
9239
9381
  useEffect4(() => {
9240
9382
  const onMessage = (e) => {
9241
9383
  if (e.data?.type === "ow:ai-select" && e.data.sectionId === null) {
9384
+ selectedIdRef.current = null;
9242
9385
  setSelectedId(null);
9243
9386
  return;
9244
9387
  }
@@ -9289,6 +9432,7 @@ function AiSectionOverlay({
9289
9432
  if (reviewIdRef.current) return;
9290
9433
  if (document.querySelector("[data-ohw-editing]")) return;
9291
9434
  if (selectedIdRef.current) {
9435
+ selectedIdRef.current = null;
9292
9436
  setSelectedId(null);
9293
9437
  report(null);
9294
9438
  }
@@ -9910,7 +10054,7 @@ function SectionTreeItem({
9910
10054
  /* @__PURE__ */ jsx20(
9911
10055
  "div",
9912
10056
  {
9913
- className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
10057
+ className: "-mr-px h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
9914
10058
  "aria-hidden": true
9915
10059
  }
9916
10060
  ),
@@ -9929,7 +10073,7 @@ function SectionTreeItem({
9929
10073
  className: cn(
9930
10074
  "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-md border border-border bg-background p-3",
9931
10075
  interactive && "cursor-pointer hover:bg-muted/30",
9932
- interactive && selected && "border-primary"
10076
+ interactive && selected && "border-bridge-primary"
9933
10077
  ),
9934
10078
  children: [
9935
10079
  /* @__PURE__ */ jsx20(
@@ -10059,7 +10203,7 @@ function UrlOrPageInput({
10059
10203
  };
10060
10204
  const fieldClassName = cn(
10061
10205
  "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]",
10062
- urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
10206
+ 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"
10063
10207
  );
10064
10208
  return /* @__PURE__ */ jsxs13("div", { className: "flex w-full flex-col gap-2 p-0", children: [
10065
10209
  /* @__PURE__ */ jsx23(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
@@ -14268,7 +14412,7 @@ function DisplaySwitch({
14268
14412
  onClick: () => onChange(!checked),
14269
14413
  className: cn(
14270
14414
  "relative h-5 w-9 shrink-0 rounded-full transition-colors",
14271
- checked ? "bg-primary" : "bg-primary-50",
14415
+ checked ? "bg-bridge-primary" : "bg-primary-50",
14272
14416
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
14273
14417
  ),
14274
14418
  children: /* @__PURE__ */ jsx28(
@@ -14276,7 +14420,7 @@ function DisplaySwitch({
14276
14420
  {
14277
14421
  className: cn(
14278
14422
  "absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all",
14279
- checked ? "left-[1.125rem]" : "left-0.5"
14423
+ checked ? "left-4.5" : "left-0.5"
14280
14424
  )
14281
14425
  }
14282
14426
  )
@@ -15911,7 +16055,7 @@ var badgeVariants = cva(
15911
16055
  {
15912
16056
  variants: {
15913
16057
  variant: {
15914
- default: "border-transparent bg-primary text-primary-foreground",
16058
+ default: "border-transparent bg-bridge-primary text-primary-foreground",
15915
16059
  secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15916
16060
  destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
15917
16061
  outline: "text-foreground"
@@ -16303,6 +16447,19 @@ function isMediaEditable(el) {
16303
16447
  const t = el.dataset.ohwEditable;
16304
16448
  return t === "image" || t === "bg-image" || t === "video";
16305
16449
  }
16450
+ var FULL_BLEED_MIN_COVERAGE = 0.98;
16451
+ function fullBleedSectionIdOf(media) {
16452
+ const section = media.closest("[data-ohw-section]");
16453
+ if (!section) return null;
16454
+ const s = section.getBoundingClientRect();
16455
+ if (s.width <= 0 || s.height <= 0) return null;
16456
+ const m = media.getBoundingClientRect();
16457
+ const overlapX = Math.min(m.right, s.right) - Math.max(m.left, s.left);
16458
+ const overlapY = Math.min(m.bottom, s.bottom) - Math.max(m.top, s.top);
16459
+ if (overlapX <= 0 || overlapY <= 0) return null;
16460
+ if (overlapX * overlapY / (s.width * s.height) < FULL_BLEED_MIN_COVERAGE) return null;
16461
+ return instanceIdOf(movableUnit(section)) || null;
16462
+ }
16306
16463
  function isIconMarkupValue(value) {
16307
16464
  return /^\s*<(svg|img)\b/i.test(value);
16308
16465
  }
@@ -17476,20 +17633,38 @@ function OhhwellsBridge() {
17476
17633
  const hoveredImageHasTextOverlapRef = useRef10(false);
17477
17634
  const dragOverElRef = useRef10(null);
17478
17635
  const [mediaHover, setMediaHover] = useState14(null);
17636
+ const [selectedAiSectionId, setSelectedAiSectionId] = useState14(null);
17637
+ const selectedAiSectionIdRef = useRef10(null);
17638
+ const handleAiSectionSelectionChange = useCallback8((id) => {
17639
+ selectedAiSectionIdRef.current = id;
17640
+ setSelectedAiSectionId(id);
17641
+ }, []);
17479
17642
  const [selectedMedia, setSelectedMedia] = useState14(null);
17480
17643
  const selectedMediaElRef = useRef10(null);
17644
+ const mediaKeyDropTokenRef = useRef10(0);
17481
17645
  const clearMediaSelection = useCallback8(() => {
17482
17646
  const prev = selectedMediaElRef.current;
17483
17647
  selectedMediaElRef.current = null;
17484
17648
  setSelectedMedia(null);
17485
17649
  const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
17486
17650
  if (sectionEl) {
17487
- postToParentRef.current({
17488
- type: "ow:section-selected",
17489
- sectionId: sectionEl.dataset.ohwSection ?? null,
17490
- sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
17491
- key: null
17492
- });
17651
+ const sectionInstanceId = instanceIdOf(movableUnit(sectionEl)) || null;
17652
+ if (!sectionInstanceId) return;
17653
+ const token = ++mediaKeyDropTokenRef.current;
17654
+ const onQueueDrained = (e) => {
17655
+ if (e.source !== window || e.data?.type !== "ow:media-key-drop" || e.data.token !== token) return;
17656
+ window.removeEventListener("message", onQueueDrained);
17657
+ if (aiSectionApiRef.current?.getSelectedId() !== sectionInstanceId) return;
17658
+ if (selectedMediaElRef.current) return;
17659
+ postToParentRef.current({
17660
+ type: "ow:section-selected",
17661
+ sectionId: sectionEl.dataset.ohwSection ?? null,
17662
+ sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
17663
+ key: null
17664
+ });
17665
+ };
17666
+ window.addEventListener("message", onQueueDrained);
17667
+ window.postMessage({ type: "ow:media-key-drop", token }, "*");
17493
17668
  }
17494
17669
  }, []);
17495
17670
  const clearMediaSelectionRef = useRef10(clearMediaSelection);
@@ -19381,7 +19556,9 @@ function OhhwellsBridge() {
19381
19556
  }, [isEditMode]);
19382
19557
  useEffect13(() => {
19383
19558
  if (isEditMode || fetchState !== "done") return;
19559
+ console.log("env", process.env.NEXT_PUBLIC_FLOWOPS_API_URL);
19384
19560
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
19561
+ console.log({ apiUrl, subdomain });
19385
19562
  bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
19386
19563
  }, [isEditMode, fetchState, subdomain]);
19387
19564
  useEffect13(() => {
@@ -19929,6 +20106,23 @@ function OhhwellsBridge() {
19929
20106
  if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
19930
20107
  clearMediaSelectionRef.current();
19931
20108
  }
20109
+ if (selectedMediaElRef.current && target.closest("[data-ohw-media-overlay]") && !findClosestButtonLike(target)) {
20110
+ const hit = findImageAtPoint(e.clientX, e.clientY, false);
20111
+ if (hit && hit !== selectedMediaElRef.current) {
20112
+ e.preventDefault();
20113
+ e.stopPropagation();
20114
+ const fullBleedSectionId = fullBleedSectionIdOf(hit);
20115
+ if (fullBleedSectionId && fullBleedSectionId !== selectedAiSectionIdRef.current) {
20116
+ clearMediaSelectionRef.current();
20117
+ deselectRef.current();
20118
+ deactivateRef.current();
20119
+ aiSectionApiRef.current?.selectFromElement(hit);
20120
+ return;
20121
+ }
20122
+ selectMediaElementRef.current(hit);
20123
+ return;
20124
+ }
20125
+ }
19932
20126
  if (isInsideFloatingPanel(target)) return;
19933
20127
  if (target.closest("[data-ohw-form-toolbar]")) return;
19934
20128
  if (target.closest(
@@ -20110,6 +20304,14 @@ function OhhwellsBridge() {
20110
20304
  if (isMediaEditable(editable) && !buttonOnMedia) {
20111
20305
  e.preventDefault();
20112
20306
  e.stopPropagation();
20307
+ const fullBleedSectionId = fullBleedSectionIdOf(editable);
20308
+ if (fullBleedSectionId && fullBleedSectionId !== selectedAiSectionIdRef.current) {
20309
+ clearMediaSelectionRef.current();
20310
+ deselectRef.current();
20311
+ deactivateRef.current();
20312
+ aiSectionApiRef.current?.selectFromElement(editable);
20313
+ return;
20314
+ }
20113
20315
  if (selectedMediaElRef.current === editable) {
20114
20316
  postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
20115
20317
  } else {
@@ -20564,6 +20766,7 @@ function OhhwellsBridge() {
20564
20766
  elementType: imgEl.dataset.ohwEditable ?? "image",
20565
20767
  hasTextOverlap,
20566
20768
  isDragOver,
20769
+ fullBleedSectionId: fullBleedSectionIdOf(imgEl),
20567
20770
  ...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
20568
20771
  });
20569
20772
  const track = imgEl.closest("[data-ohw-hover-pause]");
@@ -20736,7 +20939,13 @@ function OhhwellsBridge() {
20736
20939
  setHoveredItemRect(null);
20737
20940
  }
20738
20941
  };
20942
+ const syncSelectedMediaPointerRelease = (released) => {
20943
+ setSelectedMedia(
20944
+ (prev) => prev && prev.hasTextOverlap !== released ? { ...prev, hasTextOverlap: released } : prev
20945
+ );
20946
+ };
20739
20947
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
20948
+ syncSelectedMediaPointerRelease(true);
20740
20949
  if (linkPopoverOpenRef.current) {
20741
20950
  if (hoveredImageRef.current) {
20742
20951
  hoveredImageRef.current = null;
@@ -20931,6 +21140,7 @@ function OhhwellsBridge() {
20931
21140
  return;
20932
21141
  }
20933
21142
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
21143
+ syncSelectedMediaPointerRelease(false);
20934
21144
  if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
20935
21145
  hoveredImageRef.current = imgEl;
20936
21146
  showImageHover(imgEl, isDragOver);
@@ -21731,10 +21941,26 @@ function OhhwellsBridge() {
21731
21941
  const handleGetBrand = (e) => {
21732
21942
  if (e.data?.type !== "ow:get-brand") return;
21733
21943
  const template = deriveTemplateBrand();
21734
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
21944
+ const fallback = template ?? (() => {
21945
+ const fonts = deriveTemplateFonts();
21946
+ return fonts ? { palette: AI_DEFAULT_BRAND.palette, fonts } : null;
21947
+ })();
21948
+ const value = brandKitRef.current || (fallback ? JSON.stringify(fallback) : "");
21735
21949
  postToParentRef.current({ type: "ow:brand-value", value });
21736
21950
  };
21737
21951
  window.addEventListener("message", handleGetBrand);
21952
+ const handleGetTemplateFonts = (e) => {
21953
+ if (e.data?.type !== "ow:get-template-fonts") return;
21954
+ const fonts = deriveTemplateFonts();
21955
+ postToParentRef.current({ type: "ow:template-fonts-value", value: fonts ? JSON.stringify(fonts) : "" });
21956
+ };
21957
+ window.addEventListener("message", handleGetTemplateFonts);
21958
+ const handleGetTemplateBrand = (e) => {
21959
+ if (e.data?.type !== "ow:get-template-brand") return;
21960
+ const brand = deriveTemplateBrand();
21961
+ postToParentRef.current({ type: "ow:template-brand-value", value: brand ? JSON.stringify(brand) : "" });
21962
+ };
21963
+ window.addEventListener("message", handleGetTemplateBrand);
21738
21964
  const handleMoveSection = (e) => {
21739
21965
  if (e.data?.type !== "ow:move-section") return;
21740
21966
  const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
@@ -22388,7 +22614,11 @@ function OhhwellsBridge() {
22388
22614
  if (!key) return;
22389
22615
  const r2 = getVisibleRect(container);
22390
22616
  setCarouselHover(
22391
- (prev) => prev && prev.key === key && prev.rect.top === r2.top && prev.rect.left === r2.left && prev.rect.width === r2.width && prev.rect.height === r2.height ? prev : { key, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } }
22617
+ (prev) => prev && prev.key === key && prev.rect.top === r2.top && prev.rect.left === r2.left && prev.rect.width === r2.width && prev.rect.height === r2.height ? prev : {
22618
+ key,
22619
+ rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
22620
+ fullBleedSectionId: fullBleedSectionIdOf(container)
22621
+ }
22392
22622
  );
22393
22623
  };
22394
22624
  const applyToolbarPos = (rect) => {
@@ -22637,6 +22867,8 @@ function OhhwellsBridge() {
22637
22867
  window.removeEventListener("message", handleAiSetBrand);
22638
22868
  window.removeEventListener("message", handleAiSetStyles);
22639
22869
  window.removeEventListener("message", handleGetBrand);
22870
+ window.removeEventListener("message", handleGetTemplateFonts);
22871
+ window.removeEventListener("message", handleGetTemplateBrand);
22640
22872
  window.removeEventListener("message", handleMoveSection);
22641
22873
  window.removeEventListener("message", handlePanelDragging);
22642
22874
  window.removeEventListener("message", handleDeleteSection);
@@ -22848,7 +23080,7 @@ function OhhwellsBridge() {
22848
23080
  postToParent2({
22849
23081
  type: "ow:ready",
22850
23082
  version: "1",
22851
- bridgeVersion: "0.1.114",
23083
+ bridgeVersion: "0.1.116",
22852
23084
  path: pathname,
22853
23085
  nodes: collectEditableNodes(editContentRef.current),
22854
23086
  sections
@@ -23315,7 +23547,14 @@ function OhhwellsBridge() {
23315
23547
  bridgeRoot ? createPortal3(
23316
23548
  /* @__PURE__ */ jsxs20(Fragment8, { children: [
23317
23549
  /* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
23318
- isEditMode && /* @__PURE__ */ jsx33(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
23550
+ isEditMode && /* @__PURE__ */ jsx33(
23551
+ AiSectionOverlay,
23552
+ {
23553
+ postToParent: postToParent2,
23554
+ apiRef: aiSectionApiRef,
23555
+ onSelectionChange: handleAiSectionSelectionChange
23556
+ }
23557
+ ),
23319
23558
  isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
23320
23559
  "div",
23321
23560
  {
@@ -23348,6 +23587,7 @@ function OhhwellsBridge() {
23348
23587
  {
23349
23588
  hover: mediaHover,
23350
23589
  isUploading: false,
23590
+ cueOnly: !mediaHover.isDragOver && !!mediaHover.fullBleedSectionId && mediaHover.fullBleedSectionId !== selectedAiSectionId,
23351
23591
  onReplace: handleMediaReplace,
23352
23592
  onSelect: handleMediaSelect,
23353
23593
  onVideoSettingsChange: handleVideoSettingsChange
@@ -23365,7 +23605,14 @@ function OhhwellsBridge() {
23365
23605
  onVideoSettingsChange: handleVideoSettingsChange
23366
23606
  }
23367
23607
  ),
23368
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
23608
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(
23609
+ CarouselOverlay,
23610
+ {
23611
+ hover: carouselHover,
23612
+ onEdit: handleEditCarousel,
23613
+ cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
23614
+ }
23615
+ ),
23369
23616
  siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
23370
23617
  siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
23371
23618
  isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
@@ -23464,7 +23711,7 @@ function OhhwellsBridge() {
23464
23711
  "span",
23465
23712
  {
23466
23713
  "data-ohw-form-count": "",
23467
- 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",
23714
+ 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",
23468
23715
  children: formPickCount
23469
23716
  }
23470
23717
  )
@@ -23702,11 +23949,11 @@ function OhhwellsBridge() {
23702
23949
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
23703
23950
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
23704
23951
  children: [
23705
- /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
23952
+ /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
23706
23953
  /* @__PURE__ */ jsx33(
23707
23954
  Badge,
23708
23955
  {
23709
- 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",
23956
+ 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",
23710
23957
  onClick: () => {
23711
23958
  window.parent.postMessage(
23712
23959
  {
@@ -23720,7 +23967,7 @@ function OhhwellsBridge() {
23720
23967
  children: "Add Section"
23721
23968
  }
23722
23969
  ),
23723
- /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
23970
+ /* @__PURE__ */ jsx33("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
23724
23971
  ]
23725
23972
  }
23726
23973
  ),