/* Wellpaged — creator account: login / signup / forgot / reset / verify + a full
   dashboard (sidebar · topbar · views, mirroring the admin shell):
     Overview · Traffic · Links · My page · Billing · Settings
   Talks to /api/auth/*, /api/account/site, /api/stats, /api/edit,
   /api/publish (rebuild) and /api/stripe/{checkout,portal} with the session
   cookie. Admins are redirected to admin.wellpaged.com. */
const { useState, useEffect } = React;

const POST = (path, body) =>
  fetch(path, { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body || {}) })
    .then((r) => r.json().then((d) => ({ ok: r.ok, d })).catch(() => ({ ok: r.ok, d: {} })));
const GET = (path) =>
  fetch(path, { credentials: "same-origin", headers: { Accept: "application/json" } })
    .then((r) => r.json().then((d) => ({ ok: r.ok, d })).catch(() => ({ ok: r.ok, d: null })));

/* thin-stroke icons (same visual language as the admin shell) */
const I = {
  grid: "M3 3h7v7H3zM14 3h7v7h-7zM14 14h7v7h-7zM3 14h7v7H3z",
  pulse: "M3 12h4l3 8 4-16 3 8h4",
  linkc: "M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7-7l-1.7 1.7M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7 7l1.7-1.7",
  layers: "M12 2 2 7l10 5 10-5zM2 17l10 5 10-5M2 12l10 5 10-5",
  card: "M2 6h20v12H2zM2 10h20",
  cog: "M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6M19 12a7 7 0 0 0-.1-1l2-1.5-2-3.5-2.4 1a7 7 0 0 0-1.7-1L14.5 2h-5l-.3 2.5a7 7 0 0 0-1.7 1l-2.4-1-2 3.5L3.1 11a7 7 0 0 0 0 2l-2 1.5 2 3.5 2.4-1a7 7 0 0 0 1.7 1l.3 2.5h5l.3-2.5a7 7 0 0 0 1.7-1l2.4 1 2-3.5-2-1.5a7 7 0 0 0 .1-1z",
};
function Icon({ d }) { return <svg className="ic" viewBox="0 0 24 24" strokeLinecap="round" strokeLinejoin="round"><path d={d} /></svg>; }
const NAV = [
  { id: "overview", label: "Overview", d: I.grid },
  { id: "traffic", label: "Traffic", d: I.pulse },
  { id: "links", label: "Links", d: I.linkc },
  { id: "page", label: "My page", d: I.layers },
  { id: "billing", label: "Billing", d: I.card },
  { id: "settings", label: "Settings", d: I.cog },
];

function App() {
  const params = new URLSearchParams(location.search);
  const resetToken = params.get("reset");
  const [me, setMe] = useState(undefined);     // undefined=loading, null=out, {email,verified,sites}=in
  const [flash, setFlash] = useState(null);    // { kind:'ok'|'err', msg }

  useEffect(() => {
    const verifyToken = params.get("verify");
    const run = async () => {
      if (verifyToken) {
        const { ok, d } = await POST("/api/auth/verify", { token: verifyToken });
        setFlash(ok ? { kind: "ok", msg: "Your email is verified ✓" } : { kind: "err", msg: (d && d.error) || "Verification failed." });
        history.replaceState(null, "", location.pathname);
      }
      if (resetToken) { setMe(null); return; } // show reset form (handled below)
      fetch("/api/auth/me", { credentials: "same-origin", headers: { Accept: "application/json" } })
        .then((r) => (r.ok ? r.json() : null))
        .then((dd) => setMe(dd && dd.authenticated ? { email: dd.email, verified: !!dd.verified, sites: dd.sites || [] } : null))
        .catch(() => setMe(null));
    };
    run();
  }, []);

  if (resetToken) return <Shell><ResetForm token={resetToken} onDone={(d) => { history.replaceState(null, "", "/account/"); setMe({ email: d.email, verified: true, sites: d.sites || [] }); }} /></Shell>;
  if (me === undefined) return <Shell><p>Loading…</p></Shell>;
  return me
    ? <Dashboard me={me} setMe={setMe} flash={flash} />
    : <AuthForm flash={flash} onAuth={(d) => setMe({ email: d.email, verified: !!d.verified, sites: d.sites || [] })} />;
}

function Shell({ children }) { return <div className="wrap"><div className="card">{children}</div></div>; }
function Flash({ flash }) { return flash ? <div className={flash.kind === "ok" ? "okmsg" : "err"}>{flash.msg}</div> : null; }

