/* global React */
const { useState, useEffect, useRef } = React;

// Focus a composer's textarea on mount, then scroll its send button into
// view once the on-screen keyboard has finished animating in. Plain
// autoFocus only guarantees the *input* is visible on iOS Safari — with a
// tall stack above the composer, the keyboard can still cover the send
// button below it. 400ms roughly matches the iOS keyboard animation; there
// is no reliable event for "keyboard finished opening".
const KEYBOARD_SETTLE_MS = 400;
const useComposerAutoFocus = () => {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    el.focus({ preventScroll: true });
    const t = setTimeout(() => {
      const composer = el.closest(".composer");
      (composer || el).scrollIntoView({ block: "end", behavior: "smooth" });
    }, KEYBOARD_SETTLE_MS);
    return () => clearTimeout(t);
  }, []);
  return ref;
};

// Deterministic avatar picker — maps a seed string to one of the illustrated portraits
const AVATARS = [window.IMG?.avatar1 || "assets/avatar-1.png", window.IMG?.avatar2 || "assets/avatar-2.png", window.IMG?.avatar3 || "assets/avatar-3.png"];
const avatarFor = (seed) => {
  const s = String(seed || "");
  let h = 0;
  for (let i = 0; i < s.length; i++) h = h * 31 + s.charCodeAt(i) >>> 0;
  return AVATARS[h % AVATARS.length];
};

// ============================================================
// Inline SVG primitives (matches design system style)
// ============================================================
const Sprig = ({ size = 22, opacity = 0.55, color = "#4C3A8F" }) =>
<svg viewBox="0 0 80 120" width={size * 0.7} height={size} fill="none" stroke={color} strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" style={{ opacity }}>
    <path d="M40 110 V40" />
    <path d="M40 60 q-10 -8 -18 -6 q4 8 18 12" />
    <path d="M40 78 q12 -10 22 -6 q-6 10 -22 12" />
    <path d="M40 50 q-8 -6 -14 -4 q3 6 14 8" />
    <path d="M40 90 q10 -6 18 -4 q-4 8 -18 8" />
    <circle cx="40" cy="36" r="3" />
    <path d="M37 32 q3 -6 6 0" />
  </svg>;


const ArrowRight = ({ size = 16 }) =>
<svg className="icon-inline" width={size} height={size} style={{ width: size, height: size }} viewBox="0 0 24 24">
    <path d="M5 12h14" /><path d="M13 6l6 6-6 6" />
  </svg>;

const ArrowLeft = ({ size = 14 }) =>
<svg className="icon-inline" width={size} height={size} style={{ width: size, height: size }} viewBox="0 0 24 24">
    <path d="M19 12H5" /><path d="M11 18l-6-6 6-6" />
  </svg>;

const EarIcon = ({ size = 18 }) =>
<svg className="icon-inline" width={size} height={size} style={{ width: size, height: size }} viewBox="0 0 24 24">
    <path d="M6 11a6 6 0 1 1 12 0c0 2-1 3-2 4s-2 2-2 4a3 3 0 0 1-6 0" />
    <path d="M9 11a3 3 0 0 1 6 0" />
  </svg>;

const VoiceIcon = ({ size = 18 }) =>
<svg className="icon-inline" width={size} height={size} style={{ width: size, height: size }} viewBox="0 0 24 24">
    <path d="M11 3.5c-3 0-5.5 2.4-5.5 5.4 0 1.4.5 2.6 1.4 3.6L4.5 15h2.3v2.2c0 .8.6 1.4 1.4 1.4h2.3v2" />
    <path d="M8.5 10.5h.01" />
    <path d="M15.5 8.5c1 1.2 1 3.3 0 4.5" />
    <path d="M18.5 6c1.9 2.2 1.9 7.3 0 9.5" />
  </svg>;

