/* ============================================================
   The Carnation — Admin (#/admin)
   Media manager · Newsroom inbox · Backup & restore
   Light passcode gate (session only). Everything local to the browser.
   ============================================================ */

// SHA-256 hash of the newsroom passcode. The plaintext is intentionally not stored here.
// To change the passcode, replace this with the SHA-256 hex digest of the new one.
const ADMIN_PASS_HASH = "5933fe0c22c40a50d04f7dff6222ed294ddec5ccc694baccf1db54fd2470937a";
async function hashPass(s) {
  const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(s));
  return [...new Uint8Array(buf)].map((b) => b.toString(16).padStart(2, "0")).join("");
}

/* ---------- one media slot: live preview + upload / replace / remove ---------- */
function AdminSlot({ slotKey, label, sub, plate, round }) {
  const photo = usePhoto(slotKey);
  const inputRef = useRef(null);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const onFile = async (e) => {
    const file = e.target.files && e.target.files[0];
    e.target.value = "";
    if (!file) return;
    setBusy(true); setErr("");
    try {
      const url = await S().media.fileToDataUrl(file, round ? 600 : 1600, 0.82);
      S().media.set(slotKey, url);
    } catch (ex) { setErr(ex && ex.message ? ex.message : "Upload failed"); }
    finally { setBusy(false); }
  };
  return (
    <div className="aslot">
      <div className={"aslot__prev" + (round ? " aslot__prev--round" : "")}>
        {round
          ? <Avatar slot={slotKey} initials={label.split(" ").map(w=>w[0]).join("").slice(0,2)} size={72} />
          : <Cover variant={plate} slot={slotKey} className="aslot__cover" />}
        {photo && <span className="aslot__badge">Photo</span>}
        {busy && <span className="aslot__busy">…</span>}
      </div>
      <div className="aslot__meta">
        <div className="aslot__label">{label}</div>
        {sub && <div className="aslot__sub">{sub}</div>}
        <code className="aslot__key">{slotKey}</code>
        {err && <div className="aslot__err">{err}</div>}
        <div className="aslot__actions">
          <button className="btn btn--line btn--sm" onClick={() => inputRef.current && inputRef.current.click()}>{photo ? "Replace" : "Upload"}</button>
          {photo && <button className="btn btn--ghost btn--sm" onClick={() => S().media.remove(slotKey)}>Remove</button>}
          <input ref={inputRef} type="file" accept="image/*" onChange={onFile} style={{display:"none"}} />
        </div>
      </div>
    </div>
  );
}

function AdminGroup({ title, count, children }) {
  return (
    <div className="agroup">
      <SecRule title={title} meta={count != null ? count + " slots" : null} />
      <div className="aslot-grid">{children}</div>
    </div>
  );
}

function adminRecordTime(row) {
  if (!row) return 0;
  if (row._at) return row._at;
  return row.created_at ? Date.parse(row.created_at) : 0;
}

function useAdminRecords(cloud, unlocked) {
  const [state, setState] = useState({ loading: !!cloud, error: "", submissions: [], members: [], newsletter: [], supporters: [] });
  const refresh = async () => {
    if (!cloud || !unlocked) return;
    setState((s) => ({ ...s, loading: true, error: "" }));
    const [submissions, members, newsletter, supporters] = await Promise.all([
      window.CLOUD.list("submissions"),
      window.CLOUD.list("members"),
      window.CLOUD.list("newsletter"),
      window.CLOUD.listAdminSupporters(),
    ]);
    const failed = [submissions, members, newsletter, supporters].some((rows) => rows === null);
    setState({
      loading: false,
      error: failed ? "Some newsroom data could not be loaded. Refresh your session and try again." : "",
      submissions: submissions || [], members: members || [], newsletter: newsletter || [], supporters: supporters || [],
    });
  };
  useEffect(() => { refresh(); }, [cloud, unlocked]);
  return { ...state, refresh };
}