function AuthForm({ onAuth, flash }) {
  const [mode, setMode] = useState("login"); // login | signup | forgot
  const [email, setEmail] = useState("");
  const [pw, setPw] = useState("");
  const [err, setErr] = useState(null);
  const [note, setNote] = useState(null);
  const [busy, setBusy] = useState(false);

  const submit = (e) => {
    e.preventDefault(); setBusy(true); setErr(null); setNote(null);
    if (mode === "forgot") {
      POST("/api/auth/forgot", { email: email.trim() }).then(() => { setBusy(false); setNote("If that email has an account, we’ve sent a reset link. Check your inbox."); });
      return;
    }
    POST("/api/auth/" + mode, { email: email.trim(), password: pw }).then(({ ok, d }) => {
      setBusy(false); if (ok) onAuth(d); else setErr((d && d.error) || "Something went wrong.");
    });
  };

  return (
    <div className="wrap"><div className="card">
      <div className="brand">Wellpaged</div>
      <h1>{mode === "login" ? "Welcome back" : mode === "signup" ? "Create your account" : "Reset your password"}</h1>
      <Flash flash={flash} />
      <form onSubmit={submit}>
        <label>Email<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} autoComplete="email" required /></label>
        {mode !== "forgot" && <label>Password<input type="password" value={pw} onChange={(e) => setPw(e.target.value)} autoComplete={mode === "login" ? "current-password" : "new-password"} minLength={8} required /></label>}
        {err && <div className="err">{err}</div>}
        {note && <div className="okmsg">{note}</div>}
        <button className="btn" disabled={busy}>{busy ? "…" : mode === "login" ? "Log in" : mode === "signup" ? "Sign up" : "Send reset link"}</button>
      </form>
      {mode === "login" && <p className="alt"><button className="link" onClick={() => { setMode("forgot"); setErr(null); setNote(null); }}>Forgot password?</button></p>}
      <p className="alt">
        {mode === "signup" ? "Already have an account? " : "New to Wellpaged? "}
        <button className="link" onClick={() => { setMode(mode === "signup" ? "login" : "signup"); setErr(null); setNote(null); }}>
          {mode === "signup" ? "Log in" : "Create an account"}
        </button>
        {mode === "forgot" && <span> · <button className="link" onClick={() => { setMode("login"); setErr(null); setNote(null); }}>Back to log in</button></span>}
      </p>
    </div></div>
  );
}

function ResetForm({ token, onDone }) {
  const [pw, setPw] = useState(""); const [err, setErr] = useState(null); const [busy, setBusy] = useState(false);
  const submit = (e) => {
    e.preventDefault(); setBusy(true); setErr(null);
    POST("/api/auth/reset", { token, password: pw }).then(({ ok, d }) => { setBusy(false); if (ok) onDone(d); else setErr((d && d.error) || "Reset failed."); });
  };
  return (
    <React.Fragment>
      <div className="brand">Wellpaged</div>
      <h1>Choose a new password</h1>
      <form onSubmit={submit}>
        <label>New password<input type="password" value={pw} onChange={(e) => setPw(e.target.value)} autoComplete="new-password" minLength={8} required /></label>
        {err && <div className="err">{err}</div>}
        <button className="btn" disabled={busy}>{busy ? "…" : "Set new password"}</button>
      </form>
    </React.Fragment>
  );
}