const HeartIcon = ({ size = 18 }) =>
<svg className="icon-inline" width={size} height={size} style={{ width: size, height: size }} viewBox="0 0 24 24">
    <path d="M12 21s-7-5-7-11a4 4 0 0 1 7-2 4 4 0 0 1 7 2c0 6-7 11-7 11z" />
  </svg>;

const PassIcon = ({ size = 18 }) =>
<svg className="icon-inline" width={size} height={size} style={{ width: size, height: size }} viewBox="0 0 24 24">
    <path d="M5 12h14" />
    <path d="M12 5l-7 7 7 7" opacity="0.4" />
    <circle cx="19" cy="12" r="1.5" />
  </svg>;


// ============================================================
// Stage decoration
// ============================================================
const StageDecor = ({ tone }) =>
<div className="stage-bg" aria-hidden="true">
    <div className="blob b1" style={tone === "warm" ? { background: "var(--tint-blush)" } : null} />
    <div className="blob b2" style={tone === "cool" ? { background: "var(--tint-periwinkle)" } : null} />
    <div className="blob b3" />
    <div className="corner-sprig tl"><Sprig size={48} opacity={0.4} /></div>
    <div className="corner-sprig br"><Sprig size={36} opacity={0.3} /></div>
  </div>;


// ============================================================
// Brand mark (top-left)
// ============================================================
const BrandMark = ({ onClick }) =>
<div className="brand" onClick={onClick} role="button" aria-label="Confide">
    Confide<span className="sprig-mini"><Sprig size={18} /></span>
  </div>;


// ============================================================
// Path dots — visual breadcrumb showing where you are
// ============================================================
const PathDots = ({ branch, step, total }) => {
  if (step === 0) return null;
  return (
    <div className="path-dots reveal delay-2">
      {Array.from({ length: total }).map((_, i) =>
      <div
        key={i}
        className={`dot ${i + 1 < step ? "done" : ""} ${i + 1 === step ? "active" : ""}`} />

      )}
      <span className="label">{branch || "beginning"}</span>
    </div>);

};

// ============================================================
// Choice card primitive
// ============================================================
const Choice = ({ label, title, desc, icon, onClick, selected }) =>
<button
  className={`choice ${selected ? "selected" : ""}`}
  onClick={onClick}>
  
    {label &&
  <span className="label">
        {icon}
        {label}
      </span>
  }
    <span className="title">{title}</span>
    {desc && <span className="desc" style={{ fontSize: "11px" }}>{desc}</span>}
    <span className="arrow"><ArrowRight size={14} /></span>
  </button>;


// ============================================================
// Step 0 — Welcome to Confide
// ============================================================
const WelcomeStep = ({ onChoose, copy }) =>
<div className="step">
    <img
    src={window.IMG?.envelope || "assets/envelope.png"}
    alt=""
    className="reveal-slow delay-1"
    style={{ width: 180, height: "auto", userSelect: "none", pointerEvents: "none" }} />

    <div className="prompt-display xl reveal-slow delay-2" style={{ fontFamily: "\"Libre Baskerville\", serif", fontSize: "44px", lineHeight: "1.25", fontWeight: 400, display: "inline-flex", alignItems: "baseline", gap: "0.3em" }}>
      <span>A place to</span><span style={{ fontFamily: "Amberly", fontSize: "1.5em" }}>Confide</span>
    </div>

    <div className="subline reveal delay-3" style={{ width: "100%", fontFamily: "Satoshi" }}>
      A safe and anonymous space for your thoughts.
    </div>

    <div className="choices two-col reveal delay-4" style={{ width: "100%", maxWidth: 620 }}>
      <Choice
      label="I want to be heard"
      title="Write what you need Confide in, and someone will listen."
      desc=""
      onClick={() => onChoose("sharer")} />

      <Choice
      label="I want to listen"
      title="Someone is about to trust you with something true."
      desc=""
      onClick={() => onChoose("listener")} />

    </div>
  </div>;


