// ─────────────────────────────────────────────────────────────────────────
//  BuyerJourneyCinema - full-width horizontal scroll-cinema
//
//  Each stage of a buyer's journey is a full-viewport panel containing a
//  product-UI peek: a stylized YachtWay screen that suggests what is
//  happening at that step. Panels animate as they enter view; the active
//  stage's UI pieces shimmer/move on their own.
//
//  Five stages: Discover (social) → Search → Browse (marketplace) →
//  Talk (broker) → Close (boat show / signature).
//
//  Layout: a 500vh-tall container with a sticky 100vh viewport. As the
//  user scrolls, the active stage advances; UI mocks slide horizontally.
//  Clicking the stage dots jumps directly. We also expose left/right
//  buttons in the section header.
// ─────────────────────────────────────────────────────────────────────────

const STAGES = [
  {
    id: "discover",
    n: "01",
    eyebrow: "Discover",
    surface: "Social - Facebook, Instagram, YouTube",
    title: "The sale starts on socials.",
    desc: "Before any search query, the buyer sees a vessel mid-scroll. YachtWay produces the content the algorithm rewards.",
    stat: { v: "2.18M", l: "followers across IG, YouTube, FB, TikTok" },
    accent: "#7c5cff",
    mock: "social",
  },
  {
    id: "search",
    n: "02",
    eyebrow: "Search",
    surface: "Google - the broad category, not just one model",
    title: "They Google \"yachts for sale.\" You are on Page 1.",
    desc: "Most yacht inventory sites never reach Page 1 for the broad category. YachtWay does, alongside legacy players, with no paid placement.",
    stat: { v: "15.7%", l: "of YachtWay keywords on Page 1 of Google" },
    accent: "#7c5cff",
    mock: "search",
  },
  {
    id: "browse",
    n: "03",
    eyebrow: "Browse",
    surface: "Marketplace - Listings, Live, 3D Tours, Events, Scheduling",
    title: "The buying experience modern buyers expect.",
    desc: "Search by nearby events, authorized dealers, monthly price range, or use classic filters. Explore select vessels in 3D.",
    stat: { v: "4.07", l: "visits per listing per month" },
    accent: "#7c5cff",
    mock: "marketplace",
  },
  {
    id: "tour",
    n: "04",
    eyebrow: "Tour",
    surface: "YachtWay LIVE, broadcast walkthrough on the listing",
    title: "Tour the boat from anywhere.",
    desc: "Buyers don't fly out to look. They show up live on the listing, hundreds in the room at once. The dealer answers questions, walks the engine room, and the recording stays on the listing for the next visitor.",
    stat: { v: "100+", l: "qualified buyers in a single live session" },
    accent: "#7c5cff",
    mock: "live",
  },
  {
    id: "talk",
    n: "05",
    eyebrow: "Talk",
    surface: "Email, phone, walk-in - the first contact with you",
    title: "By the time they contact, the research is done.",
    desc: "Buyers arrive informed. They have watched the walkthroughs and compared the specs. The qualifying questions are already answered. Your conversation is closing, not convincing.",
    stat: { v: "1 day", l: "from broker call to signed contract" },
    accent: "#7c5cff",
    mock: "broker",
  },
  {
    id: "close",
    n: "06",
    eyebrow: "Close",
    surface: "Digital contracts, e-signatures",
    title: "Sign in minutes. Closed in days. Compliant by default.",
    desc: "Digital contracts and verified e-signatures replace the weeks of paperwork the industry tolerated. Documents signed with DocuSign.",
    stat: { v: "$0", l: "paid acquisition needed" },
    accent: "#7c5cff",
    mock: "close",
    compliance: [
      { label: "SOC 2 Type I & II",  tip: "Independently audited controls for data security, availability, and confidentiality. The same standard Fortune 500 vendors are held to before they are allowed near sensitive customer data." },
      { label: "GDPR Compliant",     tip: "EU buyer and dealer records handled under the General Data Protection Regulation. Buyers can request, export, or delete their data at any time, and we can prove it." },
      { label: "CCPA Aligned",       tip: "California Consumer Privacy Act rights honored for US buyers. Opt-out, disclosure, and deletion requests routed through a documented process." },
    ],
  },
];

