// screens-flows.jsx — sheets and flows used across the app:
//   • ClassSheet (slide-up class detail; "Book" → review → confirmed)
//   • WaitlistSheet (when class is full)
//   • PackagesSheet (grid of packs to buy) + CheckoutSheet
//   • SplashScreen / SignInScreen (returning member focused)
//   • SettingsSheet (notification prefs etc)

const { fmtIDR, findClass, findCoach, findFriend, minutesUntil, fmtCountdown, DAYS_SHORT, DAYS_LONG, DATES_THIS_WEEK } = window.NADI_HELPERS;

// ── Class detail sheet (slide-up; first step of booking) ─────────────
function ClassSheet({ session, user, onClose, onBookConfirmed, onWaitlist, onBuyPack, toggleSavedClass, toggleSavedCoach, openFriendProfile }) {
  const [reviewing, setReviewing] = useState(false);
  const [attendAnon, setAttendAnon] = useState(false);
  // Reset privacy choice each time a fresh session opens; default to user pref
  useEffect(() => {
    if (session) {
      setReviewing(false);
      setAttendAnon(!user.visibleByDefault);
    }
  }, [session && session.id]);
  if (!session) return null;
  const c = findClass(session.classId);
  const co = findCoach(session.coachId);
  const left = session.capacity - session.booked;
  const full = left === 0;
  const booked = user.booked.includes(session.id);
  const onWait = user.waitlist.includes(session.id);
  const friends = (session.friends || []).map(findFriend).filter(Boolean);
  const isFav = user.savedClasses.includes(c.id);

  // packs sorted by expiry — used to show which credit funds this
  const packs = (user.creditPacks || []).slice().sort((a, b) => new Date(a.expires) - new Date(b.expires));
  const fundingPack = packs.find((p) => p.credits > 0);

  const fmtDate = (iso) => new Date(iso).toLocaleDateString("en-GB", { day: "2-digit", month: "short" }).toLowerCase();

  // Two screens slide horizontally inside the sheet body
  return (
    <Sheet open={!!session} onClose={onClose} maxHeight="92%">
      <div style={{ position: "relative", overflow: "hidden", width: "100%" }}>
        <div style={{
          display: "flex", width: "200%",
          transform: reviewing ? "translateX(-50%)" : "translateX(0)",
          transition: "transform 0.32s cubic-bezier(0.2, 0.7, 0.2, 1)",
        }}>
          {/* ── DETAIL ── */}
          <div style={{ width: "50%", padding: "0 22px 26px" }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "6px 0 16px" }}>
              <Mono>{DAYS_LONG[session.day].toLowerCase()} · {session.time} · {c.duration} min</Mono>
              <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}>
                <Mono>close ×</Mono>
              </button>
            </div>

            <h2 className="display" style={{ fontSize: 56, color: "var(--ink)", letterSpacing: "-0.03em" }}>
              <em style={{ fontStyle: "italic", color: "var(--primary)" }}>{c.name}</em>
            </h2>
            <p style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink-soft)", marginTop: 10, fontWeight: 300, lineHeight: 1.5 }}>
              {c.tagline}.
            </p>

            {/* Teacher block */}
            <button onClick={() => toggleSavedCoach && toggleSavedCoach(co.id)} className="press" style={{
              marginTop: 22, width: "100%",
              padding: "14px 16px",
              background: "var(--surface)", border: "1px solid var(--rule)",
              display: "flex", alignItems: "center", gap: 14,
              textAlign: "left",
            }}>
              <Avatar name={co.name} initials={co.initials} tone={co.tone} size={48} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontFamily: "Newsreader, serif", fontSize: 20, color: "var(--ink)" }}>{co.name}</div>
                <Mono color="var(--ink-soft)">{co.title.toLowerCase()} · {co.yrs} yrs</Mono>
              </div>
              <FavIcon size={14} active={user.savedCoaches.includes(co.id)} />
            </button>

            {/* Detail grid */}
            <div style={{ marginTop: 18, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 1, background: "var(--rule)", border: "1px solid var(--rule)" }}>
              <DetailCell label="room" value={session.roomShort} sub={session.room.split("—")[0].trim().toLowerCase()} />
              <DetailCell label="level" value={c.level} sub="all welcome" />
              <DetailCell label="cost" value="1 credit" sub="cancel up to 1h before" />
              <DetailCell
                label="spots"
                value={`${left}/${session.capacity}`}
                sub={full ? "waitlist open" : left < 3 ? "almost full" : "open"}
                accent={left < 3}
              />
            </div>

            {/* Friends going */}
            {friends.length > 0 && (
              <div style={{ marginTop: 20 }}>
                <Mono>going</Mono>
                <div style={{ marginTop: 8, display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
                  <FriendStack friends={friends} anonCount={session?.anonCount || 0} size={32} max={6} />
                  <Mono>
                    {friends.length} from your circle
                    {session.anonCount > 0 ? ` · ${session.anonCount} anon` : ""}
                  </Mono>
                </div>
                <div style={{ marginTop: 10, display: "flex", flexWrap: "wrap", gap: 6 }}>
                  {friends.slice(0, 6).map((f) => (
                    <button key={f.id} onClick={() => openFriendProfile && openFriendProfile(f)} className="press" style={{
                      padding: "5px 10px 5px 5px",
                      border: "1px solid var(--rule)", background: "var(--bg)",
                      display: "inline-flex", alignItems: "center", gap: 8,
                      borderRadius: 999,
                    }}>
                      <Avatar name={f.name} initials={f.initials} tone={f.tone} size={22} />
                      <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10.5, letterSpacing: "0.04em", textTransform: "lowercase", color: "var(--ink-soft)" }}>
                        {f.firstName || f.name}
                      </span>
                    </button>
                  ))}
                </div>
              </div>
            )}

            {/* About this class */}
            <div style={{ marginTop: 22 }}>
              <Mono>about this class</Mono>
              <p style={{ marginTop: 6, fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.55 }}>
                A {c.duration}-minute class for {c.level.toLowerCase()} practitioners. Slow warm-up, deliberate sequencing, and time at the end for stillness. Mats and props provided.
              </p>
            </div>

            {/* Save toggle */}
            <button onClick={() => toggleSavedClass && toggleSavedClass(c.id)} className="press" style={{
              marginTop: 20, width: "100%",
              display: "flex", alignItems: "center", justifyContent: "center", gap: 10,
              padding: "12px 14px",
              border: `1px solid ${isFav ? "var(--primary)" : "var(--rule)"}`,
              background: "transparent",
              color: isFav ? "var(--primary)" : "var(--ink-soft)",
            }}>
              <FavIcon size={13} active={isFav} />
              <span style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: "0.08em", textTransform: "lowercase" }}>
                {isFav ? "saved · tap to remove" : "save this class"}
              </span>
            </button>

            {/* Sticky CTA */}
            <div style={{ marginTop: 22 }}>
              {booked ? (
                <Button variant="ghost" size="lg" fullWidth disabled>Already booked</Button>
              ) : full ? (
                onWait ? (
                  <Button variant="ghost" size="lg" fullWidth disabled>On waitlist · we'll notify you</Button>
                ) : (
                  <Button variant="accent" size="lg" fullWidth onClick={() => onWaitlist(session)}>Join waitlist</Button>
                )
              ) : fundingPack ? (
                <Button variant="primary" size="lg" fullWidth onClick={() => setReviewing(true)}>
                  Continue · 1 credit
                </Button>
              ) : (
                <Button variant="accent" size="lg" fullWidth onClick={onBuyPack}>Buy a pack to book →</Button>
              )}
              <Mono style={{ display: "block", marginTop: 10, textAlign: "center" }}>
                cancel up to 1h before · credit refunded
              </Mono>
            </div>
          </div>

          {/* ── REVIEW (step 2) ── */}
          <div style={{ width: "50%", padding: "0 22px 26px" }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "6px 0 16px" }}>
              <button onClick={() => setReviewing(false)} className="press" style={{
                background: "transparent", display: "inline-flex", alignItems: "center", gap: 6,
              }}>
                <svg width="13" height="13" viewBox="0 0 13 13" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"><path d="M8 2L3.5 6.5 8 11"/><path d="M3.5 6.5h7.5"/></svg>
                <Mono>back</Mono>
              </button>
              <Mono>booking · review</Mono>
            </div>

            <h2 className="display" style={{ fontSize: 36, marginBottom: 6 }}>
              Confirm your seat.
            </h2>
            <Mono>1 credit will be used.</Mono>

            <div style={{ marginTop: 22, padding: "18px 18px 16px", background: "var(--surface)", border: "1px solid var(--rule)" }}>
              <Mono color="var(--ink-soft)">{DAYS_LONG[session.day].toLowerCase()} · {session.time}</Mono>
              <h3 style={{ fontFamily: "Newsreader, serif", fontSize: 28, fontWeight: 400, marginTop: 6, color: "var(--ink)" }}>{c.name}</h3>
              <Mono style={{ marginTop: 6 }}>with {co.name.toLowerCase()} · {session.roomShort.toLowerCase()}</Mono>
            </div>

            {fundingPack && (
              <div style={{ marginTop: 16 }}>
                <Mono>credit from</Mono>
                <div style={{ marginTop: 8, padding: "16px 18px", border: "1px solid var(--ink)", background: "var(--bg)" }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                    <span style={{ fontFamily: "Newsreader, serif", fontSize: 20, color: "var(--ink)" }}>{fundingPack.packageName}</span>
                    <Mono color="var(--primary)">expires {fmtDate(fundingPack.expires)}</Mono>
                  </div>
                  <div style={{ marginTop: 8, display: "flex", alignItems: "center", gap: 10 }}>
                    <Mono style={{ fontSize: 18, color: "var(--ink)", fontFamily: "Newsreader, serif", textTransform: "none", letterSpacing: 0 }}>
                      {fundingPack.credits}
                    </Mono>
                    <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="var(--ink-soft)" strokeWidth="1.4"><path d="M3 7h9M9 4l3 3-3 3"/></svg>
                    <Mono style={{ fontSize: 18, color: "var(--primary)", fontFamily: "Newsreader, serif", textTransform: "none", letterSpacing: 0 }}>
                      {fundingPack.credits - 1}
                    </Mono>
                    <Mono>credit{fundingPack.credits - 1 === 1 ? "" : "s"} left</Mono>
                  </div>
                </div>
              </div>
            )}

            {/* Add to calendar toggle */}
            <div style={{ marginTop: 16, display: "flex", justifyContent: "space-between", alignItems: "center", padding: "14px 16px", border: "1px solid var(--rule)" }}>
              <div>
                <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>Add to calendar</div>
                <Mono>plus a 30-min before reminder</Mono>
              </div>
              <ToggleSwitch defaultOn />
            </div>

            {/* Anonymous attendance toggle */}
            <div style={{ marginTop: 10, display: "flex", justifyContent: "space-between", alignItems: "center", padding: "14px 16px", border: "1px solid var(--rule)", background: attendAnon ? "var(--surface)" : "transparent" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 12, minWidth: 0 }}>
                <Avatar size={28} initials={user.initials} tone={user.tone || "var(--primary)"} anon={attendAnon} />
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>
                    {attendAnon ? "Going anonymously" : "Going as Sinta"}
                  </div>
                  <Mono>{attendAnon ? "hidden from your friends" : "visible to your circle"}</Mono>
                </div>
              </div>
              <ToggleSwitch defaultOn={attendAnon} onChange={setAttendAnon} key={String(attendAnon)} />
            </div>

            <div style={{ marginTop: 22 }}>
              <Button variant="primary" size="lg" fullWidth onClick={() => { onBookConfirmed(session, attendAnon ? "anon" : "self"); }}>
                Confirm booking
              </Button>
              <Mono style={{ display: "block", marginTop: 10, textAlign: "center" }}>
                you can cancel up to 1h before class
              </Mono>
            </div>
          </div>
        </div>
      </div>
    </Sheet>
  );
}

