// Feature Spotlights — one section per item in the sticky feature nav.
// Order: stream · ticketing · chat · clips · merch · brand
// Article ids match the chip hrefs in Section_3_Unified.

// Shared hook — respects prefers-reduced-motion (and reacts to changes live).
function usePrefersReducedMotion() {
  const [reduced, setReduced] = React.useState(() => {
    if (typeof window === "undefined" || !window.matchMedia) return false;
    return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  });
  React.useEffect(() => {
    if (!window.matchMedia) return;
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    const onChange = () => setReduced(mq.matches);
    mq.addEventListener?.("change", onChange);
    return () => mq.removeEventListener?.("change", onChange);
  }, []);
  return reduced;
}

function FeatureSpotlights() {
  const [purchases, setPurchases] = React.useState(3);
  const reduced = usePrefersReducedMotion();
  React.useEffect(() => {
    if (reduced) return;
    const t = setInterval(() => setPurchases(p => p + Math.floor(Math.random() * 2)), 2600);
    return () => clearInterval(t);
  }, [reduced]);

  const cardShell = {
    display: "grid", gridTemplateColumns: "1fr 1fr", gap: 0,
    borderRadius: 24, overflow: "hidden",
    background: "rgb(255 255 255 / 0.03)",
    border: "1px solid rgb(255 255 255 / 0.08)",
    minHeight: 480,
    scrollMarginTop: 90,
  };
  const copyPane = { padding: 56, display: "flex", flexDirection: "column", justifyContent: "center" };
  const visualPane = { position: "relative", background: "oklch(0.15 0.01 260)", overflow: "hidden" };
  const bullet = (x, i) => (
    <li key={i} style={{ display: "flex", gap: 10, fontSize: 14, color: "var(--fg-2)" }}>
      <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="var(--color-primary)" strokeWidth="2.5" strokeLinecap="round" style={{ marginTop: 4, flexShrink: 0 }}><path d="M20 6L9 17l-5-5"/></svg>
      {x}
    </li>
  );
  const eyebrowStyle = { color: "var(--color-primary)", marginBottom: 18 };
  const h3Style = { fontSize: 40, fontWeight: 700, letterSpacing: "-0.03em", lineHeight: 1.05, margin: 0, marginBottom: 18, textWrap: "balance" };
  const leadStyle = { fontSize: 16, lineHeight: 1.55, color: "var(--fg-2)", margin: 0, marginBottom: 24, textWrap: "pretty" };
  const listStyle = { margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: 10 };

  return (
    <section id="spotlights" style={{ padding: "80px 60px 120px", borderTop: "1px solid rgb(255 255 255 / 0.06)" }}>
      <div style={{ maxWidth: 1440, margin: "0 auto" }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>

          {/* 01 — Live stream */}
          <article id="stream" style={cardShell}>
            <div style={copyPane}>
              <div className="eyebrow" style={eyebrowStyle}>01 · Live stream</div>
              <h3 style={h3Style}>Broadcast-grade<br/>playback, everywhere.</h3>
              <p style={leadStyle}>
                Adaptive delivery that holds up on a phone in a tunnel and a 4K TV on a gigabit line. Sub-second joins, tight stream-to-screen latency, and graceful handling of the messy network between you and your viewer.
              </p>
              <ul style={listStyle}>
                {[
                  "Adaptive bitrate — from 144p mobile to 4K TV",
                  "Low-latency delivery, global by default",
                  "Multi-bitrate ingest with a documented failover path",
                ].map(bullet)}
              </ul>
            </div>
            <div style={visualPane}><StreamVisual /></div>
          </article>

          {/* 02 — Ticketing */}
          <article id="ticketing" style={cardShell}>
            <div style={visualPane}><TicketingVisual /></div>
            <div style={copyPane}>
              <div className="eyebrow" style={eyebrowStyle}>02 · Ticketing</div>
              <h3 style={h3Style}>Sell exactly<br/>the way you sell.</h3>
              <p style={leadStyle}>
                The same event, priced four ways: full-event pass, day pass, single stage, single session. Sale windows, quantity caps, promo codes, refunds, revenue splits. Ticketing that matches the shape of your event, not the other way around.
              </p>
              <ul style={listStyle}>
                {[
                  "Four pricing granularities on the same event",
                  "Sale windows, quantity caps, promo codes, refunds",
                  "Per-ticket licensing — one ticket, one active session",
                ].map(bullet)}
              </ul>
            </div>
          </article>

          {/* 03 — Real-time chat */}
          <article id="chat" style={cardShell}>
            <div style={copyPane}>
              <div className="eyebrow" style={eyebrowStyle}>03 · Real-time chat</div>
              <h3 style={h3Style}>A room,<br/>not a firehose.</h3>
              <p style={leadStyle}>
                Chat filters run before messages land on screen, not after. Moderators have single-tap ban, mute, slow mode, subscriber-only — the tools a live operation actually uses. Viewers feel like they're in a room together, not scrolling a deluge.
              </p>
              <ul style={listStyle}>
                {[
                  "Two-layer moderation: instant filter + intelligent review",
                  "Full operator toolkit — ban, mute, slow mode, subscriber-only",
                  "Scales with the audience — 50 people or 200,000",
                ].map(bullet)}
              </ul>
            </div>
            <div style={visualPane}><ChatVisual /></div>
          </article>

          {/* 04 — Clips for social */}
          <article id="clips" style={cardShell}>
            <div style={visualPane}><ClippingVisual /></div>
            <div style={copyPane}>
              <div className="eyebrow" style={eyebrowStyle}>04 · Clips for social</div>
              <h3 style={h3Style}>Clip it now.<br/>Post it now.</h3>
              <p style={leadStyle}>
                The best clip of the night goes viral the night of, not three days later. Mark a moment mid-stream, trim it, export 9:16 for TikTok/Reels/Shorts, 1:1 for feeds, 16:9 for everything else — while the event is still running.
              </p>
              <ul style={listStyle}>
                {[
                  "Mark-and-trim mid-stream, no post-production wait",
                  "Multi-format export — 9:16, 1:1, 4:5, 16:9",
                  "One-click publish to social with your brand overlay",
                ].map(bullet)}
              </ul>
            </div>
          </article>

          {/* 05 — Merch store */}
          <article id="merch" style={{ ...cardShell, minHeight: 620 }}>
            <div style={visualPane}><MerchVisual purchases={purchases} /></div>
            <div style={copyPane}>
              <div className="eyebrow" style={eyebrowStyle}>05 · Merch store</div>
              <h3 style={h3Style}>Merch at the<br/>moment of peak intent.</h3>
              <p style={leadStyle}>
                A vinyl shout-out on stage mid-set. A limited print offered at the end of the comedy special. The merch store sits on the same page as the stream — same brand, same checkout, same cart. No redirect, no friction, no lost sale.
              </p>
              <ul style={listStyle}>
                {[
                  "Attached to the viewer page, never a redirect",
                  "Drop items mid-event — timed releases, limited runs",
                  "One checkout for ticket, chat subscription, and merch",
                ].map(bullet)}
              </ul>
            </div>
          </article>

          {/* 06 — Your brand, your domain */}
          <article id="brand" style={cardShell}>
            <div style={copyPane}>
              <div className="eyebrow" style={eyebrowStyle}>06 · Your brand, your domain</div>
              <h3 style={h3Style}>It's your product.<br/>It should look like it.</h3>
              <p style={leadStyle}>
                Run on your own domain with automatic certificates. Your logo, your colours, your type, your language — right down to right-to-left scripts. Viewers never see us. They see you. That's the whole point.
              </p>
              <ul style={listStyle}>
                {[
                  "Custom domain with automatic SSL",
                  "Full visual theme — colours, type, logo, favicon",
                  "Multi-language with full right-to-left support",
                ].map(bullet)}
              </ul>
            </div>
            <div style={visualPane}><BrandVisual /></div>
          </article>

        </div>
      </div>
    </section>
  );
}

/* ---------- Visuals ---------- */

function StreamVisual() {
  const reduced = usePrefersReducedMotion();
  // Rungs, ordered top→bottom from highest to lowest.
  const rungs = [
    { q: "4K", k: "2160p · 12 Mbps"  },
    { q: "HD", k: "1080p · 6 Mbps"   },
    { q: "HD", k: "720p · 3 Mbps"    },
    { q: "SD", k: "480p · 1.2 Mbps"  },
    { q: "LD", k: "240p · 500 kbps"  },
  ];
  // Active rung sweeps up and down to mimic bandwidth adapting.
  // Sequence: 1 → 2 → 3 → 2 → 1 → 0 → 1 (loops)
  const sequence = [1, 2, 3, 2, 1, 0];
  const [step, setStep] = React.useState(0);
  React.useEffect(() => {
    if (reduced) return;
    const t = setInterval(() => setStep(s => (s + 1) % sequence.length), 1700);
    return () => clearInterval(t);
  }, [reduced]);

  const activeIdx = reduced ? 1 : sequence[step];
  const bitrate = rungs[activeIdx].k.split(" · ")[1];
  const res = rungs[activeIdx].k.split(" · ")[0];

  return (
    <div style={{ position: "absolute", inset: 0, padding: 32, display: "flex", flexDirection: "column", gap: 14 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div className="eyebrow" style={{ color: "var(--fg-2)" }}>Adaptive ladder</div>
        <span style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: "oklch(0.72 0.17 155)", display: "inline-flex", alignItems: "center", gap: 6 }}>
          <span style={{ width: 6, height: 6, borderRadius: 99, background: "oklch(0.72 0.17 155)" }} />
          LIVE · 01:14:22
        </span>
      </div>
      {/* Preview tile */}
      <div style={{ aspectRatio: "16/9", borderRadius: 10, background: "linear-gradient(135deg, oklch(0.28 0.15 320), oklch(0.18 0.08 280))", border: "1px solid rgb(255 255 255 / 0.08)", position: "relative", overflow: "hidden" }}>
        <div style={{ position: "absolute", left: 12, top: 12, display: "inline-flex", alignItems: "center", gap: 6, padding: "4px 8px", borderRadius: 6, background: "rgb(0 0 0 / 0.5)", fontSize: 10, color: "#fff", fontWeight: 600 }}>
          <span style={{ width: 6, height: 6, borderRadius: 99, background: "var(--color-primary)" }} /> LIVE
        </div>
        <div
          key={activeIdx}
          style={{
            position: "absolute", right: 12, top: 12,
            padding: "4px 8px", borderRadius: 6,
            background: "rgb(0 0 0 / 0.5)", fontSize: 10,
            fontFamily: "var(--font-mono)", color: "#fff",
            animation: reduced ? "none" : "fade-up 300ms var(--ease-standard) both",
          }}
        >
          {res} · {bitrate}
        </div>
        {/* Bandwidth bar — pulses with the active rung */}
        <div style={{ position: "absolute", left: 12, right: 12, bottom: 12, display: "flex", alignItems: "center", gap: 6 }}>
          <span style={{ fontSize: 9, fontFamily: "var(--font-mono)", color: "rgb(255 255 255 / 0.6)" }}>NET</span>
          <div style={{ flex: 1, height: 4, borderRadius: 2, background: "rgb(0 0 0 / 0.4)", overflow: "hidden" }}>
            <div style={{
              height: "100%",
              width: `${[95, 78, 55, 32, 18][activeIdx]}%`,
              background: "linear-gradient(90deg, var(--color-primary), oklch(0.72 0.17 155))",
              transition: reduced ? "none" : "width 800ms var(--ease-standard)",
            }} />
          </div>
        </div>
      </div>
      {/* Ladder with animated selector */}
      <div style={{ display: "flex", flexDirection: "column", gap: 6, position: "relative" }}>
        {/* Sliding highlight */}
        <div
          aria-hidden
          style={{
            position: "absolute", left: 0, right: 0,
            height: 32,
            top: activeIdx * 38,
            borderRadius: 8,
            background: "rgb(217 36 42 / 0.10)",
            border: "1px solid rgb(217 36 42 / 0.45)",
            boxShadow: "0 0 24px rgb(217 36 42 / 0.18)",
            transition: reduced ? "none" : "top 500ms var(--ease-standard)",
            pointerEvents: "none",
          }}
        />
        {rungs.map((r, i) => {
          const on = i === activeIdx;
          return (
            <div key={i} style={{
              position: "relative",
              display: "grid", gridTemplateColumns: "36px 1fr 60px", gap: 10,
              alignItems: "center",
              padding: "6px 10px", height: 32, borderRadius: 8,
              transition: reduced ? "none" : "color 300ms var(--ease-standard)",
            }}>
              <span style={{
                fontSize: 10, fontFamily: "var(--font-mono)", fontWeight: 600,
                color: on ? "var(--color-primary)" : "var(--fg-3)",
                transition: reduced ? "none" : "color 300ms",
              }}>{r.q}</span>
              <span style={{
                fontSize: 11,
                color: on ? "var(--fg-1)" : "var(--fg-3)",
                transition: reduced ? "none" : "color 300ms",
              }}>{r.k}</span>
              <span style={{
                fontSize: 9, fontFamily: "var(--font-mono)", textAlign: "right",
                color: on ? "oklch(0.72 0.17 155)" : "var(--fg-3)",
                transition: reduced ? "none" : "color 300ms",
              }}>{on ? "ACTIVE" : "—"}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function TicketingVisual() {
  const reduced = usePrefersReducedMotion();
  const tiers = [
    { n: "Full event pass",    p: "£180", d: "All 3 days · every stage",  accent: "oklch(0.54 0.23 27)",  promo: true },
    { n: "Saturday day pass",  p: "£85",  d: "Sat only · all stages",      accent: "oklch(0.65 0.16 200)" },
    { n: "Main stage only",    p: "£60",  d: "Sat · main stage",           accent: "oklch(0.72 0.17 140)" },
    { n: "Single session",     p: "£14",  d: "Headliner set · 90 min",     accent: "oklch(0.62 0.20 50)"  },
  ];

  // front index — the card currently on top; every tick, the top flicks off and
  // the next slides forward. Cards behind stack with offset + scale.
  const [front, setFront] = React.useState(0);
  React.useEffect(() => {
    if (reduced) return;
    const t = setInterval(() => setFront(f => (f + 1) % tiers.length), 2400);
    return () => clearInterval(t);
  }, [reduced]);

  const N = tiers.length;

  return (
    <div style={{ position: "absolute", inset: 0, padding: 32, display: "flex", flexDirection: "column", gap: 14 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div className="eyebrow" style={{ color: "var(--fg-2)" }}>Nocturne Festival · tiers</div>
        <span style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: "var(--fg-3)" }}>4 on sale</span>
      </div>

      {/* Card stack — constrained width */}
      <div style={{
        position: "relative",
        flex: 1,
        perspective: 1200,
        display: "flex", alignItems: "center", justifyContent: "center",
      }}>
        <div style={{ position: "relative", width: "min(320px, 100%)", height: "100%" }}>
          {tiers.map((t, i) => {
            const depth = (i - front + N) % N;
            const onTop = depth === 0;
            const translateY  = depth * 14;
            const scale       = 1 - depth * 0.04;
            const opacity     = depth === N - 1 ? 0 : 1 - depth * 0.18;
            const zIndex      = N - depth;

            return (
              <div
                key={i}
                style={{
                  position: "absolute",
                  left: 0, right: 0,
                  top: "50%",
                  transform: `translateY(calc(-50% + ${-translateY}px)) scale(${scale})`,
                  opacity,
                  zIndex,
                  transition: reduced ? "none" : "transform 650ms var(--ease-standard), opacity 500ms var(--ease-standard)",
                  transformOrigin: "50% 50%",
                  willChange: "transform, opacity",
                }}
              >
                <TicketCard tier={t} highlighted={onTop} />
              </div>
            );
          })}
        </div>
      </div>

      {/* Dots indicator */}
      <div style={{ display: "flex", justifyContent: "center", gap: 6 }}>
        {tiers.map((_, i) => (
          <span key={i} style={{
            width: i === front ? 18 : 6, height: 6, borderRadius: 99,
            background: i === front ? "var(--color-primary)" : "rgb(255 255 255 / 0.15)",
            transition: reduced ? "none" : "width 400ms var(--ease-standard), background 400ms",
          }} />
        ))}
      </div>
    </div>
  );
}

function TicketCard({ tier, highlighted }) {
  // Only the tier flagged with `promo` shows the applied EARLYBIRD discount.
  const hasPromo = !!tier.promo;
  const priceNum = parseFloat(tier.p.replace(/[^0-9.]/g, ""));
  const discounted = "£" + Math.round(priceNum * 0.85);

  return (
    <div style={{
      position: "relative",
      display: "grid",
      gridTemplateColumns: "14px 1fr",
      borderRadius: 12,
      overflow: "hidden",
      background: "linear-gradient(135deg, oklch(0.19 0.02 260), oklch(0.15 0.02 260))",
      border: `1px solid ${highlighted ? "rgb(217 36 42 / 0.45)" : "rgb(255 255 255 / 0.12)"}`,
      boxShadow: highlighted
        ? "0 20px 50px -10px rgb(0 0 0 / 0.6), 0 0 0 1px rgb(217 36 42 / 0.1)"
        : "0 8px 24px -6px rgb(0 0 0 / 0.5)",
      height: 128,
    }}>
      {/* left stub */}
      <div style={{
        background: tier.accent,
        position: "relative",
        borderRight: "1px dashed rgb(255 255 255 / 0.2)",
      }}>
        <div style={{ position: "absolute", top: -6, left: "50%", transform: "translateX(-50%)", width: 12, height: 12, borderRadius: 99, background: "oklch(0.15 0.01 260)" }} />
        <div style={{ position: "absolute", bottom: -6, left: "50%", transform: "translateX(-50%)", width: 12, height: 12, borderRadius: 99, background: "oklch(0.15 0.01 260)" }} />
      </div>
      {/* body */}
      <div style={{
        padding: "12px 16px",
        display: "grid",
        gridTemplateColumns: "minmax(0, 1fr) auto",
        gridTemplateRows: "auto auto auto 1fr auto",
        columnGap: 12,
        rowGap: 2,
        alignItems: "start",
        position: "relative",
      }}>
        <div style={{
          gridColumn: "1 / 2", gridRow: "1 / 2",
          fontSize: 14, fontWeight: 600, color: "var(--fg-1)",
          letterSpacing: "-0.01em", lineHeight: 1.2,
          whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
          minWidth: 0,
        }}>{tier.n}</div>
        <div style={{
          gridColumn: "2 / 3", gridRow: "1 / 2",
          display: "flex", alignItems: "baseline", gap: 6,
          whiteSpace: "nowrap",
        }}>
          {hasPromo && (
            <span style={{
              fontSize: 11, fontFamily: "var(--font-mono)", color: "var(--fg-3)",
              textDecoration: "line-through",
            }}>{tier.p}</span>
          )}
          <span style={{
            fontSize: 17, fontWeight: 700, lineHeight: 1.2,
            color: hasPromo ? "var(--color-primary)" : "var(--fg-1)",
            fontFamily: "var(--font-mono)",
          }}>{hasPromo ? discounted : tier.p}</span>
        </div>
        <div style={{
          gridColumn: "1 / 3", gridRow: "2 / 3",
          fontSize: 11, color: "var(--fg-3)",
          whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
          minWidth: 0,
        }}>{tier.d}</div>

        {/* Applied promo pill — only on the tier flagged with `promo` */}
        {hasPromo && (
          <div style={{
            gridColumn: "1 / 3", gridRow: "3 / 4",
            marginTop: 6,
            display: "inline-flex", alignItems: "center", gap: 6, alignSelf: "start", justifySelf: "start",
            padding: "3px 8px 3px 6px", borderRadius: 99,
            background: "oklch(0.72 0.17 155 / 0.12)",
            border: "1px solid oklch(0.72 0.17 155 / 0.35)",
            fontSize: 10, fontFamily: "var(--font-mono)",
            color: "oklch(0.82 0.17 155)",
            letterSpacing: "0.04em",
          }}>
            <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M20 6L9 17l-5-5"/></svg>
            EARLYBIRD applied · −15%
          </div>
        )}

        <div style={{
          gridColumn: "1 / 3", gridRow: "5 / 6",
          marginTop: 6, display: "flex", justifyContent: "space-between", alignItems: "center",
          fontSize: 9, fontFamily: "var(--font-mono)", color: "var(--fg-3)",
          letterSpacing: "0.12em",
        }}>
          <span>NOCTURNE · 2026</span>
          <span>ADMIT ONE</span>
        </div>
      </div>
    </div>
  );
}

function ChatVisual() {
  const reduced = usePrefersReducedMotion();

  // A larger pool we cycle through. Some carry reactions, some arrive as replies.
  const POOL = React.useMemo(() => [
    { u: "maya_r",    c: "that drop was insane 🔥",           t: "#f59e0b", r: ["🔥", "👏"] },
    { u: "deon__",    c: "who's on next?",                      t: "#10b981" },
    { u: "priya.l",   c: "stream quality is unreal",            t: "#8b5cf6", r: ["💯"] },
    { u: "tomek_b",   c: "merch link in chat?",                 t: "#ec4899" },
    { u: "isla.w",    c: "Saturday ticket still available",     t: "#06b6d4" },
    { u: "rafi.k",    c: "that transition was clean 🎛️",        t: "#f472b6", r: ["🎛️"] },
    { u: "noor_a",    c: "London tuning in, hi everyone 👋",    t: "#fb923c" },
    { u: "sam.bee",   c: "best set of the night imo",           t: "#22d3ee", r: ["❤️", "🔥", "🙌"] },
    { u: "kenji.w",   c: "encore pls 🙏",                       t: "#a78bfa" },
    { u: "elena_g",   c: "the bass in this room 🫠",            t: "#34d399", r: ["🫠"] },
    { u: "dre_x",     c: "watching with my crew in Berlin",     t: "#fbbf24" },
    { u: "juno.p",    c: "already bought the vinyl lol",        t: "#f87171", r: ["😅"] },
    { u: "omari_k",   c: "this quality on 4G?? magic",          t: "#60a5fa" },
    { u: "viv_m",     c: "chat is moving fast tonight",         t: "#c084fc" },
    { u: "hana.t",    c: "goosebumps this whole set",           t: "#fb7185", r: ["🥹"] },
    { u: "leo__",     c: "mods are on it 👏",                   t: "#2dd4bf" },
  ], []);

  // Visible queue of messages. We keep a rolling window of ~8–9 items.
  const MAX_VISIBLE = 8;
  const [messages, setMessages] = React.useState(() =>
    POOL.slice(0, 6).map((m, i) => ({ ...m, id: -i - 1, blocked: false, self: false }))
  );
  const [poolIdx, setPoolIdx] = React.useState(6);
  const [slow, setSlow] = React.useState(false);
  const [subsOnly, setSubsOnly] = React.useState(false);
  const [modMode, setModMode] = React.useState(false);
  const [banned, setBanned] = React.useState(() => new Set());
  const [muted, setMuted] = React.useState(() => new Set());
  const [input, setInput] = React.useState("");
  const nextIdRef = React.useRef(1);

  // Auto-loop incoming messages. Slow mode = 3× the interval.
  React.useEffect(() => {
    if (reduced) return;
    const base = slow ? 2400 : 900;
    const t = setInterval(() => {
      setMessages(prev => {
        const picked = POOL[poolIdx % POOL.length];
        setPoolIdx(i => i + 1);
        // Skip if user banned — show a blocked stub occasionally to demo filtering.
        if (banned.has(picked.u)) {
          const stub = { id: nextIdRef.current++, u: picked.u, c: "[filtered]", t: picked.t, blocked: true };
          const next = [...prev, stub];
          return next.slice(-MAX_VISIBLE);
        }
        if (muted.has(picked.u)) {
          // just skip entirely
          return prev;
        }
        const msg = { ...picked, id: nextIdRef.current++, self: false };
        const next = [...prev, msg];
        return next.slice(-MAX_VISIBLE);
      });
    }, base);
    return () => clearInterval(t);
  }, [reduced, slow, poolIdx, banned, muted, POOL]);

  function handleSend(e) {
    e?.preventDefault();
    const text = input.trim();
    if (!text) return;
    setMessages(prev => {
      const msg = {
        id: nextIdRef.current++,
        u: "you",
        c: text,
        t: "var(--color-primary)",
        self: true,
      };
      return [...prev, msg].slice(-MAX_VISIBLE);
    });
    setInput("");
  }

  function banUser(u) {
    setBanned(b => { const n = new Set(b); n.add(u); return n; });
    // remove their existing messages immediately
    setMessages(prev => prev.map(m => (m.u === u && !m.self) ? { ...m, c: "[removed by mod]", blocked: true } : m));
  }
  function muteUser(u) {
    setMuted(b => { const n = new Set(b); n.add(u); return n; });
  }

  const toolBtn = (on, label, onClick) => (
    <button
      key={label}
      onClick={onClick}
      style={{
        padding: "3px 8px", borderRadius: 6, fontSize: 10, cursor: "pointer",
        background: on ? "rgb(217 36 42 / 0.18)" : "rgb(255 255 255 / 0.05)",
        border: `1px solid ${on ? "rgb(217 36 42 / 0.5)" : "rgb(255 255 255 / 0.08)"}`,
        color: on ? "var(--color-primary)" : "var(--fg-2)",
        fontFamily: "inherit",
        transition: "all 150ms var(--ease-standard)",
      }}
      aria-pressed={on}
    >
      {label}{on ? " · ON" : ""}
    </button>
  );

  return (
    <div style={{ position: "absolute", inset: 0, padding: 32, display: "flex", flexDirection: "column", gap: 8 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span className="live-dot" style={{ width: 6, height: 6 }} />
          <span style={{ fontSize: 11, color: "var(--fg-2)", fontWeight: 500 }}>2,847 watching</span>
        </div>
        <div style={{ display: "flex", gap: 4 }}>
          {toolBtn(slow,     "Slow", () => setSlow(s => !s))}
          {toolBtn(subsOnly, "Subs", () => setSubsOnly(s => !s))}
          {toolBtn(modMode,  "Mod",  () => setModMode(s => !s))}
        </div>
      </div>

      {/* Message list */}
      <div style={{
        flex: 1, minHeight: 0,
        display: "flex", flexDirection: "column", justifyContent: "flex-end",
        gap: 2,
        overflow: "hidden",
        maskImage: "linear-gradient(to bottom, transparent 0, black 32px)",
        WebkitMaskImage: "linear-gradient(to bottom, transparent 0, black 32px)",
      }}>
        {messages.map((m) => (
          <ChatMessage
            key={m.id}
            m={m}
            modMode={modMode}
            reduced={reduced}
            onBan={() => banUser(m.u)}
            onMute={() => muteUser(m.u)}
          />
        ))}
      </div>

      <div style={{ fontSize: 10, lineHeight: 1.4, color: "var(--fg-3)", padding: "4px 8px", borderRadius: 6, background: "rgb(255 255 255 / 0.02)", border: "1px dashed rgb(255 255 255 / 0.1)", display: "flex", alignItems: "center", gap: 8 }}>
        <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="10"/><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"/></svg>
        {banned.size + muted.size > 0
          ? <>Filter active · {banned.size} banned · {muted.size} muted</>
          : <>Filter running · 1 message blocked this minute</>}
      </div>

      {/* Composer — actually works */}
      <form onSubmit={handleSend} style={{
        display: "flex", gap: 6, alignItems: "center",
        padding: "4px 4px 4px 12px", borderRadius: 10,
        background: "rgb(255 255 255 / 0.04)",
        border: `1px solid ${input ? "rgb(217 36 42 / 0.35)" : "rgb(255 255 255 / 0.1)"}`,
        transition: "border-color 150ms",
      }}>
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder={slow ? "Slow mode · 30s between messages…" : "Say something…"}
          style={{
            flex: 1, background: "transparent", border: "none", outline: "none",
            color: "var(--fg-1)", fontSize: 12, fontFamily: "inherit", padding: "6px 0",
          }}
        />
        <button
          type="submit"
          disabled={!input.trim()}
          style={{
            padding: "6px 10px", borderRadius: 8, border: "none", cursor: input.trim() ? "pointer" : "not-allowed",
            background: input.trim() ? "var(--color-primary)" : "rgb(255 255 255 / 0.08)",
            color: input.trim() ? "#fff" : "var(--fg-3)",
            fontSize: 11, fontWeight: 600, fontFamily: "inherit",
            transition: "background 150ms",
          }}
        >
          Send
        </button>
      </form>
    </div>
  );
}

function ChatMessage({ m, modMode, reduced, onBan, onMute }) {
  const [hover, setHover] = React.useState(false);
  const [gone, setGone]   = React.useState(false);

  if (gone) return null;

  const bg = m.blocked
    ? "rgb(255 255 255 / 0.02)"
    : (hover && modMode ? "rgb(217 36 42 / 0.06)" : "transparent");

  return (
    <div
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        position: "relative",
        fontSize: 12, lineHeight: 1.45,
        color: m.blocked ? "var(--fg-3)" : "var(--fg-2)",
        padding: "4px 8px",
        borderRadius: 6,
        background: bg,
        fontStyle: m.blocked ? "italic" : "normal",
        animation: reduced ? "none" : "chat-in 260ms var(--ease-standard) both",
        transition: "background 150ms",
        display: "flex", alignItems: "flex-start", gap: 8,
      }}
    >
      <span style={{ flex: 1, minWidth: 0, wordBreak: "break-word" }}>
        <span style={{ fontWeight: 600, color: m.t }}>
          {m.self && <span style={{ fontSize: 8, fontFamily: "var(--font-mono)", color: "var(--color-primary)", marginRight: 4, padding: "1px 4px", borderRadius: 3, background: "rgb(217 36 42 / 0.15)" }}>YOU</span>}
          {m.u}
        </span>
        <span style={{ color: "var(--fg-3)" }}>{" · "}</span>
        <span>{m.c}</span>
        {/* Emoji reactions — inline so they flow with the text */}
        {m.r && !m.blocked && m.r.map((emo, i) => (
          <span key={i} style={{
            display: "inline-block",
            fontSize: 10, lineHeight: 1,
            padding: "2px 5px", marginLeft: 4, borderRadius: 99,
            background: "rgb(255 255 255 / 0.06)",
            border: "1px solid rgb(255 255 255 / 0.08)",
            verticalAlign: "middle",
            animation: reduced ? "none" : `fade-up 360ms ${i * 80}ms var(--ease-standard) both`,
          }}>
            {emo}
          </span>
        ))}
      </span>

      {/* Mod actions */}
      {modMode && hover && !m.blocked && !m.self && (
        <span style={{
          display: "inline-flex", gap: 4, flexShrink: 0, alignSelf: "center",
        }}>
          <ModBtn label="Mute" onClick={(e) => { e.stopPropagation(); onMute(); setGone(true); }} />
          <ModBtn label="Ban"  variant="danger" onClick={(e) => { e.stopPropagation(); onBan(); }} />
        </span>
      )}
    </div>
  );
}

function ModBtn({ label, onClick, variant }) {
  const danger = variant === "danger";
  return (
    <button
      onClick={onClick}
      style={{
        padding: "2px 7px", borderRadius: 5, fontSize: 9,
        fontFamily: "inherit", fontWeight: 600, cursor: "pointer",
        letterSpacing: "0.08em", textTransform: "uppercase",
        background: danger ? "rgb(217 36 42 / 0.2)" : "rgb(255 255 255 / 0.06)",
        border: `1px solid ${danger ? "rgb(217 36 42 / 0.5)" : "rgb(255 255 255 / 0.12)"}`,
        color: danger ? "var(--color-primary)" : "var(--fg-2)",
      }}
    >
      {label}
    </button>
  );
}

const CLIP_VIDEO_SRC = "https://assets.slipstreamtv.co.uk/website/8042164-uhd_4096_2160_25fps.mp4";

function ClipVideo({ aspect, style }) {
  // aspect: "9:16" | "1:1" | "16:9"
  // The underlying video is 16:9 landscape. To crop to the middle for portrait/square
  // we scale the video up so the short side fills the container, centered.
  // For 9:16 the video needs to be much taller than wide — we let height fill and let
  // width overflow (object-fit: cover handles the maths).
  return (
    <div style={{
      position: "relative",
      overflow: "hidden",
      background: "#000",
      ...style,
    }}>
      <video
        src={CLIP_VIDEO_SRC}
        autoPlay
        muted
        loop
        playsInline
        preload="metadata"
        disableRemotePlayback
        controls={false}
        style={{
          position: "absolute", inset: 0,
          width: "100%", height: "100%",
          objectFit: "cover",
          objectPosition: "center center",
          pointerEvents: "none",
        }}
      />
      {/* subtle overlay to keep chrome legible */}
      <div style={{
        position: "absolute", inset: 0,
        background: "linear-gradient(180deg, rgb(0 0 0 / 0) 60%, rgb(0 0 0 / 0.35) 100%)",
      }} />
    </div>
  );
}

function ClipWaveform({ reduced }) {
  // A more realistic waveform: amplitudes combine a couple of sine waves,
  // a slow envelope (verses/chorus), occasional "hits", and a small jitter.
  // We render ONE period, then render it TWICE back-to-back, and translate
  // by exactly one period width so the loop is truly seamless with no gap.
  const BARS = 120;        // bars per period
  const BAR_W = 4;         // px
  const BAR_GAP = 2;       // px
  const STRIDE = BAR_W + BAR_GAP;
  const PERIOD_W = BARS * STRIDE;
  const H = 40;

  function amp(i) {
    // Two overlapping sines give a natural rise-and-fall pulse.
    const s1 = Math.sin((i / BARS) * Math.PI * 6) * 0.45;
    const s2 = Math.sin((i / BARS) * Math.PI * 2 + 1.3) * 0.35;
    // Envelope so the whole pattern breathes across the period.
    const env = 0.55 + 0.45 * Math.sin((i / BARS) * Math.PI * 2);
    // Deterministic pseudo-random jitter.
    const r = (Math.sin(i * 12.9898) * 43758.5453) % 1;
    const jit = (r - Math.floor(r)) * 0.25;
    // Occasional accent hits.
    const hit = (i % 17 === 0) ? 0.25 : 0;
    const v = Math.abs(s1 + s2) * env + jit + hit;
    return Math.max(0.12, Math.min(1, v));
  }

  const bars = Array.from({ length: BARS }, (_, i) => amp(i));

  function renderPeriod(offset) {
    return bars.map((a, i) => {
      const h = Math.max(2, Math.round(a * (H - 6)));
      const x = offset + i * STRIDE;
      return (
        <rect
          key={`${offset}-${i}`}
          x={x}
          y={(H - h) / 2}
          width={BAR_W}
          height={h}
          rx={BAR_W / 2}
          fill="rgb(255 255 255 / 0.4)"
        />
      );
    });
  }

  return (
    <div style={{ position: "relative", height: H, borderRadius: 6, background: "rgb(0 0 0 / 0.3)", overflow: "hidden" }}>
      <div style={{
        position: "absolute", top: 0, left: 0, bottom: 0,
        width: PERIOD_W * 2,
        animation: reduced ? "none" : `wave-scroll-${PERIOD_W} 12s linear infinite`,
        willChange: "transform",
      }}>
        <svg
          width={PERIOD_W * 2}
          height={H}
          viewBox={`0 0 ${PERIOD_W * 2} ${H}`}
          preserveAspectRatio="none"
          style={{ display: "block" }}
        >
          {renderPeriod(0)}
          {renderPeriod(PERIOD_W)}
        </svg>
      </div>
      {/* Clip selection window */}
      <div style={{
        position: "absolute", top: 2, bottom: 2,
        left: "38%", width: "22%",
        background: "rgb(217 36 42 / 0.22)",
        border: "1px solid var(--color-primary)",
        borderRadius: 4,
        boxShadow: "0 0 12px rgb(217 36 42 / 0.3)",
      }} />
      {/* Playhead */}
      <div style={{
        position: "absolute", top: -2, bottom: -2,
        left: "49%", width: 2,
        background: "#fff",
        boxShadow: "0 0 8px rgb(255 255 255 / 0.6)",
      }} />
      <style>{`
        @keyframes wave-scroll-${PERIOD_W} {
          from { transform: translate3d(0, 0, 0); }
          to   { transform: translate3d(-${PERIOD_W}px, 0, 0); }
        }
      `}</style>
    </div>
  );
}

function ClippingVisual() {
  const reduced = usePrefersReducedMotion();
  const formats = [
    { label: "9:16", name: "TikTok / Reels", w: 56, h: 100 },
    { label: "1:1",  name: "Feed post",      w: 78, h: 78  },
    { label: "16:9", name: "YouTube",        w: 100, h: 56 },
  ];

  return (
    <div style={{ position: "absolute", inset: 0, padding: 32, display: "flex", flexDirection: "column", justifyContent: "center", gap: 16 }}>
      <div style={{ padding: 14, borderRadius: 12, background: "rgb(255 255 255 / 0.04)", border: "1px solid rgb(255 255 255 / 0.08)" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 10 }}>
          <span style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: "var(--fg-3)" }}>LIVE · 01:24:37</span>
          <span style={{ fontSize: 10, color: "var(--color-primary)", fontWeight: 600 }}>● CLIP SELECTED</span>
        </div>
        <ClipWaveform reduced={reduced} />
      </div>
      <div className="clips-formats" style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 10 }}>
        {formats.map((f) => (
          <div key={f.label} style={{ padding: 12, borderRadius: 10, background: "rgb(255 255 255 / 0.03)", border: "1px solid rgb(255 255 255 / 0.08)", display: "flex", flexDirection: "column", alignItems: "center", gap: 8 }}>
            <ClipVideo
              aspect={f.label}
              style={{
                width: f.w, height: f.h,
                borderRadius: 4,
                border: "1px solid rgb(255 255 255 / 0.1)",
              }}
            />
            <div style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: "var(--fg-1)", fontWeight: 600 }}>{f.label}</div>
            <div style={{ fontSize: 9, color: "var(--fg-3)" }}>{f.name}</div>
          </div>
        ))}
      </div>
      <button style={{
        padding: "10px 16px", borderRadius: 10, border: "none", fontFamily: "inherit",
        background: "var(--color-primary)", color: "#fff", fontSize: 12, fontWeight: 600,
        display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8, cursor: "pointer",
      }}>
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8M16 6l-4-4-4 4M12 2v13"/></svg>
        Export & publish
      </button>
    </div>
  );
}

function MerchVisual({ purchases }) {
  return (
    <div style={{ position: "absolute", inset: 0, padding: 32, display: "flex", flexDirection: "column", gap: 14 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 }}>
        <div className="eyebrow" style={{ color: "var(--fg-2)" }}>Shop the show</div>
        <span style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: "oklch(0.72 0.17 155)", display: "inline-flex", alignItems: "center", gap: 6 }}>
          <span style={{ width: 6, height: 6, borderRadius: 99, background: "oklch(0.72 0.17 155)" }} />
          {purchases} sold in last 30s
        </span>
      </div>
      <div className="merch-grid" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, flex: 1 }}>
        {[
          { name: "Nocturne Tour Tee", price: "£28", c1: "oklch(0.35 0.1 30)", c2: "oklch(0.2 0.05 10)", icon: "shirt", hot: true },
          { name: "Helix Vinyl 12\"", price: "£24", c1: "oklch(0.2 0.05 300)", c2: "oklch(0.35 0.15 260)", icon: "disc" },
          { name: "Poster · signed", price: "£18", c1: "oklch(0.4 0.18 50)", c2: "oklch(0.25 0.1 20)", icon: "image" },
          { name: "Crewneck · navy", price: "£42", c1: "oklch(0.25 0.05 240)", c2: "oklch(0.18 0.03 240)", icon: "shirt" },
        ].map((p, i) => (
          <div key={i} style={{
            padding: 10, borderRadius: 10,
            background: "rgb(255 255 255 / 0.03)",
            border: `1px solid ${p.hot ? "rgb(217 36 42 / 0.3)" : "rgb(255 255 255 / 0.08)"}`,
            display: "flex", flexDirection: "column", gap: 6, position: "relative",
          }}>
            {p.hot && <span style={{ position: "absolute", top: 8, right: 8, fontSize: 9, fontWeight: 600, color: "var(--color-primary)", background: "rgb(217 36 42 / 0.1)", padding: "2px 6px", borderRadius: 4 }}>NEW</span>}
            <div style={{ aspectRatio: "1", borderRadius: 6, background: `linear-gradient(135deg, ${p.c1}, ${p.c2})`, display: "flex", alignItems: "center", justifyContent: "center" }}>
              <MerchIcon kind={p.icon} />
            </div>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 6 }}>
              <span style={{ fontSize: 11, color: "var(--fg-1)", fontWeight: 500, lineHeight: 1.3 }}>{p.name}</span>
              <span style={{ fontSize: 11, color: "var(--color-primary)", fontWeight: 600, flexShrink: 0 }}>{p.price}</span>
            </div>
          </div>
        ))}
      </div>
      <button style={{
        padding: "10px 16px", borderRadius: 10, border: "1px solid rgb(255 255 255 / 0.1)", fontFamily: "inherit",
        background: "rgb(255 255 255 / 0.04)", color: "var(--fg-1)", fontSize: 12, fontWeight: 500,
        display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8, cursor: "pointer",
      }}>
        View cart · £52 (2 items)
      </button>
    </div>
  );
}