function BuyerJourneyCinema({ T, A, glow, tint }) {
  // `progress` is a continuous float in [0, STAGES.length-1] driven directly
  // by the user's scroll position within the journey section. The currently-
  // "active" stage (used for things like the dot nav and the SectionHeader
  // copy) is just round(progress), but the panels themselves cross-fade
  // smoothly using the fractional part, so motion tracks the scroll wheel
  // 1:1 instead of stepping at IO thresholds.
  const [progress, setProgress] = React.useState(0);
  const active = Math.max(0, Math.min(STAGES.length - 1, Math.round(progress)));
  const wrapRef = React.useRef(null);
  const slidesRef = React.useRef([]);

  React.useEffect(() => {
    let raf = 0;
    const update = () => {
      raf = 0;
      const wrap = wrapRef.current;
      if (!wrap) return;
      const r = wrap.getBoundingClientRect();
      const vh = window.innerHeight;
      // Section is (N+1)*vh tall (sticky stage + N anchors via -100vh
      // margin). The sticky stage pins from r.top=0 down to r.bottom=vh,
      // so the usable scroll range is from r.top=0 to r.top=-(N-1)*vh.
      const total = (STAGES.length - 1) * vh;
      const scrolled = Math.max(0, Math.min(total, -r.top));
      const p = total > 0 ? scrolled / vh : 0;
      setProgress(p);
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(update); };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    update();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);

  // Direct nav: smooth-scroll to the target stage's anchor using
  // window.scrollTo so we never trigger scrollIntoView side-effects.
  // When advancing past the last stage (or before the first), exit the
  // journey section to the neighbouring section instead of looping.
  const jumpTo = (i) => {
    const wrap = wrapRef.current;
    if (typeof window === "undefined") return;
    const docTop = (el) => el.getBoundingClientRect().top + window.scrollY;
    if (i >= STAGES.length) {
      const next = wrap && wrap.nextElementSibling;
      if (next) window.scrollTo({ top: docTop(next), behavior: "smooth" });
      else window.scrollBy({ top: window.innerHeight, behavior: "smooth" });
      return;
    }
    if (i < 0) {
      const prev = wrap && wrap.previousElementSibling;
      if (prev) {
        // Land at the prev section so its bottom sits roughly at viewport
        // bottom, feels like "stepping back out".
        const target = docTop(prev) + Math.max(0, prev.offsetHeight - window.innerHeight);
        window.scrollTo({ top: target, behavior: "smooth" });
      } else {
        window.scrollBy({ top: -window.innerHeight, behavior: "smooth" });
      }
      return;
    }
    const el = slidesRef.current[i];
    if (!el) return;
    window.scrollTo({ top: docTop(el), behavior: "smooth" });
  };

  // Keyboard: ←/→ advance stages while the section is in view.
  React.useEffect(() => {
    const onKey = (e) => {
      const wrap = wrapRef.current;
      if (!wrap) return;
      const r = wrap.getBoundingClientRect();
      const vh = window.innerHeight;
      // Section must be substantially in view.
      if (r.bottom < vh * 0.4 || r.top > vh * 0.6) return;
      if (e.key === "ArrowRight") { e.preventDefault(); jumpTo(active + 1); }
      else if (e.key === "ArrowLeft") { e.preventDefault(); jumpTo(active - 1); }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [active]);

  return (
    <section id="journey" ref={wrapRef} style={{
      position: "relative",
      background: T.bgDark,
      color: "#fff",
      scrollMarginTop: 0,
    }}>
      {/* Sticky visual stage. As the user scrolls through the section's
          N×100vh height, this stays pinned to the top of the viewport,
          and the active panel cross-fades to the next. */}
      <div style={{
        position: "sticky", top: 0,
        height: "100vh", minHeight: 720,
        overflow: "hidden",
        zIndex: 1,
      }}>
        {/* Ambient glow that shifts hue per stage. Position is driven by
            continuous progress so it tracks the scroll wheel smoothly
            instead of stepping on stage transitions. */}
        <div aria-hidden="true" style={{
          position: "absolute", inset: 0,
          background: `radial-gradient(ellipse 70% 60% at ${20 + progress * 12}% ${30 + (Math.round(progress) % 2) * 30}%, ${glow(.35)}, transparent 65%)`,
        }}/>

        {/* Section header overlay, pushed below the page-level sticky nav
            (~56px tall) so the eyebrow, title and stage dots remain visible
            as the user scrolls through the cinema sequence. */}
        <div style={{
          position: "absolute", top: 72, left: 0, right: 0,
          padding: "0 48px",
          display: "flex", alignItems: "center", justifyContent: "space-between",
          zIndex: 10, pointerEvents: "none",
        }}>
          <div style={{ pointerEvents: "auto" }}>
            <div style={{
              fontSize: 12, fontWeight: 700, color: tint(1),
              textTransform: "uppercase", letterSpacing: ".18em", marginBottom: 6,
            }}>The buyer journey</div>
            <div style={{
              fontFamily: T.fDisplay, fontSize: 28, fontWeight: 700,
              color: "#fff", letterSpacing: "-0.025em", lineHeight: 1.05,
              maxWidth: 720,
            }}>The modern day buyer journey.</div>
          </div>


        </div>

        {/* Stage panels rendered as a horizontal film strip. The track is
            N viewports wide; we translate it left by progress*100/N to
            slide the active panel into view. Panels stay fully opaque, no cross-fade ghosting between two stages. The motion tracks
            scroll position 1:1 so it feels like the user is dragging the
            strip with their wheel. */}
        <div style={{
          position: "absolute", inset: 0,
          overflow: "hidden",
        }}>
          <div style={{
            display: "flex",
            width: `${STAGES.length * 100}%`,
            height: "100%",
            transform: `translate3d(${-progress * (100 / STAGES.length)}%, 0, 0)`,
            willChange: "transform",
          }}>
            {STAGES.map((s, i) => (
              <div key={s.id} style={{ width: `${100 / STAGES.length}%`, height: "100%", flexShrink: 0 }}>
                <StagePanel
                  T={T} A={A} tint={tint}
                  stage={s}
                  stages={STAGES}
                  activeIndex={active}
                  isActive={i === active}
                  onJump={jumpTo}
                />
              </div>
            ))}
          </div>
        </div>

        {/* Bottom controls, stage dots on the left, prev/next + counter
            on the right. Arrows live in the bottom corner so they never
            overlap the copy or the product UI. */}
        <div style={{
          position: "absolute", bottom: 28, left: 48, right: 48,
          display: "flex", alignItems: "center", justifyContent: "space-between",
          zIndex: 10, pointerEvents: "none",
        }}>
          <div style={{ display: "flex", gap: 10, pointerEvents: "auto" }}>
            {STAGES.map((s, i) => (
              <button key={s.id}
                aria-label={`Go to stage ${i + 1}: ${s.eyebrow}`}
                aria-current={i === active}
                onClick={() => jumpTo(i)}
                style={{
                  width: i === active ? 32 : 8, height: 8,
                  borderRadius: 4,
                  background: i === active ? "#fff" : "rgba(255,255,255,.25)",
                  border: "none", cursor: "pointer", padding: 0,
                  transition: "width .35s ease, background .35s ease",
                }}
              />
            ))}
          </div>
          <div style={{
            display: "flex", alignItems: "center", gap: 14,
            pointerEvents: "auto",
          }}>
            <button
              aria-label="Previous stage"
              onClick={() => jumpTo(active - 1)}
              style={{
                width: 36, height: 36, borderRadius: "50%",
                background: "rgba(255,255,255,.06)",
                border: "1px solid rgba(255,255,255,.15)",
                color: "#fff", cursor: "pointer",
                display: "flex", alignItems: "center", justifyContent: "center",
                backdropFilter: "blur(8px)",
                transition: "background .2s ease, border-color .2s ease",
              }}
              onMouseEnter={(e) => { e.currentTarget.style.background = "rgba(255,255,255,.14)"; e.currentTarget.style.borderColor = "rgba(255,255,255,.3)"; }}
              onMouseLeave={(e) => { e.currentTarget.style.background = "rgba(255,255,255,.06)"; e.currentTarget.style.borderColor = "rgba(255,255,255,.15)"; }}
            >
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
                <path d="M15 18l-6-6 6-6"/>
              </svg>
            </button>
            <div style={{
              fontSize: 12, fontWeight: 700, color: "rgba(255,255,255,.55)",
              textTransform: "uppercase", letterSpacing: ".18em",
              fontVariantNumeric: "tabular-nums",
            }}>{String(active + 1).padStart(2, "0")} / {String(STAGES.length).padStart(2, "0")}</div>
            <button
              aria-label="Next stage"
              onClick={() => jumpTo(active + 1)}
              style={{
                width: 36, height: 36, borderRadius: "50%",
                background: "rgba(255,255,255,.06)",
                border: "1px solid rgba(255,255,255,.15)",
                color: "#fff", cursor: "pointer",
                display: "flex", alignItems: "center", justifyContent: "center",
                backdropFilter: "blur(8px)",
                transition: "background .2s ease, border-color .2s ease",
              }}
              onMouseEnter={(e) => { e.currentTarget.style.background = "rgba(255,255,255,.14)"; e.currentTarget.style.borderColor = "rgba(255,255,255,.3)"; }}
              onMouseLeave={(e) => { e.currentTarget.style.background = "rgba(255,255,255,.06)"; e.currentTarget.style.borderColor = "rgba(255,255,255,.15)"; }}
            >
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
                <path d="M9 6l6 6-6 6"/>
              </svg>
            </button>
          </div>
        </div>
      </div>

      {/* ───────────────────────────────────────────────────────────────────
          Snap-anchor track. One invisible 100vh anchor per stage, marked
          with scroll-snap-align so the browser softly snaps the user's
          wheel/touch input to the start of each anchor. The IntersectionObserver
          above watches these anchors to set the active stage. The track is
          pulled into the same scroll-region as the sticky stage above with
          margin-top: -100vh, total section height ends up at exactly N×100vh
          (1 viewport per stage), and the user just keeps scrolling normally.
      ─────────────────────────────────────────────────────────────────── */}
      <div style={{
        position: "relative",
        marginTop: "-100vh",
      }}>
        {STAGES.map((s, i) => (
          <div key={s.id}
            ref={el => slidesRef.current[i] = el}
            data-stage-idx={i}
            data-screen-label={`Journey ${s.n} ${s.eyebrow}`}
            style={{
              height: "100vh",
              pointerEvents: "none",
            }}
          />
        ))}
      </div>
    </section>
  );
}

function StagePanel({ T, A, tint, stage, stages, activeIndex, isActive, onJump }) {
  return (
    <div aria-hidden={!isActive}
      data-screen-label={isActive ? `Journey ${stage.n} ${stage.eyebrow}` : undefined}
      style={{
      width: "100%", height: "100%",
      display: "grid", gridTemplateColumns: "minmax(380px, 1fr) minmax(0, 1.3fr)",
      alignItems: "center", gap: 64,
      padding: "120px 64px 80px",
      boxSizing: "border-box",
    }}>
      {/* LEFT - copy */}
      <div style={{ maxWidth: 520 }}>
        <div style={{
          display: "inline-flex", alignItems: "center", gap: 10,
          padding: "5px 12px", borderRadius: 999,
          background: tint(.15), border: `1px solid ${tint(.30)}`,
          fontSize: 13, fontWeight: 700, color: "#fff",
          textTransform: "uppercase", letterSpacing: ".14em",
          marginBottom: 24,
        }}>
          <span style={{
            width: 6, height: 6, borderRadius: 3,
            background: A, animation: isActive ? "pulse-dot 1.4s ease-in-out infinite" : "none",
          }}/>
          {stage.eyebrow}
        </div>

        <h3 style={{
          fontFamily: T.fDisplay, fontSize: 56, fontWeight: 700,
          letterSpacing: "-0.03em", lineHeight: 1.0,
          margin: "0 0 22px", color: "#fff",
        }}>{stage.title}</h3>

        <div style={{
          fontSize: 13, fontWeight: 600,
          color: "rgba(255,255,255,.45)",
          textTransform: "uppercase", letterSpacing: ".12em",
          marginBottom: 14,
        }}>{stage.surface}</div>

        <p style={{
          fontSize: 17, lineHeight: 1.6,
          color: "rgba(255,255,255,.78)",
          margin: "0 0 36px",
          maxWidth: 460,
        }}>{stage.desc}</p>

        {/* Compliance badges - only on the "close" stage. Brokers care that
            their paperwork holds up legally; surfacing the certs here, where
            we talk about contracts + KYC, makes the trust claim land harder.
            Hover reveals a plain-English explanation of what each cert means. */}
        {stage.compliance && (
          <div style={{
            display: "flex", flexWrap: "wrap", gap: 8,
            marginBottom: 36,
          }}>
            {stage.compliance.map((c, i) => (
              <div key={i} className="compliance-chip" style={{
                position: "relative",
                display: "inline-flex", alignItems: "center", gap: 8,
                padding: "8px 14px", borderRadius: 999,
                background: "rgba(255,255,255,.06)",
                border: "1px solid rgba(255,255,255,.14)",
                fontSize: 13, fontWeight: 600, color: "#fff",
                letterSpacing: ".02em",
                cursor: "help",
              }}>
                <span style={{
                  width: 6, height: 6, borderRadius: 3, background: A,
                }}/>
                {c.label}
                <span className="compliance-tip" style={{
                  position: "absolute", bottom: "calc(100% + 10px)", left: 0,
                  width: 280, padding: "12px 14px",
                  background: "#0a0a0c", color: "rgba(255,255,255,.85)",
                  border: "1px solid rgba(255,255,255,.14)",
                  borderRadius: 10, fontSize: 13, fontWeight: 400,
                  lineHeight: 1.5, letterSpacing: 0,
                  opacity: 0, transform: "translateY(4px)",
                  transition: "opacity .18s ease, transform .18s ease",
                  pointerEvents: "none",
                  boxShadow: "0 20px 40px -10px rgba(0,0,0,.6)",
                  zIndex: 5,
                }}>{c.tip}</span>
              </div>
            ))}
          </div>
        )}

        {/* Headline stat removed - too dense alongside the live UI mock on the right */}
      </div>

      {/* RIGHT - product UI peek */}
      <div style={{
        position: "relative",
        display: "flex", alignItems: "center", justifyContent: "center",
        height: "100%", maxHeight: 640,
      }}>
        <div style={{
          width: "100%", maxWidth: 720,
        }}>
          <UIMock kind={stage.mock} T={T} A={A} tint={tint} active={isActive}/>
        </div>
      </div>

      <style>{`
        @keyframes pulse-dot {
          0%, 100% { opacity: 1; transform: scale(1); }
          50% { opacity: .4; transform: scale(.7); }
        }
        .compliance-chip:hover .compliance-tip,
        .compliance-chip:focus-within .compliance-tip {
          opacity: 1;
          transform: translateY(0);
        }
        .journey-dot:hover { background: rgba(255,255,255,.7) !important; transform: scale(1.5) !important; }
        .journey-dot:hover .journey-dot__tip,
        .journey-dot:focus-visible .journey-dot__tip {
          opacity: 1;
          transform: translateY(-50%) translateX(0);
        }
      `}</style>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
//  UIMock - chooses which product-UI peek to render per stage.
//  All mocks share a "device frame" with browser chrome + drop shadow.
// ─────────────────────────────────────────────────────────────────────────
function UIMock({ kind, T, A, tint, active }) {
  return (
    <div style={{
      position: "relative",
      borderRadius: 14,
      background: "#fff",
      color: "#0a0a0c",
      overflow: "hidden",
      boxShadow: "0 60px 100px -40px rgba(0,0,0,.6), 0 20px 40px -20px rgba(0,0,0,.4)",
      border: "1px solid rgba(255,255,255,.10)",
      transform: active ? "translateY(0) scale(1)" : "translateY(20px) scale(.98)",
      transition: "transform .8s cubic-bezier(.2,.7,.2,1)",
    }}>
      {/* Browser chrome */}
      <div style={{
        display: "flex", alignItems: "center", gap: 8,
        padding: "10px 14px",
        background: "#f3f3f5",
        borderBottom: "1px solid rgba(0,0,0,.06)",
      }}>
        <div style={{ display: "flex", gap: 6 }}>
          <span style={{ width: 10, height: 10, borderRadius: 5, background: "#ff5f57" }}/>
          <span style={{ width: 10, height: 10, borderRadius: 5, background: "#febc2e" }}/>
          <span style={{ width: 10, height: 10, borderRadius: 5, background: "#28c840" }}/>
        </div>
        <div style={{
          flex: 1, marginLeft: 10,
          padding: "5px 12px", borderRadius: 6,
          background: "#fff", border: "1px solid rgba(0,0,0,.08)",
          fontSize: 13, color: "#71717a",
          fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
        }}>
          {kind === "social"      && "instagram.com/yachtway"}
          {kind === "search"      && "google.com/search?q=yachts+for+sale"}
          {kind === "marketplace" && "yachtway.com/listings"}
          {kind === "watch"       && "youtube.com/@yachtway"}
          {kind === "live"        && "yachtway.com/listings/SP-2841/live"}
          {kind === "broker"      && "www.YachtWay.com/inbox"}
          {kind === "close"       && "www.YachtWay.com/contracts/SP-2841"}
        </div>
      </div>

      {/* Body - different layout per kind */}
      <div style={{ background: "#fff" }}>
        {kind === "social"      && <MockSocial active={active} A={A} T={T}/>}
        {kind === "search"      && <MockSearch active={active} A={A} T={T}/>}
        {kind === "marketplace" && <MockMarketplace active={active} A={A} T={T} tint={tint}/>}
        {kind === "watch"       && <MockWatch active={active} A={A} T={T} tint={tint}/>}
        {kind === "live"        && <MockLive active={active} A={A} T={T} tint={tint}/>}
        {kind === "broker"      && <MockBroker active={active} A={A} T={T} tint={tint}/>}
        {kind === "close"       && <MockClose active={active} A={A} T={T} tint={tint}/>}
      </div>
    </div>
  );
}

// ─── Mock 01 - Instagram-like feed with a YachtWay reel scrolling
function MockSocial({ active, A, T }) {
  return (
    <div style={{ padding: 16, background: "#fff", height: 460 }}>
      <style>{`
        /* Seamless top-to-bottom scroll. The grid is duplicated below so
           translating up by exactly the height of one copy + its bottom
           gap loops back to the original position with no visible seam. */
        @keyframes feed-scroll {
          0%   { transform: translateY(0); }
          100% { transform: translateY(-50%); }
        }
        .feed-scroller { animation: feed-scroll 24s linear infinite; }
      `}</style>
      {/* Profile header */}
      <div style={{ display: "flex", gap: 12, alignItems: "center", marginBottom: 14, paddingBottom: 14, borderBottom: "1px solid #f0f0f2" }}>
        <div style={{
          width: 48, height: 48, borderRadius: 24,
          background: `conic-gradient(from 0deg, ${A}, #ff5e8c, ${A})`,
          padding: 2, boxSizing: "border-box",
        }}>
          <div style={{
            width: "100%", height: "100%", borderRadius: "50%",
            background: "#000",
            backgroundImage: `url(${(window.__YW_ASSET && window.__YW_ASSET("assets/yachtway-square.png")) || "assets/yachtway-square.png"})`,
            backgroundSize: "cover",
            backgroundPosition: "center",
          }}></div>
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 600, fontSize: 14 }}>YachtWay</div>
          <div style={{ fontSize: 13, color: "#71717a" }}>472K · Your Yacht. Your Way.</div>
        </div>
        <div style={{ padding: "6px 14px", borderRadius: 8, background: A, color: "#fff", fontSize: 13, fontWeight: 600 }}>Follow</div>
      </div>

      {/* Reel grid - rendered TWICE back-to-back so the scroller can loop
          seamlessly. Translating the wrapper by -50% lands the second
          copy exactly where the first started, with no jump. */}
      <div style={{ overflow: "hidden", height: 380 }}>
        <div className={active ? "feed-scroller" : ""} style={{
          display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 4,
        }}>
          {(() => {
            // Editorial color-coded feed. The 12 unique tiles are arranged
            // top-to-bottom as four horizontal color bands:
            //   Row 1, DEEP MIDNIGHT (dark navy water)
            //   Row 2, MID TEAL (medium ocean)
            //   Row 3, WARM (sunset, interior, forest, the punctuation band)
            //   Row 4, BRIGHT AQUA (turquoise + cloud)
            // Reading left-to-right also flows: cool → cool → warm break →
            // bright. The whole grid then duplicates once for the seamless
            // scroll loop. Each tile gets a deterministic, sub-20k view
            // count so the numbers feel realistic and don't reshuffle on
            // every render.
            const tiles = [
              // Row 1, deep midnight
              { src: "assets/social/yacht-action-2.jpg",   pos: "50% 50%", views: 14.2 },
              { src: "assets/social/yacht-deck.jpg",       pos: "50% 45%", views: 11.6 },
              { src: "assets/social/yacht-overhead-2.jpg", pos: "50% 50%", views: 18.4 },
              // Row 2, mid teal
              { src: "assets/social/yacht-overhead-1.jpg", pos: "50% 50%", views: 10.3 },
              { src: "assets/social/yacht-action-1.jpg",   pos: "50% 50%", views: 16.1 },
              { src: "assets/social/yacht-overhead-4.jpg", pos: "50% 50%", views:  9.9 },
              // Row 3, warm break
              { src: "assets/social/yacht-interior.jpg",   pos: "50% 50%", views: 19.7 },
              { src: "assets/social/yacht-sunset.jpg",     pos: "50% 50%", views: 13.0 },
              { src: "assets/social/yacht-axopar.jpg",     pos: "50% 60%", views: 12.4 },
              // Row 4, bright aqua / cloud
              { src: "assets/social/yacht-anchored.jpg",   pos: "50% 50%", views: 11.2 },
              { src: "assets/social/yacht-bow.jpg",        pos: "50% 50%", views: 17.5 },
              { src: "assets/social/yacht-skipper.jpg",    pos: "50% 55%", views: 10.7 },
            ];
            // Render twice back-to-back for the seamless -50% scroll.
            return Array.from({ length: 24 }).map((_, idx) => {
              const t = tiles[idx % 12];
              const label = t.views < 1
                ? `${Math.round(t.views * 1000)}`
                : `${t.views.toFixed(1)}K`;
              return (
                <div key={idx} style={{
                  aspectRatio: "9/16", borderRadius: 4,
                  backgroundColor: "#0a0a0c",
                  backgroundImage: `url('${(window.__YW_ASSET && window.__YW_ASSET(t.src)) || t.src}')`,
                  backgroundSize: "cover",
                  backgroundPosition: t.pos,
                  position: "relative", overflow: "hidden",
                }}>
                  <div style={{
                    position: "absolute", top: 6, right: 6,
                    fontSize: 13, color: "#fff",
                    background: "rgba(0,0,0,.4)",
                    padding: "2px 5px", borderRadius: 3,
                  }}>▶ {label}</div>
                </div>
              );
            });
          })()}
        </div>
      </div>
    </div>
  );
}

// ─── Mock 02 - Google SERP with YachtWay dominating page 1
function MockSearch({ active, A }) {
  return (
    <div style={{ padding: "16px 20px", background: "#fff", height: 460 }}>
      {/* Search bar */}
      <div style={{
        display: "flex", alignItems: "center", gap: 10,
        padding: "10px 16px", border: "1px solid #dadce0", borderRadius: 24, marginBottom: 18,
        boxShadow: "0 1px 3px rgba(0,0,0,.08)",
      }}>
        <span style={{ color: "#9aa0a6" }}>🔍</span>
        <span style={{ fontSize: 14 }}>yachts for sale</span>
      </div>

      {/* Tools row */}
      <div style={{ display: "flex", gap: 18, fontSize: 13, color: "#5f6368", marginBottom: 18, paddingBottom: 8, borderBottom: "1px solid #ebebeb" }}>
        <span style={{ color: "#202124", fontWeight: 500, paddingBottom: 6, borderBottom: "3px solid #1a73e8" }}>All</span>
        <span>Images</span><span>Videos</span><span>News</span><span>Shopping</span>
      </div>

      {/* Results */}
      <style>{`
        @keyframes serp-highlight {
          0%, 100% { background: transparent; }
          50% { background: rgba(124, 92, 255, .08); }
        }
        .serp-yw { animation: serp-highlight 2.4s ease-in-out infinite; border-radius: 8px; padding: 10px; margin: -10px; }
      `}</style>
      {[
        { yw: false, host: "yachtworld.com › boats", title: "Yachts for Sale - YachtWorld", desc: "Find new and used yachts for sale on YachtWorld. Browse listings from brokers." },
        { yw: true,  host: "yachtway.com › yachts-for-sale", title: "Yachts for Sale - 2,900+ listings worldwide · YachtWay", desc: "The category-leading marketplace for yachts. Filter 2,900+ listings by length, price, year, builder and location. Updated daily. Direct from dealers and brokers." },
        { yw: false, host: "iyc.com › luxury-yacht-sales", title: "Luxury Yachts for Sale", desc: "Over 550 Luxury Yachts for Sale and access to all yachts globally: View the best Super yachts and Mega Yachts for Sale. New Construction and pre-owned." },
        { yw: false, host: "imsyachts.com › boats-for-sale-in-miami", title: "Boats for Sale in Miami", desc: "YACHTS FOR SALE. 548 results. AZIMUT (80); SEA RAY (68); SUNSEEKER (36); INTREPID (24); BOSTON WHALER (22); FERRETTI YACHTS (18); PERSHING (17)" },
      ].map((r, i) => (
        <div key={i} className={r.yw && active ? "serp-yw" : ""} style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 13, color: "#202124", marginBottom: 2 }}>
            {r.yw && <span style={{ color: A, fontWeight: 700 }}>● </span>}
            {r.host}
          </div>
          <div style={{ fontSize: 17, color: "#1a0dab", marginBottom: 4, lineHeight: 1.3 }}>{r.title}</div>
          <div style={{ fontSize: 13, color: "#4d5156", lineHeight: 1.5 }}>{r.desc}</div>
        </div>
      ))}
    </div>
  );
}

// ─── Mock 03 - Marketplace listing grid with hover/featured states
function MockMarketplace({ active, A, T, tint }) {
  return (
    <div style={{ padding: 18, background: "#f7f7f8", height: 460 }}>
      <style>{`
        @keyframes live-pulse {
          0%, 100% { opacity: 1; transform: scale(1); }
          50%      { opacity: .35; transform: scale(.55); }
        }
      `}</style>
      {/* Filter bar */}
      <div style={{ display: "flex", gap: 8, marginBottom: 14, alignItems: "center", flexWrap: "nowrap", overflow: "hidden", minWidth: 0 }}>
        {["Type ▾", "Length 60-90ft", "Year 2023-25", "Price 1M+"].map((c, i) => (
          <span key={i} style={{
            fontSize: 13, padding: "5px 10px", borderRadius: 999,
            background: "#fff", color: "#52525b",
            border: "1px solid #e4e4e7",
            fontWeight: 400,
            whiteSpace: "nowrap", flex: "0 0 auto",
          }}>{c}</span>
        ))}
        <div style={{ marginLeft: "auto", fontSize: 13, color: "#71717a", whiteSpace: "nowrap", flex: "0 0 auto" }}>Showing <strong>247</strong> yachts</div>
      </div>

      {/* Grid */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 10 }}>
        {[
          { name: "Benetti 125", price: "€12.8M", year: "2024", loc: "Monaco", badge: "event", photo: "benetti" },
          { name: "Vanquish VQ70", price: "€7.2M", year: "2025", loc: "Antibes", photo: "vanquish" },
          { name: "Westport 130", price: "€21.9M", year: "2022", loc: "Bahamas", badge: "live", photo: "westport" },
          { name: "Feadship Tasia", price: "€44.6M", year: "2024", loc: "Palm Beach", photo: "moran" },
          { name: "Skipper 42", price: "€1.1M", year: "2025", loc: "Caribbean", photo: "powerboats" },
          { name: "Benetti 125", price: "€13.1M", year: "2025", loc: "Cannes", badge: "new", photo: "benetti" },
        ].map((y, i) => (
          <div key={i} style={{
            background: "#fff", borderRadius: 10,
            border: "1px solid #e4e4e7", overflow: "hidden",
            boxShadow: i === 0 && active ? `0 0 0 2px ${A}, 0 8px 24px -8px ${tint(.40)}` : "none",
            transform: i === 0 && active ? "translateY(-2px)" : "translateY(0)",
            transition: "transform .3s, box-shadow .3s",
          }}>
            <div style={{
              aspectRatio: "16/10",
              background: "#0a0a0c",
              backgroundImage: `url(${(window.__YW_ASSETS && window.__YW_ASSETS.listings && window.__YW_ASSETS.listings[y.photo]) || ""})`,
              backgroundSize: "cover",
              backgroundPosition: "center",
              position: "relative",
            }}>
              {/* photo loaded from listings; subtle scrim for badge legibility */}
              <div style={{
                position: "absolute", inset: 0,
                background: "linear-gradient(180deg, rgba(0,0,0,.18) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,.18) 100%)",
                pointerEvents: "none",
              }}/>
              {y.badge === "event" && (
                <div style={{
                  position: "absolute", top: 8, left: 8,
                  display: "inline-flex", alignItems: "center", gap: 4,
                  fontSize: 11, padding: "3px 7px", borderRadius: 4,
                  background: "#f4f4f5", color: "#0a0a0c", fontWeight: 700,
                  textTransform: "uppercase", letterSpacing: ".08em",
                  border: "1px solid rgba(0,0,0,.08)",
                }}>
                  <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                    strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                    <rect x="3" y="4" width="18" height="18" rx="2"/>
                    <path d="M16 2v4M8 2v4M3 10h18"/>
                  </svg>
                  <span>Event: FLIBS</span>
                </div>
              )}
              {y.badge === "live" && (
                <div style={{
                  position: "absolute", top: 8, left: 8,
                  display: "inline-flex", alignItems: "center", gap: 5,
                  fontSize: 11, padding: "3px 7px", borderRadius: 4,
                  background: "#dc2626", color: "#fff", fontWeight: 700,
                  textTransform: "uppercase", letterSpacing: ".08em",
                }}>
                  <span aria-hidden="true" style={{
                    width: 5, height: 5, borderRadius: 3, background: "#fff",
                    animation: "live-pulse 1.2s ease-in-out infinite",
                  }}/>
                  <span>Live now</span>
                </div>
              )}
              {y.badge === "new" && (
                <div style={{
                  position: "absolute", top: 8, left: 8,
                  fontSize: 11, padding: "3px 7px", borderRadius: 4,
                  background: "#fff", color: "#0a0a0c", fontWeight: 700,
                  textTransform: "uppercase", letterSpacing: ".08em",
                  border: "1px solid #e4e4e7",
                }}>New</div>
              )}
              {/* Photo count overlay removed per design feedback */}
            </div>
            <div style={{ padding: "10px 12px" }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                <div style={{ fontSize: 13, fontWeight: 600, color: "#0a0a0c" }}>{y.name}</div>
                <div style={{ fontSize: 13, fontWeight: 700, color: "#0a0a0c", fontFamily: T.fDisplay }}>{y.price}</div>
              </div>
              <div style={{ fontSize: 13, color: "#71717a", marginTop: 3 }}>{y.year} · {y.loc}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ─── Mock 04 - YouTube watch page with playing video + scrubber
function MockWatch({ active, A, T }) {
  const [progress, setProgress] = React.useState(0);
  React.useEffect(() => {
    if (!active) return;
    const id = setInterval(() => setProgress(p => (p + 1) % 100), 80);
    return () => clearInterval(id);
  }, [active]);
  return (
    <div style={{ padding: 0, background: "#0f0f0f", height: 460, color: "#fff", display: "flex", flexDirection: "column" }}>
      {/* Player */}
      <div style={{
        position: "relative", flex: "0 0 280px",
        background: `linear-gradient(180deg, #1a3a5e, #0a1a2e)`,
        overflow: "hidden",
      }}>
        {/* Faux yacht in motion */}
        <div style={{
          position: "absolute", inset: 0,
          background: `radial-gradient(ellipse 120% 80% at 50% 110%, rgba(124,92,255,.15), transparent 60%)`,
        }}/>
        <div style={{
          position: "absolute", left: "50%", top: "50%",
          transform: `translate(-50%, -50%) translateX(${active ? Math.sin(progress / 15) * 8 : 0}px)`,
          width: "60%", height: "20%",
          transition: "transform 1s ease-in-out",
        }}>
          <div style={{
            width: "100%", height: "60%",
            background: "rgba(255,255,255,.12)",
            borderRadius: "20% 20% 8px 8px / 100% 100% 8px 8px",
          }}/>
          <div style={{
            position: "absolute", left: "20%", right: "20%", top: "0",
            height: "70%",
            background: "rgba(255,255,255,.06)",
            clipPath: "polygon(15% 100%, 85% 100%, 95% 50%, 50% 0%, 5% 50%)",
          }}/>
        </div>
        {/* Sea reflection */}
        <div style={{
          position: "absolute", left: 0, right: 0, bottom: 0, height: "30%",
          background: "linear-gradient(180deg, transparent, rgba(255,255,255,.04))",
        }}/>
        {/* Live time */}
        <div style={{
          position: "absolute", top: 12, left: 12,
          padding: "3px 8px", background: "rgba(0,0,0,.6)", borderRadius: 4,
          fontSize: 13, fontFamily: "ui-monospace, monospace",
        }}>4K · 7:07 / 12:34</div>
        {/* Progress bar */}
        <div style={{
          position: "absolute", left: 0, right: 0, bottom: 0, height: 4,
          background: "rgba(255,255,255,.15)",
        }}>
          <div style={{
            height: "100%", width: `${progress}%`,
            background: "#ff0033", transition: "width .08s linear",
          }}/>
        </div>
      </div>

      {/* Title + meta */}
      <div style={{ padding: "14px 18px 0" }}>
        <div style={{
          fontSize: 16, fontWeight: 600, color: "#fff",
          fontFamily: T.fDisplay, letterSpacing: "-0.01em",
          marginBottom: 8, lineHeight: 1.3,
        }}>Princess Y85 · Full walkthrough · Cannes 2025</div>
        <div style={{ display: "flex", gap: 16, fontSize: 13, color: "#aaa", marginBottom: 12 }}>
          <span>847K views</span>
          <span>3 weeks ago</span>
          <span>Avg. watch: 7:07</span>
        </div>
      </div>

      {/* Channel row */}
      <div style={{ padding: "12px 18px", borderTop: "1px solid #272727", display: "flex", alignItems: "center", gap: 12 }}>
        <div style={{
          width: 36, height: 36, borderRadius: 18,
          background: `linear-gradient(135deg, ${A}, #ff5e8c)`,
          display: "flex", alignItems: "center", justifyContent: "center",
          fontSize: 13, fontWeight: 700, color: "#fff",
        }}>YW</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 600 }}>YachtWay</div>
          <div style={{ fontSize: 13, color: "#aaa" }}>500K subscribers</div>
        </div>
        <div style={{ padding: "7px 14px", borderRadius: 18, background: "#fff", color: "#000", fontSize: 13, fontWeight: 600 }}>Subscribe</div>
      </div>
    </div>
  );
}

// ─── Mock 04b - YachtWay LIVE broadcast frame on the listing page.
//    Live REC pill, viewer count, scrolling chat, "Schedule a tour"
//    affordance underneath. The point is: this isn't a separate site;
//    the live show lives on the same listing the buyer just opened.
function MockLive({ active, A, T, tint }) {
  // Animated viewer count + chat scroll. Both pause when off-screen
  // so the cinema doesn't burn frames in the background.
  const [viewers, setViewers] = React.useState(127);
  const [chatIdx, setChatIdx] = React.useState(0);
  React.useEffect(() => {
    if (!active) return;
    const v = setInterval(() => {
      setViewers((c) => Math.max(80, Math.min(220, c + (Math.random() < 0.55 ? 1 : -1) * Math.ceil(Math.random() * 3))));
    }, 700);
    const c = setInterval(() => setChatIdx((i) => i + 1), 1800);
    return () => { clearInterval(v); clearInterval(c); };
  }, [active]);

  const CHAT = [
    { who: "Marcus T.",  msg: "What's the cruising range?", role: "buyer" },
    { who: "Sofia R.",   msg: "Show me the engine room?",   role: "buyer" },
    { who: "YachtWay",   msg: "Heading down now, full tour next.", role: "host" },
    { who: "Kenji M.",   msg: "Trim tabs standard?",        role: "buyer" },
    { who: "Yara L.",    msg: "Beautiful saloon.",          role: "buyer" },
    { who: "James W.",   msg: "Is she available for a sea trial in May?", role: "buyer" },
    { who: "Olivia D.",  msg: "Is a refit needed?",         role: "buyer" },
    { who: "YachtWay",   msg: "Hull was redone in '23, full report on listing.", role: "host" },
  ];
  const visible = [];
  for (let i = 0; i < 4; i++) visible.push(CHAT[(chatIdx + i) % CHAT.length]);

  return (
    <div style={{
      background: "#0a0a0c", height: 460, color: "#fff",
      display: "grid", gridTemplateColumns: "1.6fr 1fr", gap: 0,
      fontFamily: T.fBody,
    }}>
      {/* ── Broadcast frame (left) ── */}
      <div style={{
        position: "relative",
        background: `radial-gradient(ellipse 100% 60% at 50% 100%, rgba(124,92,255,.20), transparent 60%), linear-gradient(180deg, #1c2738 0%, #0a1726 100%)`,
        overflow: "hidden",
      }}>
        {/* faux yacht, bow on, gentle horizon */}
        <div aria-hidden="true" style={{
          position: "absolute", left: 0, right: 0, bottom: "30%",
          height: 1, background: "rgba(255,255,255,.10)",
        }}/>
        <div aria-hidden="true" style={{
          position: "absolute", left: "50%", bottom: "26%",
          transform: `translateX(-50%) ${active ? `translateX(${Math.sin(Date.now()/2400) * 4}px)` : ""}`,
          width: "62%", maxWidth: 360, transition: "transform 1.5s ease-in-out",
        }}>
          <svg viewBox="0 0 200 80" width="100%" height="auto" style={{ display: "block" }}>
            {/* hull */}
            <path d="M 12 56 Q 100 70 188 56 L 178 70 Q 100 80 22 70 Z" fill="rgba(255,255,255,.16)"/>
            {/* superstructure */}
            <path d="M 38 56 L 162 56 L 152 38 L 48 38 Z" fill="rgba(255,255,255,.10)"/>
            <path d="M 70 38 L 130 38 L 124 22 L 76 22 Z" fill="rgba(255,255,255,.07)"/>
            {/* warm window glow */}
            <rect x="56"  y="42" width="14" height="6" fill="rgba(255,210,140,.55)"/>
            <rect x="78"  y="42" width="14" height="6" fill="rgba(255,210,140,.55)"/>
            <rect x="100" y="42" width="14" height="6" fill="rgba(255,210,140,.55)"/>
            <rect x="122" y="42" width="14" height="6" fill="rgba(255,210,140,.55)"/>
            {/* mast */}
            <line x1="100" y1="22" x2="100" y2="2" stroke="rgba(255,255,255,.25)" strokeWidth="1"/>
          </svg>
        </div>
        {/* sea reflection */}
        <div aria-hidden="true" style={{
          position: "absolute", left: 0, right: 0, bottom: 0, height: "28%",
          background: "linear-gradient(180deg, transparent, rgba(124,92,255,.10) 60%, rgba(0,0,0,.4))",
        }}/>

        {/* REC pill (top-left) */}
        <div style={{
          position: "absolute", top: 14, left: 14,
          display: "inline-flex", alignItems: "center", gap: 8,
          padding: "6px 12px", borderRadius: 999,
          background: "rgba(0,0,0,.55)", backdropFilter: "blur(8px)",
          fontSize: 11, fontWeight: 700, letterSpacing: ".18em", textTransform: "uppercase",
        }}>
          <span style={{
            width: 8, height: 8, borderRadius: 4, background: "#ff2d55",
            animation: active ? "pulse-dot 1.2s ease-in-out infinite" : "none",
          }}/>
          LIVE
        </div>

        {/* Viewer count (top-right) */}
        <div style={{
          position: "absolute", top: 14, right: 14,
          display: "inline-flex", alignItems: "center", gap: 6,
          padding: "6px 10px", borderRadius: 999,
          background: "rgba(0,0,0,.55)", backdropFilter: "blur(8px)",
          fontSize: 12, fontWeight: 600,
          fontVariantNumeric: "tabular-nums",
        }}>
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2"><circle cx="12" cy="12" r="3"/><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z"/></svg>
          {viewers} watching
        </div>

        {/* Bottom strap, listing context */}
        <div style={{
          position: "absolute", left: 0, right: 0, bottom: 0,
          padding: "12px 16px",
          background: "linear-gradient(180deg, transparent, rgba(0,0,0,.6))",
          display: "flex", alignItems: "center", gap: 12,
        }}>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{
              fontSize: 11, fontWeight: 700, letterSpacing: ".14em", textTransform: "uppercase",
              color: "rgba(255,255,255,.55)", marginBottom: 3,
            }}>Now showing</div>
            <div style={{
              fontFamily: T.fDisplay, fontSize: 15, fontWeight: 600,
              letterSpacing: "-0.01em", color: "#fff", lineHeight: 1.2,
              whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
            }}>Princess Y85 · 2024 · €5.2M</div>
          </div>
          <button style={{
            appearance: "none", border: "none",
            padding: "8px 14px", borderRadius: 999,
            background: "#fff", color: "#0a0a0c",
            fontSize: 12, fontWeight: 700, letterSpacing: "-0.005em",
            cursor: "pointer", flex: "none",
          }}>Schedule tour</button>
        </div>
      </div>

      {/* ── Side rail: chat ── */}
      <div style={{
        background: "#111114",
        borderLeft: "1px solid rgba(255,255,255,.06)",
        display: "flex", flexDirection: "column",
      }}>
        <div style={{
          padding: "12px 16px",
          borderBottom: "1px solid rgba(255,255,255,.06)",
          display: "flex", alignItems: "center", justifyContent: "space-between",
        }}>
          <div style={{
            fontSize: 11, fontWeight: 700, letterSpacing: ".14em",
            color: "rgba(255,255,255,.55)", textTransform: "uppercase",
          }}>Live Q&amp;A</div>
          <div style={{
            fontSize: 11, color: "rgba(255,255,255,.45)",
            fontVariantNumeric: "tabular-nums",
          }}>{viewers} buyers</div>
        </div>
        <div style={{
          padding: "10px 12px", flex: 1, overflow: "hidden",
          display: "flex", flexDirection: "column", gap: 10,
          fontSize: 12, lineHeight: 1.4,
        }}>
          {visible.map((m, i) => {
            const isHost = m.role === "host";
            const initials = m.who.split(" ").map(p => p[0]).join("").slice(0, 2);
            return (
              <div key={chatIdx + "-" + i} style={{
                display: "flex", gap: 8, alignItems: "flex-start",
                opacity: 1 - (i * 0.18),
                transition: "opacity .35s ease",
              }}>
                <div style={{
                  width: 22, height: 22, borderRadius: 11, flex: "none",
                  background: isHost ? A : "rgba(255,255,255,.10)",
                  color: "#fff",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  fontSize: 10, fontWeight: 700, letterSpacing: ".02em",
                }}>{initials}</div>
                <div style={{ minWidth: 0, flex: 1 }}>
                  <div style={{
                    fontSize: 11, fontWeight: 700, letterSpacing: "-0.005em",
                    color: isHost ? A : "#fff", marginBottom: 1,
                  }}>{m.who}{isHost && <span style={{
                    marginLeft: 6, fontSize: 9, padding: "1px 6px",
                    borderRadius: 4, background: tint(.20), color: A,
                    letterSpacing: ".08em", textTransform: "uppercase",
                  }}>Host</span>}</div>
                  <div style={{ color: "rgba(255,255,255,.78)" }}>{m.msg}</div>
                </div>
              </div>
            );
          })}
        </div>
        {/* Composer */}
        <div style={{
          padding: "10px 12px",
          borderTop: "1px solid rgba(255,255,255,.06)",
          display: "flex", gap: 8, alignItems: "center",
        }}>
          <div style={{
            flex: 1, padding: "8px 12px", borderRadius: 8,
            background: "rgba(255,255,255,.06)",
            fontSize: 11, color: "rgba(255,255,255,.45)",
          }}>Ask a question…</div>
          <button style={{
            appearance: "none", border: "none",
            width: 28, height: 28, borderRadius: 8,
            background: A, color: "#fff",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            cursor: "pointer", flex: "none",
          }}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/></svg></button>
        </div>
      </div>
    </div>
  );
}

// ─── Mock 05 - Broker dashboard inbox with a hot lead
function MockBroker({ active, A, T, tint }) {
  return (
    <div style={{ background: "#fff", height: 460, display: "flex" }}>
      {/* Sidebar */}
      <div style={{ width: 130, background: "#fafafa", borderRight: "1px solid #ececef", padding: "14px 10px" }}>
        <div style={{ fontSize: 11, color: "#a1a1aa", textTransform: "uppercase", letterSpacing: ".12em", marginBottom: 10, fontWeight: 700 }}>YachtWay</div>
        {["Inbox", "Listings", "Studio"].map((it, i) => (
          <div key={i} style={{
            padding: "7px 10px", borderRadius: 6,
            background: i === 0 ? tint(.10) : "transparent",
            color: i === 0 ? A : "#52525b",
            fontSize: 13, fontWeight: i === 0 ? 600 : 500,
            marginBottom: 2,
            display: "flex", justifyContent: "space-between", alignItems: "center",
          }}>{it} {i === 0 && <span style={{ fontSize: 13, padding: "1px 5px", borderRadius: 8, background: A, color: "#fff", fontWeight: 700 }}>3</span>}</div>
        ))}
      </div>

      {/* Inbox list */}
      <div style={{ flex: 1, display: "flex" }}>
        <div style={{ width: 220, borderRight: "1px solid #ececef" }}>
          <div style={{ padding: "12px 14px", borderBottom: "1px solid #ececef", fontSize: 13, fontWeight: 600 }}>Inbox <span style={{ color: "#a1a1aa", fontWeight: 500 }}>· 12</span></div>
          {[
            { name: "James Whitmore", msg: "Re: Princess Y85, Monaco viewing", time: "2m", hot: true, unread: true },
            { name: "Elena Krasner", msg: "Pre-approval for Sunseeker 95", time: "1h", unread: true },
            { name: "Marco Bellini", msg: "Schedule: Cannes show, Stand B-12", time: "3h" },
            { name: "Priya Shah", msg: "Do you have a 3D Tour I could see?", time: "1d" },
          ].map((m, i) => (
            <div key={i} style={{
              padding: "12px 14px", borderBottom: "1px solid #f4f4f5",
              background: i === 0 ? tint(.05) : "transparent",
              borderLeft: i === 0 ? `3px solid ${A}` : "3px solid transparent",
              cursor: "pointer",
            }}>
              <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 2 }}>
                <span style={{ fontSize: 13, fontWeight: m.unread ? 700 : 500, color: "#0a0a0c" }}>{m.name}</span>
                <span style={{ fontSize: 13, color: m.hot ? A : "#a1a1aa", fontWeight: m.hot ? 700 : 500 }}>{m.hot ? "● " : ""}{m.time}</span>
              </div>
              <div style={{ fontSize: 13, color: "#71717a", lineHeight: 1.4, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{m.msg}</div>
            </div>
          ))}
        </div>

        {/* Conversation */}
        <div style={{ flex: 1, padding: 16, display: "flex", flexDirection: "column", gap: 10 }}>
          <div style={{ paddingBottom: 12, borderBottom: "1px solid #ececef" }}>
            <div style={{ fontSize: 13, fontWeight: 600 }}>James Whitmore</div>
            <div style={{ fontSize: 13, color: "#71717a" }}>Princess Y85 · Monaco</div>
          </div>

          <style>{`
            @keyframes typing {
              0%, 60%, 100% { transform: translateY(0); opacity: .4; }
              30% { transform: translateY(-3px); opacity: 1; }
            }
            .typing-dot { animation: typing 1.2s ease-in-out infinite; }
          `}</style>

          <div style={{
            background: "#f4f4f5", padding: "8px 12px", borderRadius: 10,
            fontSize: 13, color: "#0a0a0c", maxWidth: "80%", lineHeight: 1.5,
          }}>Saw the walkthrough on YouTube last night. Sent a request for viewing.</div>

          <div style={{ alignSelf: "flex-end", maxWidth: "80%" }}>
            <div style={{
              background: A, color: "#fff", padding: "8px 12px", borderRadius: 10,
              fontSize: 13, lineHeight: 1.5,
            }}>Yes - showing confirmed! See you on Saturday 11AM.</div>
            <div style={{ fontSize: 13, color: "#a1a1aa", textAlign: "right", marginTop: 3 }}>Sent · Read</div>
          </div>

          {active && (
            <div style={{ display: "flex", gap: 4, padding: "6px 12px", background: "#f4f4f5", borderRadius: 10, alignSelf: "flex-start", marginTop: 4 }}>
              {[0,1,2].map(i => (
                <span key={i} className="typing-dot" style={{
                  width: 5, height: 5, borderRadius: "50%", background: "#71717a",
                  animationDelay: `${i*0.15}s`,
                }}/>
              ))}
            </div>
          )}

          {/* Message input row - paperclip + reply field + send */}
          <div style={{
            marginTop: "auto",
            display: "flex", alignItems: "center", gap: 8,
            paddingTop: 12, borderTop: "1px solid #ececef",
          }}>
            {/* Attach (paperclip) */}
            <button style={{
              width: 30, height: 30, borderRadius: 8,
              border: "1px solid #e4e4e7", background: "#fff",
              display: "flex", alignItems: "center", justifyContent: "center",
              color: "#52525b", cursor: "pointer", flexShrink: 0,
            }} aria-label="Attach a file">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
                stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/>
              </svg>
            </button>
            {/* Reply field */}
            <div style={{
              flex: 1, height: 30, borderRadius: 8,
              border: "1px solid #e4e4e7", background: "#fafafa",
              padding: "0 10px",
              display: "flex", alignItems: "center",
              fontSize: 13, color: "#a1a1aa",
            }}>
              Reply to Priya...
            </div>
            {/* Send */}
            <button style={{
              width: 30, height: 30, borderRadius: 8,
              border: "none", background: A, color: "#fff",
              display: "flex", alignItems: "center", justifyContent: "center",
              cursor: "pointer", flexShrink: 0,
            }} aria-label="Send">
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none"
                stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M22 2L11 13"/>
                <path d="M22 2l-7 20-4-9-9-4 20-7z"/>
              </svg>
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Mock 06 - Contract closing screen with signature ticking
function MockClose({ active, A, T, tint }) {
  const [signed, setSigned] = React.useState(false);
  React.useEffect(() => {
    if (!active) { setSigned(false); return; }
    const id = setTimeout(() => setSigned(true), 1400);
    return () => clearTimeout(id);
  }, [active]);
  return (
    <div style={{ background: "#fff", height: 460, padding: 24, display: "grid", gridTemplateColumns: "1fr 240px", gap: 18 }}>
      {/* Document */}
      <div style={{
        background: "#fafafa", border: "1px solid #ececef", borderRadius: 8,
        padding: "20px 22px", overflow: "hidden", position: "relative",
      }}>
        <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 14 }}>
          <div>
            <div style={{ fontSize: 11, color: "#a1a1aa", textTransform: "uppercase", letterSpacing: ".14em", fontWeight: 700, marginBottom: 4 }}>EasySign · Purchase Agreement</div>
            <div style={{ fontFamily: T.fDisplay, fontSize: 17, fontWeight: 700, letterSpacing: "-0.01em" }}>Princess Y85 · 2024</div>
          </div>
          <div style={{ fontSize: 13, color: "#a1a1aa" }}>SP-2841</div>
        </div>

        {/* Faux text rows */}
        {[100, 92, 96, 70, 100, 88, 100, 60].map((w, i) => (
          <div key={i} style={{
            height: 6, width: `${w}%`,
            background: i % 3 === 0 ? "#d4d4d8" : "#e4e4e7",
            borderRadius: 3, marginBottom: 8,
          }}/>
        ))}

        <div style={{ height: 14 }}/>

        <div style={{ display: "flex", gap: 24 }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13, color: "#71717a", marginBottom: 4, fontWeight: 600 }}>BUYER</div>
            <div style={{
              border: `1.5px dashed ${signed ? A : "#d4d4d8"}`,
              borderRadius: 6, padding: "8px 12px", height: 56,
              display: "flex", alignItems: "center",
              background: signed ? tint(.05) : "transparent",
              transition: "all .4s",
              overflow: "hidden",
            }}>
              {/* Buyer's signature - real cursive font with reveal-mask animation */}
              <div style={{
                position: "relative",
                width: "100%", height: "100%",
                overflow: "visible",
                display: "flex", alignItems: "center",
              }}>
                <div style={{
                  fontFamily: "'Mrs Saint Delafield', 'Allura', 'Pinyon Script', cursive",
                  fontSize: 30, lineHeight: 1,
                  color: signed ? A : "transparent",
                  letterSpacing: "0.01em",
                  whiteSpace: "nowrap",
                  // Mask reveal: gradient mask wipes left→right when signed.
                  // Width animates from 0 to 100% giving the illusion of the
                  // pen drawing across the page.
                  WebkitMaskImage: "linear-gradient(90deg, #000 0%, #000 100%)",
                  maskImage: "linear-gradient(90deg, #000 0%, #000 100%)",
                  clipPath: signed ? "inset(-20% 0 -20% 0)" : "inset(-20% 100% -20% 0)",
                  transition: "clip-path 1.6s cubic-bezier(.65,.05,.36,1), color .2s",
                  transform: "rotate(-2deg)",
                  transformOrigin: "left center",
                  paddingBottom: 4,
                }}>
                  James Whitmore
                </div>
              </div>
            </div>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13, color: "#71717a", marginBottom: 4, fontWeight: 600 }}>BROKER</div>
            <div style={{
              border: `1.5px dashed ${A}`, background: tint(.05),
              borderRadius: 6, padding: "8px 12px", height: 56,
              display: "flex", alignItems: "center",
              overflow: "hidden",
            }}>
              {/* Broker's signature - cursive font with reveal-mask animation */}
              <div style={{
                position: "relative",
                width: "100%", height: "100%",
                overflow: "hidden",
                display: "flex", alignItems: "center",
              }}>
                <div style={{
                  fontFamily: "'Homemade Apple', 'Caveat', cursive",
                  fontSize: 18, lineHeight: 1,
                  color: A,
                  letterSpacing: "0.01em",
                  whiteSpace: "nowrap",
                  // Vertical clip is loose so cursive descenders are not chopped;
                  // horizontal clip stays tight so the signature cannot escape
                  // its dashed box into the next column.
                  clipPath: "inset(-50% 0 -50% 0)",
                  animation: "broker-sig-reveal 1.4s cubic-bezier(.65,.05,.36,1) both",
                  transform: "rotate(-1deg)",
                  transformOrigin: "left center",
                  paddingBottom: 4,
                }}>
                  Marcus Reed
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* DocuSign attribution */}
        <div style={{
          marginTop: 10, display: "flex", alignItems: "center", justifyContent: "center", gap: 6,
          fontSize: 13, color: "#a1a1aa",
        }}>
          <span>Signatures powered by</span>
          {/* Docusign logo - 2024 brand: Nexus icon + wordmark.
              Nexus icon = two semicircle/blob shapes joining to form an
              agreement-shape in the center. Brand colors: navy (#23252A)
              and Cobalt blue (#3858E9). */}
          <svg viewBox="0 0 128 22" width="108" height="18" aria-label="Docusign" style={{ display: "block" }}>
            {/* Nexus icon - two interlocking rounded shapes */}
            <g transform="translate(0 1)">
              {/* Left half - cobalt blue */}
              <path
                d="M 10 0
                   C 4.48 0, 0 4.48, 0 10
                   C 0 15.52, 4.48 20, 10 20
                   C 10 16, 7 14, 7 10
                   C 7 6, 10 4, 10 0 Z"
                fill="#3858E9"
              />
              {/* Right half - navy */}
              <path
                d="M 10 0
                   C 15.52 0, 20 4.48, 20 10
                   C 20 15.52, 15.52 20, 10 20
                   C 10 16, 13 14, 13 10
                   C 13 6, 10 4, 10 0 Z"
                fill="#23252A"
              />
            </g>
            {/* Wordmark "Docusign" in their navy */}
            <text x="26" y="16"
              fontFamily="-apple-system, system-ui, 'Segoe UI', sans-serif"
              fontWeight="700"
              fontSize="15"
              letterSpacing="-0.5"
              fill="#23252A">Docusign</text>
          </svg>
        </div>

        <style>{`
          @keyframes broker-sig {
            from { stroke-dashoffset: var(--bs-from, 280); }
            to   { stroke-dashoffset: 0; }
          }
          @keyframes broker-sig-reveal {
            from { clip-path: inset(0 100% 0 0); }
            to   { clip-path: inset(0 0 0 0); }
          }
        `}</style>
      </div>

      {/* Side rail */}
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        <div style={{ padding: 14, background: tint(.05), borderRadius: 10, border: `1px solid ${tint(.20)}` }}>
          <div style={{ fontSize: 11, color: A, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".12em", marginBottom: 6 }}>Status</div>
          <div style={{
            fontSize: 13, fontWeight: 600, color: "#0a0a0c",
            display: "flex", alignItems: "center", gap: 8,
          }}>
            <span style={{
              width: 8, height: 8, borderRadius: 4,
              background: signed ? "#10b981" : A,
              animation: signed ? "none" : "pulse-dot 1.4s ease-in-out infinite",
            }}/>
            {signed ? "Closed · funds wired" : "Awaiting buyer signature"}
          </div>
        </div>

        <div style={{ padding: 14, background: "#fafafa", borderRadius: 10, border: "1px solid #ececef" }}>
          <div style={{ fontSize: 11, color: "#a1a1aa", fontWeight: 700, textTransform: "uppercase", letterSpacing: ".12em", marginBottom: 10 }}>Built-in</div>
          {[
            "Purchase agreements",
            "Listing agreements",
            "Vessel acceptance",
            "Bill of sale",
            "USCG documentation",
            "+ more",
          ].map((k, i) => (
            <div key={i} style={{
              fontSize: 13, fontWeight: 600, color: i === 5 ? "#a1a1aa" : "#0a0a0c",
              padding: "5px 0",
              borderBottom: i < 5 ? "1px solid #f0f0f2" : "none",
            }}>{k}</div>
          ))}
        </div>

        <div style={{
          padding: "11px 14px", borderRadius: 10,
          background: signed ? "#3b1d6e" : "#0a0a0c",
          color: "#fff", fontSize: 13, fontWeight: 600,
          textAlign: "center",
          transition: "background .4s",
        }}>{signed ? "✓ Deal closed" : "Send to buyer"}</div>
      </div>
    </div>
  );
}

window.BuyerJourneyCinema = BuyerJourneyCinema;
window.BUYER_JOURNEY_STAGES = STAGES;
window.BuyerJourneyUIMock = UIMock;