function DetailCell({ label, value, sub, accent }) {
  return (
    <div style={{ background: "var(--bg)", padding: "12px 14px" }}>
      <Mono>{label}</Mono>
      <div style={{ fontFamily: "Newsreader, serif", fontSize: 19, fontWeight: 400, marginTop: 4, color: accent ? "var(--primary)" : "var(--ink)" }}>{value}</div>
      <Mono style={{ marginTop: 2, fontSize: 9.5 }}>{sub}</Mono>
    </div>
  );
}

function ToggleSwitch({ defaultOn, onChange }) {
  const [on, setOn] = useState(!!defaultOn);
  const flip = () => {
    const next = !on;
    setOn(next);
    onChange && onChange(next);
  };
  return (
    <button onClick={flip} className="press" style={{
      width: 42, height: 24, borderRadius: 12,
      background: on ? "var(--primary)" : "var(--surface-2)",
      position: "relative",
      transition: "background 0.2s ease",
      border: "1px solid " + (on ? "var(--primary)" : "var(--rule)"),
      flexShrink: 0,
    }}>
      <span style={{
        position: "absolute", top: 1, left: on ? 19 : 1,
        width: 20, height: 20, borderRadius: "50%",
        background: "var(--bg)",
        transition: "left 0.2s cubic-bezier(0.2, 0.7, 0.2, 1)",
        boxShadow: "0 1px 3px rgba(0,0,0,0.2)",
      }} />
    </button>
  );
}

// ── Confirmation full-screen ─────────────────────────────────────────
function BookingConfirmed({ open, session, onClose }) {
  if (!open || !session) return null;
  const c = findClass(session.classId), co = findCoach(session.coachId);
  return (
    <FullCover open={open} onClose={onClose}>
      <div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center", padding: "0 32px", textAlign: "center" }}>
        <div style={{ position: "relative", display: "flex", alignItems: "center", justifyContent: "center" }}>
          <span aria-hidden style={{
            position: "absolute", width: 200, height: 200, borderRadius: "50%",
            background: "var(--primary)", opacity: 0.18,
            animation: "nadi-breath 8s ease-in-out infinite",
          }} />
          <span aria-hidden style={{
            position: "absolute", width: 120, height: 120, borderRadius: "50%",
            background: "var(--primary)", opacity: 0.35,
            animation: "nadi-breath 8s ease-in-out infinite", animationDelay: "0.4s",
          }} />
          <BreathDot size={64} duration={8} />
        </div>
        <h1 className="display stretch-in" style={{ fontSize: 56, marginTop: 48, letterSpacing: "-0.03em", color: "var(--ink)" }}>
          You're on<br/>the <em style={{ fontStyle: "italic", color: "var(--primary)" }}>mat.</em>
        </h1>
        <p style={{ marginTop: 22, fontFamily: "Newsreader, serif", fontSize: 18, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.5, maxWidth: 300 }}>
          {c.name} · {DAYS_LONG[session.day]} at {session.time}.<br/>with {co.name}.
        </p>
        <Mono style={{ marginTop: 28 }}>we'll send a quiet reminder.</Mono>
      </div>
      <div style={{ padding: "16px 22px calc(20px + var(--safe-bot))" }}>
        <Button variant="primary" size="lg" fullWidth onClick={onClose}>Done</Button>
      </div>
    </FullCover>
  );
}