// ============================================================
// Step 1 — Are you here to speak, or to be present for someone?
// ============================================================
const BranchStep = ({ onChoose, copy }) => {
  const [hover, setHover] = useState(null);
  return (
    <div className="step">
      <div className="reveal delay-1">
        <span className="eyebrow"><span className="dot"></span>a soft question</span>
      </div>

      <div className="prompt lg reveal delay-2">
        {copy.branchTitle.split('\n').map((l, i) => <div key={i}>{l}</div>)}
      </div>

      <div className="subline reveal delay-3">
        {copy.branchSub}
      </div>

      <div className="choices two-col reveal delay-4">
        <Choice
          label="listener"
          icon={<EarIcon size={14} />}
          title="To be present for someone"
          desc="Hold space for a stranger's truth. Stay quiet, or speak gently back."
          onClick={() => onChoose("listener")} />
        
        <Choice
          label="sharer"
          icon={<VoiceIcon size={14} />}
          title="To speak something true"
          desc="Say what's on your chest. We'll find people who want to listen."
          onClick={() => onChoose("sharer")} />
        
      </div>
    </div>);

};

// ============================================================
// LISTENER PATH
// ============================================================

// L1 — Someone is about to trust you
const ListenerPrelude = ({ onContinue, copy }) =>
<div className="step">
    <div className="prompt lg reveal-slow delay-2">
      {copy.listenerPrelude.split('\n').map((l, i) => <div key={i}>{l}</div>)}
    </div>

    <div className="subline reveal delay-3">
      Read slowly. There's no need to fix anything. <br />Their words are the ceremony.
    </div>

    <div className="reveal delay-4">
      <div className="dots-listening">
        <div className="d"></div><div className="d"></div><div className="d"></div>
      </div>
    </div>

    <div className="reveal delay-5">
      <button className="btn btn-primary" onClick={onContinue}>
        I'm here to listen <ArrowRight />
      </button>
    </div>
  </div>;


// L2 — Message + reply composer (or skip)
const ListenerAskMode = ({ onChoose, copy, message, onBack }) => {
  const [text, setText] = useState("");
  const ready = text.trim().length > 12;
  return (
    <div className="step">
      <div className="message-card reveal delay-1">
        <div className="who">
          <div className="av" style={{ backgroundImage: `url(${avatarFor(message.seed)})` }} />
          <div>
            <div className="name">{message.name}</div>
            <div className="time">{message.time}</div>
          </div>
        </div>
        <div className="body">
          {message.body.split('\n').map((l, i) => <div key={i}>{l}</div>)}
        </div>
        {message.topics && message.topics.length > 0 &&
        <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
          {message.topics.map((t) =>
          <span key={t} className="ask-mode" style={{ margin: 0 }}>{t}</span>
          )}
        </div>
        }
      </div>

      <div className="composer reveal delay-3">
        <textarea
          value={text}
          onChange={(e) => setText(e.target.value)}
          placeholder="How would you like to support?"
          style={{ minHeight: 160, fontSize: "16px", lineHeight: "24px" }} />

        <div className="composer-row">
          {onBack &&
          <button onClick={onBack} aria-label="Back" style={{ display: "flex", alignItems: "center", justifyContent: "center", width: 30, height: 30, marginRight: 12, borderRadius: "50%", border: "1px solid var(--border-soft)", background: "transparent", cursor: "pointer", color: "var(--fg-2)", flexShrink: 0 }}><ArrowLeft size={14} /></button>
          }
          <div style={{ flex: 1 }} />
          <button className="btn btn-skip" onClick={() => onChoose("pass")}>
            Skip
          </button>
          <button className="btn btn-primary" disabled={!ready} onClick={() => onChoose("stay", text)}>
            Send anonymously
          </button>
        </div>
      </div>
    </div>);

};