function MerchIcon({ kind }) {
  const s = { width: 32, height: 32, stroke: "rgb(255 255 255 / 0.5)", strokeWidth: 1.5, fill: "none", strokeLinecap: "round" };
  if (kind === "shirt") return (<svg {...s} viewBox="0 0 24 24"><path d="M20 6l-4-2-4 2-4-2-4 2 2 5h3v11h6V11h3z"/></svg>);
  if (kind === "disc")  return (<svg {...s} viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>);
  if (kind === "image") return (<svg {...s} viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="M21 15l-5-5L5 21"/></svg>);
  return null;
}

function BrandVisual() {
  const themes = [
    { n: "nocturne.tv",    c: "oklch(0.54 0.23 27)",  a: "oklch(0.18 0.03 260)", label: "NOCTURNE" },
    { n: "faithnetwork.co", c: "oklch(0.65 0.16 200)", a: "oklch(0.15 0.02 240)", label: "Faith Network" },
    { n: "clubhouse.fc",   c: "oklch(0.72 0.17 140)", a: "oklch(0.12 0.02 140)", label: "Clubhouse FC" },
  ];
  return (
    <div style={{ position: "absolute", inset: 0, padding: 32, display: "flex", flexDirection: "column", gap: 12 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 }}>
        <div className="eyebrow" style={{ color: "var(--fg-2)" }}>Three tenants · one platform</div>
        <span style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: "var(--fg-3)" }}>SSL · isolated</span>
      </div>
      {themes.map((t, i) => (
        <div key={i} style={{
          padding: 14, borderRadius: 10,
          background: t.a, border: `1px solid ${t.c}`,
          display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 12, alignItems: "center",
        }}>
          <div style={{ width: 36, height: 36, borderRadius: 8, background: `linear-gradient(135deg, ${t.c}, oklch(from ${t.c} calc(l - 0.15) c h))`, display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 700, fontSize: 14, color: "#fff", letterSpacing: "-0.02em" }}>
            {t.label.slice(0, 1)}
          </div>
          <div>
            <div style={{ fontSize: 13, fontWeight: 600, color: "#fff" }}>{t.label}</div>
            <div style={{ fontSize: 11, fontFamily: "var(--font-mono)", color: "rgb(255 255 255 / 0.6)" }}>{t.n}</div>
          </div>
          <span style={{ fontSize: 10, padding: "4px 8px", borderRadius: 99, background: `${t.c}`, color: "#fff", fontWeight: 600, letterSpacing: "0.06em" }}>LIVE</span>
        </div>
      ))}
      <div style={{ flex: 1 }} />
      <div style={{ padding: "10px 12px", borderRadius: 10, background: "rgb(255 255 255 / 0.03)", border: "1px dashed rgb(255 255 255 / 0.12)", fontSize: 11, color: "var(--fg-2)", display: "flex", justifyContent: "space-between", fontFamily: "var(--font-mono)" }}>
        <span>Languages · EN · ES · AR ⇦</span>
        <span style={{ color: "oklch(0.72 0.17 155)" }}>RTL ready</span>
      </div>
    </div>
  );
}

window.FeatureSpotlights = FeatureSpotlights;
