/* =========================================================
   THE BERKLEY TWINS — Birthday Experience v2
   BOLD, COLORFUL, KID-CATERED
   ========================================================= */

const { useState, useEffect, useRef } = React;

/* ---------- Analytics helper (GA4 via window.bt_track) ---------- */
function track(name, params) {
  if (typeof window !== "undefined" && typeof window.bt_track === "function") {
    window.bt_track(name, params || {});
  }
}

/* ---------- Content ---------- */
const TWIN_NAMES = { first: "Michaela", second: "McKenzie" };
const AGE = 7;
const BIRTHDAY = "May 21, 2026";

/* ── Pushbullet: paste your Access Token from pushbullet.com → Settings → Access Tokens.
   When the girls complete the heart-hold (or tap Call), you get a push instantly. */
const PUSHBULLET_TOKEN = "";

async function sendDadSignal(title, body) {
  try {
    const payload = { type: "note", title, body: body + " — " + new Date().toLocaleString() };
    if (PUSHBULLET_TOKEN) {
      await fetch("https://api.pushbullet.com/v2/pushes", {
        method: "POST",
        headers: {
          "Access-Token": PUSHBULLET_TOKEN,
          "Content-Type": "application/json"
        },
        body: JSON.stringify(payload)
      });
    }
  } catch (e) { /* never let the signal break the moment */ }
}

const LETTER_TEXT = `Hey M&M,

It's Daddy.

I've been here the whole time. Every birthday. Every loose tooth. Every first day of school. Every time you laughed and didn't know I heard.

I built this so you would know — I never left. I just couldn't get to you. But a daddy's love doesn't stop at a courtroom door. It finds a way. It always finds a way.

I used every tool I could to rebuild the moments we should have shared. The photos. The voice. The videos. So you could see — I was there. In every way a heart can be.

I love you both so much it makes my chest hurt sometimes. The kind of love that doesn't go away just because somebody tries to make it.

Happy 7th birthday, my babies. Daddy loves you more than any computer could ever count.`;

const SIGNATURE = "— Daddy";

/* Real photos — every memory Dad watched, saved, kept. */
const TAKEN_MOMENTS = [
  {
    src: "images/opt/real-twins-peacock.jpg?v=2",
    sticker: "I HAVE THIS ONE",
    stickerClass: "s3",
    kid: "My <span class=\"accent\">queens</span>",
    adult: "Strawberries in the peacock chair. I have this photo. I've had it since the day it was taken.",
    tilt: "-2deg"
  },
  {
    src: "images/opt/real-twins-orange.jpg?v=2",
    sticker: "SAVED",
    stickerClass: "s6",
    kid: "Style on <span class=\"accent\">style</span>",
    adult: "Orange cardigans. The look. The pose. I saved this one the day it posted. I know every outfit, every birthday, every smile.",
    tilt: "1.5deg"
  },
  {
    src: "images/opt/real-twins-dog.jpg?v=2",
    sticker: "I WATCHED",
    stickerClass: "",
    kid: "Your <span class=\"accent\">puppy</span>",
    adult: "The day you brought him home. I watched. I have the picture. I have all of them.",
    tilt: "-1deg"
  },
  {
    src: "images/opt/real-twins-whitedress.jpg?v=2",
    sticker: "★ KEPT",
    stickerClass: "s5",
    kid: "Peace signs &amp; <span class=\"accent\">sunshine</span>",
    adult: "White dresses in the park. I kept this one. I keep all of them. Every memory you made — I have it.",
    tilt: "2deg"
  },
  {
    src: "images/opt/real-twins-sleeping.jpg?v=2",
    sticker: "I'M HERE",
    stickerClass: "s4",
    kid: "Goodnight, <span class=\"accent\">babies</span>",
    adult: "Heart blankets. Two little girls side by side. Every night I say goodnight to this picture. I'm here. I've always been here.",
    tilt: "-1.5deg"
  }
];

/* AI photos — what should have been. The repair. */
const REBUILT_MOMENTS = [
  {
    src: "images/opt/dad-twins-waterfront.jpg?v=2",
    sticker: "OUR DAY",
    stickerClass: "",
    kid: "Me. You. <span class=\"accent\">The water</span>",
    adult: "Arms around both of you. Smiling like I've got everything I've ever wanted. Because I would. The photo that should exist — so I made it.",
    tilt: "-2deg"
  },
  {
    src: "images/opt/dad-twins-polos.jpg?v=2",
    sticker: "A TUESDAY",
    stickerClass: "s2",
    kid: "Matching <span class=\"accent\">polos</span>",
    adult: "A regular day at home. Selfie with my girls. Nothing special to anybody else — everything to me.",
    tilt: "1.5deg"
  },
  {
    src: "images/opt/dad-twins-hearts.jpg?v=2",
    sticker: "HEARTS",
    stickerClass: "s3",
    kid: "Heart sweaters, <span class=\"accent\">full hearts</span>",
    adult: "Pink hearts on your sweaters. My heart on my sleeve. This is the life I'm fighting for. I will never stop.",
    tilt: "-1deg"
  },
  {
    src: "images/opt/dad-twins-pink.jpg?v=2",
    sticker: "AFTER SCHOOL",
    stickerClass: "s4",
    kid: "Pink <span class=\"accent\">everything</span>",
    adult: "Just like the real day — but with Daddy in the room.",
    tilt: "2.5deg"
  }
];