// L3a — Stay with them (compose a reply)
const ListenerCompose = ({ onSent, message, onBack }) => {
  const [text, setText] = useState("");
  const ready = text.trim().length > 12;
  const textareaRef = useComposerAutoFocus();
  return (
    <div style={{ position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }}>
    <div className="step">
      <div className="reveal delay-1">
        <span className="eyebrow"><span className="dot"></span>stay with them</span>
      </div>

      <div className="prompt md reveal delay-2" style={{ maxWidth: 520 }}>
        Write what you would whisper, <br />not what you would post.
      </div>

      <div className="message-card reveal delay-3" style={{ background: "var(--color-action-tint)", borderColor: "var(--color-action-edge)" }}>
        <div className="who">
          <div className="av" style={{ backgroundImage: `url(${avatarFor(message.seed)})` }} />
          <div>
            <div className="name">{message.name} said</div>
            <div className="time">{message.time}</div>
          </div>
        </div>
        <div className="body" style={{ fontSize: "var(--type-body-size)", lineHeight: "24px", color: "var(--fg-2)" }}>
          {message.body.split('\n').map((l, i) => <div key={i}>{l}</div>)}
        </div>
      </div>

      <div className="composer reveal delay-4">
        <textarea
          ref={textareaRef}
          value={text}
          onChange={(e) => setText(e.target.value)}
          placeholder="How would you like to support?"
          style={{ minHeight: 160, fontSize: "16px", lineHeight: "24px" }} />

        <div className="composer-row">
          <button onClick={() => onBack ? onBack() : window.location.reload()} aria-label="Back" style={{ display: "flex", alignItems: "center", justifyContent: "center", width: 30, height: 30, marginRight: 12, borderRadius: "50%", border: "1px solid var(--border-soft)", background: "transparent", cursor: "pointer", color: "var(--fg-2)", flexShrink: 0 }}><ArrowLeft size={14} /></button>
          <span className="meta"><Sprig size={12} opacity={0.7} /> entries are sent anonymously</span>
          <div style={{ flex: 1 }} />
          <span style={{ fontSize: 11, color: "var(--fg-2)" }}>{text.length}/280</span>
          <button className="btn btn-primary" disabled={!ready} onClick={() => onSent(text)}>
            Send softly <ArrowRight />
          </button>
        </div>
      </div>
    </div>
    </div>
  );
};

// L3b — Pass gently
const ListenerPassed = ({ onContinue }) =>
<div className="step">
    <div className="reveal delay-1">
      <span className="eyebrow"><span className="dot"></span>passed gently</span>
    </div>

    <div className="prompt-display lg reveal-slow delay-2">
      Thank you for being honest <br />about your room tonight.
    </div>

    <div className="subline reveal delay-3">
      We'll find them another listener. <br />You being here, even briefly, is something.
    </div>

    <div className="reveal delay-4">
      <button className="btn btn-secondary" onClick={onContinue}>
        Read another <ArrowRight />
      </button>
    </div>
  </div>;


// L4 — Listener acknowledgement (after sending)
const ListenerSent = ({ onDone, onHome, sentText, message }) =>
<div className="step">
    <div className="reveal-slow delay-1" style={{ position: "relative", display: "grid", placeItems: "center", width: 84, height: 84 }}>
      <div className="av" style={{ width: 84, height: 84, backgroundImage: `url(${avatarFor(message.seed)})`, borderRadius: "50%", backgroundSize: "cover", backgroundPosition: "center center" }} />
      <div style={{ position: "absolute", top: -10, right: -10, width: 36, height: 36, borderRadius: "50%", background: "var(--color-action-tint)", display: "grid", placeItems: "center", color: "var(--color-action)" }}>
        <HeartIcon size={18} />
      </div>
    </div>

    <div className="prompt-display lg reveal-slow delay-2" style={{ fontFamily: "\"Libre Baskerville\"", fontSize: "40px" }}>
      You added light to someone today.
    </div>

    <div className="subline reveal delay-4">
      The room is warmer because you wrote back.
    </div>

    <div className="reveal delay-5" style={{ display: "flex", gap: 12, alignItems: "center" }}>
      <button className="btn btn-secondary" onClick={onHome}>
        Back to home
      </button>
      <button className="btn btn-primary" onClick={onDone}>
        Listen to another <ArrowRight />
      </button>
    </div>
  </div>;


