// hero.jsx — Moby landing page hero
const { useState, useRef, useEffect } = React;

const COFFEE_PRICE  = 7.00;
const { calcCheckout, formatUsd, getFeeBreakdown } = MobyPricing;
const DEFAULT_SENDER = "Michael Scott";
const DEMO_PHONE = "(415) 555-0192";
const DEMO_EMAIL = "alex@thoughtful.cafe";
const DEMO_RECIPIENT = "Alex Chen";
const NOTE_MAX_LENGTH = 100;
const MIN_AMOUNT = 1;
const MAX_AMOUNT = 500;
const SHOW_PAYPAL_PAYMENT = false;

const BRANDS = [
  { id: "starbucks", label: "Starbucks",  logo: "screenshots/coffee/starbucks.png", color: "#00704A" },
  { id: "dunkin",    label: "Dunkin'",    logo: "screenshots/coffee/dunkin.png",    color: "#FF6319" },
  { id: "timhortons", label: "Tim Hortons", logo: "screenshots/coffee/horton.png", color: "#C8102E", logoScale: 0.9 },
  { id: "peets",     label: "Peet's",     logo: "screenshots/coffee/peets.png",     color: "#2C1503" },
  { id: "dutchbros", label: "Dutch Bros", logo: "screenshots/coffee/dutch.png",     color: "#0047AB" },
  { id: "saxbys",    label: "Saxby's",    logo: "screenshots/coffee/saxby.png",   color: "#E87722", logoScale: 1.18 },
];

function brandLogoStyle(brand) {
  if (!brand?.logoScale) return undefined;
  return { transform: `scale(${brand.logoScale})` };
}

function clampAmount(value) {
  if (!Number.isFinite(value)) return COFFEE_PRICE;
  return Math.min(MAX_AMOUNT, Math.max(MIN_AMOUNT, Math.round(value * 100) / 100));
}

let audioCtx = null;

function getAudioContext() {
  const AudioCtx = window.AudioContext || window.webkitAudioContext;
  if (!AudioCtx) return null;
  if (!audioCtx) audioCtx = new AudioCtx();
  return audioCtx;
}

function primeAudioContext() {
  const ctx = getAudioContext();
  if (ctx?.state === "suspended") ctx.resume();
}

const SUCCESS_SOUND = "screenshots/coffee/whale.mp3";

function playSuccessChime() {
  primeAudioContext();
  try {
    const audio = new Audio(SUCCESS_SOUND);
    audio.volume = 0.35;
    audio.play().catch(() => {});
  } catch (_) {}
}

function EditableAmount({ value, onChange }) {
  const [editing, setEditing] = useState(false);
  const [draftWhole, setDraftWhole] = useState("");
  const wholeRef = useRef(null);
  const whole = Math.round(value).toString();

  useEffect(() => {
    if (!editing) return;
    wholeRef.current?.focus();
    wholeRef.current?.select();
  }, [editing]);

  function startEdit() {
    setDraftWhole(whole);
    setEditing(true);
  }

  function commit() {
    const dollars = draftWhole.replace(/\D/g, "") || "0";
    const parsed = parseFloat(`${dollars}.00`);
    if (Number.isFinite(parsed)) onChange(clampAmount(parsed));
    setEditing(false);
  }

  function cancel() {
    setEditing(false);
  }

  function handleKeyDown(e) {
    if (e.key === "Enter") { e.preventDefault(); commit(); }
    if (e.key === "Escape") { e.preventDefault(); cancel(); }
  }

  return (
    <div className="hp-amount-wrap">
      <div
        className={"hp-amount" + (editing ? " is-editing" : "")}
        onClick={!editing ? startEdit : undefined}
        onKeyDown={!editing ? (e) => {
          if (e.key === "Enter" || e.key === " ") { e.preventDefault(); startEdit(); }
        } : undefined}
        role={!editing ? "button" : undefined}
        tabIndex={!editing ? 0 : undefined}
        aria-label={!editing ? `Amount $${value.toFixed(2)}, click to edit` : undefined}
      >
        <span className="hp-amount-cur">$</span>
        {editing ? (
          <input
            ref={wholeRef}
            className="hp-amount-whole-input"
            type="text"
            inputMode="numeric"
            size={Math.max(1, draftWhole.length || 1)}
            value={draftWhole}
            onChange={e => setDraftWhole(e.target.value.replace(/\D/g, ""))}
            onBlur={commit}
            onKeyDown={handleKeyDown}
            aria-label="Dollars"
          />
        ) : (
          <span className="hp-amount-whole">{whole}</span>
        )}
        <span className="hp-amount-dec">.00</span>
      </div>
      {!editing && (
        <span className="hp-amount-edit-hint" aria-hidden="true">
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M12 20h9" />
            <path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z" />
          </svg>
        </span>
      )}
    </div>
  );
}

function isValidPhone(value) {
  return value.replace(/\D/g, "").length >= 10;
}

function isValidEmail(value) {
  const v = value.trim();
  const at = v.indexOf("@");
  return at > 0 && at < v.length - 1 && v.includes(".");
}

const CONTACTS = [
  { name: "Alex Chen",      phone: "(415) 555-0192", email: "alex@thoughtful.cafe",    initials: "AC", color: "#e8b87c" },
  { name: "Brianna Moore",  phone: "(628) 555-0147", email: "brianna@design.co",       initials: "BM", color: "#a8c5e0" },
  { name: "Carlos Rivera",  phone: "(510) 555-0183", email: "carlos@startup.io",       initials: "CR", color: "#98d4a8" },
  { name: "Dana Kim",       phone: "(213) 555-0261", email: "dana.kim@gmail.com",      initials: "DK", color: "#c5a8d8" },
  { name: "Ethan Park",     phone: "(669) 555-0134", email: "ethan@studio.xyz",        initials: "EP", color: "#f0c88a" },
  { name: "Fiona Walsh",    phone: "(408) 555-0278", email: "fiona.walsh@company.com", initials: "FW", color: "#f5a0b0" },
  { name: "Jordan Lee",     phone: "(347) 555-0159", email: "jordan@teamname.com",     initials: "JL", color: "#a0d4c8" },
  { name: "Maya Patel",     phone: "(718) 555-0216", email: "maya@creative.studio",    initials: "MP", color: "#d4b896" },
  { name: "Noah Williams",  phone: "(312) 555-0193", email: "noah.w@gmail.com",        initials: "NW", color: "#b8d4a0" },
  { name: "Sofia Torres",   phone: "(305) 555-0247", email: "sofia@designstudio.com",  initials: "ST", color: "#e8b4c8" },
];

