/* =====================================================================
   ADMIN — dashboard, listings CRUD, media & branding
   Writes to the shared store → reflects live on the public site.
   ===================================================================== */

function UploadField({ label, dataUrl, onChange, h = 140, accept = "image/*", hint }) {
  const ref = useRef(null);
  const pick = (e) => {
    const f = e.target.files && e.target.files[0]; if (!f) return;
    const r = new FileReader(); r.onload = () => onChange(r.result); r.readAsDataURL(f);
  };
  return (
    <div className="field">
      {label && <label>{label}</label>}
      <div className="card" style={{ overflow: "hidden", borderStyle: dataUrl ? "solid" : "dashed", borderColor: "var(--line-2)" }}>
        {dataUrl ? (
          <div style={{ position: "relative" }}>
            <img src={dataUrl} alt="" style={{ width: "100%", height: h, objectFit: "cover", display: "block" }} />
            <div style={{ position: "absolute", top: 8, right: 8, display: "flex", gap: 6 }}>
              <button className="btn sm" onClick={() => ref.current.click()}><Icon name="upload" size={14} /> Replace</button>
              <button className="btn sm danger" onClick={() => onChange(null)}><Icon name="trash" size={14} /></button>
            </div>
          </div>
        ) : (
          <button onClick={() => ref.current.click()} style={{ width: "100%", height: h, border: "none", background: "var(--paper-2)", cursor: "pointer", display: "grid", placeItems: "center", color: "var(--slate)" }}>
            <div style={{ textAlign: "center" }}><Icon name="upload" size={22} /><div className="small b6" style={{ marginTop: 8 }}>Click to upload</div>{hint && <div className="xsmall muted" style={{ marginTop: 2 }}>{hint}</div>}</div>
          </button>
        )}
      </div>
      <input ref={ref} type="file" accept={accept} onChange={pick} style={{ display: "none" }} />
    </div>
  );
}

function LocationPicker({ lat, lng, onChange }) {
  const ref = useRef(null), map = useRef(null), marker = useRef(null);
  useEffect(() => {
    if (!window.L || !ref.current || map.current) return;
    const m = window.L.map(ref.current, { zoomControl: true, attributionControl: false, scrollWheelZoom: false });
    m.setView([lat || 39.7684, lng || -86.1581], 11);
    window.L.tileLayer("https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png", { subdomains: "abcd" }).addTo(m);
    const ic = window.L.divIcon({ html: '<div class="glr-pin active"><span></span></div>', className: "", iconSize: [30, 30], iconAnchor: [15, 28] });
    marker.current = window.L.marker([lat || 39.7684, lng || -86.1581], { icon: ic, draggable: true }).addTo(m);
    marker.current.on("dragend", (e) => { const p = e.target.getLatLng(); onChange(p.lat, p.lng); });
    m.on("click", (e) => { marker.current.setLatLng(e.latlng); onChange(e.latlng.lat, e.latlng.lng); });
    map.current = m;
    return () => { m.remove(); map.current = null; };
  }, []);
  return (
    <div className="field"><label>Location · click or drag the pin</label>
      <div className="card" style={{ overflow: "hidden", height: 220 }}><div ref={ref} style={{ width: "100%", height: "100%" }} />{!window.L && <div className="map-fallback" />}</div>
      <div className="row gap16" style={{ marginTop: 8 }}>
        <div className="field grow"><label>Latitude</label><input className="input" value={lat || ""} onChange={(e) => onChange(parseFloat(e.target.value) || 0, lng)} /></div>
        <div className="field grow"><label>Longitude</label><input className="input" value={lng || ""} onChange={(e) => onChange(lat, parseFloat(e.target.value) || 0)} /></div>
      </div>
    </div>
  );
}

function AdminShell({ section, children }) {
  useStore();
  const status = window.GLR.apiStatus();
  const nav = [["Dashboard", "/admin", "dash"], ["Listings", "/admin/listings", "list"], ["Contacts", "/admin/contacts", "users"], ["Messages", "/admin/messages", "phone"], ["Analytics", "/admin/analytics", "dash"], ["Inbox", "/admin/inbox", "mail"], ["Users", "/admin/users", "shield"], ["Security", "/admin/security", "lock"], ["Requests", "/admin/requests", "shield"], ["Q&A", "/admin/qa", "msg"], ["Content", "/admin/content", "doc"], ["Media", "/admin/media", "image"], ["Branding", "/admin/branding", "settings"], ["Audit", "/admin/audit", "clock"]];
  const mobile = useIsMobile(900);
  if (!status.admin) return <AdminLogin />;
  if (status.mfa && status.mfa.requiredNow && section !== "Security") return <AdminSecurity required />;
  if (mobile) {
    return (
      <div style={{ minHeight: "100vh", background: "var(--paper-2)" }}>
        <div className="surface-navy" style={{ position: "sticky", top: 0, zIndex: 40 }}>
          <div className="row jb ac" style={{ padding: "12px 18px" }}>
            <Logo onNavy onClick={() => navigate("/")} />
            <button className="btn ghost sm" style={{ color: "#c8d6e5", borderColor: "rgba(255,255,255,0.2)" }} onClick={() => navigate("/")}><Icon name="ext" size={14} /> Site</button>
          </div>
          <div className="row gap6" style={{ padding: "0 12px 12px", overflowX: "auto" }}>
            {nav.map(([l, p, ic]) => (
              <button key={l} onClick={() => navigate(p)} style={{ whiteSpace: "nowrap", flex: "none", border: "none", cursor: "pointer", padding: "8px 14px", borderRadius: 999, display: "flex", alignItems: "center", gap: 7, fontSize: 13.5, fontWeight: 600, background: section === l ? "#fff" : "rgba(255,255,255,0.1)", color: section === l ? "var(--navy)" : "#c8d6e5" }}>
                <Icon name={ic} size={15} /> {l}
              </button>
            ))}
          </div>
        </div>
        <main style={{ padding: "24px 18px 64px" }}>{children}</main>
      </div>
    );
  }
  return (
    <div style={{ minHeight: "100vh", display: "grid", gridTemplateColumns: "240px 1fr", background: "var(--paper-2)" }}>
      <aside className="surface-navy scroll-y" style={{ position: "sticky", top: 0, height: "100vh", padding: "24px 16px", display: "flex", flexDirection: "column" }}>
        <Logo onNavy onClick={() => navigate("/")} />
        <div className="xsmall" style={{ color: "#7f97b0", margin: "22px 8px 10px", letterSpacing: "0.12em", textTransform: "uppercase", fontWeight: 700 }}>Admin Console</div>
        <nav className="col gap4">
          {nav.map(([l, p, ic]) => (
            <button key={l} onClick={() => navigate(p)} style={{ textAlign: "left", border: "none", cursor: "pointer", padding: "10px 12px", borderRadius: 4, display: "flex", alignItems: "center", gap: 10, fontSize: 14.5, fontWeight: 600,
              background: section === l ? "rgba(255,255,255,0.12)" : "transparent", color: section === l ? "#fff" : "#c8d6e5" }}>
              <Icon name={ic} size={17} /> {l}
            </button>
          ))}
        </nav>
        <div style={{ marginTop: "auto" }}>
          <button className="btn ghost sm block" style={{ color: "#c8d6e5", borderColor: "rgba(255,255,255,0.2)" }} onClick={() => { window.GLR.reset(); showToast("Sample data restored"); }}><Icon name="clock" size={14} /> Reset to sample</button>
          <button className="btn ghost sm block" style={{ marginTop: 8, color: "#c8d6e5", borderColor: "rgba(255,255,255,0.2)" }} onClick={() => navigate("/")}><Icon name="ext" size={14} /> View live site</button>
          <button className="btn ghost sm block" style={{ marginTop: 8, color: "#c8d6e5", borderColor: "rgba(255,255,255,0.2)" }} onClick={() => { window.GLR.adminLogout().then(() => showToast("Signed out")); }}><Icon name="logout" size={14} /> Sign out</button>
        </div>
      </aside>
      <main className="scroll-y" style={{ height: "100vh", padding: "32px 40px 80px" }}>{children}</main>
    </div>
  );
}

function AdminLogin() {
  const [email, setEmail] = useState("admin@greatlkrealty.com");
  const [password, setPassword] = useState("");
  const [mfaCode, setMfaCode] = useState("");
  const [showMfa, setShowMfa] = useState(false);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const submit = () => {
    if (!email || !password) return;
    setBusy(true); setErr("");
    window.GLR.adminLogin(email, password, mfaCode)
      .then(() => showToast("Admin signed in"))
      .catch((e) => {
        if ((e.message || "").toLowerCase().includes("mfa")) setShowMfa(true);
        setErr(e.message || "Login failed");
      })
      .finally(() => setBusy(false));
  };
  return (
    <div style={{ minHeight: "100vh", display: "grid", placeItems: "center", background: "var(--paper-2)", padding: 24 }}>
      <div className="card pad32" style={{ width: "100%", maxWidth: 440 }}>
        <Logo onClick={() => navigate("/")} />
        <div className="eyebrow" style={{ marginTop: 24 }}>Admin console</div>
        <h1 className="h2" style={{ marginTop: 8 }}>Broker login</h1>
        <div className="col gap14" style={{ marginTop: 20 }}>
          <div className="field"><label>Email</label><input className="input" value={email} onChange={(e) => setEmail(e.target.value)} /></div>
          <div className="field"><label>Password</label><input className="input" type="password" value={password} onChange={(e) => setPassword(e.target.value)} onKeyDown={(e) => e.key === "Enter" && submit()} /></div>
          {showMfa && <div className="field"><label>MFA code</label><input className="input" inputMode="numeric" value={mfaCode} onChange={(e) => setMfaCode(e.target.value)} onKeyDown={(e) => e.key === "Enter" && submit()} /></div>}
          {err && <div className="xsmall" style={{ color: "var(--danger)" }}>{err}</div>}
          <button className="btn block" disabled={busy || !email || !password} onClick={submit}><Icon name="lock" size={15} /> {busy ? "Signing in..." : "Sign in"}</button>
        </div>
      </div>
    </div>
  );
}