// ============================================================
// SHARER PATH
// ============================================================

// S1 — What do you need tonight?
const SharerNeed = ({ onChoose, copy }) => (
  <div className="step">
    <div className="reveal-slow delay-2" style={{ fontFamily: "var(--font-serif)", fontSize: "var(--type-h2-size)", lineHeight: "var(--type-h2-line)", fontWeight: 500, textAlign: "center" }}>
      {copy.sharerNeedTitle}
    </div>

    <div className="choices reveal delay-4">
      <Choice
        label="Just Once To Be Heard"
        icon={<EarIcon size={20} />}
        title="Someone will read this, and stay with it"
        desc=""
        onClick={() => onChoose("silent")} />
    </div>
  </div>
);


// S2 — Say what's true (composer)
const SharerCompose = ({ mode, onSend, copy, onBack }) => {
  const [text, setText] = useState("");
  const ready = text.trim().length > 8;
  const textareaRef = useComposerAutoFocus();
  return (
    <div className="step">
      <div className="prompt md reveal delay-2">
        {copy.sharerComposeTitle.split('\n').map((l, i) => <div key={i}>{l}</div>)}
      </div>

      <div className="composer reveal delay-3">
        <textarea
          ref={textareaRef}
          value={text}
          onChange={(e) => setText(e.target.value)}
          placeholder={mode === "words" ?
          "Whatever's pressing tonight. The smallest thing counts." :
          "I keep replaying a conversation I had with my dad three days ago…"}
          style={{ minHeight: 160, fontSize: "16px", lineHeight: "24px" }} />

        <div className="composer-row">
          {onBack &&
          <button onClick={onBack} aria-label="Back" style={{ display: "flex", alignItems: "center", justifyContent: "center", width: 30, height: 30, marginRight: 12, borderRadius: "50%", border: "1px solid var(--border-soft)", background: "transparent", cursor: "pointer", color: "var(--fg-2)", flexShrink: 0 }}><ArrowLeft size={14} /></button>
          }
          <div style={{ flex: 1 }} />
          <button className="btn btn-primary" disabled={!ready} onClick={() => onSend(text)}>
            Send anonymously
          </button>
        </div>
      </div>

      <div className="reveal delay-4" style={{ fontSize: 12, color: "var(--fg-2)", maxWidth: 460 }}>
        if you're in crisis, please reach out to a local crisis line —
        <a
          style={{ color: "var(--color-action)", marginLeft: 4 }}
          href="https://findahelpline.com"
          target="_blank"
          rel="noopener noreferrer">find one here</a>.
      </div>
    </div>);

};