// ── Waitlist sheet ───────────────────────────────────────────────────
function WaitlistSheet({ open, session, onClose, onConfirm }) {
  if (!open || !session) return null;
  const c = findClass(session.classId), co = findCoach(session.coachId);
  return (
    <Sheet open={open} onClose={onClose} maxHeight="60%">
      <div style={{ padding: "10px 24px 26px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <Mono>waitlist · this class is full</Mono>
          <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
        </div>
        <h2 className="display" style={{ fontSize: 36, marginTop: 14 }}>
          Want a <em style={{ fontStyle: "italic", color: "var(--primary)" }}>seat</em> if one opens?
        </h2>
        <div style={{ marginTop: 18, padding: 16, background: "var(--surface)", border: "1px solid var(--rule)" }}>
          <Mono>{DAYS_LONG[session.day].toLowerCase()} · {session.time}</Mono>
          <div style={{ fontFamily: "Newsreader, serif", fontSize: 22, marginTop: 6, color: "var(--ink)" }}>{c.name}</div>
          <Mono style={{ marginTop: 4 }}>with {co.name.toLowerCase()}</Mono>
        </div>
        <ul style={{ listStyle: "none", padding: 0, margin: "18px 0 0", display: "flex", flexDirection: "column", gap: 10 }}>
          {[
            "We'll text you the moment a seat opens.",
            "You'll have 10 minutes to grab it.",
            "No credit is used unless you book."
          ].map((t, i) => (
            <li key={i} style={{ display: "flex", gap: 10, alignItems: "flex-start" }}>
              <span style={{ marginTop: 6, width: 5, height: 5, borderRadius: "50%", background: "var(--primary)", flexShrink: 0 }} />
              <span style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.5 }}>{t}</span>
            </li>
          ))}
        </ul>
        <div style={{ marginTop: 24, display: "flex", gap: 8 }}>
          <Button variant="ghost" size="md" fullWidth onClick={onClose}>Not now</Button>
          <Button variant="accent" size="md" fullWidth onClick={() => { onConfirm(session); onClose(); }}>Join waitlist</Button>
        </div>
      </div>
    </Sheet>
  );
}