function AdminDashboard() {
  const s = useStore();
  const G = window.GLR;
  const active = s.listings.filter((l) => l.status !== "closed");
  const gated = s.listings.filter((l) => l.gated);
  const totalSF = s.listings.reduce((a, l) => a + (l.sf || 0), 0);
  const pendingReq = s.requests.filter((r) => r.status === "pending").length;
  const openQA = s.qa.filter((q) => !q.a).length;
  return (
    <AdminShell section="Dashboard">
      <div className="row jb ac" style={{ marginBottom: 24 }}>
        <div><div className="eyebrow">Console</div><h1 className="h1" style={{ marginTop: 6 }}>Dashboard</h1></div>
        <button className="btn" onClick={() => navigate("/admin/listings/new")}><Icon name="plus" size={16} /> Add listing</button>
      </div>
      <div className="m-stack2" style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 16 }}>
        {[["Active listings", active.length, "building"], ["Confidential / NDA", gated.length, "lock"], ["On-market SF", (totalSF / 1000).toFixed(0) + "k", "ruler"], ["Closed deals", s.closed.length, "check"]].map((x, i) => (
          <div key={i} className="card pad24"><div className="row jb ac"><span className="label">{x[0]}</span><Icon name={x[2]} size={18} style={{ color: "var(--slate-2)" }} /></div><div className="stat" style={{ marginTop: 12 }}><div className="n">{x[1]}</div></div></div>
        ))}
      </div>

      {(pendingReq > 0 || openQA > 0) && (
        <div className="gate-band pad20 m-col" style={{ marginTop: 16, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 14 }}>
          <div className="row gap12 ac"><Icon name="shield" size={20} style={{ color: "var(--brass)" }} />
            <div><div className="b6">{pendingReq} access request{pendingReq === 1 ? "" : "s"} awaiting review{openQA > 0 ? " · " + openQA + " unanswered question" + (openQA === 1 ? "" : "s") : ""}</div><div className="xsmall muted">Parties are waiting on the data room and the deal team.</div></div>
          </div>
          <div className="row gap8">
            {pendingReq > 0 && <button className="btn sm" onClick={() => navigate("/admin/requests")}>Review requests</button>}
            {openQA > 0 && <button className="btn ghost sm" onClick={() => navigate("/admin/qa")}>Answer Q&amp;A</button>}
          </div>
        </div>
      )}

      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "1.7fr 1fr", gap: 24, marginTop: 24 }}>
        <div className="card m-tablewrap">
          <div className="row jb ac" style={{ padding: "18px 20px", borderBottom: "1px solid var(--line)" }}><h3 className="h3">Recent listings</h3><button className="linklike small" onClick={() => navigate("/admin/listings")}>Manage all</button></div>
          <table className="ledger">
            <thead><tr><th>Property</th><th>Type</th><th>Status</th><th className="num">Size</th><th></th></tr></thead>
            <tbody>{s.listings.slice(0, 6).map((l) => (
              <tr key={l.id} className="clickable" onClick={() => navigate("/admin/listings/" + l.id)}>
                <td className="b6">{l.address}</td><td><span className="tag outline">{l.type}</span></td><td><StatusTag status={l.status} /></td><td className="num tnum">{G.fmtSF(l.sf)}</td><td className="num"><Icon name="edit" size={15} style={{ color: "var(--slate)" }} /></td>
              </tr>))}</tbody>
          </table>
        </div>
        <div className="card pad24">
          <h3 className="h3">Quick actions</h3>
          <div className="col gap10" style={{ marginTop: 16 }}>
            <button className="btn ghost block" style={{ justifyContent: "flex-start" }} onClick={() => navigate("/admin/listings/new")}><Icon name="plus" size={16} /> Add a property listing</button>
            <button className="btn ghost block" style={{ justifyContent: "flex-start" }} onClick={() => navigate("/admin/media")}><Icon name="image" size={16} /> Update website photos</button>
            <button className="btn ghost block" style={{ justifyContent: "flex-start" }} onClick={() => navigate("/admin/branding")}><Icon name="settings" size={16} /> Edit logo &amp; brand</button>
          </div>
          <hr className="divider" style={{ margin: "18px 0" }} />
          <p className="xsmall muted"><Icon name="shield" size={13} style={{ verticalAlign: "-2px" }} /> Changes here publish instantly to the live site.</p>
        </div>
      </div>
    </AdminShell>
  );
}

function AdminListings() {
  const s = useStore();
  const G = window.GLR;
  return (
    <AdminShell section="Listings">
      <div className="row jb ac" style={{ marginBottom: 24 }}>
        <div><div className="eyebrow">Console</div><h1 className="h1" style={{ marginTop: 6 }}>Listings</h1></div>
        <button className="btn" onClick={() => navigate("/admin/listings/new")}><Icon name="plus" size={16} /> Add listing</button>
      </div>
      <div className="card m-tablewrap" style={{ overflow: "hidden" }}>
        <table className="ledger">
          <thead><tr><th>Property</th><th>Submarket</th><th>Type</th><th>Deal</th><th className="num">Size</th><th className="num">Price / Rate</th><th>Status</th><th>NDA</th><th></th></tr></thead>
          <tbody>{s.listings.map((l) => (
            <tr key={l.id}>
              <td className="b6">{l.address}</td><td className="muted small">{l.submarket}</td><td><span className="tag outline">{l.type}</span></td>
              <td className="small">{l.deal}</td><td className="num tnum">{G.fmtSF(l.sf)}</td><td className="num b6">{l.price || l.rate}</td>
              <td><StatusTag status={l.status} /></td>
              <td>{l.gated ? <Icon name="lock" size={15} style={{ color: "var(--brass)" }} /> : <span className="muted">—</span>}</td>
              <td className="num"><div className="row gap6 je">
                <button className="btn ghost sm" onClick={() => navigate("/admin/listings/" + l.id + "/launch")} title="Launch"><Icon name="cal" size={14} /></button>
                <button className="btn ghost sm" onClick={() => navigate("/admin/listings/" + l.id + "/dataroom")} title="Data room"><Icon name="folder" size={14} /></button>
                <button className="btn ghost sm" onClick={() => navigate("/admin/listings/" + l.id)}><Icon name="edit" size={14} /></button>
                <button className="btn ghost sm danger" onClick={() => { if (confirm("Delete " + l.address + "?")) { G.removeListing(l.id); showToast("Listing removed"); } }}><Icon name="trash" size={14} /></button>
              </div></td>
            </tr>))}</tbody>
        </table>
      </div>
    </AdminShell>
  );
}

const BLANK = { id: "", slug: "", address: "", city: "Indianapolis", submarket: "CBD", type: "Office", deal: "Lease", sf: 0, rate: "", price: "", cap: "", cls: "B", status: "available", year: 2020, lat: 39.7684, lng: -86.1581, gated: false, featured: false, photo: null, tagline: "", highlights: [], specs: {} };

function AdminListingEdit({ id }) {
  const s = useStore();
  const isNew = id === "new";
  const existing = s.listings.find((l) => l.id === id);
  const [f, setF] = useState(() => existing ? { ...BLANK, ...existing } : { ...BLANK, id: "p" + Date.now() });
  const upd = (k, v) => setF((p) => ({ ...p, [k]: v }));
  const slug = f.slug || f.address.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");

  const save = () => {
    const out = { ...f, slug, sf: Number(f.sf) || 0, highlights: f.highlights.length ? f.highlights : ["Well-located asset", "Quality construction", "Strong access", "Professional management"], specs: Object.keys(f.specs).length ? f.specs : { "Size": (Number(f.sf) || 0).toLocaleString() + " SF", "Type": f.type, "Class": f.cls, "Deal": f.deal, "Submarket": f.submarket, "Year": f.year } };
    window.GLR.upsertListing(out);
    showToast(isNew ? "Listing published" : "Listing updated");
    navigate("/admin/listings");
  };

  return (
    <AdminShell section="Listings">
      <div className="row gap8 ac small muted" style={{ marginBottom: 14 }}><button className="linklike small" onClick={() => navigate("/admin/listings")}><Icon name="chevL" size={14} /> Listings</button><Icon name="chevR" size={13} /><span className="b6" style={{ color: "var(--ink)" }}>{isNew ? "New listing" : f.address}</span></div>
      <div className="row jb ac" style={{ marginBottom: 24 }}>
        <h1 className="h1">{isNew ? "Add listing" : "Edit listing"}</h1>
        <div className="row gap10">{!isNew && <button className="btn ghost" onClick={() => navigate("/admin/listings/" + f.id + "/launch")}><Icon name="cal" size={15} /> Launch</button>}{!isNew && <button className="btn ghost" onClick={() => navigate("/admin/listings/" + f.id + "/dataroom")}><Icon name="folder" size={15} /> Data room</button>}<button className="btn ghost" onClick={() => navigate("/admin/listings")}>Cancel</button><button className="btn" onClick={save} disabled={!f.address}><Icon name="check" size={16} /> {isNew ? "Publish" : "Save changes"}</button></div>
      </div>

      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 24, alignItems: "start" }}>
        <div className="col gap20">
          <div className="card pad24">
            <h3 className="h3" style={{ marginBottom: 16 }}>Property details</h3>
            <div className="col gap16">
              <div className="field"><label>Address</label><input className="input" value={f.address} onChange={(e) => upd("address", e.target.value)} placeholder="120 Monument Circle" /></div>
              <div className="row gap16 m-col">
                <div className="field grow"><label>City</label><input className="input" value={f.city} onChange={(e) => upd("city", e.target.value)} /></div>
                <div className="field grow"><label>Submarket</label><select className="select" value={f.submarket} onChange={(e) => upd("submarket", e.target.value)}>{s.categories.submarkets.map((t) => <option key={t}>{t}</option>)}</select></div>
              </div>
              <div className="field"><label>Tagline</label><input className="input" value={f.tagline} onChange={(e) => upd("tagline", e.target.value)} placeholder="One-line positioning for the listing" /></div>
              <div className="row gap16 m-col">
                <div className="field grow"><label>Type</label><select className="select" value={f.type} onChange={(e) => upd("type", e.target.value)}>{s.categories.types.map((t) => <option key={t}>{t}</option>)}</select></div>
                <div className="field grow"><label>Deal</label><select className="select" value={f.deal} onChange={(e) => upd("deal", e.target.value)}><option>Lease</option><option>Sale</option></select></div>
                <div className="field grow"><label>Class</label><select className="select" value={f.cls} onChange={(e) => upd("cls", e.target.value)}>{s.categories.classes.map((t) => <option key={t}>{t}</option>)}</select></div>
              </div>
              <div className="row gap16 m-col">
                <div className="field grow"><label>Size (SF)</label><input className="input" type="number" value={f.sf} onChange={(e) => upd("sf", e.target.value)} /></div>
                <div className="field grow"><label>{f.deal === "Sale" ? "Price" : "Rate"}</label><input className="input" value={f.deal === "Sale" ? f.price : f.rate} onChange={(e) => upd(f.deal === "Sale" ? "price" : "rate", e.target.value)} placeholder={f.deal === "Sale" ? "$9,100,000" : "$24.50 NNN"} /></div>
                <div className="field grow"><label>Cap rate</label><input className="input" value={f.cap || ""} onChange={(e) => upd("cap", e.target.value)} placeholder="6.8%" /></div>
              </div>
              <div className="row gap16 m-col">
                <div className="field grow"><label>Status</label><select className="select" value={f.status} onChange={(e) => upd("status", e.target.value)}><option value="draft">Draft</option><option value="review">Review</option><option value="available">Available</option><option value="published">Published</option><option value="paused">Paused</option><option value="loi">Under LOI</option><option value="closed">Closed</option></select></div>
                <div className="field grow"><label>Year built</label><input className="input" type="number" value={f.year} onChange={(e) => upd("year", e.target.value)} /></div>
              </div>
            </div>
          </div>
          <div className="card pad24">
            <h3 className="h3" style={{ marginBottom: 16 }}>SEO &amp; routing</h3>
            <div className="col gap14">
              <div className="field"><label>Clean URL slug</label><input className="input" value={slug} onChange={(e) => upd("slug", e.target.value)} /></div>
              <div className="field"><label>SEO title</label><input className="input" value={f.seoTitle || ""} onChange={(e) => upd("seoTitle", e.target.value)} placeholder={f.address ? f.address + " · Great Lakes Realty" : ""} /></div>
              <div className="field"><label>SEO description</label><textarea className="textarea" value={f.seoDescription || ""} onChange={(e) => upd("seoDescription", e.target.value)} style={{ minHeight: 80 }} /></div>
              <div className="field"><label>Inquiry routing email</label><input className="input" value={f.inquiryEmail || ""} onChange={(e) => upd("inquiryEmail", e.target.value)} placeholder="deals@greatlkrealty.com" /></div>
              <Toggle label="Published to public site" sub="Unpublished listings stay out of sitemap and public API" on={f.published !== false} onClick={() => upd("published", f.published === false)} />
            </div>
          </div>
          <div className="card pad24"><LocationPicker lat={f.lat} lng={f.lng} onChange={(la, ln) => setF((p) => ({ ...p, lat: la, lng: ln }))} /></div>
          <div className="card pad24">
            <h3 className="h3" style={{ marginBottom: 4 }}>Highlights</h3>
            <p className="xsmall muted" style={{ marginBottom: 12 }}>Bullet points shown on the listing's Overview tab.</p>
            <ListEditor items={f.highlights || []} onChange={(v) => upd("highlights", v)} placeholder="e.g. 32′ clear height" />
            <hr className="divider" style={{ margin: "20px 0" }} />
            <h3 className="h3" style={{ marginBottom: 4 }}>Specifications</h3>
            <p className="xsmall muted" style={{ marginBottom: 12 }}>Key facts shown in the listing's spec grid.</p>
            <KVEditor obj={f.specs || {}} onChange={(v) => upd("specs", v)} />
          </div>
        </div>

        <div className="col gap20">
          <div className="card pad24">
            <h3 className="h3" style={{ marginBottom: 16 }}>Photos</h3>
            <div className="label" style={{ marginBottom: 8 }}>Cover photo</div>
            <UploadField dataUrl={f.photo} onChange={(d) => upd("photo", d)} hint="Shown on cards and as the hero" />
            <div className="label" style={{ margin: "18px 0 8px" }}>Gallery</div>
            <GalleryEditor photos={f.photos || []} onChange={(v) => upd("photos", v)} />
          </div>
          <div className="card pad24">
            <h3 className="h3" style={{ marginBottom: 16 }}>Visibility</h3>
            <Toggle label="Featured on homepage" sub="Show in the featured grid" on={f.featured} onClick={() => upd("featured", !f.featured)} />
            <hr className="divider" style={{ margin: "14px 0" }} />
            <Toggle label="Confidential (NDA gate)" sub="Hide financials & data room behind NDA" on={f.gated} onClick={() => upd("gated", !f.gated)} />
          </div>
          <div className="card pad24">
            <h3 className="h3" style={{ marginBottom: 8 }}>Preview</h3>
            <ListingCard l={{ ...f, slug, sf: Number(f.sf) || 0 }} />
          </div>
        </div>
      </div>
    </AdminShell>
  );
}