/* ════════ Dashboard shell ════════ */
function Dashboard({ me, setMe, flash }) {
  // Operators belong on the operator dashboard.
  useEffect(() => {
    fetch("/api/admin/me", { credentials: "same-origin" })
      .then((r) => (r.ok ? r.json() : null))
      .then((d) => { if (d && d.role && d.role !== "none") location.href = "https://admin.wellpaged.com/"; })
      .catch(() => {});
  }, []);

  const sites = me.sites || [];
  const [site, setSite] = useState(sites[0] || null);
  const [view, setView] = useState("overview");
  const [info, setInfo] = useState({});   // slug -> /api/account/site result | null
  const [stats, setStats] = useState({}); // slug -> /api/stats result | null | {configured:false}
  const [note, setNote] = useState(null);

  const loadInfo = (s) => GET("/api/account/site?slug=" + encodeURIComponent(s))
    .then(({ ok, d }) => setInfo((m) => ({ ...m, [s]: ok && d && d.ok ? d : null })));
  const loadStats = (s) => GET("/api/stats?slug=" + encodeURIComponent(s))
    .then(({ ok, d }) => setStats((m) => ({ ...m, [s]: ok && d && (d.ok || d.configured === false) ? d : null })));
  useEffect(() => { sites.forEach((s) => { loadInfo(s); loadStats(s); }); }, []);

  const logout = () => fetch("/api/auth/logout", { method: "POST", credentials: "same-origin" }).then(() => setMe(null)).catch(() => setMe(null));
  const resend = () => POST("/api/auth/resend", {}).then(() => setNote("Verification email sent — check your inbox."));
  const titles = { overview: "Overview", traffic: "Traffic", links: "Your links", page: "My page", billing: "Billing & plan", settings: "Settings" };
  const si = site ? info[site] : null;
  const st = site ? stats[site] : null;

  return (
    <div className="shell">
      <aside className="sidebar">
        <div className="brand"><span className="wm">wellpaged</span><span className="tag">creator</span></div>
        <nav className="nav-group">
          <span className="label">Your site</span>
          {NAV.map((n) => (
            <div key={n.id} className={"nav-item" + (view === n.id ? " active" : "")} onClick={() => setView(n.id)}
                 role="button" aria-current={view === n.id ? "page" : undefined}>
              <Icon d={n.d} />{n.label}
            </div>
          ))}
        </nav>
        <div className="side-foot">
          <span className="avatar">{me.email.charAt(0).toUpperCase()}</span>
          <span className="who">Creator<small>{me.email}</small></span>
        </div>
      </aside>
      <div className="main">
        <header className="topbar">
          <h1>{titles[view]}</h1>
          {sites.length > 1 && (
            <select className="site-pick" value={site || ""} onChange={(e) => setSite(e.target.value)} aria-label="Choose site">
              {sites.map((s) => <option key={s} value={s}>{s}.wellpaged.com</option>)}
            </select>
          )}
          {site && <a className="topbtn ghost" href={"https://" + site + ".wellpaged.com/"} target="_blank" rel="noreferrer">View site ↗</a>}
          {site && si && <a className="topbtn" href={editUrl(site, si)} target="_blank" rel="noreferrer">Edit page</a>}
        </header>
        <div className="content">
          {!me.verified && <div className="banner2">Please verify your email. <button className="link" onClick={resend}>Resend verification</button>{note && <span> {note}</span>}</div>}
          {flash && <div className={flash.kind === "ok" ? "okmsg2" : "errmsg2"} style={{ marginBottom: 16 }}>{flash.msg}</div>}
          {!sites.length ? (
            <div className="panel"><div className="empty">
              You haven’t built a site yet — your page, stats and links will live here.{" "}
              <a className="btn" style={{ marginLeft: 8 }} href="https://wellpaged.com/builder/">Build your page →</a>
            </div></div>
          ) : view === "overview" ? <OverviewView site={site} si={si} st={st} go={setView} />
            : view === "traffic" ? <TrafficViewC site={site} st={st} onRefresh={() => loadStats(site)} />
            : view === "links" ? <LinksView site={site} si={si} onSaved={() => loadInfo(site)} />
            : view === "page" ? <PageView site={site} si={si} onChanged={() => loadInfo(site)} />
            : view === "billing" ? <BillingView site={site} si={si} />
            : <SettingsView me={me} onLogout={logout} />}
        </div>
      </div>
    </div>
  );
}

function editUrl(site, si) {
  return si && si.editToken
    ? "https://wellpaged.com/" + site + "/?edit=" + si.editToken
    : "https://wellpaged.com/" + site + "/?edit=";
}
function sum(arr, f) { return (arr || []).reduce((a, x) => a + f(x), 0); }
function tilesFrom(st) {
  const days = (st && st.days) || [];
  const weekAgo = new Date(Date.now() - 7 * 864e5).toISOString().slice(0, 10);
  return {
    v7: sum(days.filter((d) => d.day >= weekAgo), (d) => d.views),
    v30: sum(days, (d) => d.views),
    clicks: sum((st && st.clicks) || [], (c) => c.clicks),
  };
}
function Bars({ days }) {
  const max = Math.max(1, ...days.map((d) => d.views));
  return (
    <div className="bars" title="Daily visits, last 30 days">
      {days.map((d) => <i key={d.day} style={{ height: Math.max(4, Math.round((d.views / max) * 100)) + "%" }} title={d.day + ": " + d.views + " visits"}></i>)}
    </div>
  );
}
function KvList({ rows, kf, vf, empty }) {
  if (!rows || !rows.length) return <p className="dim">{empty}</p>;
  return <ul className="kv-list">{rows.map((r, i) => <li key={i}><span title={kf(r)}>{kf(r)}</span><b>{vf(r)}</b></li>)}</ul>;
}
function StatTile({ k, v, d }) { return <div className="stat"><div className="k">{k}</div><div className="v">{v}</div><div className="d">{d}</div></div>; }
function StatsGate({ st, children }) {
  if (st === undefined) return <div className="empty">Loading stats…</div>;
  if (st && st.configured === false) return <div className="empty">Analytics is warming up — visits and clicks start counting shortly.</div>;
  if (!st) return <div className="empty">Stats are unavailable right now — check back in a minute.</div>;
  return children;
}