// ── Packages sheet ──────────────────────────────────────────────────
function PackagesSheet({ open, onClose, onChoose }) {
  return (
    <Sheet open={open} onClose={onClose} maxHeight="92%">
      <div style={{ padding: "10px 22px 26px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <Mono>packages · every pack 30-day</Mono>
          <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
        </div>
        <h2 className="display" style={{ fontSize: 40, marginTop: 14 }}>
          Practice <em style={{ fontStyle: "italic", color: "var(--primary)" }}>often</em>,<br/>pay less.
        </h2>
        <p style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink-soft)", fontWeight: 300, marginTop: 12, lineHeight: 1.5 }}>
          Buy a pack of class credits. Every pack is good for thirty days. Use them on any class, any teacher.
        </p>

        <div style={{ marginTop: 22, display: "flex", flexDirection: "column", gap: 12 }}>
          {window.NADI.PACKAGES.map((p) => {
            const isStd = p.id === "five";
            return (
              <button key={p.id} onClick={() => onChoose(p)} className="press" style={{
                width: "100%", textAlign: "left",
                padding: "18px 20px",
                background: isStd ? "var(--ink)" : "var(--bg)",
                color: isStd ? "var(--bg)" : "var(--ink)",
                border: isStd ? "1px solid var(--ink)" : "1px solid var(--rule)",
                display: "grid", gridTemplateColumns: "1fr auto", gap: 12, alignItems: "center",
              }}>
                <div>
                  {p.badge && <Mono color={isStd ? "#E8A07F" : "var(--primary)"}>{p.badge.toLowerCase()}</Mono>}
                  <div style={{ marginTop: p.badge ? 6 : 0, display: "flex", alignItems: "baseline", gap: 10 }}>
                    <span style={{ fontFamily: "Newsreader, serif", fontSize: 32, fontWeight: 400, letterSpacing: "-0.02em" }}>{p.name}</span>
                  </div>
                  <Mono color={isStd ? "rgba(248,241,225,0.6)" : "var(--ink-soft)"} style={{ marginTop: 4 }}>
                    {p.classes} class{p.classes === 1 ? "" : "es"} · {fmtIDR(Math.round(p.price / p.classes))}/class
                  </Mono>
                </div>
                <div style={{ textAlign: "right" }}>
                  <div style={{ fontFamily: "Newsreader, serif", fontSize: 24, fontWeight: 400 }}>
                    {fmtIDR(p.price)}
                  </div>
                  <Mono color={isStd ? "rgba(248,241,225,0.55)" : "var(--ink-soft)"} style={{ marginTop: 4 }}>choose →</Mono>
                </div>
              </button>
            );
          })}
        </div>

        <div style={{ marginTop: 24, padding: 16, background: "var(--surface)", border: "1px solid var(--rule)" }}>
          <Mono color="var(--primary)">how it works</Mono>
          <ul style={{ margin: "10px 0 0", padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: 8 }}>
            {[
              ["01", "Buy a pack — valid 30 days."],
              ["02", "Spend one credit per class, any teacher."],
              ["03", "Cancel up to 1h before to get the credit back."],
            ].map(([n, t]) => (
              <li key={n} style={{ display: "flex", gap: 12, alignItems: "baseline" }}>
                <Mono color="var(--primary)">{n}</Mono>
                <span style={{ fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink-soft)", fontWeight: 300 }}>{t}</span>
              </li>
            ))}
          </ul>
        </div>
      </div>
    </Sheet>
  );
}

// ── Checkout sheet (payment method) ─────────────────────────────────
// Bank transfer is the only enabled method for now — QRIS and Card are
// shown as "coming soon" so members still see the roadmap.
function CheckoutSheet({ pkg, onClose, onConfirm }) {
  const method = "Bank Transfer";
  if (!pkg) return null;
  const methods = [
    { id: "Bank Transfer", sub: "transfer & upload proof", enabled: true },
    { id: "QRIS",          sub: "coming soon",             enabled: false },
    { id: "Card",          sub: "coming soon",             enabled: false },
  ];
  return (
    <Sheet open={!!pkg} onClose={onClose} maxHeight="80%">
      <div style={{ padding: "10px 22px 26px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <Mono>checkout</Mono>
          <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
        </div>
        <h2 className="display" style={{ fontSize: 36, marginTop: 14 }}>{pkg.name}.</h2>
        <Mono style={{ marginTop: 4 }}>{pkg.classes} class{pkg.classes !== 1 ? "es" : ""} · valid {pkg.validityDays} days</Mono>

        <div style={{ marginTop: 22, padding: "16px 0", borderTop: "1px solid var(--rule)", borderBottom: "1px solid var(--rule)", display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
          <span style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink-soft)" }}>Total</span>
          <span style={{ fontFamily: "Newsreader, serif", fontSize: 32, color: "var(--ink)" }}>{fmtIDR(pkg.price)}</span>
        </div>

        <div style={{ marginTop: 20 }}>
          <Mono>payment</Mono>
          <div style={{ display: "flex", flexDirection: "column", gap: 8, marginTop: 12 }}>
            {methods.map((m) => {
              const sel = m.id === method;
              return (
                <div key={m.id} aria-disabled={!m.enabled} style={{
                  padding: "14px 16px",
                  background: sel ? "var(--surface)" : "var(--bg)",
                  border: `1px solid ${sel ? "var(--ink)" : "var(--rule)"}`,
                  display: "flex", justifyContent: "space-between", alignItems: "center",
                  textAlign: "left",
                  opacity: m.enabled ? 1 : 0.42,
                  cursor: m.enabled ? "default" : "not-allowed",
                }}>
                  <div>
                    <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink)" }}>{m.id}</div>
                    <Mono>{m.sub}</Mono>
                  </div>
                  {m.enabled ? (
                    <span style={{
                      width: 18, height: 18, borderRadius: "50%",
                      border: "1px solid var(--ink)",
                      background: "var(--ink)",
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                    }}>
                      <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--bg)" }} />
                    </span>
                  ) : (
                    <span style={{
                      fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5,
                      letterSpacing: "0.08em", textTransform: "uppercase",
                      padding: "3px 6px", border: "1px solid var(--rule-strong)", color: "var(--ink-soft)",
                    }}>soon</span>
                  )}
                </div>
              );
            })}
          </div>
        </div>

        <div style={{ marginTop: 22 }}>
          <Button variant="accent" size="lg" fullWidth onClick={() => onConfirm(pkg, method)}>Confirm purchase</Button>
          <Mono style={{ display: "block", marginTop: 10, textAlign: "center" }}>
            next: transfer & upload your proof
          </Mono>
        </div>
      </div>
    </Sheet>
  );
}

// ── Bank transfer sheet (after checkout: account list + upload proof) ────
function BankTransferSheet({ pkg, onClose, onSubmit }) {
  const [selected, setSelected] = useState(null);
  const [copied, setCopied] = useState(null);
  const [proof, setProof] = useState(null); // {name, dataUrl}
  const [note, setNote] = useState("");
  const fileRef = React.useRef(null);

  // pick first active bank by default when sheet opens
  useEffect(() => {
    if (pkg) {
      const banks = (window.NADI_ADMIN.BANK_ACCOUNTS || []).filter((b) => b.active);
      setSelected(banks[0]?.id || null);
      setProof(null); setNote(""); setCopied(null);
    }
  }, [pkg && pkg.id]);

  if (!pkg) return null;
  const banks = (window.NADI_ADMIN.BANK_ACCOUNTS || []).filter((b) => b.active);

  const copy = (text, key) => {
    try { navigator.clipboard && navigator.clipboard.writeText(text); } catch (e) {}
    setCopied(key);
    setTimeout(() => setCopied(null), 1400);
  };

  const onPick = (e) => {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    const reader = new FileReader();
    reader.onload = () => setProof({ name: f.name, dataUrl: reader.result, size: f.size });
    reader.readAsDataURL(f);
  };

  const canSubmit = !!selected && !!proof;
  const submit = () => {
    if (!canSubmit) return;
    onSubmit && onSubmit({ pkg, bankId: selected, proof, note });
  };

  return (
    <Sheet open={!!pkg} onClose={onClose} maxHeight="94%">
      <div style={{ padding: "10px 22px 26px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <Mono>step 2 of 2 · bank transfer</Mono>
          <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
        </div>
        <h2 className="display" style={{ fontSize: 32, marginTop: 12, letterSpacing: "-0.025em" }}>
          Transfer <em style={{ fontStyle: "italic", color: "var(--primary)" }}>{fmtIDR(pkg.price)}</em>
        </h2>
        <p style={{ marginTop: 10, fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.5 }}>
          Send to any of the accounts below, then upload a screenshot of your receipt. The studio will confirm within a few hours and your credits will be activated.
        </p>

        {/* Order summary card */}
        <div style={{ marginTop: 18, padding: "14px 16px", border: "1px solid var(--rule)", background: "var(--surface)", display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
          <div>
            <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink)" }}>{pkg.name}</div>
            <Mono>{pkg.classes} credit{pkg.classes === 1 ? "" : "s"} · valid {pkg.validityDays}d</Mono>
          </div>
          <div style={{ fontFamily: "Newsreader, serif", fontSize: 22, color: "var(--ink)" }}>{fmtIDR(pkg.price)}</div>
        </div>

        {/* Bank accounts */}
        <div style={{ marginTop: 22 }}>
          <Eyebrow>01 · transfer to one of</Eyebrow>
          <div style={{ marginTop: 12, display: "flex", flexDirection: "column", gap: 10 }}>
            {banks.length === 0 && (
              <Mono>no accounts configured · contact studio</Mono>
            )}
            {banks.map((b) => {
              const sel = selected === b.id;
              return (
                <div key={b.id} style={{
                  border: `1px solid ${sel ? "var(--ink)" : "var(--rule)"}`,
                  background: sel ? "var(--bg)" : "var(--bg)",
                  padding: "14px 16px",
                }}>
                  <button onClick={() => setSelected(b.id)} className="press" style={{
                    width: "100%", textAlign: "left", background: "transparent",
                    display: "grid", gridTemplateColumns: "20px 1fr", gap: 12, alignItems: "center",
                  }}>
                    <span style={{
                      width: 18, height: 18, borderRadius: "50%",
                      border: `1px solid ${sel ? "var(--ink)" : "var(--rule-strong)"}`,
                      background: sel ? "var(--ink)" : "transparent",
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                    }}>
                      {sel && <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--bg)" }} />}
                    </span>
                    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 10 }}>
                      <div style={{ fontFamily: "Newsreader, serif", fontSize: 18, color: "var(--ink)" }}>{b.bank}</div>
                      <Mono>{b.branch.toLowerCase()}</Mono>
                    </div>
                  </button>

                  <div style={{ marginTop: 10, paddingLeft: 30 }}>
                    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }}>
                      <div style={{
                        fontFamily: "'JetBrains Mono', monospace", fontSize: 15,
                        color: "var(--ink)", letterSpacing: "0.04em",
                      }}>{b.number}</div>
                      <button onClick={() => copy(b.number.replace(/\s/g, ""), b.id + "-num")} className="press" style={{
                        padding: "4px 8px", border: "1px solid var(--rule)", background: "var(--surface)",
                        fontFamily: "'JetBrains Mono', monospace", fontSize: 10,
                        letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink)",
                      }}>{copied === b.id + "-num" ? "copied ✓" : "copy"}</button>
                    </div>
                    <Mono style={{ marginTop: 4, display: "block" }}>a/n {b.name.toLowerCase()}</Mono>
                  </div>
                </div>
              );
            })}
          </div>
          <button onClick={() => copy(String(pkg.price), "amount")} className="press" style={{
            marginTop: 12, width: "100%", padding: "12px 14px",
            border: "1px dashed var(--rule-strong)", background: "transparent",
            display: "flex", justifyContent: "space-between", alignItems: "center",
          }}>
            <Mono>exact amount · {fmtIDR(pkg.price)}</Mono>
            <Mono color="var(--primary)">{copied === "amount" ? "copied ✓" : "tap to copy"}</Mono>
          </button>
        </div>

        {/* Upload proof */}
        <div style={{ marginTop: 26 }}>
          <Eyebrow>02 · upload your receipt</Eyebrow>
          <input ref={fileRef} type="file" accept="image/*" onChange={onPick} style={{ display: "none" }} />
          {!proof ? (
            <button onClick={() => fileRef.current && fileRef.current.click()} className="press" style={{
              marginTop: 12, width: "100%", padding: "26px 14px",
              border: "1px dashed var(--rule-strong)", background: "var(--surface)",
              display: "flex", flexDirection: "column", alignItems: "center", gap: 8,
            }}>
              <svg width="28" height="28" viewBox="0 0 28 28" fill="none" stroke="var(--ink)" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round">
                <rect x="3" y="5" width="22" height="18"/>
                <path d="M3 19l6-6 5 5 4-4 7 7"/><circle cx="9" cy="11" r="1.4"/>
              </svg>
              <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>Choose screenshot</div>
              <Mono>jpg or png · the transfer confirmation</Mono>
            </button>
          ) : (
            <div style={{ marginTop: 12, border: "1px solid var(--rule)", background: "var(--bg)" }}>
              <div style={{
                width: "100%", background: "var(--surface)",
                display: "flex", alignItems: "center", justifyContent: "center",
                maxHeight: 280, overflow: "hidden",
              }}>
                <img src={proof.dataUrl} alt="receipt"
                  style={{ display: "block", width: "100%", maxHeight: 280, objectFit: "contain", background: "var(--ink)" }} />
              </div>
              <div style={{ padding: 12, display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }}>
                <div style={{ minWidth: 0, overflow: "hidden" }}>
                  <Mono color="var(--accent)">uploaded ✓</Mono>
                  <div style={{
                    fontFamily: "'JetBrains Mono', monospace", fontSize: 11,
                    color: "var(--ink)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
                  }}>{proof.name}</div>
                </div>
                <button onClick={() => fileRef.current && fileRef.current.click()} className="press" style={{
                  padding: "6px 10px", border: "1px solid var(--rule)", background: "var(--surface)",
                  fontFamily: "'JetBrains Mono', monospace", fontSize: 10,
                  letterSpacing: "0.08em", textTransform: "uppercase",
                }}>replace</button>
              </div>
            </div>
          )}
        </div>

        {/* Optional note */}
        <div style={{ marginTop: 18 }}>
          <Eyebrow>note (optional)</Eyebrow>
          <input value={note} onChange={(e) => setNote(e.target.value)}
            placeholder="e.g. transferred from my BCA account"
            style={{
              marginTop: 10, width: "100%", padding: "12px 14px",
              border: "1px solid var(--rule)", background: "var(--bg)",
              fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink)",
            }} />
        </div>

        <div style={{ marginTop: 24 }}>
          <Button variant="primary" size="lg" fullWidth onClick={submit} disabled={!canSubmit}>
            {canSubmit ? "Submit for confirmation" : (proof ? "Pick a bank account" : "Upload your receipt")}
          </Button>
          <Mono style={{ display: "block", marginTop: 10, textAlign: "center" }}>
            credits activate once the studio verifies your transfer
          </Mono>
        </div>
      </div>
    </Sheet>
  );
}