function ListEditor({ items, onChange, placeholder }) {
  return (
    <div className="col gap8">
      {items.map((it, i) => (
        <div key={i} className="row gap8 ac">
          <input className="input" value={it} onChange={(e) => onChange(items.map((x, j) => j === i ? e.target.value : x))} placeholder={placeholder} />
          <button className="btn ghost sm danger" onClick={() => onChange(items.filter((_, j) => j !== i))}><Icon name="trash" size={13} /></button>
        </div>
      ))}
      <button className="btn ghost sm" style={{ alignSelf: "flex-start" }} onClick={() => onChange([...items, ""])}><Icon name="plus" size={14} /> Add highlight</button>
    </div>
  );
}

function KVEditor({ obj, onChange }) {
  const entries = Object.entries(obj);
  return (
    <div className="col gap8">
      {entries.map(([k, v], i) => (
        <div key={i} className="row gap8 ac">
          <input className="input" style={{ flex: "0 0 42%" }} value={k} onChange={(e) => onChange(Object.fromEntries(entries.map((x, j) => j === i ? [e.target.value, x[1]] : x)))} placeholder="Label" />
          <input className="input" value={v} onChange={(e) => onChange(Object.fromEntries(entries.map((x, j) => j === i ? [x[0], e.target.value] : x)))} placeholder="Value" />
          <button className="btn ghost sm danger" onClick={() => onChange(Object.fromEntries(entries.filter((_, j) => j !== i)))}><Icon name="trash" size={13} /></button>
        </div>
      ))}
      <button className="btn ghost sm" style={{ alignSelf: "flex-start" }} onClick={() => onChange({ ...obj, ["Field " + (entries.length + 1)]: "" })}><Icon name="plus" size={14} /> Add field</button>
    </div>
  );
}

function GalleryEditor({ photos, onChange }) {
  const ref = useRef(null);
  const add = (e) => { const fl = [...(e.target.files || [])]; if (!fl.length) return; const out = []; let n = 0; fl.forEach((file) => { const r = new FileReader(); r.onload = () => { out.push(r.result); if (++n === fl.length) onChange([...photos, ...out]); }; r.readAsDataURL(file); }); };
  return (
    <div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 8 }}>
        {photos.map((p, i) => (
          <div key={i} className="card" style={{ overflow: "hidden", position: "relative", height: 70 }}>
            <img src={p} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
            <button className="btn danger" style={{ position: "absolute", top: 4, right: 4, padding: "0 6px", height: 22 }} onClick={() => onChange(photos.filter((_, j) => j !== i))}><Icon name="x" size={12} /></button>
          </div>
        ))}
        <button onClick={() => ref.current.click()} style={{ height: 70, border: "1px dashed var(--line-2)", borderRadius: "var(--r)", background: "var(--paper-2)", cursor: "pointer", display: "grid", placeItems: "center", color: "var(--slate)" }}><Icon name="plus" size={18} /></button>
      </div>
      <input ref={ref} type="file" accept="image/*" multiple onChange={add} style={{ display: "none" }} />
    </div>
  );
}

function Toggle({ label, sub, on, onClick }) {
  return (
    <div className="row jb ac" style={{ cursor: "pointer" }} onClick={onClick}>
      <div><div className="b6 small">{label}</div>{sub && <div className="xsmall muted">{sub}</div>}</div>
      <div style={{ width: 42, height: 24, borderRadius: 999, background: on ? "var(--navy)" : "var(--line-2)", position: "relative", transition: "background .16s", flex: "none" }}>
        <div style={{ position: "absolute", top: 2, left: on ? 20 : 2, width: 20, height: 20, borderRadius: "50%", background: "#fff", transition: "left .16s", boxShadow: "0 1px 2px rgba(0,0,0,0.2)" }} />
      </div>
    </div>
  );
}

function AdminMedia() {
  const s = useStore();
  return (
    <AdminShell section="Media">
      <div className="eyebrow">Console</div><h1 className="h1" style={{ marginTop: 6, marginBottom: 8 }}>Website media</h1>
      <p className="lede" style={{ marginBottom: 28 }}>Photos used across the public site. Uploads publish instantly.</p>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 24 }}>
        {s.media.map((m) => (
          <div key={m.id} className="card pad20">
            <div className="row jb ac" style={{ marginBottom: 12 }}><div><div className="b6">{m.label}</div><div className="xsmall muted">Slot · {m.slot}</div></div>{m.dataUrl && <span className="tag avail"><span className="dot" /> Set</span>}</div>
            <UploadField dataUrl={m.dataUrl} onChange={(d) => { window.GLR.setMedia(m.id, { dataUrl: d }); showToast(m.label + " updated"); }} h={160} hint="Recommended 1600×1000" />
          </div>
        ))}
      </div>
    </AdminShell>
  );
}

function AdminBranding() {
  const s = useStore();
  const b = s.branding;
  const upd = (k, v) => window.GLR.setBranding({ [k]: v });
  return (
    <AdminShell section="Branding">
      <div className="eyebrow">Console</div><h1 className="h1" style={{ marginTop: 6, marginBottom: 28 }}>Branding</h1>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24, alignItems: "start" }}>
        <div className="card pad24">
          <h3 className="h3" style={{ marginBottom: 16 }}>Identity</h3>
          <div className="col gap16">
            <div className="field"><label>Firm name</label><input className="input" value={b.name} onChange={(e) => upd("name", e.target.value)} /></div>
            <div className="field"><label>Tagline</label><input className="input" value={b.tagline} onChange={(e) => upd("tagline", e.target.value)} /></div>
            <div className="row gap16 m-col">
              <div className="field grow"><label>Established</label><input className="input" value={b.est} onChange={(e) => upd("est", e.target.value)} /></div>
              <div className="field grow"><label>City</label><input className="input" value={b.city} onChange={(e) => upd("city", e.target.value)} /></div>
            </div>
            <UploadField label="Logo mark" dataUrl={b.logoDataUrl} onChange={(d) => upd("logoDataUrl", d)} h={120} hint="Square · shown in the nav seal" />
          </div>
        </div>
        <div className="col gap20">
          <div className="card pad24">
            <h3 className="h3" style={{ marginBottom: 16 }}>Contact</h3>
            <div className="col gap16">
              <div className="row gap16 m-col">
                <div className="field grow"><label>Phone</label><input className="input" value={b.phone} onChange={(e) => upd("phone", e.target.value)} /></div>
                <div className="field grow"><label>Email</label><input className="input" value={b.email} onChange={(e) => upd("email", e.target.value)} /></div>
              </div>
              <div className="field"><label>Office address</label><textarea className="textarea" value={b.address} onChange={(e) => upd("address", e.target.value)} /></div>
            </div>
          </div>
          <div className="card pad24">
            <h3 className="h3" style={{ marginBottom: 12 }}>Live preview</h3>
            <div className="card pad20" style={{ background: "var(--navy)" }}><Logo onNavy /></div>
            <p className="xsmall muted" style={{ marginTop: 12 }}><Icon name="shield" size={13} style={{ verticalAlign: "-2px" }} /> The seal shows your uploaded logo, or initials as a fallback.</p>
          </div>
        </div>
      </div>
    </AdminShell>
  );
}

function TextLinkPanel({ contact, onSent }) {
  const s = useStore();
  const [kind, setKind] = useState("property");
  const [listingId, setListingId] = useState((s.listings[0] && s.listings[0].id) || "");
  const [phone, setPhone] = useState(contact ? (contact.phone || "") : "");
  const [consent, setConsent] = useState(contact ? contact.smsStatus === "opted_in" : true);
  const [busy, setBusy] = useState(false);
  const listing = s.listings.find((l) => l.id === listingId) || s.listings[0];
  useEffect(() => { setPhone(contact ? (contact.phone || "") : ""); setConsent(contact ? contact.smsStatus === "opted_in" : true); }, [contact && contact.id]);
  const send = () => {
    if (!listing || !phone) return;
    const payload = { contactId: contact && contact.id, listingId: listing.id, phone, consentConfirmed: consent };
    setBusy(true);
    const fn = kind === "dataroom" ? window.GLR.sendDataroomText : window.GLR.sendPropertyText;
    fn(payload).then((msg) => {
      showToast((kind === "dataroom" ? "Data room" : "Property") + " link text queued");
      onSent && onSent(msg);
    }).catch((e) => showToast(e.message || "Text failed")).finally(() => setBusy(false));
  };
  return (
    <div className="card pad20">
      <div className="row jb ac wrapf gap8">
        <div><div className="label">Text a link</div><div className="small b6" style={{ marginTop: 4 }}>{contact ? contact.name : "Select a contact"}</div></div>
        <span className="tag outline">{contact && contact.smsStatus ? contact.smsStatus.replace("_", " ") : "consent required"}</span>
      </div>
      <div className="col gap12" style={{ marginTop: 14 }}>
        <div className="row gap8">
          <button className={"chip" + (kind === "property" ? " on" : "")} onClick={() => setKind("property")}>Property link</button>
          <button className={"chip" + (kind === "dataroom" ? " on" : "")} onClick={() => setKind("dataroom")}>Data room link</button>
        </div>
        <div className="field"><label>Property</label><select className="select" value={listingId} onChange={(e) => setListingId(e.target.value)}>{s.listings.map((l) => <option key={l.id} value={l.id}>{l.address}</option>)}</select></div>
        <div className="field"><label>Recipient phone</label><input className="input" value={phone} onChange={(e) => setPhone(e.target.value)} placeholder="+1 317 555 0140" /></div>
        <Toggle label="SMS consent confirmed" sub="Required before sending broker-initiated text messages" on={consent} onClick={() => setConsent(!consent)} />
        <button className="btn block" disabled={!contact || !phone || !consent || busy} onClick={send}><Icon name="phone" size={15} /> {busy ? "Sending..." : "Send text link"}</button>
        {kind === "dataroom" && <p className="xsmall muted">Secure links still require approved identity and portal session before private documents are visible.</p>}
      </div>
    </div>
  );
}