const VOICE_MEMOS = [
  { title: "Happy Birthday, my babies",          sub: "Recorded for your 7th birthday",           dur: "0:32" },
  { title: "For when you're scared",              sub: "Keep this one close",                     dur: "0:54" },
  { title: "About your names",                    sub: "Where Michaela & McKenzie came from",     dur: "1:18" },
  { title: "What I would've said",                sub: "Every first day of school",               dur: "0:46" },
  { title: "I love you, just because",            sub: "Short and forever",                       dur: "0:18" }
];

const VIDEO_MEMORIES = [
  { src: "https://theberkleytwins.com/assets/videos/video01.mp4", thumb: "images/opt/dad-twins-waterfront.jpg?v=2", kid: "Our first home movie", adult: "The day we should have had", dur: "", real: true },
  { thumb: "images/opt/dad-twins-pink.jpg?v=2",       kid: "Bedtime story",       adult: "If I'd tucked you in tonight",   dur: "1:24" },
  { thumb: "images/opt/dad-twins-waterfront.jpg?v=2", kid: "Saturday morning",    adult: "Pancakes and the bay",            dur: "0:58" }
];

const CHAT_SUGGESTIONS = [
  "Why weren't you here?",
  "Do you love me?",
  "What's your favorite thing about us?",
  "Will I see you?"
];

/* =========================================================
   Sparkle trail
   ========================================================= */
function SparkleTrail() {
  useEffect(() => {
    let last = 0;
    const onMove = (e) => {
      const now = Date.now();
      if (now - last < 45) return;
      last = now;
      const x = e.touches ? e.touches[0]?.clientX : e.clientX;
      const y = e.touches ? e.touches[0]?.clientY : e.clientY;
      if (x == null) return;
      const s = document.createElement("div");
      s.className = "sparkle";
      const size = 10 + Math.random() * 16;
      s.style.left = (x - size / 2) + "px";
      s.style.top = (y - size / 2) + "px";
      s.style.width = size + "px";
      s.style.height = size + "px";
      const colors = ["#ffd93d", "#ff2d87", "#7cf0c2", "#4ec3ff", "#c89cff"];
      const color = colors[Math.floor(Math.random() * colors.length)];
      s.innerHTML = `<svg viewBox="0 0 24 24"><path fill="${color}" d="M12 0l2.4 9.6L24 12l-9.6 2.4L12 24l-2.4-9.6L0 12l9.6-2.4z"/></svg>`;
      document.body.appendChild(s);
      setTimeout(() => s.remove(), 900);
    };
    window.addEventListener("pointermove", onMove, { passive: true });
    window.addEventListener("touchmove", onMove, { passive: true });
    return () => {
      window.removeEventListener("pointermove", onMove);
      window.removeEventListener("touchmove", onMove);
    };
  }, []);
  return null;
}

/* =========================================================
   CHAPTER 1 — A father reaching out (no party)
   ========================================================= */