// ── Purchase pending confirmation (after submitting proof) ──────────
function PurchaseSubmittedSheet({ open, pkg, onClose }) {
  if (!pkg) return null;
  return (
    <Sheet open={open} onClose={onClose} maxHeight="60%">
      <div style={{ padding: "20px 22px 28px", textAlign: "center" }}>
        <div style={{ display: "flex", justifyContent: "center", marginTop: 6 }}>
          <Logo size={84} />
        </div>
        <Mono style={{ marginTop: 14, display: "block" }}>received · awaiting confirmation</Mono>
        <h2 className="display stretch-in" style={{ fontSize: 36, marginTop: 10, letterSpacing: "-0.025em" }}>
          Thank you,<br/><em style={{ fontStyle: "italic", color: "var(--primary)" }}>we'll verify shortly.</em>
        </h2>
        <p style={{ marginTop: 14, fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.5 }}>
          Your <em style={{ fontStyle: "italic" }}>{pkg.name}</em> is pending. Once the studio matches your transfer we'll activate your {pkg.classes} credit{pkg.classes === 1 ? "" : "s"} and notify you.
        </p>
        <div style={{ marginTop: 22 }}>
          <Button variant="primary" size="lg" fullWidth onClick={onClose}>Done</Button>
        </div>
      </div>
    </Sheet>
  );
}