function EmailPanel({ contact, onSent }) {
  const s = useStore();
  const [listingId, setListingId] = useState((s.listings[0] && s.listings[0].id) || "");
  const [subject, setSubject] = useState("");
  const [body, setBody] = useState("");
  const [category, setCategory] = useState("transactional");
  const [busy, setBusy] = useState(false);
  const listing = s.listings.find((l) => l.id === listingId) || s.listings[0];
  useEffect(() => {
    if (!subject && listing) setSubject("Great Lakes Realty: " + listing.address);
    if (!body && listing) setBody("Hi " + (contact ? contact.name.split(" ")[0] : "") + ",\n\nHere is the latest information for " + listing.address + ". Reply here and the Great Lakes Realty team will track the thread in the shared inbox.\n\nBest,\nGreat Lakes Realty");
  }, [contact && contact.id, listing && listing.id]);
  const send = () => {
    if (!contact || !contact.email || !subject || !body) return;
    setBusy(true);
    window.GLR.sendEmail({ contactId: contact.id, listingId: listing && listing.id, email: contact.email, subject, body, category, template: category === "marketing" ? "property_launch" : "manual_email", consentConfirmed: true })
      .then((msg) => { showToast("Email queued"); onSent && onSent(msg); })
      .catch((e) => showToast(e.message || "Email failed"))
      .finally(() => setBusy(false));
  };
  return (
    <div className="card pad20">
      <div className="row jb ac wrapf gap8">
        <div><div className="label">Email outreach</div><div className="small b6" style={{ marginTop: 4 }}>{contact ? contact.email || "No email" : "Select a contact"}</div></div>
        <span className="tag outline">{contact && contact.emailStatus ? contact.emailStatus.replace("_", " ") : "consent tracked"}</span>
      </div>
      <div className="col gap12" style={{ marginTop: 14 }}>
        <div className="row gap8">
          <button className={"chip" + (category === "transactional" ? " on" : "")} onClick={() => setCategory("transactional")}>Transactional</button>
          <button className={"chip" + (category === "marketing" ? " on" : "")} onClick={() => setCategory("marketing")}>Property launch</button>
        </div>
        <div className="field"><label>Property</label><select className="select" value={listingId} onChange={(e) => setListingId(e.target.value)}>{s.listings.map((l) => <option key={l.id} value={l.id}>{l.address}</option>)}</select></div>
        <div className="field"><label>Subject</label><input className="input" value={subject} onChange={(e) => setSubject(e.target.value)} /></div>
        <div className="field"><label>Message</label><textarea className="textarea" value={body} onChange={(e) => setBody(e.target.value)} style={{ minHeight: 150 }} /></div>
        <button className="btn block" disabled={!contact || !contact.email || !subject || !body || busy} onClick={send}><Icon name="mail" size={15} /> {busy ? "Sending..." : "Send email"}</button>
        <p className="xsmall muted">Replies are captured in the shared inbox when SendGrid inbound parse is configured.</p>
      </div>
    </div>
  );
}

function AdminContacts() {
  const s = useStore();
  const [selId, setSelId] = useState((s.contacts[0] && s.contacts[0].id) || null);
  const selected = s.contacts.find((c) => c.id === selId) || null;
  const [draft, setDraft] = useState(selected || { name: "", email: "", phone: "", companyName: "", title: "", relationshipType: "", tagsText: "", interestsText: "", smsConsentStatus: "unknown", emailConsentStatus: "unknown" });
  const [note, setNote] = useState("");
  useEffect(() => { setDraft(selected ? { ...selected, tagsText: (selected.tags || []).join(", "), interestsText: (selected.interests || []).join(", ") } : { name: "", email: "", phone: "", companyName: "", title: "", relationshipType: "", tagsText: "", interestsText: "", smsConsentStatus: "unknown", emailConsentStatus: "unknown" }); }, [selId, s.contacts.length]);
  const save = () => {
    const payload = { ...draft, tags: (draft.tagsText || "").split(",").map((x) => x.trim()).filter(Boolean), interests: (draft.interestsText || "").split(",").map((x) => x.trim()).filter(Boolean) };
    window.GLR.saveContact(payload).then((contact) => {
      setSelId(contact.id);
      showToast("Contact saved");
    }).catch((e) => showToast(e.message || "Contact save failed"));
  };
  const addNote = () => {
    if (!selected || !note.trim()) return;
    window.GLR.addContactNote(selected.id, note.trim()).then(() => { setNote(""); showToast("Note added"); });
  };
  return (
    <AdminShell section="Contacts">
      <div className="row jb ac wrapf gap12" style={{ marginBottom: 22 }}>
        <div><div className="eyebrow">CRM</div><h1 className="h1" style={{ marginTop: 6 }}>Contacts</h1></div>
        <button className="btn" onClick={() => { setSelId(null); setDraft({ name: "", email: "", phone: "", companyName: "", title: "", relationshipType: "", tagsText: "", interestsText: "", smsConsentStatus: "unknown", emailConsentStatus: "unknown" }); }}><Icon name="plus" size={15} /> New contact</button>
      </div>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "1.2fr 420px", gap: 22, alignItems: "start" }}>
        <div className="card m-tablewrap">
          <table className="ledger">
            <thead><tr><th>Name</th><th>Company</th><th>Email</th><th>Phone</th><th>Consent</th></tr></thead>
            <tbody>
              {s.contacts.map((c) => (
                <tr key={c.id} className="clickable" onClick={() => setSelId(c.id)} style={{ background: c.id === selId ? "var(--paper-2)" : undefined }}>
                  <td><div className="b6">{c.name}</div><div className="xsmall muted">{c.title || c.source}</div></td>
                  <td className="small">{c.companyName || "—"}</td>
                  <td className="small muted">{c.email || "—"}</td>
                  <td className="small tnum">{c.phone || "—"}</td>
                  <td><div className="row gap6 wrapf"><span className={"tag " + (c.smsStatus === "opted_in" ? "avail" : "")}>SMS {c.smsStatus || "unknown"}</span><span className={"tag " + (c.emailStatus === "opted_in" ? "avail" : "")}>Email {c.emailStatus || "unknown"}</span></div></td>
                </tr>
              ))}
              {s.contacts.length === 0 && <tr><td colSpan="5" className="muted" style={{ textAlign: "center", padding: 28 }}>No contacts yet.</td></tr>}
            </tbody>
          </table>
        </div>
        <div className="col gap18">
          <div className="card pad20">
            <div className="label">{selected ? "Edit contact" : "New contact"}</div>
            <div className="col gap12" style={{ marginTop: 14 }}>
              <div className="field"><label>Name</label><input className="input" value={draft.name || ""} onChange={(e) => setDraft({ ...draft, name: e.target.value })} /></div>
              <div className="field"><label>Email</label><input className="input" value={draft.email || ""} onChange={(e) => setDraft({ ...draft, email: e.target.value })} /></div>
              <div className="field"><label>Phone</label><input className="input" value={draft.phone || ""} onChange={(e) => setDraft({ ...draft, phone: e.target.value })} /></div>
              <div className="field"><label>Company</label><input className="input" value={draft.companyName || ""} onChange={(e) => setDraft({ ...draft, companyName: e.target.value })} /></div>
              <div className="field"><label>Title</label><input className="input" value={draft.title || ""} onChange={(e) => setDraft({ ...draft, title: e.target.value })} /></div>
              <div className="field"><label>Relationship</label><input className="input" value={draft.relationshipType || ""} onChange={(e) => setDraft({ ...draft, relationshipType: e.target.value })} placeholder="Buyer, broker, lender, owner..." /></div>
              <div className="field"><label>Tags</label><input className="input" value={draft.tagsText || ""} onChange={(e) => setDraft({ ...draft, tagsText: e.target.value })} placeholder="industrial, active buyer" /></div>
              <div className="field"><label>Interests</label><input className="input" value={draft.interestsText || ""} onChange={(e) => setDraft({ ...draft, interestsText: e.target.value })} placeholder="100k SF industrial, CBD office" /></div>
              <div className="field"><label>SMS consent</label><select className="select" value={draft.smsConsentStatus || "unknown"} onChange={(e) => setDraft({ ...draft, smsConsentStatus: e.target.value, smsConsentBasis: "business_relationship", smsConsentSource: "admin" })}><option value="unknown">Unknown</option><option value="opted_in">Opted in</option><option value="opted_out">Opted out</option></select></div>
              <div className="field"><label>Email consent</label><select className="select" value={draft.emailConsentStatus || "unknown"} onChange={(e) => setDraft({ ...draft, emailConsentStatus: e.target.value, emailConsentBasis: "business_relationship", emailConsentSource: "admin" })}><option value="unknown">Unknown</option><option value="opted_in">Opted in</option><option value="opted_out">Opted out</option></select></div>
              <button className="btn block" disabled={!draft.name} onClick={save}><Icon name="check" size={15} /> Save contact</button>
            </div>
          </div>
          <TextLinkPanel contact={selected} />
          <EmailPanel contact={selected} />
          {selected && <div className="card pad20">
            <div className="label">Notes</div>
            <div className="col gap8" style={{ marginTop: 12 }}>
              {(selected.notes || []).map((n) => <div key={n.id} className="small" style={{ paddingBottom: 8, borderBottom: "1px solid var(--line)" }}>{n.body}<div className="xsmall muted" style={{ marginTop: 3 }}>{n.author ? n.author.name + " · " : ""}{new Date(n.createdAt).toLocaleDateString()}</div></div>)}
              <textarea className="textarea" value={note} onChange={(e) => setNote(e.target.value)} placeholder="Add relationship note..." style={{ minHeight: 70 }} />
              <button className="btn ghost sm" disabled={!note.trim()} onClick={addNote}>Add note</button>
            </div>
          </div>}
        </div>
      </div>
    </AdminShell>
  );
}