function ContactsDrawer({ onSelect, onClose, sendMode }) {
  const [search, setSearch] = useState("");
  const [open, setOpen] = useState(false);
  const searchRef = useRef(null);
  const filtered = CONTACTS.filter(c =>
    c.name.toLowerCase().includes(search.toLowerCase()) ||
    c.phone.includes(search) ||
    c.email.toLowerCase().includes(search.toLowerCase())
  );

  useEffect(() => {
    function onKey(e) { if (e.key === "Escape") onClose(); }
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [onClose]);

  useEffect(() => {
    const raf = requestAnimationFrame(() => {
      requestAnimationFrame(() => setOpen(true));
    });
    return () => cancelAnimationFrame(raf);
  }, []);

  useEffect(() => {
    if (!open) return;
    const t = setTimeout(() => searchRef.current?.focus(), 420);
    return () => clearTimeout(t);
  }, [open]);

  return (
    <div className="hp-cd-overlay" onClick={onClose} role="dialog" aria-modal="true" aria-labelledby="hp-contacts-heading">
      <div className="hp-sheet-track hp-contacts-track">
        <div className={"hp-cd-sheet hp-contacts-sheet" + (open ? " is-open" : "")} onClick={e => e.stopPropagation()}>
          <div className="hp-drawer-handle" />
          <div className="hp-cd-top">
            <div className="hp-cd-top-row">
              <h2 className="hp-cd-heading" id="hp-contacts-heading">Contacts</h2>
              <button type="button" className="hp-cd-close" onClick={onClose} aria-label="Close">
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                  <path d="M6 6l12 12M18 6L6 18" />
                </svg>
              </button>
            </div>
          </div>
          <div className="hp-drawer-search">
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <circle cx="11" cy="11" r="7"/><path d="M21 21l-4.35-4.35"/>
            </svg>
            <input
              ref={searchRef}
              className="hp-drawer-search-input"
              placeholder="Search"
              value={search}
              onChange={e => setSearch(e.target.value)}
            />
          </div>
          <div className="hp-drawer-list">
            {filtered.map(c => (
              <div key={c.phone} className="hp-contact-row" onClick={() => onSelect(c)}>
                <div className="hp-contact-avatar" style={{ background: c.color }}>{c.initials}</div>
                <div className="hp-contact-info">
                  <div className="hp-contact-name">{c.name}</div>
                  <div className="hp-contact-email">{sendMode === "email" ? c.email : c.phone}</div>
                  <div className="hp-contact-email" style={{opacity: 0.6}}>{sendMode === "email" ? c.phone : c.email}</div>
                </div>
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{opacity:.3}}>
                  <path d="M9 18l6-6-6-6"/>
                </svg>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

const BEAN_CONFETTI = [
  { src: "assets/beans.png", tx: "-115px", ty: "-100px", rot: "-35deg", delay: "0s", size: 26 },
  { src: "assets/beans-two.png", tx: "110px", ty: "-115px", rot: "40deg", delay: ".12s", size: 24 },
  { src: "assets/beans.png", tx: "-130px", ty: "-55px", rot: "-60deg", delay: ".24s", size: 22 },
  { src: "assets/beans-two.png", tx: "125px", ty: "-60px", rot: "55deg", delay: ".08s", size: 28 },
  { src: "assets/beans.png", tx: "20px", ty: "-140px", rot: "15deg", delay: ".18s", size: 30 },
  { src: "assets/beans-two.png", tx: "-90px", ty: "-125px", rot: "-20deg", delay: ".3s", size: 23 },
  { src: "assets/beans.png", tx: "95px", ty: "-90px", rot: "70deg", delay: ".15s", size: 25 },
];

function BeanConfetti({ className = "" }) {
  return (
    <div className={"hp-confirm-confetti" + (className ? " " + className : "")} aria-hidden="true">
      {BEAN_CONFETTI.map((bean, i) => (
        <img
          key={i}
          src={bean.src}
          alt=""
          className="hp-confirm-bean"
          style={{
            "--tx": bean.tx,
            "--ty": bean.ty,
            "--rot": bean.rot,
            "--delay": bean.delay,
            width: bean.size,
            height: bean.size,
          }}
        />
      ))}
    </div>
  );
}

function ConfirmScreen({ recipientName, brand, onReset }) {
  useEffect(() => {
    playSuccessChime();
  }, []);

  return (
    <div className="hp-confirm">
      <BeanConfetti />
      <div className="hp-confirm-content">
        <img src="assets/moby-logo.png" alt="" className="hp-confirm-logo" />
        <div className="hp-confirm-title">Coffee sent!</div>
        <div className="hp-confirm-sub">
          {recipientName} will get their {brand ? brand.label : "coffee"} in{"\u00A0"}seconds.
        </div>
        <div className="hp-confirm-check" aria-hidden="true">
          <SuccessCheckIcon />
        </div>
      </div>
      <button className="hp-send" onClick={onReset}>Done</button>
    </div>
  );
}

function Icon({ name, size = 18 }) {
  const s = size;
  const stroke = { fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case "mail":
      return (
        <svg width={s} height={s} viewBox="0 0 24 24" {...stroke}>
          <rect x="3" y="5" width="18" height="14" rx="3" />
          <path d="M4 7l8 6 8-6" />
        </svg>
      );
    case "arrow":
      return (
        <svg width={s} height={s} viewBox="0 0 24 24" {...stroke}>
          <path d="M5 12h14M13 6l6 6-6 6" />
        </svg>
      );
    case "cup":
      return (
        <svg width={s} height={s} viewBox="0 0 24 24" {...stroke}>
          <path d="M5 9h12v6a4 4 0 0 1-4 4H9a4 4 0 0 1-4-4V9z" />
          <path d="M17 11h2a2 2 0 0 1 0 4h-2" />
          <path d="M9 3c0 1 1 1 1 2s-1 1-1 2M13 3c0 1 1 1 1 2s-1 1-1 2" />
        </svg>
      );
    case "play":
      return (
        <svg width={s} height={s} viewBox="0 0 24 24" {...stroke}>
          <circle cx="12" cy="12" r="9" />
          <path d="M10 9l5 3-5 3V9z" fill="currentColor" />
        </svg>
      );
    case "close":
      return (
        <svg width={s} height={s} viewBox="0 0 24 24" {...stroke}>
          <path d="M6 6l12 12M18 6L6 18" />
        </svg>
      );
    default: return null;
  }
}

function PhoneStatusIcons() {
  return (
    <span className="phone-status-icons" aria-hidden="true">
      <svg className="phone-status-cell" width="18" height="12" viewBox="0 0 18 12">
        <rect x="0.5" y="7" width="3" height="4.5" rx="0.75" fill="currentColor" />
        <rect x="5" y="4.5" width="3" height="7" rx="0.75" fill="currentColor" />
        <rect x="9.5" y="2" width="3" height="9.5" rx="0.75" fill="currentColor" />
        <rect x="14" y="0" width="3" height="11.5" rx="0.75" fill="currentColor" />
      </svg>
      <svg className="phone-status-wifi" width="16" height="12" viewBox="0 0 16 12">
        <path d="M8 10.25a.9.9 0 110-1.8.9.9 0 010 1.8z" fill="currentColor" />
        <path d="M5.2 7.1a3.8 3.8 0 015.6 0" fill="none" stroke="currentColor" strokeWidth="1.35" strokeLinecap="round" />
        <path d="M2.6 4.4a7.4 7.4 0 0110.8 0" fill="none" stroke="currentColor" strokeWidth="1.35" strokeLinecap="round" />
        <path d="M0 1.6a10.6 10.6 0 0116 0" fill="none" stroke="currentColor" strokeWidth="1.35" strokeLinecap="round" />
      </svg>
      <svg className="phone-status-battery" width="27" height="13" viewBox="0 0 27 13">
        <rect x="0.5" y="0.5" width="22" height="12" rx="3" fill="none" stroke="currentColor" strokeWidth="1" />
        <path d="M23.5 4.5v4c.8 0 1.5-.6 1.5-1.4v-1.2c0-.8-.7-1.4-1.5-1.4z" fill="currentColor" opacity="0.35" />
        <rect x="2" y="2" width="17" height="9" rx="2" fill="currentColor" />
      </svg>
    </span>
  );
}

function InfoBubble({ label, onClick }) {
  return (
    <button type="button" className="hp-cd-info" onClick={onClick} aria-label={label}>
      <img src="assets/info.svg" alt="" className="hp-cd-info-icon" />
    </button>
  );
}

function LineInfoDrawer({ title, body, headingId, onClose }) {
  const [open, setOpen] = useState(false);

  useEffect(() => {
    const raf = requestAnimationFrame(() => {
      requestAnimationFrame(() => setOpen(true));
    });
    return () => cancelAnimationFrame(raf);
  }, []);

  return (
    <div
      className="hp-cd-detail-overlay"
      onClick={(e) => {
        e.stopPropagation();
        if (e.target === e.currentTarget) onClose();
      }}
      role="dialog"
      aria-modal="true"
      aria-labelledby={headingId}
    >
      <div className="hp-sheet-track">
        <div className={"hp-cd-detail-sheet" + (open ? " is-open" : "")} onClick={e => e.stopPropagation()}>
          <button type="button" className="hp-cd-detail-close" onClick={(e) => { e.stopPropagation(); onClose(); }} aria-label="Close">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
              <path d="M6 6l12 12M18 6L6 18" />
            </svg>
          </button>
          <div className="hp-drawer-handle" />
          <h3 className="hp-cd-detail-heading" id={headingId}>{title}</h3>
          <div className="hp-cd-detail-body">
            {typeof body === "string" ? <p>{body}</p> : body}
          </div>
          <button type="button" className="hp-cd-detail-done" onClick={(e) => { e.stopPropagation(); onClose(); }}>
            Got it
          </button>
        </div>
      </div>
    </div>
  );
}

function ServiceFeeInfoBody({ price, quoteMethod }) {
  const quote = calcCheckout(price, quoteMethod);
  const breakdown = getFeeBreakdown(quote);
  const processorLabel = quoteMethod === "paypal" ? "PayPal" : "Stripe";
  const fmt = (n) => `$${formatUsd(n)}`;

  return (
    <div className="hp-cd-service-info">
      <p className="hp-cd-detail-lede">
        A small fee is how we keep Moby running; no ads, no selling your data, no tracking, just coffee goodness.
      </p>
      <section className="hp-cd-breakdown" aria-label="Service fee breakdown">
        <div className="hp-cd-line">
          <span className="hp-cd-line-label">
            <span className="hp-cd-line-brand">
              <img src="screenshots/coffee/stripe.png" alt="" className="hp-cd-line-service-logo" />
              <span>{processorLabel} Fee</span>
            </span>
          </span>
          <span className="hp-cd-line-amt">{fmt(breakdown.processingFee)}</span>
        </div>
        <div className="hp-cd-line hp-cd-line-stacked">
          <span className="hp-cd-line-label">
            <span className="hp-cd-line-brand hp-cd-line-brand-stack">
              <img src="assets/moby-logo.png" alt="" className="hp-cd-line-brand-logo" />
              <span className="hp-cd-line-brand-copy">
                <span>Moby fee</span>
                <span className="hp-cd-line-subnote">{fmt(breakdown.mobyFee)} flat fee. Less than a US postage stamp.</span>
              </span>
            </span>
          </span>
          <span className="hp-cd-line-amt">{fmt(breakdown.mobyFee)}</span>
        </div>
        <div className="hp-cd-line hp-cd-line-total">
          <span>Total</span>
          <span className="hp-cd-line-amt">{fmt(breakdown.total)}</span>
        </div>
      </section>
    </div>
  );
}

function PremiumFeatureCheck() {
  return (
    <svg className="hp-premium-check" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true">
      <path d="M3.5 8.2l2.6 2.6 6.4-6.4" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

const POD_PREMIUM_PRICE = "$0.99 per month";

const POD_PREMIUM_FEATURES = [
  "Send 1-10 second audio files",
  "Unlimited audio messages",
];

const POD_PREMIUM_FOOTNOTE = "Note: Messenger only, not email";

const POD_PREMIUM_BENEFITS = POD_PREMIUM_FEATURES;

function SuccessCheckIcon() {
  return (
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M5 12l5 5L20 7"/>
    </svg>
  );
}

function PodPremiumSuccess({ celebrate, onDone }) {
  useEffect(() => {
    if (celebrate) playSuccessChime();
  }, [celebrate]);

  return (
    <div className="hp-premium-success">
      {celebrate && <BeanConfetti />}
      <div className="hp-confirm-content">
        <img src="assets/moby-logo.png" alt="" className="hp-confirm-logo" />
        <div className="hp-confirm-title" id="hp-pod-premium-heading">Congrats!</div>
        <div className="hp-confirm-sub">You can now send audio files with each message.</div>
        <div className="hp-confirm-check" aria-hidden="true">
          <SuccessCheckIcon />
        </div>
      </div>
      <button type="button" className="hp-send" onClick={onDone}>Done</button>
    </div>
  );
}

function PodPremiumDrawer({ onClose, isSubscribed, onSubscribe }) {
  const [open, setOpen] = useState(false);
  const [subscribing, setSubscribing] = useState(false);
  const [celebrate, setCelebrate] = useState(false);

  useEffect(() => {
    const raf = requestAnimationFrame(() => {
      requestAnimationFrame(() => setOpen(true));
    });
    return () => cancelAnimationFrame(raf);
  }, []);

  useEffect(() => {
    function onKey(e) {
      if (e.key === "Escape" && !subscribing) onClose();
    }
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [onClose, subscribing]);

  function handleSubscribe() {
    setSubscribing(true);
    window.setTimeout(() => {
      setSubscribing(false);
      onSubscribe();
      setCelebrate(true);
    }, 1100);
  }

  return (
    <div
      className={"hp-cd-detail-overlay hp-premium-overlay" + (isSubscribed ? " is-success" : "")}
      onClick={(e) => {
        e.stopPropagation();
        if (e.target === e.currentTarget && !subscribing && !isSubscribed) onClose();
      }}
      role="dialog"
      aria-modal="true"
      aria-labelledby="hp-pod-premium-heading"
    >
      <div className="hp-sheet-track">
        <div className={"hp-premium-drawer" + (open ? " is-open" : "") + (isSubscribed ? " is-success" : "")} onClick={e => e.stopPropagation()}>
          <div className="hp-premium-drawer-bg" aria-hidden="true" />
          {isSubscribed ? (
            <PodPremiumSuccess celebrate={celebrate} onDone={onClose} />
          ) : (
            <>
              <button type="button" className="hp-premium-close" onClick={(e) => { e.stopPropagation(); if (!subscribing) onClose(); }} aria-label="Close">
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                  <path d="M6 6l12 12M18 6L6 18" />
                </svg>
              </button>
              <div className="hp-drawer-handle" />
              <div className="hp-premium-drawer-inner">
                <img src="assets/moby-logo.png" alt="" className="hp-premium-whale" />
                <h3 className="hp-premium-title" id="hp-pod-premium-heading">Try Pod Premium</h3>
                <p className="hp-premium-lede">Subscribe · {POD_PREMIUM_PRICE}</p>
                <div className="hp-premium-features-block">
                  <ul className="hp-premium-features">
                    {POD_PREMIUM_FEATURES.map((feature) => (
                      <li key={feature}><PremiumFeatureCheck />{feature}</li>
                    ))}
                  </ul>
                  <p className="hp-premium-features-foot">{POD_PREMIUM_FOOTNOTE}</p>
                </div>
                <div className="hp-premium-pay">
                  <button
                    type="button"
                    className={"hp-pay-apple" + (subscribing ? " hp-pay-loading" : "")}
                    onClick={handleSubscribe}
                    disabled={subscribing}
                  >
                    {subscribing ? (
                      <span className="hp-pay-spinner" />
                    ) : (
                      <>
                        <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                          <path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/>
                        </svg>
                        Subscribe · $0.99/month
                      </>
                    )}
                  </button>
                  <p className="hp-premium-fine">Cancel anytime in Settings.</p>
                </div>
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

const AUDIO_MAX_SECONDS = 10;

function formatAudioTime(totalSeconds) {
  const s = Math.min(AUDIO_MAX_SECONDS, Math.max(0, totalSeconds));
  return `0:${String(s).padStart(2, "0")}`;
}

function AudioRecordDrawer({ onClose, onAttach }) {
  const [open, setOpen] = useState(false);
  const [phase, setPhase] = useState("idle");
  const [seconds, setSeconds] = useState(0);
  const timerRef = useRef(null);

  useEffect(() => {
    const raf = requestAnimationFrame(() => {
      requestAnimationFrame(() => setOpen(true));
    });
    return () => cancelAnimationFrame(raf);
  }, []);

  useEffect(() => {
    function onKey(e) {
      if (e.key === "Escape" && phase !== "recording") onClose();
    }
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [onClose, phase]);

  useEffect(() => () => {
    if (timerRef.current) clearInterval(timerRef.current);
  }, []);

  function stopRecording(finalSeconds) {
    if (timerRef.current) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
    setSeconds(finalSeconds);
    setPhase("done");
  }

  function startRecording() {
    setPhase("recording");
    setSeconds(0);
    timerRef.current = setInterval(() => {
      setSeconds(prev => Math.min(prev + 1, AUDIO_MAX_SECONDS));
    }, 1000);
  }

  useEffect(() => {
    if (phase === "recording" && seconds >= AUDIO_MAX_SECONDS) {
      stopRecording(AUDIO_MAX_SECONDS);
    }
  }, [phase, seconds]);

  function handleStop() {
    if (seconds === 0) {
      if (timerRef.current) clearInterval(timerRef.current);
      timerRef.current = null;
      setPhase("idle");
      return;
    }
    stopRecording(seconds);
  }

  function handleReRecord() {
    setPhase("idle");
    setSeconds(0);
  }

  return (
    <div
      className="hp-cd-detail-overlay hp-audio-overlay"
      onClick={(e) => {
        e.stopPropagation();
        if (e.target === e.currentTarget && phase !== "recording") onClose();
      }}
      role="dialog"
      aria-modal="true"
      aria-labelledby="hp-audio-heading"
    >
      <div className="hp-sheet-track">
        <div className={"hp-audio-drawer" + (open ? " is-open" : "")} onClick={e => e.stopPropagation()}>
          <div className="hp-drawer-handle" />
          <button
            type="button"
            className="hp-cd-close hp-audio-close"
            onClick={onClose}
            disabled={phase === "recording"}
            aria-label="Close"
          >
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
              <path d="M6 6l12 12M18 6L6 18" />
            </svg>
          </button>
          <div className="hp-audio-top">
            <h3 className="hp-audio-title" id="hp-audio-heading">Audio note</h3>
          </div>

          <div className="hp-audio-body">
            {phase === "idle" && (
              <>
                <p className="hp-audio-lede">Record up to 10 seconds</p>
                <button type="button" className="hp-audio-record-btn" onClick={startRecording} aria-label="Start recording">
                  <span className="hp-audio-record-dot" />
                </button>
                <p className="hp-audio-sub">Tap to record</p>
              </>
            )}

            {phase === "recording" && (
              <>
                <div className="hp-audio-timer">
                  {formatAudioTime(seconds)}
                  <span className="hp-audio-timer-max">/ {formatAudioTime(AUDIO_MAX_SECONDS)}</span>
                </div>
                <div className="hp-audio-wave" aria-hidden="true">
                  {Array.from({ length: 28 }, (_, i) => (
                    <span key={i} className="hp-audio-wave-bar" style={{ "--i": i }} />
                  ))}
                </div>
                <button type="button" className="hp-audio-record-btn is-recording" onClick={handleStop} aria-label="Stop recording">
                  <span className="hp-audio-stop-square" />
                </button>
                <p className="hp-audio-sub">Tap to stop</p>
              </>
            )}

            {phase === "done" && (
              <>
                <div className="hp-audio-timer is-done">{formatAudioTime(seconds)}</div>
                <div className="hp-audio-playback" aria-label="Audio preview">
                  <button type="button" className="hp-audio-play-btn" aria-label="Play preview">
                    <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                      <path d="M8 5v14l11-7z" />
                    </svg>
                  </button>
                  <div className="hp-audio-playback-track">
                    <span className="hp-audio-playback-fill" />
                  </div>
                </div>
                <div className="hp-audio-done-actions">
                  <button type="button" className="hp-audio-redo" onClick={handleReRecord}>Re-record</button>
                  <button
                    type="button"
                    className="hp-audio-attach"
                    onClick={() => {
                      onAttach(seconds);
                      onClose();
                    }}
                  >
                    Add
                  </button>
                </div>
              </>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

const LINE_INFO = {
  coffee: {
    title: "Starbucks Coffee",
    body: "Your gift lands in their inbox as a Starbucks gift card. They can use it in-store or on the Starbucks app.",
    headingId: "hp-cd-coffee-heading",
  },
  delivery: {
    title: "Service fee",
    headingId: "hp-cd-service-heading",
  },
};

/* ── Card entry overlay (second bottom sheet) ── */
/* ── Combined checkout drawer: order summary + payment in one ── */
function SettingsIcon() {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <circle cx="12" cy="12" r="3"/>
      <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
    </svg>
  );
}

function CheckoutDrawer({ email, recipientName, senderName, note, sendMode, brand, price, onSuccess, onClose }) {
  const [paying, setPaying] = useState(false);
  const [method, setMethod] = useState(null);
  const [quoteMethod, setQuoteMethod] = useState("stripe");
  const [infoDrawer, setInfoDrawer] = useState(null);
  const [open, setOpen] = useState(false);
  const faceValue = clampAmount(price);
  const quote = calcCheckout(faceValue, quoteMethod);

  useEffect(() => {
    function onKey(e) {
      if (e.key !== "Escape" || paying) return;
      if (infoDrawer) setInfoDrawer(null);
      else onClose();
    }
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [onClose, paying, infoDrawer]);

  useEffect(() => {
    const raf = requestAnimationFrame(() => {
      requestAnimationFrame(() => setOpen(true));
    });
    return () => cancelAnimationFrame(raf);
  }, []);

  async function pay(m) {
    primeAudioContext();
    const processor = m === "paypal" ? "paypal" : "stripe";
    setQuoteMethod(processor);
    setMethod(m);
    setPaying(true);

    if (sendMode === "email") {
      try {
        const res = await fetch("/api/checkout", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            to_email: email,
            note: note || "",
            sender_name: senderName,
            recipient_name: recipientName,
            amount: faceValue,
            payment_method: processor,
          }),
        });
        const data = await res.json();
        if (res.ok && data.checkoutUrl) {
          window.location.href = data.checkoutUrl;
          return;
        }
      } catch (_) {
        // fall through to prototype success flow
      }
    }

    await new Promise(r => setTimeout(r, 1800));
    onSuccess();
  }

  const activeInfo = infoDrawer ? {
    ...LINE_INFO[infoDrawer],
    title: infoDrawer === "coffee"
      ? `${brand ? brand.label : "Coffee"} Gift Card`
      : LINE_INFO[infoDrawer].title,
    body: infoDrawer === "coffee"
      ? `Your $${formatUsd(faceValue)} lands in their inbox as a ${brand ? brand.label : "coffee"} gift card. They can use it in-store or on the app.`
      : infoDrawer === "delivery"
      ? <ServiceFeeInfoBody price={faceValue} quoteMethod={quoteMethod} />
      : LINE_INFO[infoDrawer].body,
  } : null;

  return (
    <div className="hp-cd-overlay" onClick={paying ? null : onClose} role="dialog" aria-modal="true" aria-labelledby="hp-cd-heading">
      <div className="hp-sheet-track">
        <div className={"hp-cd-sheet" + (open ? " is-open" : "")} onClick={e => e.stopPropagation()}>
        <div className="hp-drawer-handle" />

        {/* header */}
        <div className="hp-cd-top">
          <div className="hp-cd-top-row">
            <h2 className="hp-cd-heading" id="hp-cd-heading">Review & Send</h2>
            <button type="button" className="hp-cd-close" onClick={onClose} disabled={paying} aria-label="Close">
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                <path d="M6 6l12 12M18 6L6 18" />
              </svg>
            </button>
          </div>
          <hr className="hp-cd-divider" />
          <p className="hp-cd-recipient-line">
            <span className="hp-cd-party-prefix">To</span>
            {recipientName && (
              <>
                <span className="hp-cd-party-sep"> · </span>
                <span className="hp-cd-party-name">{recipientName}</span>
              </>
            )}
            <span className="hp-cd-party-sep"> · </span>
            <span className="hp-cd-party-detail">{email}</span>
          </p>
          <hr className="hp-cd-divider hp-cd-content-divider hp-cd-content-divider-top" aria-hidden="true" />
        </div>

        <section className="hp-cd-breakdown" aria-label="Order summary">
          <div className="hp-cd-line">
            <span className="hp-cd-line-label">
              <span className="hp-cd-line-brand">
                <img src={(brand || BRANDS[0]).logo} alt="" className="hp-cd-line-brand-logo" style={brandLogoStyle(brand || BRANDS[0])} />
                <span>{(brand || BRANDS[0]).label} Coffee</span>
              </span>
              <InfoBubble label="About the coffee price" onClick={() => setInfoDrawer("coffee")} />
            </span>
            <span className="hp-cd-line-amt">${formatUsd(quote.giftCardCost)}</span>
          </div>
          <div className="hp-cd-line">
            <span className="hp-cd-line-label">
              <span className="hp-cd-line-brand">
                <img src="screenshots/coffee/stripe.png" alt="" className="hp-cd-line-service-logo" />
                <span>Service fee</span>
              </span>
              <InfoBubble label="About the service fee" onClick={() => setInfoDrawer("delivery")} />
            </span>
            <span className="hp-cd-line-amt">${formatUsd(quote.serviceFee)}</span>
          </div>

          <div className="hp-cd-line hp-cd-line-total">
            <span>Total</span>
            <span className="hp-cd-line-amt">${formatUsd(quote.total)}</span>
          </div>
          <hr className="hp-cd-divider hp-cd-content-divider hp-cd-content-divider-bottom" aria-hidden="true" />
        </section>

        <div className="hp-pay-methods">
          <button
            type="button"
            className={"hp-pay-apple" + (quoteMethod === "stripe" ? " is-quote-active" : "") + (paying && method === "apple" ? " hp-pay-loading" : "")}
            onMouseEnter={() => setQuoteMethod("stripe")}
            onFocus={() => setQuoteMethod("stripe")}
            onClick={() => pay("apple")}
            disabled={paying}
          >
            {paying && method === "apple" ? <span className="hp-pay-spinner" /> : (
              <>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                  <path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/>
                </svg>
                Pay with Apple Pay
              </>
            )}
          </button>

          {SHOW_PAYPAL_PAYMENT && (
          <button
            type="button"
            className={"hp-pay-paypal" + (quoteMethod === "paypal" ? " is-quote-active" : "") + (paying && method === "paypal" ? " hp-pay-loading" : "")}
            onMouseEnter={() => setQuoteMethod("paypal")}
            onFocus={() => setQuoteMethod("paypal")}
            onClick={() => pay("paypal")}
            disabled={paying}
          >
            {paying && method === "paypal" ? <span className="hp-pay-spinner hp-pay-spinner-dark" /> : (
              <span className="hp-pay-paypal-logo">
                <span className="hp-pay-paypal-p">Pay</span><span className="hp-pay-paypal-pal">Pal</span>
              </span>
            )}
          </button>
          )}
        </div>

        <div className="hp-pay-secure">
          <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>
          </svg>
          Secured by Stripe
        </div>
        </div>
      </div>

      {activeInfo && (
        <LineInfoDrawer
          title={activeInfo.title}
          body={activeInfo.body}
          headingId={activeInfo.headingId}
          onClose={() => setInfoDrawer(null)}
        />
      )}
    </div>
  );
}

/* ── Brand picker bottom sheet ── */
function BrandPickerDrawer({ selected, onSelect, onClose }) {
  const [open, setOpen] = useState(false);
  useEffect(() => { requestAnimationFrame(() => setOpen(true)); }, []);

  function choose(b) {
    onSelect(b);
    onClose();
  }

  return (
    <div className="hp-cd-overlay" onClick={onClose} role="dialog" aria-modal="true" aria-label="Choose a coffee brand">
      <div className="hp-sheet-track">
        <div className={"hp-cd-sheet hp-brand-sheet" + (open ? " is-open" : "")} onClick={e => e.stopPropagation()}>
          <div className="hp-drawer-handle" />
          <div className="hp-brand-sheet-top">
            <h2 className="hp-brand-sheet-heading">Choose a brand</h2>
            <button type="button" className="hp-cd-close" onClick={onClose} aria-label="Close">
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                <path d="M6 6l12 12M18 6L6 18" />
              </svg>
            </button>
          </div>
          <div className="hp-brand-list">
            {BRANDS.map(b => (
              <button
                key={b.id}
                type="button"
                className={"hp-brand-row" + (selected.id === b.id ? " is-selected" : "")}
                onClick={() => choose(b)}
              >
                <img src={b.logo} alt={b.label} className="hp-brand-row-logo" style={brandLogoStyle(b)} />
                <span className="hp-brand-row-name">{b.label}</span>
                {selected.id === b.id && (
                  <svg className="hp-brand-row-check" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M5 12l5 5L20 7"/>
                  </svg>
                )}
              </button>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── Settings bottom sheet ── */
function SettingsDrawer({ senderName, onSave, onClose, podPremium, onUpgradePremium, onCancelPremium }) {
  const [open, setOpen] = useState(false);
  const [draftSenderName, setDraftSenderName] = useState(senderName);
  const [cancelConfirm, setCancelConfirm] = useState(false);

  useEffect(() => {
    const raf = requestAnimationFrame(() => {
      requestAnimationFrame(() => setOpen(true));
    });
    return () => cancelAnimationFrame(raf);
  }, []);
  useEffect(() => { setDraftSenderName(senderName); }, [senderName]);
  useEffect(() => {
    function onKey(e) {
      if (e.key === "Escape") onClose();
    }
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [onClose]);

  function save() {
    onSave(draftSenderName.trim() || DEFAULT_SENDER);
    onClose();
  }

  function handleCancel() {
    onCancelPremium();
    setCancelConfirm(false);
  }

  return (
    <div
      className="hp-cd-detail-overlay hp-settings-overlay"
      onClick={(e) => {
        e.stopPropagation();
        if (e.target === e.currentTarget) onClose();
      }}
      role="dialog"
      aria-modal="true"
      aria-labelledby="hp-settings-heading"
    >
      <div className="hp-sheet-track">
        <div className={"hp-settings-drawer" + (open ? " is-open" : "")} onClick={e => e.stopPropagation()}>
          <div className="hp-drawer-handle" />
          <div className="hp-settings-drawer-inner">
            <div className="hp-settings-top">
              <h3 className="hp-settings-heading" id="hp-settings-heading">Settings</h3>
              <button type="button" className="hp-cd-close" onClick={(e) => { e.stopPropagation(); onClose(); }} aria-label="Close">
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
                  <path d="M6 6l12 12M18 6L6 18" />
                </svg>
              </button>
            </div>

            <div className="hp-settings-card">
              <div className="hp-settings-card-head">Sender info</div>
              <label className="hp-settings-field-label" htmlFor="hp-settings-sender">Display name</label>
              <input
                id="hp-settings-sender"
                className="hp-settings-field-input"
                type="text"
                value={draftSenderName}
                onChange={e => setDraftSenderName(e.target.value)}
                placeholder="Michael Scott"
                maxLength={40}
              />
              <p className="hp-settings-field-hint">The name your recipient sees.</p>
            </div>

            <div className="hp-settings-card">
              <div className="hp-settings-card-head">Account</div>
              <p className="hp-settings-plan-line">
                Plan:{" "}
                {podPremium ? (
                  "Pod Premium"
                ) : (
                  <span className="hp-settings-plan-free">Free Account</span>
                )}
              </p>
              {podPremium && (
                <p className="hp-settings-plan-sub">{POD_PREMIUM_PRICE}</p>
              )}
              {podPremium ? (
                <>
                  <ul className="hp-settings-benefits">
                    {POD_PREMIUM_BENEFITS.map((benefit) => (
                      <li key={benefit}>{benefit}</li>
                    ))}
                  </ul>
                  <p className="hp-settings-benefits-foot">{POD_PREMIUM_FOOTNOTE}</p>
                  {!cancelConfirm ? (
                    <button type="button" className="hp-settings-cancel" onClick={() => setCancelConfirm(true)}>
                      Cancel subscription
                    </button>
                  ) : (
                    <div className="hp-settings-cancel-box">
                      <p className="hp-settings-cancel-prompt">Cancel Pod Premium?</p>
                      <div className="hp-settings-cancel-actions">
                        <button type="button" className="hp-settings-cancel-yes" onClick={handleCancel}>Yes, cancel</button>
                        <button type="button" className="hp-settings-cancel-no" onClick={() => setCancelConfirm(false)}>Keep it</button>
                      </div>
                    </div>
                  )}
                </>
              ) : (
                <button
                  type="button"
                  className="hp-settings-upgrade"
                  onClick={() => {
                    onClose();
                    onUpgradePremium();
                  }}
                >
                  Try Pod Premium
                </button>
              )}
            </div>

            <button type="button" className="hp-settings-save" onClick={save}>Save</button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── iPhone with the sending UI inside ── */
function HeroPhone({ note }) {
  const [phone, setPhone] = useState(DEMO_PHONE);
  const [sendMode, setSendMode] = useState("text"); // "text" | "email"
  const [phoneEdited, setPhoneEdited] = useState(true);
  const [phoneFocused, setPhoneFocused] = useState(false);
  const [noteText, setNoteText] = useState("Great job on that project!");
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [phoneError, setPhoneError] = useState("");
  const [sent, setSent] = useState(false);
  const [checkoutOpen, setCheckoutOpen] = useState(false);
  const [recipientName, setRecipientName] = useState(DEMO_RECIPIENT);
  const [amount, setAmount] = useState(COFFEE_PRICE);
  const [splashDone, setSplashDone] = useState(false);
  const [splashExiting, setSplashExiting] = useState(false);
  const [defaults, setDefaults] = useState({
    brand: BRANDS[0],
    sendMode: "text",
    price: COFFEE_PRICE,
    senderName: DEFAULT_SENDER,
  });
  const [brand, setBrand] = useState(BRANDS[0]);
  const [brandPickerOpen, setBrandPickerOpen] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [premiumOpen, setPremiumOpen] = useState(false);
  const [audioOpen, setAudioOpen] = useState(false);
  const [audioNote, setAudioNote] = useState(null);
  const [podPremium, setPodPremium] = useState(false);
  const [logoBurst, setLogoBurst] = useState(0);
  const homeQuote = calcCheckout(amount, "stripe");

  function handleLogoTap() {
    primeAudioContext();
    playSuccessChime();
    setLogoBurst(n => n + 1);
  }

  useEffect(() => {
    if (!logoBurst) return;
    const t = setTimeout(() => setLogoBurst(0), 1500);
    return () => clearTimeout(t);
  }, [logoBurst]);

  function handleSaveSettings(senderName) {
    setDefaults(d => ({ ...d, senderName }));
  }

  function switchMode(mode) {
    if (mode === sendMode) return;
    setSendMode(mode);
    setPhone(mode === "text" ? DEMO_PHONE : DEMO_EMAIL);
    setPhoneEdited(true);
    setPhoneError("");
    setRecipientName(DEMO_RECIPIENT);
    if (mode === "email") setAudioNote(null);
  }

  function handleSelectContact(c) {
    setPhone(sendMode === "text" ? c.phone : c.email);
    setPhoneEdited(true);
    setRecipientName(c.name);
    setDrawerOpen(false);
    setPhoneError("");
  }

  function isValid(value) {
    return sendMode === "text" ? isValidPhone(value) : isValidEmail(value);
  }

  function handlePhoneChange(value) {
    setPhone(value);
    setPhoneEdited(true);
    if (isValid(value)) setPhoneError("");
  }

  function handleAudioTap() {
    if (podPremium) setAudioOpen(true);
    else setPremiumOpen(true);
  }

  function handleAttachAudio(duration) {
    setAudioNote({ duration });
  }

  function handleSend() {
    if (!isValid(phone)) {
      setPhoneError(sendMode === "text" ? "Enter a valid phone number" : "Enter a valid email address");
      return;
    }
    primeAudioContext();
    setPhoneError("");
    setCheckoutOpen(true);
  }

  useEffect(() => {
    if (phoneError && isValid(phone)) setPhoneError("");
  }, [phone, phoneError, sendMode]);

  useEffect(() => {
    if (splashDone) return;
    const exitTimer = setTimeout(() => setSplashExiting(true), 1100);
    const doneTimer = setTimeout(() => setSplashDone(true), 1500);
    return () => {
      clearTimeout(exitTimer);
      clearTimeout(doneTimer);
    };
  }, [splashDone]);

  function handleCheckoutSuccess() {
    setCheckoutOpen(false);
    setSent(true);
  }

  function handleReset() {
    setSent(false);
    setCheckoutOpen(false);
    setPhone(sendMode === "text" ? DEMO_PHONE : DEMO_EMAIL);
    setPhoneEdited(true);
    setNoteText("Great job on that project!");
    setRecipientName(DEMO_RECIPIENT);
    setAmount(defaults.price);
    setPhoneError("");
    setSendMode(defaults.sendMode);
    setBrand(defaults.brand);
    setAudioNote(null);
  }

  return (
    <div className="hero-phone-stage">
      {/* small floating "received" card peeking behind */}
      <div className="received-peek">
        <div className="rp-cup">
          <Icon name="cup" size={18} />
        </div>
        <div>
          <div className="rp-eyebrow">delivered</div>
          <div className="rp-name">A coffee for Alex</div>
        </div>
        <div className="rp-check">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M5 12l5 5L20 7" />
          </svg>
        </div>
      </div>

      {/* the phone */}
      <div className="phone hero-phone">
        <div className="phone-notch" />
        <div className="phone-screen hero-phone-screen">
          {!splashDone && <PhoneSplash exiting={splashExiting} />}
          {logoBurst > 0 && (
            <div className="hp-bean-burst" key={logoBurst} aria-hidden="true">
              <BeanConfetti />
            </div>
          )}
          <div className="hp-phone-body">
          <div className="hp-phone-main">
          <div className="phone-status">
            <span>9:41</span>
            <PhoneStatusIcons />
          </div>

          <div className="hp-app-head">
            <div style={{ width: 28 }} />
            <div className="hp-app-title">Send a Coffee</div>
            <button type="button" className="hp-settings-btn" onClick={() => setSettingsOpen(true)} aria-label="Settings">
              <SettingsIcon />
            </button>
          </div>

          {/* Logo — tap for whale + beans */}
          <div className="hp-cup-wrap">
            <button type="button" className="hp-cup-btn" onClick={handleLogoTap} aria-label="Moby">
              <div className="hp-cup">
                <img src="assets/moby-logo.png" alt="" className="hp-cup-img hp-cup-logo" />
              </div>
            </button>
          </div>

          <EditableAmount value={amount} onChange={setAmount} />
          <div className="hp-amount-label hp-amount-fee">
            ${formatUsd(homeQuote.total)} total
          </div>

          {/* brand picker pill */}
          <button type="button" className="hp-brand-pill" onClick={() => setBrandPickerOpen(true)}>
            <img src={brand.logo} alt={brand.label} className="hp-brand-pill-logo" style={brandLogoStyle(brand)} />
            <span className="hp-brand-pill-name">{brand.label}</span>
            <svg className="hp-brand-pill-chevron" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M6 9l6 6 6-6"/>
            </svg>
          </button>

          {/* phone field */}
          <div className="hp-field-group">
            <div
              className={
                "hp-field-box" +
                (!phoneEdited && !phoneFocused ? " hp-field-ghost" : "") +
                (phoneError ? " hp-field-error" : "")
              }
            >
              <div className="hp-field-mode-toggle" role="group" aria-label="Send via">
                <button type="button" className={"hp-fmt-btn" + (sendMode === "text" ? " is-active" : "")} onClick={() => switchMode("text")}>Text</button>
                <button type="button" className={"hp-fmt-btn" + (sendMode === "email" ? " is-active" : "")} onClick={() => switchMode("email")}>Email</button>
              </div>
              {recipientName && (
                <div className="hp-field-label">{recipientName}</div>
              )}
              <div className="hp-field-row">
                <input
                type={sendMode === "text" ? "tel" : "email"}
                inputMode={sendMode === "text" ? "tel" : "email"}
                value={phone}
                onChange={e => handlePhoneChange(e.target.value)}
                onFocus={() => setPhoneFocused(true)}
                onBlur={() => setPhoneFocused(false)}
                placeholder={sendMode === "text" ? "their phone number" : "their@email.com"}
                aria-invalid={phoneError ? "true" : "false"}
                aria-describedby={phoneError ? "hp-phone-error" : undefined}
              />
              <button type="button" className="hp-field-plus" onClick={() => setDrawerOpen(true)} title="Choose from contacts" aria-label="Choose from contacts">
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                  <path d="M12 5v14M5 12h14"/>
                </svg>
              </button>
              </div>
            </div>
            {phoneError && (
              <p className="hp-email-hint" id="hp-phone-error" role="alert">
                <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" aria-hidden="true">
                  <circle cx="12" cy="12" r="10"/><path d="M12 8v4M12 16h.01"/>
                </svg>
                {phoneError}
              </p>
            )}
          </div>

          {/* editable note */}
          <div className="hp-note">
            <div className="hp-note-head">
              <div className="hp-note-label">Add a note</div>
              {audioNote && sendMode === "text" && (
                <div className="hp-note-audio-chip">
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                    <path d="M12 14a3 3 0 0 0 3-3V5a3 3 0 1 0-6 0v6a3 3 0 0 0 3 3zm5-3a5 5 0 0 1-10 0H5a7 7 0 0 0 6 6.92V21h2v-3.08A7 7 0 0 0 19 11h-2z"/>
                  </svg>
                  <span>Audio · {formatAudioTime(audioNote.duration)}</span>
                  <button
                    type="button"
                    className="hp-note-audio-chip-remove"
                    onClick={() => setAudioNote(null)}
                    aria-label="Remove audio note"
                  >
                    ×
                  </button>
                </div>
              )}
            </div>
            <div className="hp-note-compose">
              <textarea
                className={"hp-note-text hp-note-editable" + (sendMode === "text" ? " has-audio-btn" : "")}
                value={noteText}
                onChange={e => setNoteText(e.target.value)}
                maxLength={NOTE_MAX_LENGTH}
                rows={2}
              />
              {sendMode === "text" && (
                <button
                  type="button"
                  className="hp-note-audio"
                  onClick={handleAudioTap}
                  aria-label={podPremium ? "Record an audio note" : "Send an audio note with Pod Premium"}
                >
                  <img src="screenshots/coffee/microphone.svg" alt="" />
                </button>
              )}
            </div>
          </div>

          {/* send button */}
          <button className="hp-send" onClick={handleSend}>
            Review & Send
            <Icon name="arrow" size={15} />
          </button>
          </div>
          </div>

          {(settingsOpen || brandPickerOpen || drawerOpen || checkoutOpen || sent || premiumOpen || audioOpen) && (
          <div className="hp-phone-layers">
            {brandPickerOpen && (
              <BrandPickerDrawer
                selected={brand}
                onSelect={setBrand}
                onClose={() => setBrandPickerOpen(false)}
              />
            )}

            {drawerOpen && (
              <ContactsDrawer
                onSelect={handleSelectContact}
                onClose={() => setDrawerOpen(false)}
                sendMode={sendMode}
              />
            )}

            {checkoutOpen && (
              <CheckoutDrawer
                email={phone}
                recipientName={recipientName}
                senderName={defaults.senderName}
                note={noteText}
                sendMode={sendMode}
                brand={brand}
                price={amount}
                onSuccess={handleCheckoutSuccess}
                onClose={() => setCheckoutOpen(false)}
              />
            )}

            {settingsOpen && (
              <SettingsDrawer
                senderName={defaults.senderName}
                onSave={handleSaveSettings}
                onClose={() => setSettingsOpen(false)}
                podPremium={podPremium}
                onUpgradePremium={() => setPremiumOpen(true)}
                onCancelPremium={() => setPodPremium(false)}
              />
            )}

            {premiumOpen && (
              <PodPremiumDrawer
                onClose={() => setPremiumOpen(false)}
                isSubscribed={podPremium}
                onSubscribe={() => setPodPremium(true)}
              />
            )}

            {audioOpen && (
              <AudioRecordDrawer
                onClose={() => setAudioOpen(false)}
                onAttach={handleAttachAudio}
              />
            )}

            {sent && <ConfirmScreen recipientName={recipientName} brand={brand} onReset={handleReset} />}
          </div>
          )}
        </div>
      </div>

      {/* floating tag — top right */}
      <div className="floating-tag">
        <span className="ft-dot" />
        <span>Delivered instantly</span>
      </div>

      {/* left mid toast */}
      <div className="toast-left">
        <div className="tl-avatar">
          <Icon name="cup" size={15} />
        </div>
        <div>
          <div className="tl-name">Jordan sent a coffee</div>
          <div className="tl-sub">just now · $7.00</div>
        </div>
      </div>

      {/* top right toast */}
      <div className="toast-tr">
        <div className="ttr-icon">
          <Icon name="cup" size={15} />
        </div>
        <div>
          <div className="ttr-label">Redeemed</div>
          <div className="ttr-sub">Starbucks · $7.00</div>
        </div>
      </div>
    </div>
  );
}

function Hero({ note }) {
  const [modalOpen, setModalOpen] = useState(false);

  return (
    <section className="hero" data-screen-label="01 Hero">
      <div className="hero-bg">
        <div className="glow glow-1" />
        <div className="glow glow-2" />
        <div className="glow glow-3" />
      </div>

      <div className="hero-grid">
        <div className="hero-copy">
          <div className="hero-ratings">
            <span className="rating-pill">
              <svg className="rp-icon rp-apple" viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true">
                <path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.3.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/>
              </svg>
              Coming to iOS
            </span>
          </div>
          <h1 className="display">
            <span className="hero-main-light">Treat someone</span>
            <br />
            <span className="serif-italic">To a coffee</span>
          </h1>
          <p className="hero-sub">
            Moby is the easiest way to say thanks or good job with a coffee.
          </p>
          <div className="hero-ctas">
            <button
              type="button"
              className="btn btn-primary btn-large"
              onClick={() => setModalOpen(true)}
            >
              Join the Waitlist
              <Icon name="arrow" size={16} />
            </button>
          </div>
        </div>

        <HeroPhone note={note} />
      </div>

      {modalOpen && <WaitlistModal onClose={() => setModalOpen(false)} />}
    </section>
  );
}

function WaitlistModal({ onClose }) {
  const [email, setEmail] = useState("");
  const [submitted, setSubmitted] = useState(false);

  useEffect(() => {
    function onKey(e) { if (e.key === "Escape") onClose(); }
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [onClose]);

  function handleSubmit(e) {
    e.preventDefault();
    if (!email.trim()) return;
    setSubmitted(true);
  }

  return (
    <div className="csm-backdrop" onClick={e => { if (e.target === e.currentTarget) onClose(); }} role="dialog" aria-modal="true" aria-labelledby="waitlist-heading">
      <div className="csm-card">
        <button type="button" className="csm-close" onClick={onClose} aria-label="Close">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
            <path d="M6 6l12 12M18 6L6 18"/>
          </svg>
        </button>

        {submitted ? (
          <>
            <div className="csm-success-icon" aria-hidden="true">
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <path d="M5 12l5 5L20 7"/>
              </svg>
            </div>
            <h2 className="csm-heading" id="waitlist-heading">You&apos;re on the list!</h2>
            <p className="csm-body">We&apos;ll email you when Moby launches on iOS.</p>
            <button type="button" className="csm-btn" onClick={onClose}>Done</button>
          </>
        ) : (
          <>
            <h2 className="csm-heading" id="waitlist-heading">Join the waitlist</h2>
            <p className="csm-body">Be first to know when Moby launches on iOS.</p>
            <form className="csm-form" onSubmit={handleSubmit}>
              <label className="csm-label" htmlFor="waitlist-email">Email</label>
              <div className="csm-field-row">
                <input
                  id="waitlist-email"
                  className="csm-input"
                  type="email"
                  inputMode="email"
                  autoComplete="email"
                  placeholder="your@email.com"
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                  required
                />
                <button type="submit" className="csm-submit">
                  Join Now
                  <Icon name="arrow" size={15} />
                </button>
              </div>
            </form>
          </>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { Hero, Icon, PhoneStatusIcons });