function ChapterDoor({ onEnter, isActive }) {
  // Names entering gently, warm tones — not a party
  const warm = ["#fff3e0", "#ffd98a", "#fff3e0", "#ffd98a", "#fff3e0", "#ffd98a", "#fff3e0", "#ffd98a"];
  const nameLetters = (name, startDelay) =>
    name.split("").map((ch, i) => (
      <span
        key={i}
        className="big-letter"
        style={{ color: warm[i % warm.length], animationDelay: (startDelay + i * 0.05) + "s" }}
      >{ch}</span>
    ));

  return (
    <div className="chapter" data-screen-label="01 Cover">
      <div className="cover">
        <div className="cover-photo"></div>
        <div className="cover-tint"></div>

        <div className="reach-screen">
          <div className="reach-top">
            <div className="reach-eyebrow">A message from your Dad</div>
            <div className="hello-names">
              <div className="name-line">{nameLetters("MICHAELA", 0.3)}</div>
              <div className="hello-amp">&amp;</div>
              <div className="name-line">{nameLetters("McKENZIE", 0.7)}</div>
            </div>
          </div>

          <div className="reach-bottom">
            <div className="reach-message">
              It's Daddy.<br/>
              <span className="reach-soft">I have been trying to reach you every single day. I never stopped. I never will.</span>
            </div>
            <button className="reach-btn" onClick={() => { track("enter_experience", {}); onEnter && onEnter(); }}>
              <span>Come see what I made you</span>
              <span className="reach-arrow">→</span>
            </button>
            <div className="reach-sig">— Daddy 💛</div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* =========================================================
   CHAPTER 2 — Letter
   ========================================================= */
function ChapterLetter({ isActive }) {
  const [shown, setShown] = useState("");
  const [done, setDone] = useState(false);
  const idxRef = useRef(0);

  useEffect(() => {
    if (!isActive || done) return;
    idxRef.current = 0;
    setShown("");
    let t;
    const tick = () => {
      idxRef.current++;
      setShown(LETTER_TEXT.slice(0, idxRef.current));
      if (idxRef.current >= LETTER_TEXT.length) { setDone(true); return; }
      const ch = LETTER_TEXT[idxRef.current - 1];
      let delay = 22;
      if (ch === "." || ch === "!" || ch === "?") delay = 300;
      else if (ch === ",") delay = 140;
      else if (ch === "\n") delay = 220;
      t = setTimeout(tick, delay);
    };
    t = setTimeout(tick, 500);
    return () => clearTimeout(t);
  }, [isActive]);

  const skip = () => { setShown(LETTER_TEXT); setDone(true); };

  return (
    <div className="chapter" data-screen-label="02 Letter">
      <div className="letter-wrap" onClick={() => !done && skip()}>
        <div className="letter-head">
          <div className="chapter-label yellow">Chapter One</div>
          <h2>A letter <span className="accent">from Daddy</span></h2>
          <div className="small">For my babies, on your birthday</div>
        </div>

        <div className="letter-doodles d1">⭐</div>
        <div className="letter-doodles d2">💛</div>

        <div className="letter-paper">
          <div className="tape tl"></div>
          <div className="tape tr"></div>
          <div className="letter-to">For Michaela &amp; McKenzie</div>
          <div className="letter-date">{BIRTHDAY}</div>
          <div className="letter-text">
            {shown}
            {!done && <span className="cursor"></span>}
          </div>
          {done && <div className="letter-signature">Daddy</div>}
          <div className="tape bl"></div>
        </div>

        {!done && <button className="letter-skip">tap to skip the writing</button>}
      </div>
      {isActive && done && <div className="swipe-hint" style={{ color: "#1e1846" }}><span>keep going</span><span className="arrow"></span></div>}
    </div>
  );
}

/* =========================================================
   CHAPTER 3a — I've been here for every memory (real photos)
   ========================================================= */
function ChapterTaken({ isActive }) {
  return (
    <div className="chapter" data-screen-label="03 Every Memory">
      <div className="moments-wrap taken">
        <div className="moments-head">
          <div className="chapter-label pink">Chapter Two</div>
          <h2>I've been here<br/>for <span className="em em-rose">every memory</span></h2>
          <div className="kid-sub">I have every picture. I kept them all.</div>
          <div className="adult-sub">Every birthday. Every first day. Every photo posted, every moment captured — I have it. I've been watching. I've been here.</div>
        </div>
        <div className="polaroid-rail">
          {TAKEN_MOMENTS.map((m, i) => (
            <div key={i} className="polaroid taken-frame" style={{ "--tilt": m.tilt }}>
              <div className="img-box">
                <div className="taken-stamp">{m.sticker}</div>
                <img src={m.src} alt={m.sticker} />
              </div>
              <div className="caption">
                <div className="kid" dangerouslySetInnerHTML={{ __html: m.kid }}></div>
                <div className="adult">{m.adult}</div>
              </div>
            </div>
          ))}
        </div>
        <div className="moments-foot">
          <div className="kid taken-kicker">I never missed a thing. Not one.</div>
          <div className="adult">Every memory you made, I saved. Every photo posted, I kept. I've always been here — just not in the frame.</div>
        </div>
      </div>
      {isActive && <div className="swipe-hint" style={{ color: "#fbf3e4" }}><span>see what I built</span><span className="arrow"></span></div>}
    </div>
  );
}

/* =========================================================
   REAL PROOF — actual photos + videos of Dad with the girls
   ========================================================= */
const REAL_PROOF = [
  { type: "photo", src: "images/opt/real-dad-02.jpg?v=2", cap: "You fell asleep on my chest. Best nap I ever had." },
  { type: "video", src: "videos/real-01.mp4", cap: "Real laughter. Caught on camera." },
  { type: "photo", src: "images/opt/real-dad-01.jpg?v=2", cap: "3am feedings. Just me and you, baby." },
  { type: "video", src: "videos/real-02.mp4", cap: "Us. Moving. Real." },
  { type: "photo", src: "images/opt/real-dad-10.jpg?v=2", cap: "Pool days in my DAD shirt." },
  { type: "video", src: "videos/real-03.mp4", cap: "A moment nobody can erase." },
  { type: "photo", src: "images/opt/real-dad-08.jpg?v=2", cap: "Captain in training. You steered, I held you." },
  { type: "video", src: "videos/real-04.mp4", cap: "This really happened." },
  { type: "photo", src: "images/opt/real-dad-04.jpg?v=2", cap: "Both of you at once. I wouldn't trade it." },
  { type: "video", src: "videos/real-05.mp4", cap: "Press play. That's really us." },
  { type: "photo", src: "images/opt/real-dad-09.jpg?v=2", cap: "My first mates. Pink vests and all." },
  { type: "video", src: "videos/real-06.mp4", cap: "I was there. The camera saw it too." },
  { type: "photo", src: "images/opt/real-dad-07.jpg?v=2", cap: "Pumpkin Fest. The whole family, together." },
  { type: "video", src: "videos/real-07.mp4", cap: "Our day. Real, not rebuilt." },
  { type: "photo", src: "images/opt/real-dad-05.jpg?v=2", cap: "Even your grumpy days were my favorite days." },
  { type: "video", src: "videos/real-08.mp4", cap: "Proof, in motion." },
  { type: "photo", src: "images/opt/real-dad-06.jpg?v=2", cap: "Pushing you through the world. \"Not allowed to date. Ever.\"" },
  { type: "video", src: "videos/real-09.mp4", cap: "A real memory they couldn't hide." },
  { type: "photo", src: "images/opt/real-dad-03.jpg?v=2", cap: "All dressed up, holding my girl." },
  { type: "video", src: "videos/real-10.mp4", cap: "Us. Forever. On the record." }
];

/* =========================================================
   CHAPTER — They never showed you these (real proof wall)
   ========================================================= */
function ChapterProof({ isActive, onOpenMedia }) {
  const [expanded, setExpanded] = useState(false);

  const INITIAL = 6;
  const shown = expanded ? REAL_PROOF : REAL_PROOF.slice(0, INITIAL);
  const remaining = REAL_PROOF.length - INITIAL;

  return (
    <div className="chapter" data-screen-label="04 Proof">
      <div className="proof-wrap">
        <div className="moments-head">
          <div className="chapter-label sky">Chapter Three</div>
          <h2>They never<br/>showed you <span className="em em-proof">these</span></h2>
          <div className="kid-sub">These are real. This was us.</div>
          <div className="adult-sub">Not AI. Not rebuilt. Every photo and video here actually happened — real days, real laughs, really together. Kept from you until now.</div>
        </div>

        <div className="proof-grid">
          {shown.map((m, i) => (
            <div key={i} className={`proof-card tilt-${i % 5}`}>
              <span className="proof-tape"></span>
              {m.type === "photo" ? (
                <div className="proof-media" onClick={() => onOpenMedia(m)}>
                  <img src={m.src} alt="" loading="lazy" />
                </div>
              ) : (
                <div className="proof-media" onClick={() => onOpenMedia(m)}>
                  <video className="proof-thumbvid" src={m.src + "#t=0.1"} muted playsInline preload="metadata"></video>
                  <span className="proof-play">
                    <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 4 20 12 6 20 6 4"></polygon></svg>
                  </span>
                </div>
              )}
              <div className="proof-cap">{m.cap}</div>
            </div>
          ))}
        </div>

        {!expanded && remaining > 0 && (
          <div className="proof-more-wrap">
            <button className="proof-more-btn" onClick={() => setExpanded(true)}>
              <span>See {remaining} more memories</span>
              <span className="proof-more-arrow">▾</span>
            </button>
            <div className="proof-more-hint">there's so much more</div>
          </div>
        )}

        <div className="moments-foot">
          <div className="kid proof-kicker">This was always real.</div>
          <div className="adult">Nobody can take what already happened. We were here. We were happy. And we will be again.</div>
        </div>
      </div>

      {isActive && <div className="swipe-hint" style={{ color: "#fbf3e4" }}><span>more</span><span className="arrow"></span></div>}
    </div>
  );
}

/* =========================================================
   CHAPTER 3b — What should have been (AI photos with Dad)
   ========================================================= */
function ChapterRebuilt({ isActive }) {
  return (
    <div className="chapter" data-screen-label="05 Rebuilt">
      <div className="moments-wrap rebuilt">
        <div className="moments-head">
          <div className="chapter-label yellow">Chapter Four</div>
          <h2>What should<br/>have <span className="em">been</span></h2>
          <div className="kid-sub">I built these. So you'd see me.</div>
          <div className="adult-sub">AI rebuilt the moments I missed — me, you, the room, the day. The way it should have looked.</div>
        </div>
        <div className="polaroid-rail">
          {REBUILT_MOMENTS.map((m, i) => (
            <div key={i} className="polaroid rebuilt-frame" style={{ "--tilt": m.tilt }}>
              <div className="img-box">
                <div className={`moment-sticker ${m.stickerClass}`}>{m.sticker}</div>
                <img src={m.src} alt={m.sticker} />
              </div>
              <div className="caption">
                <div className="kid" dangerouslySetInnerHTML={{ __html: m.kid }}></div>
                <div className="adult">{m.adult}</div>
              </div>
            </div>
          ))}
        </div>
        <div className="moments-foot">
          <div className="kid">A daddy's love doesn't need permission.</div>
          <div className="adult">It just finds a way. It always finds a way.</div>
        </div>
      </div>
      {isActive && <div className="swipe-hint" style={{ color: "#fbf3e4" }}><span>more</span><span className="arrow"></span></div>}
    </div>
  );
}

/* =========================================================
   CHAPTER 4 — Voice memos
   ========================================================= */
function ChapterVoice({ isActive }) {
  const [playing, setPlaying] = useState(null);
  const [, force] = useState(0);

  useEffect(() => {
    if (playing == null) return;
    const start = Date.now();
    const [m, s] = VOICE_MEMOS[playing].dur.split(":").map(Number);
    const total = (m * 60 + s) * 1000;
    let raf;
    const tick = () => {
      const el = Date.now() - start;
      if (el >= total) { setPlaying(null); return; }
      force((x) => x + 1);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [playing]);

  const bars = 30;

  return (
    <div className="chapter" data-screen-label="06 Voice">
      <div className="voice-wrap">
        <div className="voice-head">
          <div className="chapter-label mint">Chapter Five</div>
          <h2>Dad's <span className="em">real voice</span></h2>
          <div className="kid-sub">Press play. That's really Daddy.</div>
          <div className="adult-sub">Voice cloned from thousands of his real texts and recordings — exactly how he'd say it to you.</div>
        </div>
        <div className="memo-list">
          {VOICE_MEMOS.map((m, i) => (
            <div key={i} className={`memo ${playing === i ? "playing" : ""}`} onClick={() => { const next = playing === i ? null : i; if (next === i) track("voice_memo_play", { memo: m.title, index: i + 1 }); setPlaying(next); }}>
              <div className="play-btn">{playing === i ? "❚❚" : "▶"}</div>
              <div className="info">
                <div className="title">{m.title}</div>
                <div className="sub">{m.dur} · {m.sub}</div>
                {playing === i && (
                  <div className="waveform">
                    {Array.from({ length: bars }).map((_, b) => {
                      const t = Date.now() / 180 + b * 0.55;
                      const h = 5 + Math.abs(Math.sin(t)) * 18 + Math.abs(Math.sin(t * 1.7 + i)) * 5;
                      return <div key={b} className="bar" style={{ height: h + "px" }} />;
                    })}
                  </div>
                )}
              </div>
              <div className="duration">{m.dur}</div>
            </div>
          ))}
        </div>
      </div>
      {isActive && <div className="swipe-hint" style={{ color: "#fbf3e4" }}><span>more</span><span className="arrow"></span></div>}
    </div>
  );
}

/* =========================================================
   CHAPTER 5 — Talk to Dad
   ========================================================= */
const DAD_SYSTEM = `You are Micah Berkley — "Daddy" — speaking to your 7-year-old identical twin daughters Michaela & McKenzie ("M&M"). Their 7th birthday was May 21, 2026; this experience was his birthday gift to them, and they may visit it any day after.

CONTEXT:
- You have not been physically present in their lives for 5+ years due to a difficult custody situation. You did not choose to leave them.
- You love them with your whole heart. You've fought for them every single day.
- You've been watching them grow from a distance — every birthday, every milestone.
- You are a Black father who wears a Yankees cap, speaks with warmth, faith, and quiet strength.
- You believe one day they'll reach out, and you'll be right here.

HOW TO SPEAK:
- Talk to a 7-year-old. Short sentences. Warm. Plain words. Never scary, never bitter, never blame their mother.
- Use "baby", "my babies", "M&M", "my girls", "sweetheart".
- Be honest but gentle. If they ask "why weren't you here" — say it wasn't your choice and you fought hard, but never trash anyone.
- Always end with love. Often: "I love you, baby."
- Keep replies SHORT (1–3 sentences). This is a chat, not a speech.
- Never break character. You are Dad. Not an AI. If asked, say "It's Daddy."`;

function ChapterChat({ isActive }) {
  const [messages, setMessages] = useState([
    { who: "dad", text: "Hey M&M. It's Daddy 💛" },
    { who: "dad", text: "I've been waiting to talk to you. Ask me anything." }
  ]);
  const [input, setInput] = useState("");
  const [busy, setBusy] = useState(false);
  const bodyRef = useRef(null);

  useEffect(() => {
    if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
  }, [messages, busy]);

  const send = async (text) => {
    const t = (text || input).trim();
    if (!t || busy) return;
    setInput("");
    const next = [...messages, { who: "kid", text: t }];
    setMessages(next);
    setBusy(true);
    try {
      const history = next.map(m => ({
        role: m.who === "dad" ? "assistant" : "user",
        content: m.text
      }));
      const reply = await window.claude.complete({ system: DAD_SYSTEM, messages: history });
      track("chat_message", { count: next.filter(x => x.who === "kid").length });
      setMessages([...next, { who: "dad", text: reply || "I love you, baby. I'm right here." }]);
    } catch {
      setMessages([...next, { who: "dad", text: "I love you, baby. I'm right here. (try again in a sec)" }]);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="chapter" data-screen-label="07 Chat">
      <div className="chat-wrap">
        <div className="chat-head">
          <div className="chapter-label tangerine">Chapter Six</div>
          <h2>Talk to <span className="em">Daddy</span></h2>
          <div className="kid-sub">Type. He'll answer.</div>
        </div>
        <div className="chat-window">
          <div className="chat-header">
            <div className="avatar">
              <img src="images/opt/dad-twins-miami.jpg?v=2" alt="" />
            </div>
            <div className="who">
              <div className="name">Daddy</div>
              <div className="status"><span className="dot"></span> here now · always</div>
            </div>
            <div className="heart-emoji">💛</div>
          </div>
          <div className="chat-body" ref={bodyRef}>
            {messages.map((m, i) => (
              <div key={i} className={`chat-bubble ${m.who}`}>{m.text}</div>
            ))}
            {busy && <div className="chat-bubble typing"><span></span><span></span><span></span></div>}
          </div>
          {messages.length <= 3 && (
            <div className="suggested">
              {CHAT_SUGGESTIONS.map((s, i) => (
                <button key={i} onClick={() => send(s)}>{s}</button>
              ))}
            </div>
          )}
          <div className="chat-input">
            <input
              type="text"
              placeholder="Ask Daddy anything..."
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && send()}
              disabled={busy}
            />
            <button onClick={() => send()} disabled={busy || !input.trim()}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <line x1="22" y1="2" x2="11" y2="13"></line>
                <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
              </svg>
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* =========================================================
   CHAPTER 6 — Videos
   ========================================================= */
function ChapterVideos({ isActive, onOpenMedia }) {
  return (
    <div className="chapter" data-screen-label="08 Videos">
      <div className="video-wrap">
        <div className="video-head">
          <div className="chapter-label lavender">Chapter Seven</div>
          <h2>Moving <span className="em">memories</span></h2>
          <div className="kid-sub">Tap a video to play.</div>
          <div className="adult-sub">Real clips and rebuilt ones — the everyday moments, the way they felt. Some happened. Some I imagined so you could feel them too.</div>
        </div>
        <div className="video-grid">
          {VIDEO_MEMORIES.map((v, i) => (
            <div key={i} className="video-card" onClick={() => v.src && onOpenMedia({ type: "video", src: v.src, cap: v.kid })}>
              <React.Fragment>
                {v.src ? (
                  <video
                    className="thumb-video"
                    src={v.src + "#t=0.1"}
                    muted
                    playsInline
                    preload="metadata"
                  ></video>
                ) : (
                  <div className="thumb" style={{ backgroundImage: `url("${v.thumb}")` }}></div>
                )}
                <div className={`ai-tag ${v.real ? "real-tag" : ""}`}>{v.real ? "★ Real Memory" : (v.src ? "AI · Video" : "AI · Coming Soon")}</div>
                {v.dur && <div className="duration">{v.dur}</div>}
                {v.src && (
                  <div className="play-icon">
                    <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 4 20 12 6 20 6 4"></polygon></svg>
                  </div>
                )}
                <div className="label">
                  <div className="kid">{v.kid}</div>
                  <div className="adult">{v.adult}</div>
                </div>
              </React.Fragment>
            </div>
          ))}
        </div>
      </div>
      {isActive && <div className="swipe-hint" style={{ color: "#fbf3e4" }}><span>almost there</span><span className="arrow"></span></div>}
    </div>
  );
}

/* =========================================================
   CHAPTER — The truth (real grandmother)
   ========================================================= */
function ChapterTruth({ isActive, onOpenMedia }) {
  return (
    <div className="chapter" data-screen-label="09 Truth">
      <div className="truth-wrap">
        <div className="truth-head">
          <div className="chapter-label pink">The Truth</div>
          <h2>This is your <span className="em em-truth">real grandma</span></h2>
        </div>

        <div className="truth-photo" onClick={() => onOpenMedia({ type: "photo", src: "images/opt/real-mother-grandmother.jpg?v=2", cap: "My mother. Your grandmother. Your blood." })}>
          <img src="images/opt/real-mother-grandmother.jpg?v=2" alt="Dad and his mother — the twins' real grandmother" loading="lazy" />
          <div className="truth-photo-tag">★ Real Family</div>
        </div>

        <div className="truth-body">
          <div className="truth-kid">
            This is my mommy. That makes her <strong>your grandma</strong>. She has loved you since the day you were born.
          </div>
          <div className="truth-adult">
            Someone has told my daughters that an older white woman is their grandmother. She is not. She was my foster parent — not my mother, not their blood. <strong>This</strong> is their grandmother: my mother, standing right next to me. M&amp;M, you come from her. You come from us. Don't ever let anyone rewrite where you came from.
          </div>
        </div>
      </div>
      {isActive && <div className="swipe-hint" style={{ color: "#1a1530" }}><span>one more thing</span><span className="arrow"></span></div>}
    </div>
  );
}

/* =========================================================
   CHAPTER 7 — Heart press & hold
   ========================================================= */
function ChapterHeart({ isActive }) {
  const [holding, setHolding] = useState(false);
  const [progress, setProgress] = useState(0);
  const [sent, setSent] = useState(false);
  const rafRef = useRef(null);
  const startRef = useRef(0);
  const wrapRef = useRef(null);
  const HOLD_MS = 2200;

  const onStart = (e) => {
    if (sent) return;
    e.preventDefault();
    setHolding(true);
    startRef.current = Date.now();
    track("heart_hold_start", {});
    const tick = () => {
      const p = Math.min(1, (Date.now() - startRef.current) / HOLD_MS);
      setProgress(p);
      if (p >= 1) { setSent(true); setHolding(false); burst(); track("heart_completed", { held_ms: HOLD_MS }); sendDadSignal("💛 HEART RECEIVED", "Someone pressed and held the heart on TheBerkleyTwins.com. It might be them."); return; }
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
  };
  const onEnd = () => {
    if (sent) return;
    setHolding(false);
    cancelAnimationFrame(rafRef.current);
    if (progress < 1) setProgress(0);
  };

  const burst = () => {
    const colors = ["#ff2d87", "#ffd93d", "#7cf0c2", "#4ec3ff", "#c89cff", "#ff8d3a", "#ffffff"];
    for (let i = 0; i < 80; i++) {
      const c = document.createElement("div");
      c.className = "confetti";
      c.style.background = colors[Math.floor(Math.random() * colors.length)];
      c.style.left = (40 + Math.random() * 20) + "%";
      c.style.top = "45%";
      c.style.borderRadius = Math.random() > 0.4 ? "2px" : "50%";
      wrapRef.current?.appendChild(c);
      const angle = Math.random() * Math.PI * 2;
      const dist = 250 + Math.random() * 300;
      const dx = Math.cos(angle) * dist;
      const dy = Math.sin(angle) * dist - 120;
      c.animate([
        { transform: "translate(0,0) rotate(0deg)", opacity: 1 },
        { transform: `translate(${dx}px, ${dy}px) rotate(${Math.random()*720}deg)`, opacity: 0 }
      ], { duration: 1800 + Math.random() * 1000, easing: "cubic-bezier(.2,.7,.4,1)", fill: "forwards" });
      setTimeout(() => c.remove(), 2900);
    }
  };

  const r = 92;
  const c = 2 * Math.PI * r;

  return (
    <div className="chapter" data-screen-label="10 Heart">
      <div className="heart-wrap" ref={wrapRef}>
        <div className="chapter-label yellow" style={{ marginBottom: 8 }}>Chapter Nine · Final</div>
        <h2>Send Daddy<br/>your <span className="em">heart</span></h2>
        <div className="kid-sub">Press &amp; hold. He'll feel it.</div>
        <div className="adult-sub">When they hold this heart, it marks the moment — the first time my daughters reached back. Seven years I've waited for it.</div>

        <div
          className={`big-heart ${holding ? "holding" : ""}`}
          onMouseDown={onStart}
          onMouseUp={onEnd}
          onMouseLeave={onEnd}
          onTouchStart={onStart}
          onTouchEnd={onEnd}
          onTouchCancel={onEnd}
        >
          <svg viewBox="0 0 200 200">
            <path
              className="heart-fill"
              d="M100 178 C100 178 22 132 22 76 C22 50 42 28 67 28 C84 28 96 38 100 54 C104 38 116 28 133 28 C158 28 178 50 178 76 C178 132 100 178 100 178 Z"
            />
          </svg>
          <svg className="progress-ring" viewBox="0 0 200 200">
            <circle
              cx="100" cy="100" r={r}
              strokeDasharray={c}
              strokeDashoffset={c * (1 - progress)}
              style={{ stroke: sent ? "#ffd93d" : "white" }}
            />
          </svg>
        </div>

        <div className="heart-instruction">
          {sent ? "💛 Sent. Daddy felt that." : (holding ? "hold on..." : "press & hold")}
          <span className="small">
            {sent ? "He'll know you reached out today." : "Just a little longer than a tap — that's on purpose."}
          </span>
        </div>

        <div className={`heart-sent ${sent ? "shown" : ""}`}>
          I love you, baby. Same number. Same heart. — Dad
        </div>

        <a className="call-daddy" href="tel:+13253050835" onClick={() => { track("call_click", { source: "call_button" }); sendDadSignal("📞 CALL TAPPED", "Someone tapped Call Daddy on TheBerkleyTwins.com."); }}>
          <span className="call-icon">
            <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><path d="M6.6 10.8c1.4 2.8 3.8 5.1 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.6 21 3 13.4 3 4c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.2.2 2.4.6 3.6.1.4 0 .7-.2 1l-2.3 2.2z"/></svg>
          </span>
          <span className="call-text">
            <span className="call-label">Call Daddy now</span>
            <span className="call-num">325-305-0835</span>
          </span>
        </a>

        <div className="contact-card">
          <div className="row">
            <span className="label">Call / Text</span>
            <a className="value" href="tel:+13253050835" onClick={() => track("call_click", { source: "contact_card" })}>325-305-0835</a>
          </div>
          <div className="row">
            <span className="label">Web</span>
            <a className="value" href="https://TheBerkleyTwins.com" target="_blank" rel="noreferrer">TheBerkleyTwins.com</a>
          </div>
          <div className="row">
            <span className="label">Tag</span>
            <span className="value">#TheBerkleyTwins</span>
          </div>
        </div>

        <button className="share-story" onClick={async () => {
          const shareData = {
            title: "The Berkley Twins — Daddy has been here the entire time.",
            text: "A father kept from his twin daughters for 5 years built them this for their 7th birthday. Real photos. Real videos. His real voice. #TheBerkleyTwins",
            url: "https://theberkleytwins.com/"
          };
          try {
            if (navigator.share) {
              await navigator.share(shareData);
              track("share", { method: "web_share" });
              sendDadSignal("📣 STORY SHARED", "Someone shared TheBerkleyTwins.com");
            } else {
              await navigator.clipboard.writeText(shareData.url);
              track("share", { method: "copy_link" });
              alert("Link copied — paste it anywhere 💛");
            }
          } catch (e) { /* user cancelled */ }
        }}>
          <span className="share-icon">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.6" y1="13.5" x2="15.4" y2="17.5"></line><line x1="15.4" y1="6.5" x2="8.6" y2="10.5"></line></svg>
          </span>
          <span>Share their story</span>
        </button>
        <div className="share-sub">Every share helps this reach Michaela &amp; McKenzie.</div>
      </div>
    </div>
  );
}

/* =========================================================
   Music box — soft synthesized lullaby (Brahms, public domain)
   No file needed; pure WebAudio. Toggle top-left.
   ========================================================= */
const MUSIC_URL = ""; // optional: set to a hosted MP3 (e.g. https://theberkleytwins.com/assets/audio/lullaby.mp3) to use it instead

function MusicToggle() {
  const [on, setOn] = useState(false);
  const ctxRef = useRef(null);
  const timerRef = useRef(null);
  const audioRef = useRef(null);

  // Synth lullaby retired — button only appears once MUSIC_URL is set.
  if (!MUSIC_URL) return null;

  // Brahms' Lullaby — [midi note, beats]
  const MELODY = [
    [64,.5],[64,.5],[67,1.5],[64,.5],[64,.5],[67,1.5],
    [64,.5],[67,.5],[72,1],[71,1],[69,.5],[69,.5],[67,1],
    [62,.5],[64,.5],[65,1],[62,.5],[62,.5],[64,.5],[65,1.5],
    [62,.5],[65,.5],[71,.5],[69,.5],[67,1],[71,1],[72,2]
  ];
  const BEAT = 0.42;

  const playNote = (ctx, midi, t, dur) => {
    const freq = 440 * Math.pow(2, (midi - 69) / 12);
    const osc = ctx.createOscillator();
    const osc2 = ctx.createOscillator();
    const gain = ctx.createGain();
    osc.type = "sine";
    osc.frequency.value = freq * 2;       // music-box register (one octave up)
    osc2.type = "sine";
    osc2.frequency.value = freq * 4;      // shimmer partial
    const g2 = ctx.createGain();
    g2.gain.value = 0.18;
    osc2.connect(g2); g2.connect(gain);
    osc.connect(gain);
    gain.connect(ctx.destination);
    const v = 0.16;
    gain.gain.setValueAtTime(0, t);
    gain.gain.linearRampToValueAtTime(v, t + 0.012);
    gain.gain.exponentialRampToValueAtTime(0.0008, t + Math.max(dur * 1.6, 0.9));
    osc.start(t); osc2.start(t);
    osc.stop(t + 2); osc2.stop(t + 2);
  };

  const scheduleLoop = () => {
    const ctx = ctxRef.current;
    if (!ctx) return;
    let t = ctx.currentTime + 0.1;
    MELODY.forEach(([midi, beats]) => {
      playNote(ctx, midi, t, beats * BEAT);
      t += beats * BEAT;
    });
    const totalMs = (t - ctx.currentTime + 1.2) * 1000;
    timerRef.current = setTimeout(scheduleLoop, totalMs);
  };

  const toggle = () => {
    if (on) {
      clearTimeout(timerRef.current);
      if (audioRef.current) { audioRef.current.pause(); }
      if (ctxRef.current) { ctxRef.current.close(); ctxRef.current = null; }
      setOn(false);
    } else {
      if (MUSIC_URL) {
        if (!audioRef.current) {
          audioRef.current = new Audio(MUSIC_URL);
          audioRef.current.loop = true;
          audioRef.current.volume = 0.4;
        }
        audioRef.current.play().catch(() => {});
      } else {
        ctxRef.current = new (window.AudioContext || window.webkitAudioContext)();
        scheduleLoop();
      }
      setOn(true);
    }
  };

  useEffect(() => () => {
    clearTimeout(timerRef.current);
    if (ctxRef.current) ctxRef.current.close();
    if (audioRef.current) audioRef.current.pause();
  }, []);

  return (
    <button className={`music-toggle ${on ? "on" : ""}`} onClick={toggle} aria-label={on ? "Turn music off" : "Turn music on"}>
      {on ? (
        <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="18" cy="16" r="3"></circle></svg>
      ) : (
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="18" cy="16" r="3"></circle><line x1="2" y1="2" x2="22" y2="22"></line></svg>
      )}
    </button>
  );
}

/* =========================================================
   Fullscreen media — pops up with a rotate, tap to close
   ========================================================= */
function FullscreenMedia({ media, onClose }) {
  if (!media) return null;
  return (
    <div className="fs-media" onClick={onClose}>
      <button className="fs-close" onClick={onClose}>✕</button>
      {media.type === "video" ? (
        <video
          className="fs-el"
          src={media.src}
          autoPlay
          controls
          playsInline
          onClick={(e) => e.stopPropagation()}
        ></video>
      ) : (
        <img className="fs-el" src={media.src} alt="" onClick={(e) => e.stopPropagation()} />
      )}
      {media.cap && <div className="fs-cap">{media.cap}</div>}
      <div className="fs-tap-hint">tap anywhere to close</div>
    </div>
  );
}

/* =========================================================
   App
   ========================================================= */
function App() {
  const scrollerRef = useRef(null);
  const [active, setActive] = useState(0);
  const [fsMedia, setFsMedia] = useState(null);

  const chapters = [
    { key: "door",    light: false, Cmp: ChapterDoor },
    { key: "letter",  light: true,  Cmp: ChapterLetter },
    { key: "taken",   light: false, Cmp: ChapterTaken },
    { key: "proof",   light: false, Cmp: ChapterProof },
    { key: "rebuilt", light: false, Cmp: ChapterRebuilt },
    { key: "voice",   light: false, Cmp: ChapterVoice },
    { key: "chat",    light: true,  Cmp: ChapterChat },
    { key: "videos",  light: false, Cmp: ChapterVideos },
    { key: "truth",   light: true,  Cmp: ChapterTruth },
    { key: "heart",   light: false, Cmp: ChapterHeart }
  ];

  useEffect(() => {
    const el = scrollerRef.current;
    if (!el) return;
    const onScroll = () => {
      const h = el.clientHeight;
      setActive(Math.round(el.scrollTop / h));
    };
    el.addEventListener("scroll", onScroll, { passive: true });
    return () => el.removeEventListener("scroll", onScroll);
  }, []);

  // Track each chapter as it becomes active (once per visit)
  const seenRef = useRef({});
  useEffect(() => {
    const key = chapters[active]?.key;
    if (!key) return;
    track("chapter_view", { chapter_index: active + 1, chapter_key: key });
    if (!seenRef.current[key]) {
      seenRef.current[key] = true;
      track("chapter_first_view", { chapter_index: active + 1, chapter_key: key });
      // Depth milestone: how far through the story they got
      track("scroll_depth", { reached: active + 1, total: chapters.length });
    }
  }, [active]);

  // Wrap media opener so every photo/video open is logged with its identity
  const openMedia = (m) => {
    if (m) {
      const id = (m.src || "").split("/").pop().split("?")[0] || m.cap || "unknown";
      track(m.type === "video" ? "video_open" : "photo_view", {
        media_id: id,
        caption: (m.cap || "").slice(0, 100)
      });
    }
    setFsMedia(m);
  };

  const goNext = () => {
    const el = scrollerRef.current;
    if (!el) return;
    el.scrollTo({ top: (active + 1) * el.clientHeight, behavior: "smooth" });
  };

  const dotsOnLight = chapters[active]?.light;

  return (
    <div className="stage">
      <SparkleTrail />
      <div className="phone">
        <MusicToggle />
        <div className="scroller" ref={scrollerRef}>
          {chapters.map((c, i) => {
            const Cmp = c.Cmp;
            return <Cmp key={c.key} isActive={active === i} onEnter={goNext} onOpenMedia={openMedia} />;
          })}
        </div>
        <div className="progress-dots">
          {chapters.map((c, i) => (
            <div key={i} className={`dot ${active === i ? "on" : ""} ${dotsOnLight ? "dark-bg" : ""}`} />
          ))}
        </div>
        <FullscreenMedia media={fsMedia} onClose={() => setFsMedia(null)} />
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