function AdminMessages() {
  const s = useStore();
  const [contactId, setContactId] = useState((s.contacts[0] && s.contacts[0].id) || null);
  const contact = s.contacts.find((c) => c.id === contactId) || null;
  return (
    <AdminShell section="Messages">
      <div className="eyebrow">Broker communications</div>
      <h1 className="h1" style={{ marginTop: 6, marginBottom: 20 }}>Texts, emails &amp; message status</h1>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "390px 1fr", gap: 22, alignItems: "start" }}>
        <div className="col gap16">
          <div className="card pad20">
            <div className="field"><label>Contact</label><select className="select" value={contactId || ""} onChange={(e) => setContactId(e.target.value)}>{s.contacts.map((c) => <option key={c.id} value={c.id}>{c.name} {c.companyName ? "· " + c.companyName : ""}</option>)}</select></div>
          </div>
          <TextLinkPanel contact={contact} />
          <EmailPanel contact={contact} />
        </div>
        <div className="card m-tablewrap">
          <table className="ledger">
            <thead><tr><th>When</th><th>Channel</th><th>To</th><th>Property</th><th>Subject / Template</th><th>Status</th><th>Link</th></tr></thead>
            <tbody>
              {(s.messages || []).map((m) => (
                <tr key={m.id}>
                  <td className="small muted">{m.date}</td>
                  <td><span className="tag outline">{m.channel}</span></td>
                  <td><div className="b6 small">{m.toName || m.contactName || m.toPhone || m.toEmail}</div><div className="xsmall muted">{m.toPhone || m.toEmail || m.fromEmail}</div></td>
                  <td className="small">{m.listingAddress || "—"}</td>
                  <td><div className="small b6">{m.subject || m.template || m.direction}</div>{m.lastEvent && <div className="xsmall muted">Last event: {m.lastEvent.event}</div>}</td>
                  <td><span className={"tag " + (m.status === "failed" ? "" : "avail")}>{m.status}</span></td>
                  <td className="small">{m.shortUrl ? <a className="linklike" href={m.shortUrl} target="_blank">Open</a> : "—"}</td>
                </tr>
              ))}
              {(!s.messages || s.messages.length === 0) && <tr><td colSpan="7" className="muted" style={{ textAlign: "center", padding: 28 }}>No messages sent yet.</td></tr>}
            </tbody>
          </table>
        </div>
      </div>
    </AdminShell>
  );
}

function AdminInbox() {
  const s = useStore();
  const [selId, setSelId] = useState((s.inboxThreads[0] && s.inboxThreads[0].id) || null);
  const selected = (s.selectedThread && s.selectedThread.id === selId) ? s.selectedThread : (s.inboxThreads || []).find((t) => t.id === selId);
  useEffect(() => { if (selId) window.GLR.loadInboxThread(selId).catch(() => null); }, [selId]);
  const setStatus = (status) => {
    if (!selected) return;
    window.GLR.assignInboxThread(selected.id, { status }).then(() => showToast("Thread updated"));
  };
  return (
    <AdminShell section="Inbox">
      <div className="row jb ac wrapf gap12" style={{ marginBottom: 20 }}>
        <div><div className="eyebrow">Shared broker inbox</div><h1 className="h1" style={{ marginTop: 6 }}>Replies &amp; forwarded email</h1></div>
        <button className="btn ghost" onClick={() => window.GLR.refresh().then(() => showToast("Inbox refreshed"))}><Icon name="clock" size={15} /> Refresh</button>
      </div>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "380px 1fr", gap: 22, alignItems: "start" }}>
        <div className="card m-tablewrap">
          <table className="ledger">
            <thead><tr><th>Thread</th><th>Status</th></tr></thead>
            <tbody>
              {(s.inboxThreads || []).map((t) => (
                <tr key={t.id} className="clickable" onClick={() => setSelId(t.id)} style={{ background: t.id === selId ? "var(--paper-2)" : undefined }}>
                  <td><div className="b6 small">{t.subject}</div><div className="xsmall muted">{t.contactName || "Unknown sender"}{t.listingAddress ? " · " + t.listingAddress : ""}</div><div className="xsmall muted">{t.date}</div></td>
                  <td><span className="tag outline">{t.status}</span></td>
                </tr>
              ))}
              {(!s.inboxThreads || s.inboxThreads.length === 0) && <tr><td colSpan="2" className="muted" style={{ textAlign: "center", padding: 28 }}>No inbound email yet.</td></tr>}
            </tbody>
          </table>
        </div>
        <div className="card pad24">
          {selected ? (
            <React.Fragment>
              <div className="row jb ac wrapf gap10">
                <div><h2 className="h2">{selected.subject}</h2><div className="small muted" style={{ marginTop: 4 }}>{selected.contact ? selected.contact.name : selected.contactName || "Unknown contact"}{selected.listing ? " · " + selected.listing.address : ""}</div></div>
                <div className="row gap8">
                  <button className="btn ghost sm" onClick={() => setStatus("open")}>Open</button>
                  <button className="btn ghost sm" onClick={() => setStatus("archived")}>Archive</button>
                  <button className="btn ghost sm" onClick={() => setStatus("closed")}>Close</button>
                </div>
              </div>
              <div className="col gap12" style={{ marginTop: 18 }}>
                {(s.selectedThreadMessages || []).map((m) => (
                  <div key={m.id} className="card pad16" style={{ background: m.direction === "inbound" ? "var(--paper-2)" : "#fff" }}>
                    <div className="row jb ac gap10"><span className="tag outline">{m.direction}</span><span className="xsmall muted">{new Date(m.createdAt).toLocaleString()}</span></div>
                    <div className="small b6" style={{ marginTop: 8 }}>{m.fromEmail || m.toEmail || m.toPhone}</div>
                    <p className="small" style={{ whiteSpace: "pre-line", marginTop: 8 }}>{m.body}</p>
                    {(m.events || []).length > 0 && <div className="xsmall muted">Events: {m.events.map((e) => e.event).join(", ")}</div>}
                  </div>
                ))}
                {(!s.selectedThreadMessages || s.selectedThreadMessages.length === 0) && <p className="muted">Select a thread to load messages.</p>}
              </div>
            </React.Fragment>
          ) : <p className="muted">Select a thread.</p>}
        </div>
      </div>
    </AdminShell>
  );
}

function AdminUsers() {
  const s = useStore();
  const [selId, setSelId] = useState((s.users[0] && s.users[0].id) || null);
  const selected = (s.users || []).find((u) => u.id === selId) || null;
  const [draft, setDraft] = useState(selected || { email: "", name: "", company: "", role: "PORTAL", status: "active", password: "" });
  const [invite, setInvite] = useState(null);
  useEffect(() => { setDraft(selected || { email: "", name: "", company: "", role: "PORTAL", status: "active", password: "" }); }, [selId, s.users.length]);
  const save = () => {
    const payload = { ...draft };
    if (!payload.password) delete payload.password;
    window.GLR.saveUser(payload).then((user) => { setSelId(user.id); showToast("User saved"); }).catch((e) => showToast(e.message || "User save failed"));
  };
  const sendInvite = () => {
    if (!draft.email) return;
    window.GLR.inviteUser({ email: draft.email, name: draft.name, company: draft.company, role: draft.role }).then((out) => { setInvite(out.inviteLink); showToast("Invitation generated"); }).catch((e) => showToast(e.message || "Invite failed"));
  };
  return (
    <AdminShell section="Users">
      <div className="row jb ac wrapf gap12" style={{ marginBottom: 22 }}>
        <div><div className="eyebrow">Access control</div><h1 className="h1" style={{ marginTop: 6 }}>Users &amp; roles</h1></div>
        <button className="btn" onClick={() => { setSelId(null); setDraft({ email: "", name: "", company: "", role: "PORTAL", status: "active", password: "" }); }}><Icon name="plus" size={15} /> New user</button>
      </div>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "1.2fr 420px", gap: 22, alignItems: "start" }}>
        <div className="card m-tablewrap">
          <table className="ledger">
            <thead><tr><th>Name</th><th>Email</th><th>Role</th><th>Status</th><th>Sessions</th></tr></thead>
            <tbody>
              {(s.users || []).map((u) => (
                <tr key={u.id} className="clickable" onClick={() => setSelId(u.id)} style={{ background: u.id === selId ? "var(--paper-2)" : undefined }}>
                  <td><div className="b6">{u.name}</div><div className="xsmall muted">{u.company || "—"}</div></td>
                  <td className="small muted">{u.email}</td>
                  <td><span className="tag outline">{u.role}</span></td>
                  <td><span className={"tag " + (u.status === "active" ? "avail" : "")}>{u.status}</span></td>
                  <td className="small tnum">{u._count ? u._count.sessions : 0}</td>
                </tr>
              ))}
              {(!s.users || s.users.length === 0) && <tr><td colSpan="5" className="muted" style={{ textAlign: "center", padding: 28 }}>No users yet.</td></tr>}
            </tbody>
          </table>
        </div>
        <div className="card pad20">
          <div className="label">{selected ? "Edit user" : "New user"}</div>
          <div className="col gap12" style={{ marginTop: 14 }}>
            <div className="field"><label>Email</label><input className="input" value={draft.email || ""} onChange={(e) => setDraft({ ...draft, email: e.target.value })} /></div>
            <div className="field"><label>Name</label><input className="input" value={draft.name || ""} onChange={(e) => setDraft({ ...draft, name: e.target.value })} /></div>
            <div className="field"><label>Company</label><input className="input" value={draft.company || ""} onChange={(e) => setDraft({ ...draft, company: e.target.value })} /></div>
            <div className="row gap12"><div className="field grow"><label>Role</label><select className="select" value={draft.role || "PORTAL"} onChange={(e) => setDraft({ ...draft, role: e.target.value })}><option value="ADMIN">Admin / Broker</option><option value="PORTAL">Client Portal</option></select></div><div className="field grow"><label>Status</label><select className="select" value={draft.status || "active"} onChange={(e) => setDraft({ ...draft, status: e.target.value })}><option value="active">Active</option><option value="invited">Invited</option><option value="disabled">Disabled</option></select></div></div>
            <div className="field"><label>{selected ? "New password" : "Password"}</label><input className="input" type="password" value={draft.password || ""} onChange={(e) => setDraft({ ...draft, password: e.target.value })} placeholder={selected ? "Leave blank to keep current" : "Optional; invite can set later"} /></div>
            <button className="btn block" disabled={!draft.email || !draft.name} onClick={save}><Icon name="check" size={15} /> Save user</button>
            <button className="btn ghost block" disabled={!draft.email} onClick={sendInvite}><Icon name="mail" size={15} /> Generate invitation link</button>
            {invite && <div className="xsmall" style={{ wordBreak: "break-all" }}><b>Invite link:</b> <a href={invite} target="_blank">{invite}</a></div>}
          </div>
        </div>
      </div>
    </AdminShell>
  );
}