function AdminOverview({ records, onTab }) {
  const D = C();
  const metrics = [
    ["Submissions", records.submissions.length, "inbox"],
    ["Members", records.members.length, "inbox"],
    ["Dispatch readers", records.newsletter.length, "inbox"],
    ["Supporters", records.supporters.length, "revenue"],
  ];
  const recent = [
    ...records.submissions.map((r) => ({ type: "Submission", title: r.title || r.type || "Reader submission", detail: r.email || r.name, at: adminRecordTime(r) })),
    ...records.members.map((r) => ({ type: "Member", title: r.name || r.email || "New member", detail: r.tier, at: adminRecordTime(r) })),
    ...records.newsletter.map((r) => ({ type: "Dispatch", title: r.email || "New signup", detail: "Newsletter signup", at: adminRecordTime(r) })),
    ...records.supporters.map((r) => ({ type: "Revenue", title: r.name || r.email || "Supporter", detail: [r.tier, r.status].filter(Boolean).join(" · "), at: adminRecordTime(r) })),
  ].sort((a, b) => b.at - a.at).slice(0, 8);
  return (
    <>
      <div className="admin-metrics">
        {metrics.map(([label, value, target]) => <button type="button" className="admin-metric" key={label} onClick={() => onTab(target)}><span>{label}</span><b>{value}</b><small>View records <span aria-hidden="true">→</span></small></button>)}
      </div>
      <div className="admin-panelhead">
        <div><div className="phead__kick">Live operations</div><h2>Recent activity</h2></div>
        <button type="button" className="btn btn--line btn--sm" onClick={records.refresh} disabled={records.loading}>{records.loading ? "Refreshing…" : "Refresh"}</button>
      </div>
      {records.error && <p className="aslot__err">{records.error}</p>}
      {recent.length ? <div className="admin-activity">{recent.map((row, i) => <div className="admin-activity__row" key={row.type + row.at + i}><span className="inboxrow__tag">{row.type}</span><div><strong>{row.title}</strong>{row.detail && <small>{row.detail}</small>}</div><time>{row.at ? D.timeAgo(row.at) : ""}</time></div>)}</div> : <p className="admin-empty">No production activity yet.</p>}
    </>
  );
}

/* ---------- MEDIA TAB ---------- */
function AdminMedia() {
  const D = C();
  const inline = [];
  D.ARTICLES.forEach((a) => (a.body || []).forEach((b) => { if (b && b.img) inline.push({ key: b.img, label: a.title, sub: b.cap, plate: b.plate || a.cover }); }));
  const spotInline = [];
  D.SPOTLIGHTS.forEach((s) => (s.body || []).forEach((b) => { if (b && b.img) spotInline.push({ key: b.img, label: s.name, sub: b.cap, plate: b.plate || s.cover }); }));
  return (
    <>
      <AdminGroup title="Story covers" count={D.ARTICLES.length}>
        {D.ARTICLES.map((a) => <AdminSlot key={a.slug} slotKey={"cover:art:" + a.slug} label={a.title} sub={a.category + " · " + a.author} plate={a.cover} />)}
      </AdminGroup>
      <AdminGroup title="In-article photos" count={inline.length}>
        {inline.map((s) => <AdminSlot key={s.key} slotKey={s.key} label={s.label} sub={s.sub} plate={s.plate} />)}
      </AdminGroup>
      <AdminGroup title="Spotlight covers" count={D.SPOTLIGHTS.length}>
        {D.SPOTLIGHTS.map((s) => <AdminSlot key={s.slug} slotKey={"cover:spot:" + s.slug} label={s.name} sub={s.kind + (s.sponsored ? " · Sponsored" : "")} plate={s.cover} />)}
      </AdminGroup>
      <AdminGroup title="In-spotlight photos" count={spotInline.length}>
        {spotInline.map((s) => <AdminSlot key={s.key} slotKey={s.key} label={s.label} sub={s.sub} plate={s.plate} />)}
      </AdminGroup>
      <AdminGroup title="Directory photos" count={D.DIRECTORY_LISTINGS.length}>
        {D.DIRECTORY_LISTINGS.map((l) => <AdminSlot key={l.slug} slotKey={"cover:dir:" + l.slug} label={l.name} sub={l.cat} plate={l.plate} />)}
      </AdminGroup>
      <AdminGroup title="Event photos" count={D.EVENTS.length}>
        {D.EVENTS.map((e) => <AdminSlot key={e.slug} slotKey={"cover:event:" + e.slug} label={e.title} sub={e.cat + " · " + e.venue} plate={e.plate} />)}
      </AdminGroup>
      <AdminGroup title="Staff headshots" count={D.STAFF.length}>
        {D.STAFF.map((p) => <AdminSlot key={p.id} slotKey={"staff:" + p.id} label={p.name} sub={p.role} round />)}
      </AdminGroup>
      <AdminGroup title="Author bylines" count={Object.keys(D.AUTHORS).length}>
        {Object.values(D.AUTHORS).map((au) => <AdminSlot key={au.key} slotKey={"author:" + au.key} label={au.name} sub={au.role} round />)}
      </AdminGroup>
    </>
  );
}