// ── Splash / Sign-in (returning member focused) ─────────────────────
function SplashScreen({ onSignIn, onContinue, onAuth }) {
  const { useState, useEffect, useRef } = React;
  const googleBtnRef = useRef(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);

  const finishGoogle = async (credential) => {
    setLoading(true);
    try {
      const res = await fetch("/api/auth/google", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ credential }),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.detail || "Google authentication failed");
      }
      const data = await res.json();
      localStorage.setItem("nadi_token", data.access_token);
      if (onAuth) {
        onAuth(data.user);
      } else {
        window.location.reload();
      }
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    let cancelled = false;
    let attempts = 0;
    
    const renderGoogleButton = () => {
      fetch("/api/config")
        .then((r) => r.ok ? r.json() : { googleClientId: "" })
        .then((d) => {
          const clientId = d.googleClientId;
          if (!clientId || cancelled) {
            renderMockButton();
            return;
          }
          
          const checkGis = () => {
            if (window.google && window.google.accounts && window.google.accounts.id) {
              window.google.accounts.id.initialize({
                client_id: clientId,
                callback: (resp) => { if (resp && resp.credential) finishGoogle(resp.credential); },
                ux_mode: "popup",
                auto_select: false,
              });
              if (googleBtnRef.current) {
                googleBtnRef.current.innerHTML = "";
                window.google.accounts.id.renderButton(googleBtnRef.current, {
                  type: "standard",
                  theme: "outline",
                  size: "large",
                  text: "continue_with",
                  shape: "rectangular",
                  logo_alignment: "center",
                  width: 320,
                });
              }
            } else if (attempts++ < 50) {
              setTimeout(checkGis, 100);
            }
          };
          checkGis();
        })
        .catch(() => {
          if (!cancelled) renderMockButton();
        });
    };

    const renderMockButton = () => {
      if (googleBtnRef.current) {
        googleBtnRef.current.innerHTML = "";
        const btn = document.createElement("button");
        btn.className = "press";
        btn.style.width = "100%";
        btn.style.padding = "14px 18px";
        btn.style.background = "var(--bg)";
        btn.style.border = "1px solid var(--rule)";
        btn.style.display = "flex";
        btn.style.alignItems = "center";
        btn.style.justifyContent = "center";
        btn.style.gap = "12px";
        btn.innerHTML = `
          <svg width="18" height="18" viewBox="0 0 48 48"><path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/><path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/><path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/><path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/></svg>
          <span style="font-family: Geist, sans-serif; font-size: 14px; color: var(--ink); font-weight: 500; letter-spacing: 0.04em;">Continue with Google</span>
        `;
        btn.onclick = () => {
          if (onAuth) {
            onAuth({ name: "Sinta Putri", email: "sinta@mail.com" });
          } else if (onContinue) {
            onContinue();
          }
        };
        googleBtnRef.current.appendChild(btn);
      }
    };

    renderGoogleButton();
    return () => { cancelled = true; };
  }, [onAuth, onContinue]);

  return (
    <div className="screen-fade" style={{
      flex: 1, display: "flex", flexDirection: "column",
      padding: "24px 28px",
      background: "var(--bg)",
      position: "relative", overflow: "hidden",
    }}>
      {/* Ambient breath */}
      <span aria-hidden style={{
        position: "absolute", right: -80, top: -60,
        width: 280, height: 280, borderRadius: "50%",
        background: "var(--primary)", opacity: 0.12,
        animation: "nadi-breath 8s ease-in-out infinite",
      }} />

      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <Logo size={56} />
        <Mono>est. 2026</Mono>
      </div>

      <div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center", position: "relative" }}>
        <Mono>suvarna sutera · tangerang</Mono>
        <h1 className="display stretch-in" style={{ fontSize: 72, marginTop: 20, letterSpacing: "-0.035em", lineHeight: 0.9, color: "var(--ink)" }}>
          Breath as<br/><em style={{ fontStyle: "italic", color: "var(--primary)" }}>practice.</em><br/>
          The body as<br/><em style={{ fontStyle: "italic" }}>home.</em>
        </h1>
        <p style={{ marginTop: 26, fontFamily: "Newsreader, serif", fontSize: 18, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.5, maxWidth: 320 }}>
          A small studio for the slow, attentive practice — in two open-air rooms above the lake.
        </p>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 10, paddingBottom: "calc(8px + var(--safe-bot))", position: "relative", alignItems: "center" }}>
        {error && (
          <div style={{ padding: "8px 12px", background: "rgba(181,86,60,0.08)", border: "1px solid var(--primary)", width: "100%", marginBottom: 8 }}>
            <Mono color="var(--primary)" style={{ fontSize: 9.5 }}>{error}</Mono>
          </div>
        )}
        
        {/* Google sign-in button container */}
        <div ref={googleBtnRef} style={{ minHeight: 44, width: "100%", display: "flex", justifyContent: "center" }} />
        
        <Button variant="ghost" size="lg" fullWidth onClick={onSignIn}>Sign in or sign up with email</Button>
        
        <Mono style={{ display: "block", textAlign: "center", marginTop: 8 }}>
          tangerang · open daily 06:00 — 21:00
        </Mono>
      </div>
    </div>
  );
}

// ── Sign-in screen (full-screen, mobile-native) ─────────────────────
// ── Sign-in screen (full-screen, mobile-native) ─────────────────────
function SignInScreen({ onClose, onAuth }) {
  const [mode, setMode] = useState("signin"); // signin | register
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [name, setName] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const googleBtnRef = React.useRef(null);

  const API_BASE = window.location.origin.includes("localhost") ? "http://localhost:8001" : "";

  // Google Sign-In finish
  const finishGoogle = async (credential) => {
    setError(null);
    setLoading(true);
    try {
      const res = await fetch(API_BASE + "/api/auth/google", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ credential }),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.detail || "Google authentication failed");
      }
      const data = await res.json();
      localStorage.setItem("nadi_token", data.access_token);
      onAuth(data.user);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  // Load Google client ID
  useEffect(() => {
    let cancelled = false;
    let attempts = 0;
    
    const renderGoogleButton = () => {
      fetch(API_BASE + "/api/config")
        .then((r) => r.ok ? r.json() : { googleClientId: "" })
        .then((d) => {
          const clientId = d.googleClientId;
          if (!clientId || cancelled) return;
          
          const checkGis = () => {
            if (window.google && window.google.accounts && window.google.accounts.id) {
              window.google.accounts.id.initialize({
                client_id: clientId,
                callback: (resp) => { if (resp && resp.credential) finishGoogle(resp.credential); },
                ux_mode: "popup",
                auto_select: false,
              });
              if (googleBtnRef.current) {
                googleBtnRef.current.innerHTML = "";
                window.google.accounts.id.renderButton(googleBtnRef.current, {
                  type: "standard",
                  theme: "outline",
                  size: "large",
                  text: mode === "signin" ? "signin_with" : "signup_with",
                  shape: "rectangular",
                  logo_alignment: "center",
                  width: 320,
                });
              }
            } else if (attempts++ < 50) {
              setTimeout(checkGis, 100);
            }
          };
          checkGis();
        })
        .catch(() => {});
    };

    renderGoogleButton();
    return () => { cancelled = true; };
  }, [mode]);

  const submit = async () => {
    setError(null);
    setLoading(true);
    try {
      const endpoint = mode === "signin" ? "/api/auth/signin" : "/api/auth/register";
      const body = mode === "signin"
        ? { email, password }
        : { name, email, password };

      const res = await fetch(API_BASE + endpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });

      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.detail || "Authentication failed");
      }

      const data = await res.json();
      localStorage.setItem("nadi_token", data.access_token);
      onAuth(data.user);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="screen-fade" style={{ flex: 1, display: "flex", flexDirection: "column", background: "var(--bg)" }}>
      <TopBar onBack={onClose} eyebrow={mode === "signin" ? "welcome back" : "create account"} title="" />
      <div className="scroll" style={{ flex: 1, padding: "8px 26px 26px" }}>
        <div style={{ display: "flex", justifyContent: "center", marginTop: 6 }}>
          <Logo size={72} />
        </div>
        <h1 className="display stretch-in" style={{ fontSize: 48, letterSpacing: "-0.03em", marginTop: 18, textAlign: "center" }}>
          {mode === "signin" ? <>Welcome <em style={{ fontStyle: "italic", color: "var(--primary)" }}>back.</em></> : <>Make a <em style={{ fontStyle: "italic", color: "var(--primary)" }}>start.</em></>}
        </h1>
        <p style={{ marginTop: 14, fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.5, textAlign: "center" }}>
          {mode === "signin" ? "Sign in to book classes and check your credits." : "Tell us where to send your booking confirmations."}
        </p>

        <div ref={googleBtnRef} style={{ marginTop: 28, minHeight: 44, display: "flex", justifyContent: "center" }} />

        <div style={{ display: "flex", alignItems: "center", gap: 12, margin: "22px 0" }}>
          <div style={{ flex: 1, height: 1, background: "var(--rule)" }} />
          <Mono>or with email</Mono>
          <div style={{ flex: 1, height: 1, background: "var(--rule)" }} />
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
          {mode === "register" && <Field label="Full name" value={name} onChange={setName} placeholder="Your name" />}
          <Field label="Email" value={email} onChange={setEmail} placeholder="you@mail.com" type="email" />
          <Field label="Password" value={password} onChange={setPassword} placeholder="•••••••" type="password" />
        </div>

        {error && (
          <div style={{ marginTop: 16, padding: "10px 14px", background: "rgba(181,86,60,0.08)", border: "1px solid var(--primary)" }}>
            <Mono color="var(--primary)">{error}</Mono>
          </div>
        )}

        <div style={{ marginTop: 28 }}>
          <Button variant="primary" size="lg" fullWidth onClick={submit} disabled={loading}>
            {loading ? "Please wait..." : (mode === "signin" ? "Sign in" : "Create account")}
          </Button>
        </div>


        <div style={{ marginTop: 22, textAlign: "center" }}>
          <button onClick={() => setMode(mode === "signin" ? "register" : "signin")} className="press" style={{ background: "transparent", padding: 6 }}>
            <Mono color="var(--primary)">
              {mode === "signin" ? "new here? create an account →" : "already a member? sign in →"}
            </Mono>
          </button>
        </div>
      </div>
    </div>
  );
}