function AdminLaunch({ id }) {
  const s = useStore();
  const listing = s.listings.find((l) => l.id === id);
  const [status, setStatus] = useState((listing && listing.launchStatus) || "draft");
  const [taskTitle, setTaskTitle] = useState("");
  useEffect(() => { window.GLR.loadLaunch(id).catch((e) => showToast(e.message || "Launch load failed")); }, [id]);
  const launch = s.launchDetail || {};
  const engagement = s.engagementDetail || {};
  const checklist = launch.checklist || {};
  const saveStatus = (next) => {
    setStatus(next);
    window.GLR.saveLaunch(id, { launchStatus: next, published: next === "launched" || undefined }).then(() => showToast("Launch status updated"));
  };
  const addTask = () => {
    if (!taskTitle.trim()) return;
    window.GLR.saveTask({ title: taskTitle.trim(), listingId: id }).then(() => { setTaskTitle(""); window.GLR.loadLaunch(id); showToast("Launch task added"); });
  };
  const funnel = engagement.funnel || {};
  const items = [["Listing facts", checklist.facts], ["SEO metadata", checklist.seo], ["Media", checklist.media], ["Broker team", checklist.brokerTeam], ["Data room", checklist.dataroom], ["NDA / access", checklist.nda], ["Audience", checklist.audience], ["Launch date", checklist.launchDate]];
  return (
    <AdminShell section="Listings">
      <div className="row gap8 ac small muted" style={{ marginBottom: 14 }}><button className="linklike small" onClick={() => navigate("/admin/listings")}><Icon name="chevL" size={14} /> Listings</button><Icon name="chevR" size={13} /><span className="b6" style={{ color: "var(--ink)" }}>{listing ? listing.address : "Launch"}</span></div>
      <div className="row jb ac wrapf gap12" style={{ marginBottom: 22 }}>
        <div><div className="eyebrow">Property launch</div><h1 className="h1" style={{ marginTop: 6 }}>{listing ? listing.address : "Launch dashboard"}</h1></div>
        <div className="row gap8">{["draft", "review", "ready", "launched", "paused", "closed"].map((x) => <button key={x} className={"chip" + (status === x ? " on" : "")} onClick={() => saveStatus(x)}>{x}</button>)}</div>
      </div>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 22, alignItems: "start" }}>
        <div className="card pad24">
          <h3 className="h3">Launch checklist</h3>
          <div className="col gap10" style={{ marginTop: 16 }}>{items.map(([label, done]) => <div key={label} className="row jb ac" style={{ padding: "10px 0", borderBottom: "1px solid var(--line)" }}><span className="small b6">{label}</span><span className={"tag " + (done ? "avail" : "")}>{done ? "Ready" : "Needs work"}</span></div>)}</div>
          <div className="row gap8" style={{ marginTop: 16 }}><button className="btn ghost" onClick={() => navigate("/admin/listings/" + id)}><Icon name="edit" size={15} /> Listing</button><button className="btn ghost" onClick={() => navigate("/admin/listings/" + id + "/dataroom")}><Icon name="folder" size={15} /> Data room</button><button className="btn ghost" onClick={() => navigate("/admin/messages")}><Icon name="mail" size={15} /> Outreach</button></div>
        </div>
        <div className="card pad24">
          <h3 className="h3">Engagement funnel</h3>
          <div className="m-stack2" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 12, marginTop: 16 }}>
            {[["Views", funnel.propertyViews], ["Access clicks", funnel.accessClicks], ["Access", funnel.accessRequests], ["Approved", funnel.approvedAccess], ["Inquiries", funnel.inquiries], ["Email opens", funnel.emailOpened], ["Clicks", funnel.emailClicked], ["Docs", funnel.documentDownloads], ["Q&A", funnel.questions], ["LOIs", funnel.lois], ["Texts", funnel.smsDelivered]].map(([label, value]) => <div key={label} className="card pad16"><div className="label">{label}</div><div className="stat" style={{ marginTop: 6 }}><div className="n">{value || 0}</div></div></div>)}
          </div>
        </div>
        <div className="card pad24">
          <h3 className="h3">Tasks</h3>
          <div className="row gap8" style={{ marginTop: 12 }}><input className="input" value={taskTitle} onChange={(e) => setTaskTitle(e.target.value)} placeholder="Add launch follow-up..." /><button className="btn" onClick={addTask}><Icon name="plus" size={15} /></button></div>
          <div className="col gap8" style={{ marginTop: 14 }}>{(launch.tasks || engagement.tasks || []).map((t) => <div key={t.id} className="row jb ac small" style={{ padding: "8px 0", borderBottom: "1px solid var(--line)" }}><span>{t.title}</span><span className="tag outline">{t.status}</span></div>)}</div>
        </div>
        <div className="card pad24">
          <h3 className="h3">Recent activity</h3>
          <div className="col gap8" style={{ marginTop: 12 }}>{(engagement.recentActivity || []).map((a) => <div key={a.id} className="small" style={{ paddingBottom: 8, borderBottom: "1px solid var(--line)" }}><span className="b6">{a.action}</span><div className="xsmall muted">{a.contact ? a.contact.name + " · " : ""}{new Date(a.createdAt).toLocaleString()}</div></div>)}</div>
        </div>
      </div>
    </AdminShell>
  );
}

function AccountScreen() {
  const s = useStore();
  const [profile, setProfile] = useState(s.accountProfile || null);
  useEffect(() => { window.GLR.loadAccount().then((out) => setProfile(out.profile)).catch(() => null); }, []);
  const save = () => {
    if (!profile) return;
    window.GLR.updateAccount({ name: profile.name, company: profile.company }).then((p) => { setProfile(p); showToast("Account updated"); });
  };
  return (
    <div style={{ minHeight: "100vh", background: "var(--paper-2)" }}>
      <Nav cur="Portal" />
      <main className="wrap" style={{ padding: "36px 0 72px" }}>
        <div className="eyebrow">Client account</div>
        <h1 className="h1" style={{ marginTop: 6 }}>Profile &amp; access history</h1>
        <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "420px 1fr", gap: 22, alignItems: "start", marginTop: 24 }}>
          <div className="card pad24">
            {profile ? <div className="col gap12">
              <div className="field"><label>Name</label><input className="input" value={profile.name || ""} onChange={(e) => setProfile({ ...profile, name: e.target.value })} /></div>
              <div className="field"><label>Email</label><input className="input" value={profile.email || ""} disabled /></div>
              <div className="field"><label>Company</label><input className="input" value={profile.company || ""} onChange={(e) => setProfile({ ...profile, company: e.target.value })} /></div>
              <button className="btn block" onClick={save}>Save profile</button>
            </div> : <p className="muted">Sign in through the client portal to view your account.</p>}
          </div>
          <div className="card m-tablewrap">
            <table className="ledger">
              <thead><tr><th>Property</th><th>Status</th><th>Signed</th></tr></thead>
              <tbody>{((profile && profile.requests) || []).map((r) => <tr key={r.id}><td className="b6">{r.listing ? r.listing.address : r.listingId}</td><td><span className="tag outline">{r.status}</span></td><td className="small muted">{new Date(r.createdAt).toLocaleDateString()}</td></tr>)}</tbody>
            </table>
          </div>
        </div>
      </main>
      <Footer />
    </div>
  );
}

function AdminAudit() {
  const s = useStore();
  return (
    <AdminShell section="Audit">
      <div className="eyebrow">Security</div>
      <h1 className="h1" style={{ marginTop: 6, marginBottom: 20 }}>Audit log</h1>
      <div className="card m-tablewrap">
        <table className="ledger">
          <thead><tr><th>When</th><th>Action</th><th>Actor</th><th>Listing</th><th>Entity</th></tr></thead>
          <tbody>
            {(s.audit || []).map((a) => (
              <tr key={a.id}>
                <td className="small muted">{new Date(a.createdAt).toLocaleString()}</td>
                <td><span className="tag outline">{a.action}</span></td>
                <td className="small">{a.actor ? a.actor.name : "System"}</td>
                <td className="small">{a.listing ? a.listing.address : "—"}</td>
                <td className="small muted">{a.entityType}{a.entityId ? " · " + a.entityId.slice(0, 8) : ""}</td>
              </tr>
            ))}
            {(!s.audit || s.audit.length === 0) && <tr><td colSpan="5" className="muted" style={{ textAlign: "center", padding: 28 }}>No audit events yet.</td></tr>}
          </tbody>
        </table>
      </div>
    </AdminShell>
  );
}

function StatusPill({ status }) {
  if (status === "approved") return <span className="tag avail"><span className="dot" /> Approved</span>;
  if (status === "denied") return <span className="tag" style={{ background: "#fbeeec", color: "var(--danger)" }}><span className="dot" /> Declined</span>;
  return <span className="tag" style={{ background: "var(--loi-bg)", color: "var(--loi)" }}><span className="dot" /> Pending</span>;
}

function AdminRequests() {
  const s = useStore();
  const G = window.GLR;
  const ordered = [...s.requests].sort((a, b) => (a.status === "pending" ? -1 : 1) - (b.status === "pending" ? -1 : 1));
  const pendingCount = s.requests.filter((r) => r.status === "pending").length;
  return (
    <AdminShell section="Requests">
      <div className="eyebrow">Console</div>
      <div className="row jb ac wrapf gap12" style={{ marginTop: 6, marginBottom: 8 }}>
        <h1 className="h1">Access requests</h1>
        {pendingCount > 0 && <span className="tag" style={{ background: "var(--loi-bg)", color: "var(--loi)" }}><span className="dot" /> {pendingCount} awaiting review</span>}
      </div>
      <p className="lede" style={{ marginBottom: 24 }}>Approve or decline NDA-signed parties. Approval opens their secure data room instantly.</p>
      <div className="card" style={{ overflowX: "auto" }}>
        <table className="ledger" style={{ minWidth: 760 }}>
          <thead><tr><th>Requested by</th><th>Email</th><th>Property</th><th>Capacity</th><th className="num">Date</th><th>Status</th><th></th></tr></thead>
          <tbody>
            {ordered.map((r) => {
              const l = s.listings.find((x) => x.slug === r.slug);
              return (
                <tr key={r.id}>
                  <td><div className="b6">{r.name}</div><div className="xsmall muted">{r.company}</div></td>
                  <td className="small muted">{r.email}</td>
                  <td className="small">{l ? <span className="b6">{l.address}</span> : <span className="muted">{r.slug}</span>}</td>
                  <td><span className="tag outline">{r.cap}</span></td>
                  <td className="num small muted tnum">{r.date}</td>
                  <td><StatusPill status={r.status} /></td>
                  <td className="num">
                    {r.status === "pending"
                      ? <div className="row gap6 je"><button className="btn sm" onClick={() => { G.setRequestStatus(r.id, "approved"); showToast("Access approved — data room opened"); }}><Icon name="check" size={14} /> Approve</button><button className="btn ghost sm danger" onClick={() => { G.setRequestStatus(r.id, "denied"); showToast("Request declined"); }}>Decline</button></div>
                      : r.status === "approved"
                        ? <button className="btn ghost sm" onClick={() => { G.setRequestStatus(r.id, "denied"); showToast("Access revoked"); }}>Revoke</button>
                        : <button className="btn ghost sm" onClick={() => { G.setRequestStatus(r.id, "approved"); showToast("Access approved"); }}>Approve</button>}
                  </td>
                </tr>
              );
            })}
            {s.requests.length === 0 && <tr><td colSpan="7" className="muted" style={{ textAlign: "center", padding: 32 }}>No access requests yet.</td></tr>}
          </tbody>
        </table>
      </div>
    </AdminShell>
  );
}

function QAAnswerRow({ q, listing }) {
  const [text, setText] = useState("");
  return (
    <div className="card pad20">
      <div className="row jb ac wrapf gap8" style={{ marginBottom: 10 }}>
        <span className="tag outline">{listing ? listing.address : q.slug}</span>
        <span className="xsmall muted">{q.name} · {q.askedAt}</span>
      </div>
      <div className="row gap10"><Icon name="msg" size={16} style={{ color: "var(--navy)", flex: "none", marginTop: 2 }} /><p className="b6" style={{ margin: 0 }}>{q.q}</p></div>
      {q.a
        ? <div style={{ marginTop: 12, paddingTop: 12, borderTop: "1px solid var(--line)" }}><div className="small" style={{ color: "var(--ink-2)" }}>{q.a}</div><div className="xsmall accent" style={{ marginTop: 4 }}>Answered by {q.by} · {q.answeredAt}</div></div>
        : <div className="row gap10" style={{ marginTop: 12, alignItems: "flex-end" }}>
            <textarea className="textarea" value={text} onChange={(e) => setText(e.target.value)} style={{ minHeight: 56, flex: 1 }} placeholder="Type an answer to the buyer…" />
            <button className="btn" disabled={!text.trim()} onClick={() => { window.GLR.answerQuestion(q.id, text.trim(), "Jordan Mercer"); showToast("Answer posted to the data room"); }}>Post answer</button>
          </div>}
    </div>
  );
}