/* ---------- INBOX TAB ---------- */
function InboxList({ title, rows, render, empty }) {
  return (
    <div className="agroup">
      <SecRule title={title} meta={rows.length + (rows.length === 1 ? " entry" : " entries")} />
      {rows.length ? (
        <div className="inbox">{rows.map((r, i) => <div className="inboxrow" key={r._id || i}>{render(r)}</div>)}</div>
      ) : <p className="note">{empty}</p>}
    </div>
  );
}
function AdminInbox({ records }) {
  const D = C();
  useStore();
  const ago = (t) => t ? D.timeAgo(t) : "";
  const cloud = window.CLOUD && window.CLOUD.enabled;
  const subs = cloud ? records.submissions : S().submissions.list();
  const mem = cloud ? records.members : S().members.list();
  const nl = cloud ? records.newsletter : S().newsletter.list();
  const respKeys = S().responses.allKeys();
  const resp = [];
  respKeys.forEach((qid) => {
    const q = D.byQ(qid);
    S().responses.get(qid).forEach((r) => resp.push({ ...r, qid, q: q ? q.q : qid }));
  });
  resp.sort((a, b) => (b._at || 0) - (a._at || 0));

  return (
    <>
      <div className="admin-panelhead"><div><div className="phead__kick">Reader records</div><h2>Newsroom inbox</h2></div>{cloud && <button type="button" className="btn btn--line btn--sm" onClick={records.refresh} disabled={records.loading}>{records.loading ? "Refreshing…" : "Refresh"}</button>}</div>
      {cloud && records.error && <p className="aslot__err" style={{marginBottom:"18px"}}>{records.error}</p>}
      <InboxList title="Submissions" rows={subs} empty="No submissions yet. Anything sent through the Submit or Corrections forms lands here."
        render={(r) => (<>
          <div className="inboxrow__top"><span className="inboxrow__tag">{r.type}</span><span className="inboxrow__time">{ago(r._at)}</span></div>
          <div className="inboxrow__t">{r.title || "(no subject)"}</div>
          {r.body && <p className="inboxrow__b">{r.body}</p>}
          <div className="inboxrow__meta">{[r.name, r.email].filter(Boolean).join(" · ") || "anonymous"}</div>
          {r.email && <a className="inboxrow__reply" href={"mailto:" + r.email + "?subject=" + encodeURIComponent("The Carnation: " + (r.title || r.type || "your submission"))}>Reply by email <span aria-hidden="true">→</span></a>}
        </>)} />

      <InboxList title="Members" rows={mem} empty="No members yet. Membership sign-ups appear here."
        render={(r) => (<>
          <div className="inboxrow__top"><span className="inboxrow__tag">{r.tier || "member"}</span><span className="inboxrow__time">{ago(r._at)}</span></div>
          <div className="inboxrow__t">{r.name || "(no name)"}</div>
          <div className="inboxrow__meta">{r.email}</div>
        </>)} />

      <InboxList title="Newsletter signups" rows={nl} empty="No signups yet. Dispatch subscribers appear here."
        render={(r) => (<div className="inboxrow__line"><span className="inboxrow__t" style={{fontSize:"1rem"}}>{r.email}</span><span className="inboxrow__time">{ago(r._at)}</span></div>)} />

      <InboxList title="Question responses" rows={resp} empty="No public answers submitted yet."
        render={(r) => (<>
          <div className="inboxrow__top"><span className="inboxrow__tag">{r.name}</span><span className="inboxrow__time">{ago(r._at)}</span></div>
          <div className="inboxrow__q">{r.q}</div>
          <p className="inboxrow__b">{r.text}</p>
          {r._id && <button type="button" className="inboxrow__del" onClick={() => { if (window.confirm("Remove this public answer? It will disappear from the site.")) S().responses.remove(r.qid, r._id); }}>Remove from site</button>}
        </>)} />
    </>
  );
}

