// Widget States, single big stage: real hotel website + animated bubble +
// dim overlay + picker pop, then forks into Personalized vs Direct call paths.

const { useState: useStateW, useEffect: useEffectW, useRef: useRefW } = React;

const W_PAPER   = "#fbfaf6";
const W_CREAM   = "#f6f4ef";
const W_INK     = "#1a1a1a";
const W_MUTED   = "#6b6358";
const W_RULE    = "rgba(0,0,0,0.10)";
const W_FUCHSIA = "#ED4D86";
const W_FUCHSIA_DEEP = "#B8336A";
const W_GOLD    = "#C9A24A";

// ───────────────────────────────────────────────────────────
//  Equalizer / wave-bar icon, the brand widget mark
//  Looping vertical bars, like an audio level meter
// ───────────────────────────────────────────────────────────
function BubbleIcon({ size = 22, color = "#fff", time = 0 }) {
  // 5 bars, each phased to create a smooth left-to-right wave loop
  const bars = [0, 1, 2, 3, 4].map(i => {
    // Two overlapping sines for richer motion
    const phase = time * 3.4 - i * 0.55;
    const a = (Math.sin(phase) + 1) / 2;            // 0..1
    const b = (Math.sin(phase * 1.7 + 0.4) + 1) / 2; // 0..1
    const m = a * 0.65 + b * 0.35;                   // 0..1
    // Map to 22%..100% of full height so the shortest bar is still visible
    const h = 0.22 + m * 0.78;
    return h;
  });

  const W = 22;       // viewBox width
  const H = 22;       // viewBox height
  const barW = 2.8;
  const gap = 1.6;
  const totalW = bars.length * barW + (bars.length - 1) * gap;
  const startX = (W - totalW) / 2;
  const cy = H / 2;
  const maxBar = H * 0.72;

  return (
    <svg width={size} height={size} viewBox={`0 0 ${W} ${H}`} fill="none">
      {bars.map((h, i) => {
        const bh = maxBar * h;
        const x = startX + i * (barW + gap);
        const y = cy - bh / 2;
        return (
          <rect key={i}
            x={x} y={y} width={barW} height={bh}
            rx={barW / 2} ry={barW / 2}
            fill={color} />
        );
      })}
    </svg>
  );
}