// S3 — Listening room (sending animation)
const SharerListening = ({ onArrived, mode, onListenNow }) => {
  const [phone, setPhone] = useState("");
  const [submitted, setSubmitted] = useState(false);
  const [notify, setNotify] = useState(false);
  const [linkMode, setLinkMode] = useState(false);
  const [copied, setCopied] = useState(false);
  const returnLink = "confide.app/r/7f3a2c91";
  const [hasNotif, setHasNotif] = useState(false);
  const valid = phone.replace(/\D/g, "").length >= 10;

  useEffect(() => {
    if (!submitted || !notify) return;
    const t = setTimeout(() => setHasNotif(true), 2400);
    return () => clearTimeout(t);
  }, [submitted, notify]);

  return (
    <div className="step">
      <div className="reveal delay-2" style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }}>
        <div className="soul-orbits" style={{ width: 220, height: 220 }}>
          <div className="ring"></div>
          <div className="ring r2"></div>
          <div className="center">
            <Sprig size={24} color="#fff" opacity={1} />
          </div>
          {[
          { seed: "mia", x: 14, y: 50 },
          { seed: "theo", x: 76, y: 18 },
          { seed: "noor", x: 78, y: 78 }].
          map((s, i) =>
          <div
            key={s.seed}
            className="soul reveal-slow"
            style={{
              left: `${s.x}%`,
              top: `${s.y}%`,
              backgroundImage: `url(${avatarFor(s.seed)})`,
              animationDelay: `${600 + i * 400}ms`
            }} />

          )}
        </div>

        <div className="prompt-display lg reveal-slow" style={{ fontFamily: "\"Libre Baskerville\"", fontSize: "40px", lineHeight: "1.2" }}>
          Your words are in good hands.
        </div>
      </div>

      {!submitted &&
      <>
        <div className="subline reveal delay-4" style={{ maxWidth: 460 }}>
          {linkMode ?
            "Come back to this link once someone has stayed with your words." :
            "We'll text you once someone has stayed with your words."}
        </div>

        {linkMode ?
        <div className="composer reveal" style={{ maxWidth: 440, padding: "8px 8px 8px 20px" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <span style={{ flex: 1, fontSize: "var(--type-body-large-size)", color: "var(--fg-1)", letterSpacing: "0.01em" }}>{returnLink}</span>
            <button
              className="btn btn-secondary"
              onClick={() => { setCopied(true); if (navigator.clipboard) navigator.clipboard.writeText("https://" + returnLink); }}>
              {copied ? "Copied" : "Copy"}
            </button>
            <button className="btn btn-primary" onClick={() => setSubmitted(true)}>
              I've saved it <ArrowRight />
            </button>
          </div>
        </div> :
        <div className="composer reveal delay-4" style={{ maxWidth: 440, padding: "8px 8px 8px 20px" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <span style={{ fontSize: "var(--type-small-size)", color: "var(--fg-2)", letterSpacing: "0.02em" }}>+1</span>
            <input
              type="tel"
              value={phone}
              onChange={(e) => setPhone(e.target.value)}
              placeholder="(555) 123-4567"
              autoFocus
              style={{
                flex: 1,
                border: 0,
                outline: 0,
                background: "transparent",
                font: "inherit",
                fontSize: "var(--type-body-large-size)",
                padding: "12px 0",
                color: "var(--fg-1)"
              }} />
            <button
              className="btn btn-primary"
              disabled={!valid}
              onClick={() => { setNotify(true); setSubmitted(true); }}>
              Notify me <ArrowRight />
            </button>
          </div>
        </div>
        }

        <div className="reveal delay-5" style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }}>
          <div style={{ fontSize: 11, color: "var(--fg-2)", letterSpacing: "0.04em" }}>
            {linkMode ?
              "Save this link to come back. Nothing is stored on our side." :
              "Not saved with your entry. Deleted after one text. No account, ever."}
          </div>
          <button className="btn btn-secondary" onClick={() => setLinkMode(!linkMode)} style={{ fontSize: 12, padding: "8px 16px" }}>
            {linkMode ? "Use my number instead" : "Get link instead"}
          </button>
        </div>
      </>
      }

      {submitted && !hasNotif &&
      <div className="reveal" style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }}>
        <div className="dots-listening">
          <span className="d"></span><span className="d"></span><span className="d"></span>
        </div>
        <div className="subline" style={{ maxWidth: 420 }}>
          {notify ?
            "We've got your number. Sit with whatever you're feeling — we'll text you once you've been heard." :
            "Nothing saved. Come back whenever you like — your entry is with someone now."}
        </div>
        {onListenNow &&
        <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 8, marginTop: 20 }}>
          <button className="btn btn-primary" onClick={onListenNow} style={{ fontSize: "var(--type-h3-size)", padding: "20px 32px" }}>
            While you wait, sit with someone else <ArrowRight />
          </button>
          <span style={{ fontSize: 11, color: "var(--fg-2)", letterSpacing: "0.04em" }}>
            someone is waiting the same way you are
          </span>
        </div>
        }
      </div>
      }

      {submitted && hasNotif &&
      <div className="reveal" style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 16, width: "100%" }}>
        <button
          className="text-notif"
          onClick={onArrived}
          aria-label="Open the message">
          <div className="text-notif-bar">
            <span className="text-notif-app">Messages</span>
            <span className="text-notif-time">now</span>
          </div>
          <div className="text-notif-body">
            <div className="text-notif-from">Confide</div>
            <div className="text-notif-preview">
              You were heard. Three people stayed with what you wrote.
            </div>
          </div>
        </button>
        <div style={{ fontSize: 12, color: "var(--fg-2)", letterSpacing: "0.02em" }}>
          tap the message
        </div>
      </div>
      }
    </div>);

};