function AdminRevenue({ records }) {
  const D = C();
  const active = records.supporters.filter((r) => r.status === "active" || r.status === "one_time").length;
  return (
    <>
      <div className="admin-panelhead"><div><div className="phead__kick">Stripe records</div><h2>Supporters & revenue</h2></div><div className="admin-panelactions"><button type="button" className="btn btn--line btn--sm" onClick={records.refresh} disabled={records.loading}>{records.loading ? "Refreshing…" : "Refresh"}</button><a className="btn btn--red btn--sm" href="https://dashboard.stripe.com/test/payments" target="_blank" rel="noreferrer">Open Stripe <span aria-hidden="true">↗</span></a></div></div>
      <div className="admin-revenue-summary"><div><span>Total records</span><b>{records.supporters.length}</b></div><div><span>Active / completed</span><b>{active}</b></div><p>Stripe is currently connected in test mode. No live funds are being collected.</p></div>
      {records.error && <p className="aslot__err">{records.error}</p>}
      {records.supporters.length ? <div className="admin-tablewrap"><table className="admin-table"><thead><tr><th>Supporter</th><th>Tier</th><th>Status</th><th>Visibility</th><th>Date</th></tr></thead><tbody>{records.supporters.map((r) => <tr key={r.id}><td><strong>{r.name || "Unnamed"}</strong><small>{r.email || "No email"}</small></td><td>{(r.tier || "—").replace(/_/g, " ")}</td><td><span className={"admin-status admin-status--" + (r.status || "unknown")}>{r.status || "unknown"}</span></td><td>{r.public ? "Public" : "Private"}</td><td>{r.created_at ? new Date(r.created_at).toLocaleDateString() : "—"}</td></tr>)}</tbody></table></div> : <p className="admin-empty">No supporter records yet.</p>}
    </>
  );
}