/* ── Overview ── */
function OverviewView({ site, si, st, go }) {
  const t = tilesFrom(st && st.ok ? st : null);
  return (
    <React.Fragment>
      <div className="stats">
        <StatTile k="Visits · 7 days" v={String(t.v7)} d="people on your page" />
        <StatTile k="Visits · 30 days" v={String(t.v30)} d="last month" />
        <StatTile k="Link clicks · 30 days" v={String(t.clicks)} d="taps on your links" />
        <StatTile k="Rebuilds left" v={si ? String(si.regen.remaining) : "…"} d={si ? "of " + si.regen.cap + " this month" : ""} />
      </div>
      <div className="panel">
        <div className="panel-head"><h2>{site}.wellpaged.com — daily visits</h2>
          <span>{si && <span className={"chip " + (si.active ? "live" : "draft")}>{si.active ? "Live" : "Private draft"}</span>}</span></div>
        <div className="panel-body">
          <StatsGate st={st}>
            {st && st.ok && (st.days || []).length ? <Bars days={st.days} /> : <p className="dim">No visits recorded yet — share your page to get the line moving.</p>}
            <div className="two-col" style={{ marginTop: 14 }}>
              <div><p className="kv-head">Top sources</p>
                <KvList rows={(st && st.sources || []).slice(0, 5)} kf={(s) => s.source} vf={(s) => s.views} empty="No visits yet." /></div>
              <div><p className="kv-head">Most-clicked links</p>
                <KvList rows={(st && st.clicks || []).slice(0, 5)} kf={(c) => c.target} vf={(c) => c.clicks} empty="No clicks yet." /></div>
            </div>
          </StatsGate>
          <p className="dim" style={{ marginTop: 12 }}>
            Want more? <button className="link" onClick={() => go("traffic")}>Full traffic view</button> · <button className="link" onClick={() => go("links")}>Manage your links</button>
          </p>
        </div>
      </div>
    </React.Fragment>
  );
}

/* ── Traffic ── */
function TrafficViewC({ site, st, onRefresh }) {
  const t = tilesFrom(st && st.ok ? st : null);
  return (
    <React.Fragment>
      <div className="stats">
        <StatTile k="Visits · 7 days" v={String(t.v7)} d="last week" />
        <StatTile k="Visits · 30 days" v={String(t.v30)} d="last month" />
        <StatTile k="Link clicks" v={String(t.clicks)} d="last 30 days" />
      </div>
      <div className="panel">
        <div className="panel-head"><h2>Daily visits <span className="muted-n">last 30 days</span></h2>
          <button className="link" onClick={onRefresh}>↻ Refresh</button></div>
        <div className="panel-body">
          <StatsGate st={st}>
            {st && st.ok && (st.days || []).length ? <Bars days={st.days} /> : <p className="dim">No visits recorded yet.</p>}
          </StatsGate>
        </div>
      </div>
      {st && st.ok && (
        <div className="panel"><div className="panel-body">
          <div className="three-col">
            <div><p className="kv-head">Where visitors come from</p>
              <KvList rows={st.sources || []} kf={(s) => s.source} vf={(s) => s.views} empty="No visits yet." /></div>
            <div><p className="kv-head">Countries</p>
              <KvList rows={st.countries || []} kf={(c) => c.country} vf={(c) => c.views} empty="No visits yet." /></div>
            <div><p className="kv-head">Most-clicked links</p>
              <KvList rows={st.clicks || []} kf={(c) => c.target} vf={(c) => c.clicks} empty="No clicks yet." /></div>
          </div>
          <p className="dim" style={{ marginTop: 12 }}>Counted with privacy in mind: no cookies, your own visits while editing aren’t included, and numbers refresh every few minutes.</p>
        </div></div>
      )}
    </React.Fragment>
  );
}