function AdminQA() {
  const s = useStore();
  const open = s.qa.filter((q) => !q.a);
  const answered = s.qa.filter((q) => q.a);
  const L = (slug) => s.listings.find((x) => x.slug === slug);
  return (
    <AdminShell section="Q&A">
      <div className="eyebrow">Console</div>
      <div className="row jb ac wrapf gap12" style={{ marginTop: 6, marginBottom: 8 }}>
        <h1 className="h1">Q&amp;A inbox</h1>
        {open.length > 0 && <span className="tag" style={{ background: "var(--loi-bg)", color: "var(--loi)" }}><span className="dot" /> {open.length} unanswered</span>}
      </div>
      <p className="lede" style={{ marginBottom: 24 }}>Questions from parties in the data room. Answers publish to their war room instantly.</p>
      {open.length > 0 && <div className="label" style={{ marginBottom: 12 }}>Awaiting answer</div>}
      <div className="col gap16">
        {open.map((q) => <QAAnswerRow key={q.id} q={q} listing={L(q.slug)} />)}
      </div>
      {answered.length > 0 && <div className="label" style={{ margin: "28px 0 12px" }}>Answered</div>}
      <div className="col gap16">
        {answered.map((q) => <QAAnswerRow key={q.id} q={q} listing={L(q.slug)} />)}
      </div>
      {s.qa.length === 0 && <div className="card pad32" style={{ textAlign: "center" }}><Icon name="msg" size={26} style={{ color: "var(--slate-2)" }} /><p className="muted" style={{ marginTop: 10 }}>No questions yet.</p></div>}
    </AdminShell>
  );
}

/* ===== Content: Categories + NDA templates ===== */
function CategoryRow({ kind, value, count }) {
  const [edit, setEdit] = useState(false);
  const [v, setV] = useState(value);
  return (
    <div className="row gap8 ac" style={{ padding: "8px 10px", border: "1px solid var(--line)", borderRadius: "var(--r)", background: "var(--paper)" }}>
      {edit
        ? <input className="input" style={{ height: 34 }} value={v} onChange={(e) => setV(e.target.value)} autoFocus />
        : <span className="b6 small" style={{ flex: 1 }}>{value}</span>}
      {!edit && <span className="xsmall muted">{count} in use</span>}
      {edit
        ? <React.Fragment><button className="btn sm" onClick={() => { window.GLR.renameCategory(kind, value, v); setEdit(false); }}><Icon name="check" size={14} /></button><button className="btn ghost sm" onClick={() => { setV(value); setEdit(false); }}>Cancel</button></React.Fragment>
        : <React.Fragment><button className="btn ghost sm" onClick={() => setEdit(true)}><Icon name="edit" size={13} /></button><button className="btn ghost sm danger" onClick={() => { if (count > 0 && !confirm(value + " is used by " + count + " listing(s). Remove anyway?")) return; window.GLR.removeCategory(kind, value); }}><Icon name="trash" size={13} /></button></React.Fragment>}
    </div>
  );
}

function CategoryGroup({ title, kind, items, field, listings }) {
  const [adding, setAdding] = useState("");
  const add = () => { window.GLR.addCategory(kind, adding); setAdding(""); };
  return (
    <div className="card pad24">
      <div className="row jb ac" style={{ marginBottom: 14 }}><h3 className="h3">{title}</h3><span className="tag outline">{items.length}</span></div>
      <div className="col gap8">
        {items.map((it) => <CategoryRow key={it} kind={kind} value={it} count={field ? listings.filter((l) => l[field] === it).length : 0} />)}
        {items.length === 0 && <p className="xsmall muted">None yet.</p>}
      </div>
      <div className="row gap8" style={{ marginTop: 14 }}>
        <input className="input" value={adding} onChange={(e) => setAdding(e.target.value)} onKeyDown={(e) => e.key === "Enter" && add()} placeholder={"Add " + title.toLowerCase().replace(/s$/, "")} />
        <button className="btn" onClick={add}><Icon name="plus" size={15} /> Add</button>
      </div>
    </div>
  );
}

function CategoriesPanel() {
  const s = useStore();
  const c = s.categories;
  return (
    <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 20, marginTop: 8 }}>
      <CategoryGroup title="Property types" kind="types" items={c.types} field="type" listings={s.listings} />
      <CategoryGroup title="Submarkets" kind="submarkets" items={c.submarkets} field="submarket" listings={s.listings} />
      <CategoryGroup title="Building classes" kind="classes" items={c.classes} field="cls" listings={s.listings} />
    </div>
  );
}

function NdaPanel() {
  const s = useStore();
  const G = window.GLR;
  const [selId, setSelId] = useState(s.ndas[0] && s.ndas[0].id);
  const sel = s.ndas.find((n) => n.id === selId) || null;
  const [draft, setDraft] = useState(sel || { name: "", governing: "Indiana", body: "" });
  useEffect(() => { setDraft(sel || { name: "", governing: "Indiana", body: "" }); }, [selId]);
  const isNew = !sel;
  const save = () => { const id = draft.id || ("nda" + Date.now()); G.upsertNda({ ...draft, id }); setSelId(id); showToast("NDA template saved"); };
  return (
    <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "300px 1fr", gap: 20, marginTop: 8, alignItems: "start" }}>
      <div className="col gap10">
        {s.ndas.map((n) => (
          <div key={n.id} className="card pad16 hover" onClick={() => setSelId(n.id)} style={{ cursor: "pointer", borderColor: n.id === selId ? "var(--navy)" : undefined, boxShadow: n.id === selId ? "var(--shadow)" : undefined }}>
            <div className="row jb ac"><span className="b6 small">{n.name}</span>{n.active && <span className="tag avail"><span className="dot" /> Active</span>}</div>
            <p className="xsmall muted" style={{ marginTop: 6, display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden" }}>{n.body}</p>
          </div>
        ))}
        <button className="btn ghost block" onClick={() => { setSelId(null); setDraft({ name: "", governing: "Indiana", body: "" }); }}><Icon name="plus" size={15} /> New template</button>
      </div>
      <div className="card pad24">
        <div className="row jb ac wrapf gap10" style={{ marginBottom: 16 }}>
          <h3 className="h3">{isNew ? "New NDA template" : "Edit template"}</h3>
          <div className="row gap8">
            {sel && !sel.active && <button className="btn ghost sm" onClick={() => { G.setActiveNda(sel.id); showToast(sel.name + " is now the active NDA"); }}><Icon name="check" size={14} /> Set active</button>}
            {sel && sel.active && <span className="tag avail" style={{ alignSelf: "center" }}><span className="dot" /> Active — signed by all parties</span>}
            {sel && s.ndas.length > 1 && <button className="btn ghost sm danger" onClick={() => { if (confirm("Delete this NDA template?")) { G.removeNda(sel.id); setSelId(s.ndas[0].id); } }}><Icon name="trash" size={14} /></button>}
          </div>
        </div>
        <div className="col gap16">
          <div className="row gap16 m-col">
            <div className="field grow"><label>Template name</label><input className="input" value={draft.name} onChange={(e) => setDraft({ ...draft, name: e.target.value })} placeholder="Standard Mutual NDA" /></div>
            <div className="field" style={{ width: 180 }}><label>Governing law (state)</label><input className="input" value={draft.governing} onChange={(e) => setDraft({ ...draft, governing: e.target.value })} /></div>
          </div>
          <div className="field"><label>Agreement body</label><textarea className="textarea" style={{ minHeight: 240 }} value={draft.body} onChange={(e) => setDraft({ ...draft, body: e.target.value })} placeholder="Enter the confidentiality agreement text…" /></div>
          <div className="row gap10"><button className="btn" onClick={save} disabled={!draft.name || !draft.body}><Icon name="check" size={16} /> Save template</button><span className="xsmall muted" style={{ alignSelf: "center" }}>The active template is what parties sign in the access flow.</span></div>
        </div>
      </div>
    </div>
  );
}

function AdminContent() {
  const [tab, setTab] = useState("categories");
  return (
    <AdminShell section="Content">
      <div className="eyebrow">Console</div>
      <h1 className="h1" style={{ marginTop: 6, marginBottom: 6 }}>Site content</h1>
      <p className="lede" style={{ marginBottom: 20 }}>Manage the building blocks behind your listings and the confidentiality agreement parties sign.</p>
      <div className="row gap8" style={{ marginBottom: 8 }}>
        <button className={"chip" + (tab === "categories" ? " on" : "")} onClick={() => setTab("categories")}>Categories</button>
        <button className={"chip" + (tab === "nda" ? " on" : "")} onClick={() => setTab("nda")}>NDA templates</button>
      </div>
      {tab === "categories" ? <CategoriesPanel /> : <NdaPanel />}
    </AdminShell>
  );
}

function AdminAnalytics() {
  const s = useStore();
  const [days, setDays] = useState(30);
  const [busy, setBusy] = useState(false);
  useEffect(() => {
    setBusy(true);
    window.GLR.loadAnalytics(days).catch((e) => showToast(e.message || "Analytics load failed")).finally(() => setBusy(false));
  }, [days]);
  const summary = s.analyticsSummary || {};
  const totals = summary.totals || {};
  const cards = [["Page views", totals.page_view], ["Property views", totals.property_view], ["Access clicks", totals.access_cta], ["Portal opens", totals.portal_open], ["Contact sends", totals.contact_submit], ["Downloads", totals.download_request]];
  return (
    <AdminShell section="Analytics">
      <div className="row jb ac wrapf gap12" style={{ marginBottom: 22 }}>
        <div><div className="eyebrow">Traffic &amp; funnel</div><h1 className="h1" style={{ marginTop: 6 }}>Analytics</h1></div>
        <div className="row gap8">{[7, 30, 90].map((d) => <button key={d} className={"chip" + (days === d ? " on" : "")} onClick={() => setDays(d)}>{d} days</button>)}</div>
      </div>
      <div className="m-stack2" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 16 }}>
        {cards.map(([label, value]) => <div key={label} className="card pad20"><div className="label">{label}</div><div className="stat" style={{ marginTop: 10 }}><div className="n">{value || 0}</div></div></div>)}
      </div>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "1fr 1.2fr", gap: 22, alignItems: "start", marginTop: 22 }}>
        <div className="card m-tablewrap">
          <div className="row jb ac" style={{ padding: "18px 20px", borderBottom: "1px solid var(--line)" }}><h3 className="h3">Top listings</h3>{busy && <span className="tag outline">Loading</span>}</div>
          <table className="ledger">
            <thead><tr><th>Property</th><th className="num">Events</th></tr></thead>
            <tbody>
              {(summary.listings || []).map((row) => (
                <tr key={row.listing.id} className="clickable" onClick={() => navigate("/admin/listings/" + row.listing.id + "/launch")}>
                  <td><div className="b6">{row.listing.address}</div><div className="xsmall muted">{row.listing.slug}</div></td>
                  <td className="num tnum">{row.count}</td>
                </tr>
              ))}
              {(!summary.listings || summary.listings.length === 0) && <tr><td colSpan="2" className="muted" style={{ textAlign: "center", padding: 28 }}>No events yet.</td></tr>}
            </tbody>
          </table>
        </div>
        <div className="card m-tablewrap">
          <div className="row jb ac" style={{ padding: "18px 20px", borderBottom: "1px solid var(--line)" }}><h3 className="h3">Recent events</h3><span className="tag outline">{summary.days || days} days</span></div>
          <table className="ledger">
            <thead><tr><th>Event</th><th>Property</th><th className="num">Time</th></tr></thead>
            <tbody>
              {(summary.recent || []).slice(0, 30).map((event) => (
                <tr key={event.id}>
                  <td><span className="tag outline">{event.type}</span><div className="xsmall muted">{event.path || "—"}</div></td>
                  <td className="small">{event.listing ? event.listing.address : "—"}</td>
                  <td className="num small muted">{new Date(event.createdAt).toLocaleString()}</td>
                </tr>
              ))}
              {(!summary.recent || summary.recent.length === 0) && <tr><td colSpan="3" className="muted" style={{ textAlign: "center", padding: 28 }}>No recent events.</td></tr>}
            </tbody>
          </table>
        </div>
      </div>
    </AdminShell>
  );
}