/* ---------- BACKUP TAB ---------- */
function download(filename, text) {
  const blob = new Blob([text], { type: "application/json" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url; a.download = filename; document.body.appendChild(a); a.click();
  document.body.removeChild(a); setTimeout(() => URL.revokeObjectURL(url), 1000);
}
function AdminBackup() {
  useStore();
  const [msg, setMsg] = useState("");
  const [paste, setPaste] = useState("");
  const fileRef = useRef(null);
  const stamp = () => new Date().toISOString().slice(0, 10);
  const doImport = (text) => {
    const ok = S().backup.importAll(text);
    setMsg(ok ? "✓ Restored. Your photos and data are back." : "✗ That file didn't look like a Carnation backup.");
    setTimeout(() => setMsg(""), 5000);
  };
  const onFile = (e) => {
    const f = e.target.files && e.target.files[0]; e.target.value = "";
    if (!f) return;
    const fr = new FileReader();
    fr.onload = () => doImport(fr.result);
    fr.readAsText(f);
  };
  return (
    <div className="agroup backup">
      <SecRule title="Backup & restore" meta="Keep your work safe" />
      <p className="note" style={{maxWidth:"64ch", marginBottom:"22px", fontSize:"1rem"}}>
        Everything you upload and capture lives in this browser only. Export a backup to move it to another device — or to keep it safe before clearing your cache.
      </p>
      <div className="backup-grid">
        <div className="backupcard">
          <h4 className="backupcard__h">Export everything</h4>
          <p className="backupcard__p">Photos, submissions, members, newsletter, responses, views & saved — one JSON file.</p>
          <button className="btn btn--red btn--sm" onClick={() => download("carnation-backup-" + stamp() + ".json", S().backup.exportAll())}>Download full backup</button>
        </div>
        <div className="backupcard">
          <h4 className="backupcard__h">Export photos only</h4>
          <p className="backupcard__p">Just the media library — useful for moving images between machines.</p>
          <button className="btn btn--line btn--sm" onClick={() => download("carnation-media-" + stamp() + ".json", S().media.export())}>Download media</button>
        </div>
        <div className="backupcard">
          <h4 className="backupcard__h">Restore from a file</h4>
          <p className="backupcard__p">Import a full backup or a media export. Existing entries are overwritten.</p>
          <button className="btn btn--line btn--sm" onClick={() => fileRef.current && fileRef.current.click()}>Choose backup file</button>
          <input ref={fileRef} type="file" accept="application/json,.json" onChange={onFile} style={{display:"none"}} />
        </div>
      </div>
      <div className="frow" style={{marginTop:"24px"}}>
        <label>…or paste backup JSON</label>
        <textarea className="textarea" value={paste} onChange={(e)=>setPaste(e.target.value)} placeholder='{"_app":"the-carnation", ...}' style={{minHeight:"110px", fontFamily:"var(--mono)", fontSize:".8rem"}} />
        <div style={{display:"flex", gap:"12px", marginTop:"10px"}}>
          <button className="btn btn--line btn--sm" disabled={!paste.trim()} onClick={() => doImport(paste)}>Restore from paste</button>
          {msg && <span className="note" style={{color: msg[0]==="✓" ? "var(--red)" : "var(--muted)", fontStyle:"normal"}}>{msg}</span>}
        </div>
      </div>
    </div>
  );
}

/* ---------- GATE ---------- */
function AdminGate({ onUnlock }) {
  const cloud = window.CLOUD && window.CLOUD.enabled;
  return cloud ? <AdminLogin /> : <AdminPasscode onUnlock={onUnlock} />;
}

/* real Supabase email + password login (production) */
function AdminLogin() {
  const [username, setUsername] = useState("");
  const [pw, setPw] = useState("");
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);
  const submit = async (e) => {
    e.preventDefault();
    setBusy(true); setErr("");
    const login = username.trim().toLowerCase();
    const email = login === "admin" ? "admin@carnationpost.com" : login;
    const { error } = await window.CLOUD.signIn(email, pw);
    setBusy(false);
    if (error) { setErr(error.message || "Sign-in failed. Check your email and password."); setPw(""); }
    // on success, the auth listener in AdminPage flips the view
  };
  return (
    <main className="route">
      <section className="section" style={{paddingTop:"clamp(60px,10vw,140px)"}}>
        <div className="wrap wrap--narrow gate">
          <CarnationMark style={{height:64, margin:"0 auto 18px"}} />
          <div className="phead__kick" style={{textAlign:"center"}}>Newsroom · Admin</div>
          <h1 className="gate__h">Staff only</h1>
          <p className="note" style={{textAlign:"center", marginBottom:"22px"}}>Sign in to manage media, read the inbox, and back up your work.</p>
          <form className="form" onSubmit={submit}>
            <div className="frow">
              <input className="input" type="text" autoFocus autoCapitalize="none" autoCorrect="off" autoComplete="username" required value={username} onChange={(e)=>{setUsername(e.target.value); setErr("");}} placeholder="Username" />
            </div>
            <div className="frow">
              <input className="input" type="password" autoComplete="current-password" required value={pw} onChange={(e)=>{setPw(e.target.value); setErr("");}} placeholder="Password" />
              {err && <span className="aslot__err">{err}</span>}
            </div>
            <button className="btn btn--red btn--lg" type="submit" disabled={busy} style={{justifyContent:"center"}}>{busy ? "Signing in…" : <>Enter the newsroom <span className="arw">→</span></>}</button>
          </form>
        </div>
      </section>
    </main>
  );
}

/* local passcode — preview only, used when Supabase isn't configured */
function AdminPasscode({ onUnlock }) {
  const [val, setVal] = useState("");
  const [err, setErr] = useState(false);
  const submit = async (e) => {
    e.preventDefault();
    const ok = (await hashPass(val)) === ADMIN_PASS_HASH;
    if (ok) { try { sessionStorage.setItem("__carn_admin", "1"); } catch (e) {} onUnlock(); }
    else { setErr(true); setVal(""); }
  };
  return (
    <main className="route">
      <section className="section" style={{paddingTop:"clamp(60px,10vw,140px)"}}>
        <div className="wrap wrap--narrow gate">
          <CarnationMark style={{height:64, margin:"0 auto 18px"}} />
          <div className="phead__kick" style={{textAlign:"center"}}>Newsroom · Admin</div>
          <h1 className="gate__h">Staff only</h1>
          <p className="note" style={{textAlign:"center", marginBottom:"22px"}}>Enter the newsroom passcode to manage media, read the inbox, and back up your work.</p>
          <form className="form" onSubmit={submit}>
            <div className="frow">
              <input className="input" type="password" autoFocus value={val} onChange={(e)=>{setVal(e.target.value); setErr(false);}} placeholder="Passcode" style={{textAlign:"center", letterSpacing:".2em"}} />
              {err && <span className="aslot__err" style={{textAlign:"center"}}>Incorrect passcode. Try again.</span>}
            </div>
            <button className="btn btn--red btn--lg" type="submit" style={{justifyContent:"center"}}>Enter the newsroom <span className="arw">→</span></button>
          </form>
          <p className="note" style={{textAlign:"center", marginTop:"18px", fontSize:".78rem", color:"var(--muted)"}}>Local preview mode — connect Supabase for real protection.</p>
        </div>
      </section>
    </main>
  );
}

/* ---------- ADMIN SHELL ---------- */
function AdminPage() {
  const cloud = window.CLOUD && window.CLOUD.enabled;
  const [unlocked, setUnlocked] = useState(() => {
    if (cloud) return false;
    try { return sessionStorage.getItem("__carn_admin") === "1"; } catch (e) { return false; }
  });
  const [authChecked, setAuthChecked] = useState(!cloud);
  const [tab, setTab] = useState("overview");
  const [confirmClear, setConfirmClear] = useState(false);
  useStore();
  const records = useAdminRecords(cloud, unlocked);

  useEffect(() => {
    if (!cloud) return;
    let off;
    window.CLOUD.getSession().then((s) => { setUnlocked(!!s); setAuthChecked(true); });
    off = window.CLOUD.onAuth((s) => setUnlocked(!!s));
    return () => { if (off) off(); };
  }, [cloud]);

  if (cloud && !authChecked) {
    return (
      <main className="route">
        <section className="section" style={{paddingTop:"clamp(60px,10vw,140px)", textAlign:"center"}}>
          <p className="note">Checking your session…</p>
        </section>
      </main>
    );
  }
  if (!unlocked) return <AdminGate onUnlock={() => setUnlocked(true)} />;

  const used = S().media.count();
  const clearAll = () => { const all = S().media.all(); Object.keys(all).forEach((k) => S().media.remove(k)); setConfirmClear(false); };

  const tabs = [["overview", "Overview"], ["inbox", "Inbox"], ["revenue", "Revenue"], ["media", "Media"], ["backup", "Backup"]];
  const inboxCount = cloud ? records.submissions.length + records.members.length + records.newsletter.length : S().submissions.list().length + S().members.list().length + S().newsletter.list().length;
  const lock = () => {
    if (cloud) { window.CLOUD.signOut(); }
    else { try { sessionStorage.removeItem("__carn_admin"); } catch (e) {} setUnlocked(false); }
  };

  return (
    <main className="route">
      <section className="phead phead--admin">
        <div className="wrap">
          <div className="phead__kick">Newsroom · Admin</div>
          <h1 className="phead__title">Newsroom</h1>
          <p className="phead__dek">Monitor reader activity, review submissions, track supporters, and manage newsroom assets from one place.</p>
          <div className="admin-bar">
            <span className="admin-stat"><b>{inboxCount}</b> reader record{inboxCount===1?"":"s"}</span>
            <span className="admin-stat"><b>{records.supporters.length}</b> supporter{records.supporters.length===1?"":"s"}</span>
            <span className="admin-note">{cloud ? "Production database connected" : "Local preview mode"}</span>
            <button className="btn btn--ghost btn--sm" style={{marginLeft:"auto"}} onClick={lock}>{cloud ? "Sign out" : "Lock"}</button>
          </div>
          <div className="admin-tabs">
            {tabs.map((t) => (
              <button key={t[0]} className={"admin-tab" + (tab===t[0] ? " on" : "")} onClick={() => setTab(t[0])}>
                {t[1]}{t[0]==="inbox" && inboxCount>0 ? <span className="admin-tab__n">{inboxCount}</span> : null}{t[0]==="revenue" && records.supporters.length>0 ? <span className="admin-tab__n">{records.supporters.length}</span> : null}
              </button>
            ))}
            {tab === "media" && used > 0 && (confirmClear
              ? <span className="admin-clear" style={{marginLeft:"auto"}}><button className="btn btn--red btn--sm" onClick={clearAll}>Yes, remove all</button><button className="btn btn--ghost btn--sm" onClick={()=>setConfirmClear(false)}>Cancel</button></span>
              : <button className="btn btn--ghost btn--sm" style={{marginLeft:"auto"}} onClick={()=>setConfirmClear(true)}>Clear all photos</button>)}
          </div>
        </div>
      </section>

      <section className="section section--tight">
        <div className="wrap">
          {tab === "overview" && <AdminOverview records={records} onTab={setTab} />}
          {tab === "media" && <AdminMedia />}
          {tab === "inbox" && <AdminInbox records={records} />}
          {tab === "revenue" && <AdminRevenue records={records} />}
          {tab === "backup" && <AdminBackup />}
          {tab === "media" && <p className="admin-localnote"><strong>Browser-local media:</strong> uploads in this tab are stored on this device only. They are not yet published to the public site or shared with other staff devices.</p>}
        </div>
      </section>

      <section className="section section--ink section--tight">
        <div className="wrap wrap--mid" style={{textAlign:"center"}}>
          <p className="pullband__by" style={{marginTop:0, color:"#c9a3a8"}}>Newsroom</p>
          <h3 className="dual__h" style={{fontFamily:"var(--serif)", marginBottom:"18px"}}>Return to the public edition.</h3>
          <a className="btn btn--red" href="#/">View the front page <span className="arw">→</span></a>
        </div>
      </section>
    </main>
  );
}

window.AdminPage = AdminPage;