function GoogleG({ size = 18 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 48 48" aria-hidden>
      <path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/>
      <path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/>
      <path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/>
      <path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/>
    </svg>
  );
}

// ── Settings sheet ─────────────────────────────────────────────────
function SettingsSheet({ open, onClose, onSignOut, user, setUser, showToast }) {
  return (
    <Sheet open={open} onClose={onClose} maxHeight="92%">
      <div style={{ padding: "10px 22px 26px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <Mono>settings</Mono>
          <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
        </div>
        <h2 className="display" style={{ fontSize: 32, marginTop: 12 }}>Preferences.</h2>

        {/* Privacy */}
        <div style={{ marginTop: 22 }}>
          <Eyebrow>privacy</Eyebrow>
          <div style={{ marginTop: 10, padding: "16px 16px", border: "1px solid var(--rule)", background: "var(--surface)" }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12 }}>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink)" }}>Show me to friends</div>
                <Mono>your default — you can switch per class</Mono>
              </div>
              <ToggleSwitch defaultOn={user ? user.visibleByDefault : true} key={user && String(user.visibleByDefault)} onChange={(v) => {
                if (setUser && user) setUser({ ...user, visibleByDefault: v });
                showToast && showToast(v ? "Visible to your friends." : "Going incognito by default.");
              }} />
            </div>
            <div style={{ marginTop: 12, display: "flex", alignItems: "center", gap: 10 }}>
              {user && <Avatar size={28} initials={user.initials} tone="var(--primary)" anon={user && !user.visibleByDefault} />}
              <Mono>
                {user && user.visibleByDefault
                  ? "friends will see you in class lists"
                  : "you'll appear as +1 anon in their feed"}
              </Mono>
            </div>
          </div>
        </div>

        <div style={{ marginTop: 22 }}>
          <Eyebrow>notifications</Eyebrow>
          <div style={{ marginTop: 10, display: "flex", flexDirection: "column" }}>
            {[
              { label: "Class reminders", sub: "30 min before · push", on: true },
              { label: "Waitlist alerts", sub: "the moment a seat opens", on: true },
              { label: "Pack expiry warnings", sub: "7 days before credit lapse", on: true },
              { label: "Friend activity", sub: "when someone you follow books a shared class", on: true },
              { label: "Weekly schedule digest", sub: "every monday morning", on: false },
              { label: "New teacher / class news", sub: "rare and slow", on: false },
            ].map((item, i) => (
              <div key={i} style={{ padding: "14px 0", borderBottom: "1px solid var(--rule)", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12 }}>
                <div>
                  <div style={{ fontFamily: "Newsreader, serif", fontSize: 16, color: "var(--ink)" }}>{item.label}</div>
                  <Mono>{item.sub}</Mono>
                </div>
                <ToggleSwitch defaultOn={item.on} />
              </div>
            ))}
          </div>
        </div>

        <div style={{ marginTop: 24 }}>
          <Button variant="dangerGhost" size="md" fullWidth onClick={onSignOut}>Sign out</Button>
        </div>
      </div>
    </Sheet>
  );
}

Object.assign(window, {
  ClassSheet, BookingConfirmed, WaitlistSheet, PackagesSheet, CheckoutSheet,
  BankTransferSheet, PurchaseSubmittedSheet,
  SplashScreen, SignInScreen, SettingsSheet,
  FindFriendsSheet, FriendProfileSheet,
  ToggleSwitch,
});