// ───────────────────────────────────────────────────────────
//  Driver hook
// ───────────────────────────────────────────────────────────
function useStageTime(duration, paused) {
  const [t, setT] = useStateW(0);
  const last = useRefW(performance.now());
  useEffectW(() => {
    if (paused) return;
    let raf;
    const tick = (now) => {
      const dt = (now - last.current) / 1000;
      last.current = now;
      setT(prev => (prev + dt) % duration);
      raf = requestAnimationFrame(tick);
    };
    last.current = performance.now();
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [duration, paused]);
  const reset = () => setT(0);
  return [t, reset];
}

// ───────────────────────────────────────────────────────────
//  Aurea Hotels hero, exact recreation as live site behind bubble
// ───────────────────────────────────────────────────────────
function AureaSite() {
  return (
    <div style={{
      position: "absolute", inset: 0, overflow: "hidden",
    }}>
      {/* hero image as actual background */}
      <img
        src="/marketing/voice-widget/aurea-hero.png"
        alt=""
        style={{
          position: "absolute", inset: 0,
          width: "100%", height: "100%", objectFit: "cover",
          objectPosition: "center center",
        }}
      />
    </div>
  );
}

// ───────────────────────────────────────────────────────────
//  Bubble mark with hover label
// ───────────────────────────────────────────────────────────
// Bubble is anchored to the bottom-right corner. Pill grows LEFTWARD on hover
// so the label appears to the left of the icon and never clips the stage.
function FloatingBubble({ time, hovered, opening, rightPx, bottomPx }) {
  const breathe = 1 + Math.sin(time * 1.6) * 0.035;

  const ripples = [0, 1, 2].map(i => {
    const phase = ((time * 0.55 + i * 0.33) % 1);
    return { r: 30 + phase * 60, opacity: (1 - phase) * 0.55 };
  });

  return (
    <div style={{
      position: "absolute",
      right: rightPx, bottom: bottomPx,
      transform: `scale(${opening ? 0.55 : 1})`,
      transformOrigin: "calc(100% - 28px) calc(100% - 28px)", // collapse toward icon centre
      transition: "transform 360ms cubic-bezier(.2,.8,.2,1), opacity 360ms",
      opacity: opening ? 0 : 1,
      pointerEvents: "none",
      zIndex: 60,
    }}>
      {/* sonar rings - centred on the icon (right side) */}
      <svg width="200" height="200" style={{
        position: "absolute", right: -72, bottom: -72, pointerEvents: "none",
      }}>
        {ripples.map((r, i) => (
          <circle key={i} cx="100" cy="100" r={r.r}
            fill="none" stroke={W_FUCHSIA}
            strokeWidth={1.4} opacity={r.opacity * 0.55} />
        ))}
      </svg>

      {/* halo removed - keeping the design strictly 2D */}

      {/* the pill */}
      <div style={{
        position: "relative",
        height: 56,
        borderRadius: 999,
        background: W_FUCHSIA,
        boxShadow: "none",
        display: "flex", alignItems: "center",
        transform: `scale(${breathe})`,
        transformOrigin: "right center",
        transition: "transform 0.08s linear",
        overflow: "hidden",
      }}>
        {/* label on the LEFT, slides out from behind the icon */}
        <div style={{
          display: "flex", flexDirection: "column", justifyContent: "center",
          color: "#fff",
          maxWidth: hovered ? 220 : 0,
          opacity: hovered ? 1 : 0,
          paddingLeft: hovered ? 20 : 0,
          paddingRight: hovered ? 4 : 0,
          overflow: "hidden",
          transition:
            "max-width 380ms cubic-bezier(.2,.8,.2,1), padding 380ms cubic-bezier(.2,.8,.2,1), opacity 240ms ease",
          whiteSpace: "nowrap",
        }}>
          <span style={{
            fontFamily: "Inter", fontSize: 15, fontWeight: 700,
            letterSpacing: "-0.005em", lineHeight: 1.1,
          }}>Talk to us</span>
          <span style={{
            fontFamily: "Inter", fontSize: 11.5, fontWeight: 400,
            opacity: 0.92, marginTop: 2, lineHeight: 1.15,
          }}>Speak instantly with our AI agent</span>
        </div>

        {/* icon stays in a fixed circle on the right */}
        <div style={{
          width: 56, height: 56, borderRadius: "50%",
          display: "flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0,
        }}>
          <BubbleIcon size={26} time={time} color="#fff" />
        </div>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────
//  Picker modal, opens centred over dimmed site
// ───────────────────────────────────────────────────────────
function PickerModal({ visible, highlightedIdx, clickedIdx }) {
  const opts = [
    {
      key: "rec",
      title: "Personalized assistance",
      sub: "Share your trip. The agent calls you back with tailored options.",
      pill: "Recommended",
      icon: (
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none"
          stroke="#fff" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
          <path d="M12 2l2.4 5.4L20 8.2l-4 3.9.9 5.6L12 15l-4.9 2.7.9-5.6-4-3.9 5.6-.8z" />
        </svg>
      ),
    },
    {
      key: "now",
      title: "Call now",
      sub: "Speak to the concierge in seconds. Direct line to availability.",
      pill: "Direct",
      icon: (
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none"
          stroke="#fff" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
          <path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6 19.8 19.8 0 0 1-3.1-8.7A2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7 12.8 12.8 0 0 0 .7 2.8 2 2 0 0 1-.4 2.1L8 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4 12.8 12.8 0 0 0 2.8.7 2 2 0 0 1 1.7 2z" />
        </svg>
      ),
    },
  ];

  return (
    <div style={{
      position: "absolute", inset: 0, zIndex: 70,
      display: "flex", alignItems: "center", justifyContent: "center",
      pointerEvents: "none",
      opacity: visible ? 1 : 0,
      transition: "opacity 320ms ease",
    }}>
      <div style={{
        width: 460, maxWidth: "100%", boxSizing: "border-box",
        background: "#fff", borderRadius: 22,
        padding: 28,
        transform: visible ? "translateY(0) scale(1)" : "translateY(16px) scale(0.97)",
        transition: "transform 360ms cubic-bezier(.2,.8,.2,1)",
        boxShadow: "0 1px 0 rgba(0,0,0,0.04)",
      }}>
        {/* header */}
        <div style={{
          display: "flex", alignItems: "center", gap: 12, marginBottom: 18,
        }}>
          <div style={{
            width: 38, height: 38, borderRadius: "50%",
            background: W_FUCHSIA,
            display: "flex", alignItems: "center", justifyContent: "center",
            boxShadow: "none",
          }}>
            <BubbleIcon size={20} />
          </div>
          <div style={{ flex: 1 }}>
            <div style={{
              fontFamily: "'Instrument Serif', 'Source Serif 4', serif",
              fontSize: 17, fontWeight: 400, color: W_INK,
              letterSpacing: "-0.01em",
            }}>How can we help?</div>
            <div style={{ fontSize: 11.5, color: W_MUTED, marginTop: 2 }}>
              Reply in seconds, never bots
            </div>
          </div>
        </div>

        {/* options */}
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {opts.map((o, i) => {
            const isHighlighted = highlightedIdx === i;
            const isClicked = clickedIdx === i;
            return (
              <div key={o.key} style={{
                display: "flex", alignItems: "center", gap: 14,
                padding: "14px 16px",
                borderRadius: 14,
                border: `1.5px solid ${isHighlighted ? W_FUCHSIA : W_RULE}`,
                background: isHighlighted ? `${W_FUCHSIA}10` : "#fff",
                transform: isClicked ? "scale(0.97)" : "scale(1)",
                boxShadow: isHighlighted ? `0 0 0 4px ${W_FUCHSIA}22` : "none",
                transition: "all 180ms cubic-bezier(.2,.8,.2,1)",
                position: "relative",
              }}>
                <div style={{
                  width: 38, height: 38, borderRadius: 11, flexShrink: 0,
                  background: isHighlighted ? W_FUCHSIA : "#1a1a1a",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  transition: "background 180ms",
                }}>{o.icon}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{
                    display: "flex", alignItems: "center", gap: 8,
                    fontFamily: "Inter", fontSize: 14, fontWeight: 600,
                    color: W_INK, marginBottom: 2,
                  }}>
                    {o.title}
                    <span style={{
                      fontFamily: "'JetBrains Mono', monospace",
                      fontSize: 9, fontWeight: 600, letterSpacing: "0.06em",
                      padding: "2px 7px", borderRadius: 4,
                      background: isHighlighted ? W_FUCHSIA : "#f0ece4",
                      color: isHighlighted ? "#fff" : W_MUTED,
                      transition: "all 180ms",
                    }}>{o.pill.toUpperCase()}</span>
                  </div>
                  <div style={{ fontSize: 12, color: W_MUTED, lineHeight: 1.4 }}>
                    {o.sub}
                  </div>
                </div>
                {/* arrow */}
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
                  stroke={isHighlighted ? W_FUCHSIA : W_MUTED}
                  strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
                  style={{ transition: "stroke 180ms" }}>
                  <path d="M9 18l6-6-6-6" />
                </svg>

                {/* click pulse */}
                {isClicked && (
                  <div style={{
                    position: "absolute", inset: 0, borderRadius: 14,
                    border: `2px solid ${W_FUCHSIA}`,
                    animation: "wb-click-ring .55s ease-out forwards",
                    pointerEvents: "none",
                  }} />
                )}
              </div>
            );
          })}
        </div>

        <div style={{
          marginTop: 18, display: "flex", alignItems: "center", gap: 6,
          fontFamily: "'JetBrains Mono', monospace",
          fontSize: 10, color: W_MUTED, letterSpacing: "0.04em",
        }}>
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none"
            stroke={W_MUTED} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
            <rect x="4" y="11" width="16" height="10" rx="2" />
            <path d="M8 11V7a4 4 0 0 1 8 0v4" />
          </svg>
          END-TO-END ENCRYPTED · POWERED BY GUESTMAKER
        </div>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────
//  Lead form (Personalized path)
// ───────────────────────────────────────────────────────────
function LeadForm({ visible, fillProgress, submitted }) {
  const fields = [
    { label: "Full name",    val: "Sarah Chen",                placeholder: "Your name" },
    { label: "Email",        val: "sarah.chen@studio.co.uk",   placeholder: "name@example.com" },
    { label: "Phone",        val: "+44 7700 900 184",          placeholder: "+44…" },
    { label: "Party",        val: "2 adults · 1 child",        placeholder: "Guests" },
    { label: "Best time",    val: "Today · 18:00–19:00 BST",   placeholder: "Window" },
  ];

  // Reveal each field as fillProgress crosses thresholds
  return (
    <div style={{
      position: "absolute", inset: 0, zIndex: 70,
      display: "flex", alignItems: "center", justifyContent: "center",
      pointerEvents: "none",
      opacity: visible ? 1 : 0,
      transition: "opacity 320ms ease",
    }}>
      <div style={{
        width: 480, background: "#fff", borderRadius: 22,
        padding: 28,
        transform: visible ? "translateY(0)" : "translateY(16px)",
        transition: "transform 360ms cubic-bezier(.2,.8,.2,1)",
        boxShadow: "0 1px 0 rgba(0,0,0,0.04)",
      }}>
        <div style={{
          display: "flex", alignItems: "center", gap: 12, marginBottom: 18,
        }}>
          <div style={{
            width: 38, height: 38, borderRadius: "50%",
            background: W_FUCHSIA,
            display: "flex", alignItems: "center", justifyContent: "center",
            boxShadow: "none",
          }}><BubbleIcon size={20} /></div>
          <div style={{ flex: 1 }}>
            <div style={{
              fontFamily: "'Instrument Serif', 'Source Serif 4', serif", fontSize: 17, fontWeight: 400,
              fontStyle: "italic", color: W_FUCHSIA,
            }}>Tell us about your stay</div>
            <div style={{ fontSize: 11.5, color: W_MUTED, marginTop: 2 }}>
              The agent calls you back within minutes
            </div>
          </div>
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {fields.map((f, i) => {
            const start = i / fields.length;
            const local = Math.max(0, Math.min(1, (fillProgress - start) * fields.length));
            const charsShown = Math.floor(f.val.length * local);
            const text = f.val.slice(0, charsShown);
            const showCursor = local > 0 && local < 1;
            return (
              <div key={f.label} style={{
                display: "flex", flexDirection: "column", gap: 4,
              }}>
                <span style={{
                  fontFamily: "'JetBrains Mono', monospace",
                  fontSize: 9.5, color: W_MUTED, letterSpacing: "0.08em",
                }}>{f.label.toUpperCase()}</span>
                <div style={{
                  height: 38, padding: "0 14px",
                  border: `1.5px solid ${local > 0 ? W_FUCHSIA + "55" : W_RULE}`,
                  background: local > 0 ? "#fff" : W_PAPER,
                  borderRadius: 10,
                  display: "flex", alignItems: "center",
                  fontFamily: "Inter", fontSize: 13.5,
                  color: text ? W_INK : "#aaa",
                  transition: "border 180ms, background 180ms",
                }}>
                  {text || f.placeholder}
                  {showCursor && (
                    <span style={{
                      width: 1.5, height: 16, background: W_FUCHSIA,
                      marginLeft: 1, animation: "wb-blink 0.7s steps(1) infinite",
                    }} />
                  )}
                </div>
              </div>
            );
          })}
        </div>

        {/* Submit button */}
        <div style={{
          marginTop: 16,
          display: "flex", alignItems: "center", justifyContent: "space-between",
        }}>
          <div style={{
            fontFamily: "'JetBrains Mono', monospace",
            fontSize: 10, color: W_MUTED, letterSpacing: "0.04em",
          }}>STEP 1 OF 1</div>
          <button style={{
            border: "none", padding: "11px 24px", borderRadius: 10,
            background: submitted ? W_FUCHSIA_DEEP : W_FUCHSIA,
            color: "#fff",
            fontFamily: "Inter", fontSize: 13, fontWeight: 600,
            boxShadow: "none",
            transition: "all 280ms",
            display: "flex", alignItems: "center", gap: 8,
          }}>
            {submitted ? (
              <>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
                  stroke="#fff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M5 12l5 5L20 7" />
                </svg>
                Submitted
              </>
            ) : (
              <>Request callback
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
                  stroke="#fff" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M5 12h14M13 6l6 6-6 6" />
                </svg>
              </>
            )}
          </button>
        </div>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────
//  Live call panel (both paths converge here)
// ───────────────────────────────────────────────────────────
function CallPanel({ visible, time, callStartT }) {
  const elapsed = Math.max(0, time - callStartT);
  const mm = Math.floor(elapsed / 60).toString().padStart(2, "0");
  const ss = Math.floor(elapsed % 60).toString().padStart(2, "0");

  // pre-scripted turns offset from callStart
  const turns = [
    { t: 0.6,  who: "agent", text: "Good evening, Aurea concierge." },
    { t: 4.2,  who: "agent", text: "How can I make your stay extraordinary?" },
    { t: 8.0,  who: "guest", text: "We're thinking late September, Mediterranean, two adults plus our daughter." },
    { t: 14.5, who: "agent", text: "Wonderful. Costa Smeralda or Mykonos suits a family of three beautifully." },
    { t: 20.8, who: "agent", text: "Our Cliffside Suite at Aurea Mykonos has direct sea access, and a private plunge pool." },
    { t: 27.4, who: "guest", text: "Mykonos sounds lovely. Could you check rates for the 22nd?" },
  ];

  // Reveal turns up to elapsed; show last 3
  const visibleTurns = turns.filter(tt => elapsed > tt.t).slice(-3);

  // pulse rings
  const rings = [0, 1, 2, 3].map(i => {
    const phase = ((elapsed * 0.55 + i * 0.25) % 1);
    return { r: 70 + phase * 100, opacity: (1 - phase) * 0.5 };
  });

  // waveform bars — all fuchsia, varying intensity. Recomputed every RAF
  // tick from `elapsed`. Two-oscillator mix so the wave reads as flowing
  // left-to-right rather than just pulsing.
  const bars = Array.from({ length: 28 }).map((_, i) => {
    const swap = Math.floor(elapsed / 4) % 2 === 0;
    // fast travelling wave + slower per-bar bias = liquid motion
    const h = 6 + Math.abs(Math.sin(elapsed * 7.2 - i * 0.55)) * 26
                + Math.abs(Math.sin(elapsed * 2.3 + i * 0.18)) * 8;
    return { h, color: swap ? W_FUCHSIA : W_FUCHSIA_DEEP };
  });

  return (
    <div style={{
      position: "absolute", inset: 0, zIndex: 70,
      display: "flex", alignItems: "center", justifyContent: "center",
      pointerEvents: "none",
      opacity: visible ? 1 : 0,
      transition: "opacity 320ms ease",
    }}>
      <div style={{
        width: 540, background: "#fff", borderRadius: 22,
        padding: "26px 28px 22px",
        transform: visible ? "translateY(0)" : "translateY(16px)",
        transition: "transform 360ms cubic-bezier(.2,.8,.2,1)",
        boxShadow: "0 1px 0 rgba(0,0,0,0.04)",
      }}>
        {/* header */}
        <div style={{
          display: "flex", alignItems: "center", gap: 12, marginBottom: 16,
        }}>
          <div style={{
            display: "flex", alignItems: "center", gap: 6,
            padding: "5px 10px", borderRadius: 999,
            background: `${W_FUCHSIA}15`,
          }}>
            <span style={{
              width: 7, height: 7, borderRadius: "50%", background: W_FUCHSIA,
              animation: "wb-pulse 1.2s ease-in-out infinite",
            }} />
            <span style={{
              fontFamily: "'JetBrains Mono', monospace",
              fontSize: 10, color: W_FUCHSIA, fontWeight: 600, letterSpacing: "0.08em",
            }}>LIVE · {mm}:{ss}</span>
          </div>
          <div style={{ flex: 1 }} />
          <span style={{
            fontFamily: "'JetBrains Mono', monospace",
            fontSize: 10, color: W_MUTED, letterSpacing: "0.06em",
          }}>AUREA HOTELS</span>
        </div>

        {/* Pulse + bubble */}
        <div style={{
          position: "relative", height: 200,
          display: "flex", alignItems: "center", justifyContent: "center",
          marginBottom: 12,
        }}>
          <svg width="220" height="200" style={{ position: "absolute" }}>
            {rings.map((r, i) => (
              <circle key={i} cx="110" cy="100" r={r.r}
                fill="none" stroke={W_FUCHSIA} strokeWidth="1.4"
                opacity={r.opacity} />
            ))}
          </svg>
          <div style={{
            position: "absolute",
            width: 76, height: 76, borderRadius: "50%",
            background: W_FUCHSIA,
            boxShadow: "none",
            display: "flex", alignItems: "center", justifyContent: "center",
            animation: "wb-breathe 2.4s ease-in-out infinite",
          }}>
            <BubbleIcon size={36} time={elapsed} />
          </div>
        </div>

        {/* waveform */}
        <div style={{
          display: "flex", alignItems: "center", justifyContent: "center",
          gap: 3, height: 36, marginBottom: 14,
        }}>
          {bars.map((b, i) => (
            <span key={i} style={{
              width: 3, height: b.h, background: b.color,
              borderRadius: 2, opacity: 0.78,
              /* No transition — bars snap to each frame's target height so
                 the wave reads as moving instead of averaging out. */
            }} />
          ))}
        </div>

        {/* captions */}
        <div style={{
          padding: "12px 14px",
          background: W_PAPER, borderRadius: 12,
          minHeight: 96, maxHeight: 96, overflow: "hidden",
          display: "flex", flexDirection: "column", gap: 6, justifyContent: "flex-end",
        }}>
          {visibleTurns.map((tt, i) => (
            <div key={`${tt.t}-${i}`} style={{
              display: "flex", alignItems: "flex-start", gap: 8,
              animation: "wb-slide-up .35s ease both",
            }}>
              <span style={{
                fontFamily: "'JetBrains Mono', monospace",
                fontSize: 9, color: tt.who === "agent" ? W_FUCHSIA : W_MUTED,
                fontWeight: 600, letterSpacing: "0.08em",
                marginTop: 3, minWidth: 42,
              }}>{tt.who === "agent" ? "AGENT" : "GUEST"}</span>
              <span style={{
                fontFamily: "Inter", fontSize: 13, color: W_INK, lineHeight: 1.45,
                flex: 1,
              }}>{tt.text}</span>
            </div>
          ))}
        </div>

        {/* controls */}
        <div style={{
          display: "flex", alignItems: "center", justifyContent: "center", gap: 12,
          marginTop: 14,
        }}>
          {[
            { kind: "mic", active: true },
            { kind: "pause" },
            { kind: "end", danger: true },
          ].map((c, i) => (
            <div key={i} style={{
              width: 42, height: 42, borderRadius: "50%",
              background: c.danger ? "#d33655" : (c.active ? `${W_FUCHSIA}15` : W_PAPER),
              border: `1px solid ${c.danger ? "#d33655" : W_RULE}`,
              display: "flex", alignItems: "center", justifyContent: "center",
              boxShadow: "none",
            }}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
                stroke={c.danger ? "#fff" : (c.active ? W_FUCHSIA : W_INK)}
                strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                {c.kind === "mic" && (<>
                  <rect x="9" y="3" width="6" height="11" rx="3" />
                  <path d="M5 11a7 7 0 0 0 14 0M12 18v3" />
                </>)}
                {c.kind === "pause" && (<>
                  <rect x="6" y="5" width="4" height="14" />
                  <rect x="14" y="5" width="4" height="14" />
                </>)}
                {c.kind === "end" && (<>
                  <path d="M2 12a10 10 0 0 1 20 0" />
                  <path d="M5 14l3-2 1-3 6 0 1 3 3 2" />
                </>)}
              </svg>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────
//  Phase track at the bottom of the stage
// ───────────────────────────────────────────────────────────
function PhaseTrack({ steps, activeIdx }) {
  return (
    <div style={{
      position: "absolute", left: 0, right: 0, bottom: 0,
      padding: "16px 22px",
      borderTop: `1px solid ${W_RULE}`,
      background: "rgba(255,255,255,0.96)",
      backdropFilter: "blur(8px)",
      display: "flex", alignItems: "center", gap: 14,
      zIndex: 90,
    }}>
      {steps.map((s, i) => (
        <div key={s.label} style={{
          display: "flex", alignItems: "center", gap: 10,
          flex: 1,
        }}>
          <div style={{
            width: 26, height: 26, borderRadius: "50%",
            background: i <= activeIdx ? W_FUCHSIA : "#fff",
            border: i <= activeIdx ? `1.5px solid ${W_FUCHSIA}` : `1.5px solid ${W_RULE}`,
            color: i <= activeIdx ? "#fff" : W_MUTED,
            display: "flex", alignItems: "center", justifyContent: "center",
            fontFamily: "'JetBrains Mono', monospace",
            fontSize: 11, fontWeight: 600,
            transition: "all 280ms",
            boxShadow: i === activeIdx ? `0 0 0 4px ${W_FUCHSIA}30` : "none",
          }}>
            {i < activeIdx ? (
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none"
                stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
                <path d="M5 12l5 5L20 7" />
              </svg>
            ) : (i + 1)}
          </div>
          <div style={{ flex: 1 }}>
            <div style={{
              fontFamily: "Inter", fontSize: 12, fontWeight: 600,
              color: i <= activeIdx ? W_INK : W_MUTED,
              transition: "color 280ms",
            }}>{s.label}</div>
            <div style={{
              fontSize: 10.5, color: W_MUTED, marginTop: 1,
            }}>{s.sub}</div>
          </div>
          {i < steps.length - 1 && (
            <div style={{
              flex: 1, height: 1.5, background: i < activeIdx ? W_FUCHSIA : W_RULE,
              maxWidth: 40,
              transition: "background 280ms",
            }} />
          )}
        </div>
      ))}
    </div>
  );
}

// ───────────────────────────────────────────────────────────
//  Persistent "or call us" chip - top left of the stage
// ───────────────────────────────────────────────────────────
function CallUsChip({ time }) {
  const pulse = 0.5 + Math.abs(Math.sin(time * 1.4)) * 0.5;
  return (
    <div style={{
      position: "absolute", top: 22, left: 22, zIndex: 95,
      display: "flex", alignItems: "stretch", gap: 0,
      padding: 0, borderRadius: 14,
      background: "rgba(255,255,255,0.96)",
      boxShadow: "0 1px 0 rgba(0,0,0,0.04)",
      overflow: "hidden",
    }}>
      {/* fuchsia rail with breathing dot */}
      <div style={{
        width: 44, padding: "10px 0",
        display: "flex", flexDirection: "column",
        alignItems: "center", justifyContent: "center",
        background: W_FUCHSIA,
        position: "relative",
      }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none"
          stroke="#fff" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6 19.8 19.8 0 0 1-3.1-8.7A2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7 12.8 12.8 0 0 0 .7 2.8 2 2 0 0 1-.4 2.1L8 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4 12.8 12.8 0 0 0 2.8.7 2 2 0 0 1 1.7 2z" />
        </svg>
        {/* live dot */}
        <span style={{
          position: "absolute", top: 6, right: 6,
          width: 6, height: 6, borderRadius: "50%",
          background: "#fff",
          opacity: pulse,
          boxShadow: "none",
        }} />
      </div>

      {/* content */}
      <div style={{
        padding: "9px 16px 9px 14px",
        display: "flex", flexDirection: "column", justifyContent: "center",
        minWidth: 200,
      }}>
        <div style={{
          display: "flex", alignItems: "center", gap: 8,
          fontFamily: "'JetBrains Mono', monospace",
          fontSize: 9.5, color: W_MUTED, letterSpacing: "0.10em", fontWeight: 600,
          marginBottom: 3,
        }}>
          <span style={{
            display: "inline-block", width: 14, height: 10, borderRadius: 2,
            background: "linear-gradient(to bottom, #AA151B 0%, #AA151B 33%, #F1BF00 33%, #F1BF00 66%, #AA151B 66%, #AA151B 100%)",
            boxShadow: "inset 0 0 0 0.5px rgba(0,0,0,0.15)",
          }} />
          OR CALL OUR AI · 24/7
        </div>
        <div style={{
          fontFamily: "'Instrument Serif', 'Source Serif 4', serif",
          fontSize: 18, fontWeight: 400,
          color: W_INK, letterSpacing: "-0.01em",
          fontVariantNumeric: "tabular-nums",
        }}>+34 900 800 720</div>
      </div>
    </div>
  );
}
function PathSelector({ path, setPath }) {
  const opts = [
    { key: "rec", label: "Personalized callback", sub: "form → call" },
    { key: "now", label: "Direct call",            sub: "tap → call" },
  ];
  return (
    <div style={{
      position: "absolute", top: 22, right: 22, zIndex: 95,
      display: "flex", alignItems: "center", gap: 8,
      padding: 6, borderRadius: 14,
      background: "rgba(255,255,255,0.95)",
      boxShadow: "0 1px 0 rgba(0,0,0,0.04)",
    }}>
      {opts.map(o => {
        const active = path === o.key;
        return (
          <button key={o.key}
            onClick={() => setPath(o.key)}
            style={{
              border: "none", cursor: "pointer",
              padding: "9px 14px", borderRadius: 10,
              background: active ? W_FUCHSIA : "transparent",
              color: active ? "#fff" : W_INK,
              boxShadow: "none",
              transition: "all 220ms",
              textAlign: "left",
              minWidth: 160,
            }}>
            <div style={{
              fontFamily: "Inter", fontSize: 12.5, fontWeight: 600,
            }}>{o.label}</div>
            <div style={{
              fontFamily: "'JetBrains Mono', monospace",
              fontSize: 9.5, opacity: active ? 0.85 : 0.6,
              letterSpacing: "0.06em", marginTop: 2,
            }}>{o.sub.toUpperCase()}</div>
          </button>
        );
      })}
    </div>
  );
}

// ───────────────────────────────────────────────────────────
//  MAIN STAGE
// ───────────────────────────────────────────────────────────
function WidgetShowcase() {
  const [path, setPath] = useStateW("rec"); // "rec" or "now"
  const [inView, setInView] = useStateW(false);
  const stageRef = useRefW(null);

  /* Pause the scripted loop until the section is scrolled into view, then
     reset it to t=0 each time it re-enters so visitors always see the
     animation from the beginning. */
  useEffectW(() => {
    if (!stageRef.current) return;
    const obs = new IntersectionObserver(([entry]) => {
      setInView(entry.isIntersecting);
    }, { threshold: 0.25 });
    obs.observe(stageRef.current);
    return () => obs.disconnect();
  }, []);

  // Per-path duration & key timestamps
  const SEQ_REC = {
    duration: 28,
    bubbleEnter:    [0,   1.2],   // bubble appears, ripples
    hoverLabel:     [3.0, 5.0],   // tooltip
    overlayIn:      [5.4, 6.0],
    pickerIn:       [6.0, 6.8],
    highlightRec:   [7.5, 9.5],
    clickRec:       [9.5, 10.0],
    pickerOut:      [10.0, 10.6],
    formIn:         [10.6, 11.4],
    formFill:       [11.4, 17.5],  // typing
    formSubmit:     [17.5, 18.5],
    formOut:        [19.5, 20.1],
    callIn:         [20.1, 20.8],
    callPlays:      [20.8, 28.0],
    callStartT:     20.1,
  };
  const SEQ_NOW = {
    duration: 22,
    bubbleEnter:    [0,   1.2],
    hoverLabel:     [3.0, 5.0],
    overlayIn:      [5.4, 6.0],
    pickerIn:       [6.0, 6.8],
    highlightNow:   [7.5, 9.0],
    clickNow:       [9.0, 9.5],
    pickerOut:      [9.5, 10.1],
    callIn:         [10.1, 10.8],
    callPlays:      [10.8, 22.0],
    callStartT:     10.1,
  };
  const SEQ = path === "rec" ? SEQ_REC : SEQ_NOW;

  const [t, reset] = useStageTime(SEQ.duration, !inView);

  useEffectW(() => { reset(); }, [path]); // reset on path change
  useEffectW(() => { if (inView) reset(); }, [inView]); // restart when scrolled in

  // Helpers
  const between = ([a, b]) => t >= a && t <= b;
  const after = (a) => t >= a;
  const before = (a) => t < a;

  // ---------- visibility flags ----------
  const overlayActive    = after(SEQ.overlayIn[0]); // dim overlay on
  const overlayOpacity   = Math.min(1, Math.max(0, (t - SEQ.overlayIn[0]) / 0.6)) * 0.55;

  const showHoverLabel   = between(SEQ.hoverLabel) && before(SEQ.overlayIn[0] + 0.1);
  const bubbleOpening    = after(SEQ.overlayIn[0] + 0.1) && before(SEQ.pickerOut[1] + 0.05);

  const pickerVisible    = after(SEQ.pickerIn[0]) && before(SEQ.pickerOut[0] + 0.4);
  const highlightedIdx   = path === "rec"
    ? (between(SEQ_REC.highlightRec) ? 0 : -1)
    : (between(SEQ_NOW.highlightNow) ? 1 : -1);
  const clickedIdx       = path === "rec"
    ? (between(SEQ_REC.clickRec) ? 0 : -1)
    : (between(SEQ_NOW.clickNow) ? 1 : -1);

  const formVisible      = path === "rec" && after(SEQ_REC.formIn[0]) && before(SEQ_REC.formOut[1]);
  const formProgress     = path === "rec"
    ? Math.min(1, Math.max(0, (t - SEQ_REC.formFill[0]) / (SEQ_REC.formFill[1] - SEQ_REC.formFill[0])))
    : 0;
  const formSubmitted    = path === "rec" && after(SEQ_REC.formSubmit[0]);

  const callVisible      = after(SEQ.callIn[0]);
  /* Top-left "OR CALL OUR AI 24/7" chip only appears in the live-call step. */
  const callUsChipVisible = callVisible;
  /* Top-right path selector only appears once a path has been chosen. */
  const pathSelectorVisible = after(SEQ.pickerOut[0]);

  // current phase index for tracker
  const STEPS_REC = [
    { label: "Idle bubble",      sub: "passive on the page" },
    { label: "Hover preview",    sub: "tooltip whisper" },
    { label: "Picker opens",     sub: "two routes offered" },
    { label: "Personalized chosen", sub: "callback form" },
    { label: "Form submitted",   sub: "lead captured" },
    { label: "Live call",        sub: "concierge connected" },
  ];
  const STEPS_NOW = [
    { label: "Idle bubble",      sub: "passive on the page" },
    { label: "Hover preview",    sub: "tooltip whisper" },
    { label: "Picker opens",     sub: "two routes offered" },
    { label: "Direct chosen",    sub: "no friction" },
    { label: "Live call",        sub: "concierge connected" },
  ];
  const steps = path === "rec" ? STEPS_REC : STEPS_NOW;
  let activeIdx = 0;
  if (path === "rec") {
    if (after(28))                 activeIdx = 5;
    else if (after(SEQ_REC.callIn[0]))     activeIdx = 5;
    else if (after(SEQ_REC.formSubmit[0])) activeIdx = 4;
    else if (after(SEQ_REC.formIn[0]))     activeIdx = 3;
    else if (after(SEQ_REC.pickerIn[0]))   activeIdx = 2;
    else if (after(SEQ_REC.hoverLabel[0])) activeIdx = 1;
  } else {
    if (after(SEQ_NOW.callIn[0]))          activeIdx = 4;
    else if (after(SEQ_NOW.clickNow[0]))   activeIdx = 3;
    else if (after(SEQ_NOW.pickerIn[0]))   activeIdx = 2;
    else if (after(SEQ_NOW.hoverLabel[0])) activeIdx = 1;
  }

  // Bubble position, lower-right (anchored to right + bottom)
  const bubbleRight = 24;
  const bubbleBottom = 122; // sit above the phase track (≈92px) + breathing room

  return (
    <section style={{
      width: "100%", padding: "80px 60px 100px",
      background: W_CREAM,
    }}>
      {/* keyframes */}
      <style>{`
        @keyframes wb-fade-in   { from { opacity: 0; transform: translateY(4px) translateY(-50%); } to { opacity: 1; transform: translateY(-50%); } }
        @keyframes wb-slide-up  { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
        @keyframes wb-pulse     { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.6); opacity: 0.5; } }
        @keyframes wb-breathe   { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }
        @keyframes wb-blink     { 0%, 50% { opacity: 1; } 51%, 100% { opacity: 0; } }
        @keyframes wb-click-ring { 0% { transform: scale(1); opacity: 1; } 100% { transform: scale(1.08); opacity: 0; } }
      `}</style>

      {/* heading */}
      <div style={{ maxWidth: "var(--rail)", margin: "0 auto 36px" }}>
        <div style={{
          display: "flex", alignItems: "center", gap: 10,
          fontFamily: "'JetBrains Mono', monospace",
          fontSize: 11, color: W_MUTED, letterSpacing: "0.12em",
          marginBottom: 12,
        }}>
          <span style={{
            width: 28, height: 1, background: W_FUCHSIA,
          }} />
          ON-SITE BUBBLE · LIVE WIDGET STATES
        </div>
        <h2 style={{
          fontFamily: "'Instrument Serif', 'Source Serif 4', serif",
          fontSize: "clamp(28px, 3.4vw, 48px)", fontWeight: 400, color: W_INK,
          margin: 0, letterSpacing: "-0.02em", lineHeight: 1.05,
          maxWidth: 880,
        }}>
          One bubble on the page,&nbsp;
          <em style={{ color: W_FUCHSIA, fontStyle: "italic" }}>two ways to talk.</em>
        </h2>
        <p style={{
          fontFamily: "Inter", fontSize: 15.5, color: W_MUTED, marginTop: 14,
          maxWidth: 720, lineHeight: 1.55,
        }}>
          Every Olea Hotels site gets a single discreet bubble. Visitors who want a curated proposal leave a callback;
          everyone else taps once and the agent picks up. Same bubble, same brand, two paths.
        </p>
      </div>

      {/* THE BIG STAGE — aspect ratio matches the hero image (16:9) so it
          fills the frame edge-to-edge without cropping. */}
      <div ref={stageRef} style={{
        position: "relative",
        maxWidth: "var(--rail)", margin: "0 auto",
        aspectRatio: "16 / 9",
        background: "#000",
        borderRadius: 22,
        overflow: "hidden",
        boxShadow: "0 1px 0 rgba(0,0,0,0.06)",
      }}>
        {/* Live website */}
        <AureaSite />

        {/* Dim overlay */}
        <div style={{
          position: "absolute", inset: 0,
          background: "#000",
          opacity: overlayOpacity,
          transition: "opacity 320ms ease",
          pointerEvents: "none",
          zIndex: 50,
        }} />

        {/* Floating bubble */}
        <FloatingBubble
          time={t}
          rightPx={bubbleRight}
          bottomPx={bubbleBottom}
          hovered={showHoverLabel}
          opening={bubbleOpening}
        />

        {/* Picker */}
        <PickerModal
          visible={pickerVisible}
          highlightedIdx={highlightedIdx}
          clickedIdx={clickedIdx}
        />

        {/* Lead form, only on rec path */}
        {path === "rec" && (
          <LeadForm
            visible={formVisible}
            fillProgress={formProgress}
            submitted={formSubmitted}
          />
        )}

        {/* Live call */}
        <CallPanel
          visible={callVisible}
          time={t}
          callStartT={SEQ.callStartT}
        />

        {/* AI phone number chip — only on the live-call step.
            zIndex 96 on the wrapper because the transform-animation creates
            a stacking context, otherwise the dim overlay (z=50) paints on
            top of it. */}
        {callUsChipVisible && (
          <div style={{
            position: "absolute", inset: 0, zIndex: 96, pointerEvents: "none",
            animation: "wb-slide-up 360ms cubic-bezier(.2,.8,.2,1) both",
          }}>
            <CallUsChip time={t} />
          </div>
        )}

        {/* Path selector — only after a path has been chosen.
            zIndex 96 for the same stacking-context reason. */}
        {pathSelectorVisible && (
          <div style={{
            position: "absolute", inset: 0, zIndex: 96,
            animation: "wb-slide-up 360ms cubic-bezier(.2,.8,.2,1) both",
          }}>
            <PathSelector path={path} setPath={setPath} />
          </div>
        )}

        {/* Phase track */}
        <PhaseTrack steps={steps} activeIdx={activeIdx} />
      </div>

      {/* footnote */}
      <div style={{
        maxWidth: "var(--rail)", margin: "20px auto 0",
        display: "flex", justifyContent: "space-between", alignItems: "center",
        fontFamily: "'JetBrains Mono', monospace",
        fontSize: 11, color: W_MUTED, letterSpacing: "0.06em",
      }}>
        <span>AUREA HOTELS · DEMO PROPERTY · LIVE PREVIEW</span>
        <span>SCRIPTED LOOP · {Math.floor(t)}s / {SEQ.duration}s</span>
      </div>
    </section>
  );
}

// expose
window.WidgetShowcase = WidgetShowcase;