function AdminSecurity({ required }) {
  const status = window.GLR.apiStatus();
  const mfa = status.mfa || {};
  const [setup, setSetup] = useState(null);
  const [code, setCode] = useState("");
  const [busy, setBusy] = useState(false);
  const start = () => {
    setBusy(true);
    window.GLR.setupMfa().then((out) => { setSetup(out); showToast("MFA secret generated"); }).catch((e) => showToast(e.message || "MFA setup failed")).finally(() => setBusy(false));
  };
  const verify = () => {
    if (!code) return;
    setBusy(true);
    window.GLR.verifyMfa(code).then(() => { setSetup(null); setCode(""); showToast("MFA enabled"); }).catch((e) => showToast(e.message || "Invalid MFA code")).finally(() => setBusy(false));
  };
  return (
    <AdminShell section="Security">
      <div className="row jb ac wrapf gap12" style={{ marginBottom: 22 }}>
        <div><div className="eyebrow">Security</div><h1 className="h1" style={{ marginTop: 6 }}>MFA rollout</h1></div>
        <span className={"tag " + (mfa.enabled ? "avail" : required || mfa.requiredNow ? "loi" : "outline")}>{mfa.enabled ? "Enabled" : mfa.required ? "Required" : "Optional"}</span>
      </div>
      {(required || mfa.requiredNow) && !mfa.enabled && (
        <div className="gate-band pad20" style={{ marginBottom: 18 }}>
          <div className="row gap12 ac"><Icon name="lock" size={20} style={{ color: "var(--brass)" }} /><div><div className="b6">MFA is required before admin work can continue.</div><div className="xsmall muted">Set it up below, then retry the admin page you were opening.</div></div></div>
        </div>
      )}
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 22, alignItems: "start" }}>
        <div className="card pad24">
          <h3 className="h3">Policy</h3>
          <div className="col gap10" style={{ marginTop: 16 }}>
            <div className="row jb ac" style={{ padding: "10px 0", borderBottom: "1px solid var(--line)" }}><span className="small b6">Required</span><span className="tag outline">{mfa.required ? "Yes" : "No"}</span></div>
            <div className="row jb ac" style={{ padding: "10px 0", borderBottom: "1px solid var(--line)" }}><span className="small b6">Current user</span><span className="tag outline">{mfa.enabled ? "MFA enabled" : "MFA not enabled"}</span></div>
            <div className="row jb ac" style={{ padding: "10px 0", borderBottom: "1px solid var(--line)" }}><span className="small b6">Grace ends</span><span className="small muted">{mfa.graceEndsAt ? new Date(mfa.graceEndsAt).toLocaleString() : "—"}</span></div>
          </div>
        </div>
        <div className="card pad24">
          <h3 className="h3">Authenticator setup</h3>
          {!mfa.enabled && !setup && <button className="btn block" style={{ marginTop: 16 }} disabled={busy} onClick={start}><Icon name="lock" size={15} /> Generate MFA secret</button>}
          {setup && (
            <div className="col gap12" style={{ marginTop: 16 }}>
              <div className="field"><label>Secret</label><input className="input" value={setup.secret || ""} readOnly /></div>
              {setup.manualTestCode && <div className="field"><label>Development test code</label><input className="input" value={setup.manualTestCode} readOnly /></div>}
              <div className="field"><label>Verification code</label><input className="input" inputMode="numeric" value={code} onChange={(e) => setCode(e.target.value)} /></div>
              <button className="btn block" disabled={busy || !code} onClick={verify}><Icon name="check" size={15} /> Verify and enable</button>
            </div>
          )}
          {mfa.enabled && <div className="gate-band pad20" style={{ marginTop: 16 }}><div className="row gap10 ac"><Icon name="check" size={17} style={{ color: "var(--avail)" }} /><span className="small b6">This admin account has MFA enabled.</span></div></div>}
        </div>
      </div>
    </AdminShell>
  );
}

function ScanTag({ status }) {
  const value = status || "pending";
  const cls = value === "clean" ? "avail" : value === "blocked" ? "closed" : value === "skipped" ? "outline" : "loi";
  return <span className={"tag " + cls}>{value}</span>;
}

function AdminDataRoom({ id }) {
  const s = useStore();
  const G = window.GLR;
  const l = s.listings.find((x) => x.id === id);
  const [folder, setFolder] = useState(0);
  const fileRef = useRef(null);
  useEffect(() => { G.loadDataroom(id).catch((e) => console.warn("Data room load failed", e)); }, [id]);
  if (!l) return <AdminShell section="Listings"><p className="muted">Listing not found.</p></AdminShell>;
  const tree = (l.dataroom && l.dataroom.length) ? l.dataroom : JSON.parse(JSON.stringify(s.dataroom));
  const fi = Math.min(folder, tree.length - 1);
  const cur = tree[fi] || { folder: "", files: [] };
  const addFolder = () => { const name = prompt("Folder name", String(tree.length + 1).padStart(2, "0") + " · New Folder"); if (name) G.addDataroomFolder(id, name).then(() => showToast("Folder added")); };
  const renameFolder = (i) => { const name = prompt("Rename folder", tree[i].folder); if (name && tree[i].id) G.renameDataroomFolder(id, tree[i].id, name).then(() => showToast("Folder renamed")); };
  const removeFolder = (i) => { if (tree[i].id && confirm("Delete \"" + tree[i].folder + "\" and its files?")) { G.removeDataroomFolder(id, tree[i].id).then(() => { setFolder(0); showToast("Folder deleted"); }); } };
  const addFiles = (e) => { const fl = [...(e.target.files || [])]; if (!fl.length || !cur.id) return; G.uploadDataroomFiles(id, cur.id, fl).then(() => showToast(fl.length + " file(s) uploaded")); e.target.value = ""; };
  const addManual = () => { const name = prompt("File name (e.g. Rent Roll.xlsx)"); if (!name || !cur.id) return; G.addDataroomEntry(id, cur.id, name).then(() => showToast("Document entry added")); };
  const removeFile = (k) => { const f = cur.files[k]; if (f && f.storageId && confirm("Delete " + f.n + "?")) G.removeDataroomFile(id, f.storageId).then(() => showToast("File deleted")); };
  return (
    <AdminShell section="Listings">
      <div className="row gap8 ac small muted" style={{ marginBottom: 14 }}><button className="linklike small" onClick={() => navigate("/admin/listings/" + id)}><Icon name="chevL" size={14} /> {l.address}</button><Icon name="chevR" size={13} /><span className="b6" style={{ color: "var(--ink)" }}>Data room</span></div>
      <div className="row jb ac wrapf gap12" style={{ marginBottom: 8 }}>
        <div><div className="eyebrow">Secure data room</div><h1 className="h1" style={{ marginTop: 6 }}>{l.address}</h1></div>
        <div className="row gap8"><button className="btn ghost" onClick={() => navigate("/portal/" + l.slug)}><Icon name="eye" size={15} /> Preview war room</button></div>
      </div>
      <p className="lede" style={{ marginBottom: 24 }}>Organize the folders and documents approved parties see in this property's war room.</p>
      <div className="m-stack" style={{ display: "grid", gridTemplateColumns: "280px 1fr", gap: 20, alignItems: "start" }}>
        <div className="card pad16">
          <div className="row jb ac" style={{ marginBottom: 10 }}><span className="label">Folders</span><span className="tag outline">{tree.length}</span></div>
          <div className="col gap2">
            {tree.map((f, i) => (
              <div key={i} className={"row gap6 ac"} style={{ padding: "7px 8px", borderRadius: 4, background: fi === i ? "var(--paper-3)" : "transparent", cursor: "pointer" }} onClick={() => setFolder(i)}>
                <Icon name="folder" size={15} style={{ color: "var(--slate)", flex: "none" }} />
                <span className="small" style={{ flex: 1, fontWeight: fi === i ? 600 : 400 }}>{f.folder}</span>
                <span className="xsmall muted">{f.files.length}</span>
                <button className="btn ghost sm" style={{ padding: "2px 6px", height: 24 }} onClick={(e) => { e.stopPropagation(); renameFolder(i); }}><Icon name="edit" size={12} /></button>
                <button className="btn ghost sm danger" style={{ padding: "2px 6px", height: 24 }} onClick={(e) => { e.stopPropagation(); removeFolder(i); }}><Icon name="trash" size={12} /></button>
              </div>
            ))}
          </div>
          <button className="btn ghost sm block" style={{ marginTop: 12 }} onClick={addFolder}><Icon name="plus" size={14} /> Add folder</button>
        </div>

        <div className="card" style={{ overflow: "hidden" }}>
          <div className="row jb ac" style={{ padding: "14px 18px", borderBottom: "1px solid var(--line)" }}>
            <h3 className="h3">{cur.folder || "—"}</h3>
            <div className="row gap8"><button className="btn ghost sm" onClick={addManual}><Icon name="plus" size={14} /> Add entry</button><button className="btn sm" onClick={() => fileRef.current.click()}><Icon name="upload" size={14} /> Upload files</button></div>
          </div>
          <table className="ledger">
            <thead><tr><th>Name</th><th>Scan</th><th>Type</th><th className="num">Size</th><th className="num">Updated</th><th></th></tr></thead>
            <tbody>
              {cur.files.map((f, k) => (
                <tr key={k}>
                  <td><div className="row gap10 ac"><Icon name={f.t === "XLSX" ? "grid" : "doc"} size={17} style={{ color: f.t === "XLSX" ? "var(--avail)" : "var(--navy)", flex: "none" }} /> <div><span className="b6">{f.n}</span>{f.scanResult && <div className="xsmall muted">{f.scanResult}</div>}</div></div></td>
                  <td><ScanTag status={f.scanStatus} /></td>
                  <td className="muted small">{f.t}</td><td className="num small tnum">{f.s}</td><td className="num small muted tnum">{f.d}</td>
                  <td className="num"><button className="btn ghost sm danger" onClick={() => removeFile(k)}><Icon name="trash" size={13} /></button></td>
                </tr>
              ))}
              {cur.files.length === 0 && <tr><td colSpan="6" className="muted" style={{ textAlign: "center", padding: 28 }}>No files in this folder yet.</td></tr>}
            </tbody>
          </table>
          <input ref={fileRef} type="file" multiple onChange={addFiles} style={{ display: "none" }} />
        </div>
      </div>
    </AdminShell>
  );
}

Object.assign(window, { AdminDashboard, AdminListings, AdminListingEdit, AdminLaunch, AdminContacts, AdminMessages, AdminAnalytics, AdminInbox, AdminUsers, AdminSecurity, AccountScreen, AdminMedia, AdminBranding, AdminRequests, AdminQA, AdminContent, AdminDataRoom, AdminAudit });