// ── Find Friends sheet ─────────────────────────────────────────────
function FindFriendsSheet({ open, onClose, user, sendRequest, openFriendProfile, showToast }) {
  const [query, setQuery] = useState("");
  const suggestions = window.NADI.FRIEND_SUGGESTIONS;
  const filtered = query
    ? suggestions.filter((s) => s.name.toLowerCase().includes(query.toLowerCase()))
    : suggestions;
  const sent = (id) => user.sentRequests.includes(id);

  return (
    <Sheet open={open} onClose={onClose} maxHeight="92%">
      <div style={{ padding: "10px 22px 26px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <Mono>friends · find people</Mono>
          <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
        </div>

        <h2 className="display" style={{ fontSize: 40, marginTop: 14 }}>
          Find your <em style={{ fontStyle: "italic", color: "var(--primary)" }}>circle</em>.
        </h2>
        <p style={{ marginTop: 10, fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink-soft)", fontWeight: 300, lineHeight: 1.5 }}>
          Practice is quieter when someone you know is on the next mat. Follow people you've shared a class with.
        </p>

        {/* Search */}
        <div style={{ position: "relative", marginTop: 22 }}>
          <span style={{ position: "absolute", left: 14, top: "50%", transform: "translateY(-50%)", display: "flex" }}>
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="var(--ink-soft)" strokeWidth="1.4" strokeLinecap="round"><circle cx="6" cy="6" r="4.5"/><path d="M10 10l3 3"/></svg>
          </span>
          <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search by name or phone…" style={{
            width: "100%", padding: "12px 14px 12px 38px",
            border: "1px solid var(--rule)", background: "var(--bg)",
            fontFamily: "Geist, sans-serif", fontSize: 14, color: "var(--ink)",
          }} />
        </div>

        {/* Quick add methods */}
        <div style={{ marginTop: 14, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
          <button onClick={() => showToast && showToast("QR scanner opened.")} className="press" style={{
            padding: "14px 12px",
            background: "var(--bg)", border: "1px solid var(--rule)",
            display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 6,
          }}>
            <svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="var(--primary)" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="6" height="6"/><rect x="11" y="3" width="6" height="6"/><rect x="3" y="11" width="6" height="6"/><path d="M11 11h2v2M15 11v2M11 15v2h2M15 15h2"/></svg>
            <div>
              <div style={{ fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink)" }}>Scan QR</div>
              <Mono>at the front desk</Mono>
            </div>
          </button>
          <button onClick={() => { navigator.clipboard?.writeText("nadi.yoga/u/sinta"); showToast && showToast("Invite link copied."); }} className="press" style={{
            padding: "14px 12px",
            background: "var(--bg)", border: "1px solid var(--rule)",
            display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 6,
          }}>
            <svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="var(--primary)" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"><path d="M8 12l4-4M6 6l2-2 4 4-2 2zM14 14l-2 2-4-4 2-2z"/></svg>
            <div>
              <div style={{ fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink)" }}>Copy invite link</div>
              <Mono>send via any app</Mono>
            </div>
          </button>
        </div>

        {/* Suggestions */}
        <div style={{ marginTop: 22 }}>
          <Eyebrow>suggested · {filtered.length}</Eyebrow>
          <Mono style={{ display: "block", marginTop: 4 }}>people you've shared classes with</Mono>
          <div style={{ marginTop: 12, display: "flex", flexDirection: "column", gap: 8 }}>
            {filtered.length === 0 ? (
              <div style={{ padding: "32px 0", textAlign: "center" }}><Mono>no matches</Mono></div>
            ) : filtered.map((s) => (
              <div key={s.id} style={{
                padding: "12px 14px",
                background: "var(--bg)", border: "1px solid var(--rule)",
                display: "grid", gridTemplateColumns: "40px 1fr auto", gap: 12, alignItems: "center",
              }}>
                <button onClick={() => openFriendProfile && openFriendProfile(s)} className="press" style={{ background: "transparent", padding: 0 }}>
                  <Avatar name={s.name} initials={s.initials} tone={s.tone} size={40} />
                </button>
                <button onClick={() => openFriendProfile && openFriendProfile(s)} className="press" style={{ background: "transparent", textAlign: "left", minWidth: 0 }}>
                  <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, color: "var(--ink)" }}>{s.name}</div>
                  <Mono>{s.reason} · {s.mutual} mutual</Mono>
                </button>
                <button onClick={() => sendRequest(s.id)} disabled={sent(s.id)} className="press" style={{
                  padding: "8px 14px",
                  background: sent(s.id) ? "transparent" : "var(--ink)",
                  color: sent(s.id) ? "var(--ink-soft)" : "var(--bg)",
                  border: `1px solid ${sent(s.id) ? "var(--rule)" : "var(--ink)"}`,
                  fontFamily: "'JetBrains Mono', monospace", fontSize: 10,
                  letterSpacing: "0.06em", textTransform: "lowercase",
                }}>{sent(s.id) ? "requested" : "+ follow"}</button>
              </div>
            ))}
          </div>
        </div>
      </div>
    </Sheet>
  );
}

// ── Friend profile sheet ───────────────────────────────────────────
function FriendProfileSheet({ friend, user, onClose, unfollowFriend, sendRequest, acceptRequest, declineRequest, showToast }) {
  if (!friend) return null;
  const isFollowing = user.following.includes(friend.id);
  const isPending = !!friend.isPending;
  const requested = user.sentRequests.includes(friend.id);

  // Find shared classes — sessions where this friend goes that current user has saved/booked
  const sharedSessions = window.NADI.SCHEDULE
    .filter((s) => s.friends.includes(friend.id))
    .slice(0, 5);
  const nextShared = sharedSessions
    .filter((s) => user.booked.includes(s.id))[0];

  // Mock stats
  const stats = {
    classesThisMonth: 6,
    favouriteClass: "Slow Flow",
    favouriteTeacher: "Ayu",
    practicing: "since Mar 2025",
  };

  return (
    <Sheet open={!!friend} onClose={onClose} maxHeight="92%">
      <div style={{ padding: "10px 22px 26px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <Mono>{isPending ? "follow request" : isFollowing ? "in your circle" : "discover"}</Mono>
          <button onClick={onClose} className="press" style={{ background: "transparent", padding: 6 }}><Mono>close ×</Mono></button>
        </div>

        <div style={{ marginTop: 18, display: "flex", flexDirection: "column", alignItems: "center", textAlign: "center" }}>
          <Avatar name={friend.name} initials={friend.initials} tone={friend.tone} size={84} />
          <h2 className="display" style={{ fontSize: 36, marginTop: 16 }}>{friend.name}</h2>
          <Mono style={{ marginTop: 6 }}>practicing {stats.practicing.toLowerCase()}</Mono>
        </div>

        {/* Mutuals + meta */}
        {(friend.mutual || friend.reason) && (
          <div style={{ marginTop: 18, padding: "12px 14px", background: "var(--surface)", border: "1px solid var(--rule)", textAlign: "center" }}>
            <Mono>{friend.reason || `${friend.mutual || 0} mutual friend${(friend.mutual || 0) === 1 ? "" : "s"}`}</Mono>
          </div>
        )}

        {/* Stats */}
        <div style={{ marginTop: 18, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 1, background: "var(--rule)", border: "1px solid var(--rule)" }}>
          <div style={{ background: "var(--bg)", padding: "14px 16px" }}>
            <Mono>this month</Mono>
            <div style={{ fontFamily: "Newsreader, serif", fontSize: 28, lineHeight: 1, marginTop: 6, color: "var(--ink)", letterSpacing: "-0.01em" }}>{stats.classesThisMonth}</div>
            <Mono style={{ marginTop: 4 }}>classes</Mono>
          </div>
          <div style={{ background: "var(--bg)", padding: "14px 16px" }}>
            <Mono>often books</Mono>
            <div style={{ fontFamily: "Newsreader, serif", fontSize: 17, lineHeight: 1.1, marginTop: 6, color: "var(--ink)" }}>{stats.favouriteClass}</div>
            <Mono style={{ marginTop: 4 }}>with {stats.favouriteTeacher.toLowerCase()}</Mono>
          </div>
        </div>

        {/* Shared upcoming */}
        {nextShared && (
          <div style={{ marginTop: 18, padding: 16, background: "var(--ink)", color: "var(--bg)" }}>
            <Mono color="rgba(248,241,225,0.6)">you're both going</Mono>
            <div style={{ fontFamily: "Newsreader, serif", fontSize: 22, marginTop: 6 }}>
              {window.NADI_HELPERS.findClass(nextShared.classId).name}
            </div>
            <Mono color="rgba(248,241,225,0.6)" style={{ marginTop: 4, display: "block" }}>
              {window.NADI_HELPERS.DAYS_LONG[nextShared.day].toLowerCase()} · {nextShared.time}
            </Mono>
          </div>
        )}

        {/* Recent shared classes */}
        {sharedSessions.length > 0 && (
          <div style={{ marginTop: 18 }}>
            <Mono>recent shared classes</Mono>
            <div style={{ marginTop: 8, borderTop: "1px solid var(--rule)" }}>
              {sharedSessions.map((s) => {
                const c = window.NADI_HELPERS.findClass(s.classId);
                return (
                  <div key={s.id} style={{ padding: "10px 0", borderBottom: "1px solid var(--rule)", display: "flex", justifyContent: "space-between" }}>
                    <span style={{ fontFamily: "Newsreader, serif", fontSize: 15, color: "var(--ink)" }}>{c.name}</span>
                    <Mono>{window.NADI_HELPERS.DAYS_SHORT[s.day].toLowerCase()} {s.time}</Mono>
                  </div>
                );
              })}
            </div>
          </div>
        )}

        {/* CTA */}
        <div style={{ marginTop: 22 }}>
          {isPending ? (
            <div style={{ display: "flex", gap: 8 }}>
              <Button variant="ghost" size="md" fullWidth onClick={() => { declineRequest && declineRequest(friend.id); onClose(); }}>Decline</Button>
              <Button variant="primary" size="md" fullWidth onClick={() => { acceptRequest && acceptRequest(friend.id); onClose(); }}>Follow back</Button>
            </div>
          ) : isFollowing ? (
            <Button variant="dangerGhost" size="md" fullWidth onClick={() => { unfollowFriend && unfollowFriend(friend.id); onClose(); }}>Unfollow</Button>
          ) : requested ? (
            <Button variant="ghost" size="md" fullWidth disabled>Request sent</Button>
          ) : (
            <Button variant="primary" size="md" fullWidth onClick={() => { sendRequest && sendRequest(friend.id); }}>+ Follow</Button>
          )}
        </div>
      </div>
    </Sheet>
  );
}