// S4 — Final card: You were heard by 3 souls
const SharerHeard = ({ onDone }) =>
<div className="step">
    <div className="heard-card reveal-slow delay-2">
      <div className="souls">
        {["mia", "theo", "noor"].map((s) =>
      <div key={s} className="av" style={{ backgroundImage: `url(${avatarFor(s)})` }} />
      )}
      </div>
      <div className="prompt-display" style={{ fontSize: 36, lineHeight: "44px", textAlign: "center", fontFamily: "\"Libre Baskerville\"" }}>You were heard.

    </div>
      <div className="number">3</div>
      <div className="number-label" style={{ fontSize: "var(--type-h3-size)" }}>souls stayed with your words tonight</div>
    </div>

    <div className="reveal delay-6" style={{ display: "flex", gap: 12 }}>
      <button className="btn btn-secondary" onClick={() => onDone("listener")}>
        Listen for someone else
      </button>
      <button className="btn btn-primary" onClick={() => onDone("home")}>
        Close the room <ArrowRight />
      </button>
    </div>
  </div>;


// ============================================================
// L5 — All caught up: no more messages waiting tonight
// ============================================================
const ListenerCaughtUp = ({ touched = 3, onHome, onNotify }) =>
<div className="step">
    <div className="reveal-slow delay-1" style={{ display: "flex", alignItems: "center", justifyContent: "center" }}>
      {["mia", "theo", "noor"].map((s, i) =>
      <div key={s} className="av" style={{ width: 64, height: 64, borderRadius: "50%", backgroundImage: `url(${avatarFor(s)})`, backgroundSize: "cover", backgroundPosition: "center center", border: "3px solid var(--color-white)", marginLeft: i === 0 ? 0 : -16, position: "relative", zIndex: 3 - i }} />
      )}
    </div>

    <div className="prompt-display lg reveal-slow delay-2" style={{ fontFamily: "\"Libre Baskerville\"", fontSize: "40px", lineHeight: "1.2" }}>
      Everyone in the room <br />have been held tonight.
    </div>

    <div className="subline reveal delay-4" style={{ maxWidth: 460 }}>
      No one else is waiting just now. <br />Rest well — there'll be more to hold tomorrow.
    </div>

    <div className="reveal delay-5" style={{ display: "flex", gap: 12, alignItems: "center" }}>
      <button className="btn btn-primary" onClick={onHome}>
        Back to home <ArrowRight />
      </button>
    </div>
  </div>;


// expose
Object.assign(window, {
  avatarFor,
  Sprig, ArrowRight, ArrowLeft, HeartIcon, EarIcon, VoiceIcon, PassIcon,
  StageDecor, BrandMark, PathDots, Choice,
  WelcomeStep, BranchStep,
  ListenerPrelude, ListenerAskMode, ListenerCompose, ListenerPassed, ListenerSent, ListenerCaughtUp,
  SharerNeed, SharerCompose, SharerListening, SharerHeard
});