/* ── Links manager ── */
function LinksView({ site, si, onSaved }) {
  const [links, setLinks] = useState(null);
  const [dirty, setDirty] = useState(false);
  const [busy, setBusy] = useState(false);
  const [note, setNote] = useState(null);
  useEffect(() => { if (si) setLinks((si.links || []).map((l) => ({ label: l.label || "", url: l.url || "", feat: !!l.feat }))); }, [si && si.slug]);
  if (!si || links === null) return <div className="panel"><div className="empty">Loading your links…</div></div>;
  const set = (i, patch) => { setLinks(links.map((l, j) => (j === i ? { ...l, ...patch } : l))); setDirty(true); };
  const save = () => {
    const clean = links.filter((l) => (l.label || "").trim() || (l.url || "").trim());
    setBusy(true); setNote(null);
    POST("/api/edit", { slug: site, links: clean }).then(({ ok, d }) => {
      setBusy(false);
      if (ok) { setDirty(false); setNote({ kind: "ok", msg: "Saved — your page is already showing the new links." }); onSaved(); }
      else setNote({ kind: "err", msg: (d && d.error) || "Couldn't save links." });
    });
  };
  return (
    <div className="panel">
      <div className="panel-head"><h2>Links on your page <span className="muted-n">{links.length}</span></h2>
        <button className="btn" disabled={!dirty || busy} onClick={save}>{busy ? "…" : "Save links"}</button></div>
      <div className="panel-body">
        {links.map((l, i) => (
          <div className="link-row" key={i}>
            <input className="lab" placeholder="Label (e.g. Watch my latest)" value={l.label} maxLength={120} onChange={(e) => set(i, { label: e.target.value })} />
            <input className="url" placeholder="https://…" value={l.url} onChange={(e) => set(i, { url: e.target.value })} />
            <button className={"feat" + (l.feat ? " on" : "")} title="Feature this link" onClick={() => set(i, { feat: !l.feat })}>✦</button>
            <button className="del" title="Remove" onClick={() => { setLinks(links.filter((_, j) => j !== i)); setDirty(true); }}>✕</button>
          </div>
        ))}
        <button className="link" onClick={() => { setLinks([...links, { label: "", url: "", feat: false }]); setDirty(true); }}>+ Add a link</button>
        <p className="dim" style={{ marginTop: 10 }}>Changes go live immediately — no rebuild, free, doesn’t touch your monthly rebuilds. Links need a full address (https://… or mailto:/tel:). ✦ marks the featured link.</p>
        {note && <div className={note.kind === "ok" ? "okmsg2" : "errmsg2"}>{note.msg}</div>}
      </div>
    </div>
  );
}

/* ── My page ── */
function PageView({ site, si, onChanged }) {
  const [busy, setBusy] = useState(false);
  const [note, setNote] = useState(null);
  if (!si) return <div className="panel"><div className="empty">Loading…</div></div>;
  const rebuild = () => {
    if (!confirm("Rebuild " + site + ".wellpaged.com with the design engine? This uses one of your " + si.regen.cap + " monthly rebuilds and takes a few minutes.")) return;
    setBusy(true); setNote(null);
    POST("/api/publish", { slug: site, rebuild: true }).then(({ ok, d }) => {
      setBusy(false);
      if (ok) { setNote({ kind: "ok", msg: "Rebuild started — your page refreshes itself in a few minutes." }); onChanged(); }
      else setNote({ kind: "err", msg: (d && d.error) || "Couldn't start the rebuild." });
    });
  };
  return (
    <React.Fragment>
      <div className="panel">
        <div className="panel-head"><h2>{site}.wellpaged.com</h2>
          <span className={"chip " + (si.active ? "live" : "draft")}>{si.active ? "Live" : "Private draft"}</span></div>
        <div className="panel-body">
          <div className="set-rows">
            <div className="set-row"><span className="k">Public address</span><span className="v">{si.active ? site + ".wellpaged.com" : "goes live when you publish"}</span></div>
            <div className="set-row"><span className="k">Plan</span><span className="v" style={{ textTransform: "capitalize" }}>{si.plan === "free" ? "Free preview" : si.plan}</span></div>
            <div className="set-row"><span className="k">Connected socials</span><span className="v">{(si.socials || []).filter((s) => s.on && s.handle).map((s) => s.platform).join(" · ") || "none"}</span></div>
          </div>
          <p className="dim" style={{ marginTop: 12 }}>
            Edit anything in place — text, photos, colors, section order — from{" "}
            <a className="link" href={editUrl(site, si)} target="_blank" rel="noreferrer">your page in edit mode</a>. Free, instant, unlimited.
          </p>
        </div>
      </div>
      <div className="panel">
        <div className="panel-head"><h2>Template rebuilds</h2>
          <button className="btn" disabled={busy || si.regen.remaining < 1} onClick={rebuild}>{busy ? "…" : "↻ Rebuild page"}</button></div>
        <div className="panel-body">
          <p className="dim">{si.regen.used} of {si.regen.cap} used this month — {si.regen.remaining} left. A rebuild has the design engine re-craft your page from your brief (keeping your saved link edits). Text/photo/color edits never cost a rebuild.</p>
          {note && <div className={note.kind === "ok" ? "okmsg2" : "errmsg2"}>{note.msg}</div>}
        </div>
      </div>
    </React.Fragment>
  );
}

/* ── Billing ── */
function BillingView({ site, si }) {
  const [busy, setBusy] = useState(false);
  const [note, setNote] = useState(null);
  if (!si) return <div className="panel"><div className="empty">Loading…</div></div>;
  const portal = () => {
    setBusy(true); setNote(null);
    POST("/api/stripe/portal", { slug: site }).then(({ ok, d }) => {
      setBusy(false);
      if (ok && d && d.url) location.href = d.url;
      else setNote({ kind: "err", msg: (d && d.error) || "Couldn't open the billing portal." });
    });
  };
  const upgrade = (plan) => {
    setBusy(true); setNote(null);
    POST("/api/stripe/checkout", { slug: site, plan, interval: "monthly", returnUrl: "https://account.wellpaged.com/" }).then(({ ok, d }) => {
      setBusy(false);
      if (ok && d && d.url) location.href = d.url;
      else setNote({ kind: "err", msg: (d && d.error) || "Couldn't start checkout." });
    });
  };
  const paying = si.hasBilling && si.billStatus === "active";
  return (
    <div className="panel">
      <div className="panel-head"><h2>Billing &amp; plan</h2></div>
      <div className="panel-body">
        <div className="set-rows">
          <div className="set-row"><span className="k">Plan</span><span className="v" style={{ textTransform: "capitalize" }}>{si.plan === "free" ? "Free preview" : si.plan}{si.interval ? " · " + si.interval : ""}</span></div>
          <div className="set-row"><span className="k">Status</span><span className="v">{si.billStatus || (si.active ? "active" : "not subscribed")}</span></div>
          {si.renewsAt && <div className="set-row"><span className="k">Renews</span><span className="v">{new Date(si.renewsAt).toLocaleDateString()}</span></div>}
        </div>
        <div style={{ display: "flex", gap: 10, marginTop: 16, flexWrap: "wrap" }}>
          {paying
            ? <button className="btn" disabled={busy} onClick={portal}>{busy ? "…" : "Manage billing →"}</button>
            : <React.Fragment>
                <button className="btn" disabled={busy} onClick={() => upgrade("launchpad")}>{busy ? "…" : "Go live — Launchpad $9.99/mo"}</button>
                <button className="btn ghost" disabled={busy} onClick={() => upgrade("studio")}>Studio $30/mo</button>
              </React.Fragment>}
        </div>
        {paying && <p className="dim" style={{ marginTop: 10 }}>Update your card, see invoices, or cancel — all on Stripe’s secure page.</p>}
        {note && <div className={note.kind === "ok" ? "okmsg2" : "errmsg2"}>{note.msg}</div>}
      </div>
    </div>
  );
}

/* ── Settings ── */
function SettingsView({ me, onLogout }) {
  const [note, setNote] = useState(null);
  const resend = () => POST("/api/auth/resend", {}).then(() => setNote("Verification email sent — check your inbox."));
  return (
    <div className="panel">
      <div className="panel-head"><h2>Account</h2></div>
      <div className="panel-body">
        <div className="set-rows">
          <div className="set-row"><span className="k">Signed in as</span><span className="v">{me.email}</span></div>
          <div className="set-row"><span className="k">Email verified</span><span className="v">{me.verified ? "Yes ✓" : "Not yet"}</span></div>
        </div>
        {!me.verified && <p className="dim" style={{ marginTop: 10 }}><button className="link" onClick={resend}>Resend verification email</button>{note && <span> {note}</span>}</p>}
        <button className="btn ghost" style={{ marginTop: 16 }} onClick={onLogout}>Log out</button>
      </div>
    </div>
  );
}

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