// Signed-in layer for the Open Marketplace.
// Loads AFTER open-marketplace.jsx. Exposes window.RLS.
// Storage: rl-user (from Simple Signup), rl-saved, rl-my-listings,
//          rl-messages, rl-requests.

const { useState, useEffect, useRef } = React;

// ── Storage helpers ──────────────────────────────────────────────────────
function rlsRead(k, d) {
  try { const v = JSON.parse(localStorage.getItem(k)); return v == null ? d : v; }
  catch (e) { return d; }
}
function rlsWrite(k, v) { try { localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} }

// ── Session ──────────────────────────────────────────────────────────────
function rlsUser() {
  try {
    const raw = localStorage.getItem("rl-user");
    if (!raw) return null;
    let u; try { u = JSON.parse(raw); } catch (e) { u = { name: raw }; }
    if (typeof u === "string") u = { name: u };
    if (!u || (!u.name && !u.company)) return null;
    return { name: u.name || "Mike", company: u.company || u.name || "My Roofing Co." };
  } catch (e) { return null; }
}
const RLS_USER = rlsUser();

// Register "you" as a seller so your listings render with the shared card components
if (RLS_USER && window.MP_SELLERS && !window.MP_SELLERS.you) {
  window.MP_SELLERS.you = {
    name: RLS_USER.company, type: "Contractor", rating: 5.0, reviews: 1,
    verified: true, member: false, resp: "~1 hr",
    grad: "linear-gradient(140deg,#2C4A3E,#6B8A66)",
  };
}

// ── Saved ────────────────────────────────────────────────────────────────
function rlsSavedIds() { return rlsRead("rl-saved", []); }
function rlsIsSaved(id) { return rlsSavedIds().includes(id); }
function rlsToggleSaved(id) {
  const ids = rlsSavedIds();
  const next = ids.includes(id) ? ids.filter(x => x !== id) : [id, ...ids];
  rlsWrite("rl-saved", next);
  return next.includes(id);
}

// ── My listings ──────────────────────────────────────────────────────────
function rlsMyListings() {
  const ls = rlsRead("rl-my-listings", []);
  ls.forEach(l => {
    if (window.MP_PHOTOS && !window.MP_PHOTOS[l.id]) {
      if (l.img) window.MP_PHOTOS[l.id] = l.img;
      else if (l.photoOf) window.MP_PHOTOS[l.id] = window.MP_PHOTOS[l.photoOf];
    }
  });
  return ls;
}
function rlsSaveMyListings(ls) { rlsWrite("rl-my-listings", ls); }
function rlsWithMine(kind, base) {
  if (!RLS_USER) return base;
  const mine = rlsMyListings().filter(l => l.kind === kind && !l.sold);
  return mine.concat(base);
}
function rlsAllItems() {
  return rlsMyListings().concat(window.MP_MATERIALS || [], window.MP_MACHINERY || []);
}

// ── Messages ─────────────────────────────────────────────────────────────
function rlsThreads() { return rlsRead("rl-messages", {}); }
function rlsThread(sellerId) { return rlsThreads()[sellerId] || []; }
function rlsAppendMsg(sellerId, msg) {
  const t = rlsThreads();
  t[sellerId] = (t[sellerId] || []).concat([msg]);
  rlsWrite("rl-messages", t);
  return t[sellerId];
}

// ── Requests ─────────────────────────────────────────────────────────────
function rlsRequests() { return rlsRead("rl-requests", []); }
function rlsAddRequest(r) { const all = [r, ...rlsRequests()]; rlsWrite("rl-requests", all); return all; }

// ── One-time CSS ─────────────────────────────────────────────────────────
if (!document.getElementById("rls-styles")) {
  const s = document.createElement("style");
  s.id = "rls-styles";
  s.textContent = `
    .rls-drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(400px, 100vw); z-index: 90;
      background: var(--bg-card); border-left: 1px solid var(--border);
      box-shadow: -12px 0 40px rgba(27,24,20,0.14); display: flex; flex-direction: column; }
    @media (prefers-reduced-motion: no-preference) {
      .rls-drawer { animation: rlsSlide .32s cubic-bezier(.2,.8,.3,1) both; }
      .rls-msg { animation: rlsMsgIn .3s cubic-bezier(.2,.7,.3,1) both; }
    }
    @keyframes rlsSlide { from { transform: translateX(100%); } to { transform: none; } }
    @keyframes rlsMsgIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
    .rls-bubble { max-width: 78%; padding: 9px 13px; border-radius: 14px; font-size: 14px; line-height: 1.4; }
    .rls-bubble.me { background: var(--text-1); color: #FBF7EB; border-bottom-right-radius: 4px; margin-left: auto; }
    .rls-bubble.them { background: var(--bg-card-soft); border: 1px solid var(--border-soft); border-bottom-left-radius: 4px; }
    .rls-typing span { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--text-3);
      margin-right: 3px; animation: rlsBlink 1.1s infinite; }
    .rls-typing span:nth-child(2) { animation-delay: .18s; } .rls-typing span:nth-child(3) { animation-delay: .36s; }
    @keyframes rlsBlink { 0%, 60%, 100% { opacity: .3; } 30% { opacity: 1; } }
    .rls-menu { position: absolute; top: calc(100% + 8px); right: 0; min-width: 210px; z-index: 80;
      background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px;
      box-shadow: 0 12px 36px rgba(27,24,20,0.16); padding: 6px; }
    .rls-menu a, .rls-menu button { display: flex; align-items: center; gap: 10px; width: 100%;
      padding: 9px 12px; border: none; background: transparent; border-radius: 8px; cursor: pointer;
      font-family: var(--sans); font-size: 14px; color: var(--text-1); text-decoration: none; text-align: left; }
    .rls-menu a:hover, .rls-menu button:hover { background: var(--bg-hover); color: var(--text-1); }
    .rls-avatar { width: 36px; height: 36px; border-radius: 50%; border: none; cursor: pointer; flex-shrink: 0;
      background: linear-gradient(140deg,#2C4A3E,#6B8A66); color: #F4E9CC;
      display: grid; place-items: center; font-weight: 600; font-size: 13px; font-family: var(--sans); }
    .rls-check { width: 64px; height: 64px; border-radius: 50%; background: var(--green-soft);
      display: grid; place-items: center; margin: 0 auto 14px; }
    @media (prefers-reduced-motion: no-preference) { .rls-check { animation: mpxSpring .45s cubic-bezier(.34,1.5,.5,1) both; } }
    .rls-photo-pick { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
    .rls-photo-pick button { border: 2px solid transparent; border-radius: 10px; padding: 0; overflow: hidden;
      aspect-ratio: 16/11; cursor: pointer; background: var(--bg-card-soft); }
    .rls-photo-pick button.on { border-color: var(--gold-dark); }
    .rls-photo-pick img { width: 100%; height: 100%; object-fit: cover; display: block; }
  `;
  document.head.appendChild(s);
}

// ── Chat drawer ──────────────────────────────────────────────────────────
const RLS_REPLIES = [
  "Yes, it's still available. When do you need it?",
  "Can do — pickup is off Country Club Dr in Mesa.",
  "If you take the whole lot I'll knock 10% off.",
  "\uD83D\uDC4D Sounds good. Anything else you need for the job?",
];

function ChatDrawer({ sellerId, onClose }) {
  const seller = MP_SELLERS[sellerId];
  const [msgs, setMsgs] = useState(() => rlsThread(sellerId));
  const [draft, setDraft] = useState("");
  const [typing, setTyping] = useState(false);
  const endRef = useRef(null);
  useEffect(() => { if (endRef.current) endRef.current.scrollTop = endRef.current.scrollHeight; }, [msgs, typing]);
  if (!seller) return null;

  const send = () => {
    const text = draft.trim();
    if (!text) return;
    setDraft("");
    const mine = rlsAppendMsg(sellerId, { from: "me", text, at: Date.now() });
    setMsgs(mine.slice());
    setTyping(true);
    const replyIdx = mine.filter(m => m.from === "them").length % RLS_REPLIES.length;
    setTimeout(() => {
      setTyping(false);
      const next = rlsAppendMsg(sellerId, { from: "them", text: RLS_REPLIES[replyIdx], at: Date.now() });
      setMsgs(next.slice());
    }, 1500);
  };

  return (
    <div className="rls-drawer" data-screen-label={"Chat with " + seller.name}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "14px 16px", borderBottom: "1px solid var(--border-soft)" }}>
        <SellerAvatar seller={seller} size={36} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontWeight: 600, fontSize: 14.5 }}>{seller.name}</div>
          <div style={{ fontSize: 12, color: "var(--text-3)" }}>Usually responds {seller.resp}</div>
        </div>
        <button className="btn ghost sm" onClick={onClose} aria-label="Close chat">✕</button>
      </div>
      <div ref={endRef} style={{ flex: 1, overflowY: "auto", padding: 16, display: "flex", flexDirection: "column", gap: 8 }}>
        {msgs.length === 0 && (
          <div style={{ textAlign: "center", color: "var(--text-3)", fontSize: 13, padding: "30px 12px" }}>
            Say hello — ask about availability, price, or pickup.
          </div>
        )}
        {msgs.map((m, i) => <div key={i} className={"rls-bubble rls-msg " + (m.from === "me" ? "me" : "them")}>{m.text}</div>)}
        {typing && <div className="rls-bubble them rls-typing"><span></span><span></span><span></span></div>}
      </div>
      <div style={{ display: "flex", gap: 8, padding: 14, borderTop: "1px solid var(--border-soft)" }}>
        <input className="filter-input" style={{ flex: 1, maxWidth: "none" }} placeholder="Write a message…"
               value={draft} onChange={e => setDraft(e.target.value)}
               onKeyDown={e => { if (e.key === "Enter") send(); }} autoFocus />
        <button className="btn primary" onClick={send} disabled={!draft.trim()}>Send</button>
      </div>
    </div>
  );
}

// ── Request to buy / rent ────────────────────────────────────────────────
function RequestModal({ item, onClose }) {
  const seller = MP_SELLERS[item.seller];
  const isRental = item.cond === "Rental";
  const [qty, setQty] = useState(isRental ? 1 : 10);
  const [start, setStart] = useState("");
  const [note, setNote] = useState("");
  const [done, setDone] = useState(false);
  const total = item.price * qty;

  const submit = () => {
    rlsAddRequest({
      id: "req" + Date.now(), itemId: item.id, title: item.title, seller: item.seller,
      qty, start: start || "Flexible", note, total, unit: item.unit,
      kind: isRental ? "Rental" : "Purchase", status: "Sent", at: Date.now(),
    });
    setDone(true);
  };

  return (
    <div className="modal-overlay mpx-overlay-in" onClick={onClose}>
      <div className="modal mpx-modal-in" style={{ maxWidth: 440 }} onClick={e => e.stopPropagation()}>
        {done ? (
          <div style={{ padding: "34px 30px 28px", textAlign: "center" }}>
            <div className="rls-check">
              <svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="var(--green)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
            </div>
            <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 24 }}>Request sent!</div>
            <div style={{ fontSize: 14, color: "var(--text-2)", marginTop: 8, lineHeight: 1.5 }}>
              {seller.name} usually responds {seller.resp}. We'll ping you the moment they reply.
            </div>
            <div style={{ display: "flex", gap: 8, marginTop: 20, justifyContent: "center" }}>
              <a className="btn" href="account.html">View my requests</a>
              <button className="btn primary" onClick={onClose}>Keep browsing</button>
            </div>
          </div>
        ) : (
          <div style={{ padding: "24px 26px 22px" }}>
            <div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
              <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 22 }}>{isRental ? "Request to rent" : "Request to buy"}</div>
              <button className="btn ghost sm" onClick={onClose} aria-label="Close">✕</button>
            </div>
            <div style={{ fontSize: 13.5, color: "var(--text-2)", marginTop: 4 }}>{item.title} — ${item.price}{item.unit} · {seller.name}</div>
            <div style={{ display: "flex", flexDirection: "column", gap: 12, marginTop: 18 }}>
              <div className="field">
                <span className="field-label">{isRental ? "How many days?" : "How many " + item.unit.replace("/", "") + "s?"}</span>
                <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
                  <button className="btn" onClick={() => setQty(q => Math.max(1, q - 1))}>−</button>
                  <input className="input" style={{ width: 80, textAlign: "center" }} value={qty}
                         onChange={e => setQty(Math.max(1, parseInt(e.target.value) || 1))} />
                  <button className="btn" onClick={() => setQty(q => q + 1)}>+</button>
                  <span style={{ marginLeft: "auto", fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 22 }}>${total.toLocaleString()}</span>
                </div>
              </div>
              {isRental && (
                <div className="field">
                  <span className="field-label">Start date</span>
                  <input className="input" type="date" value={start} onChange={e => setStart(e.target.value)} />
                </div>
              )}
              <div className="field">
                <span className="field-label">Note to seller (optional)</span>
                <textarea className="textarea" rows="2" placeholder={isRental ? "Job site address, delivery needs…" : "Pickup time, questions…"}
                          value={note} onChange={e => setNote(e.target.value)}></textarea>
              </div>
              <button className="btn gold" style={{ justifyContent: "center", padding: "12px", fontSize: 15 }} onClick={submit}>
                Send request — ${total.toLocaleString()}
              </button>
              <div style={{ fontSize: 12, color: "var(--text-3)", textAlign: "center" }}>No charge yet — the seller confirms first.</div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Post a listing ───────────────────────────────────────────────────────
const RLS_PHOTO_OPTS = [
  { key: "m1", label: "Shingles" }, { key: "m3", label: "Underlayment" }, { key: "m5", label: "Pallet" },
  { key: "q1", label: "Lift" }, { key: "q2", label: "Hoist" }, { key: "q4", label: "Trailer" },
];

function PostListingModal({ onClose, onPublished }) {
  const [kind, setKind] = useState("materials");
  const [title, setTitle] = useState("");
  const [detail, setDetail] = useState("");
  const [price, setPrice] = useState("");
  const [cat, setCat] = useState("Shingles");
  const [photoOf, setPhotoOf] = useState("m1");
  const [done, setDone] = useState(false);
  const cats = (kind === "materials" ? MP_MATERIAL_CATS : MP_MACHINERY_CATS).filter(c => c !== "All");
  const unit = kind === "materials" ? "/bundle" : "/day";
  const canPost = title.trim() && parseFloat(price) > 0;

  const publish = () => {
    const id = "u" + Date.now();
    const item = {
      id, title: title.trim(), detail: detail.trim() || "Posted just now",
      price: Math.round(parseFloat(price)), unit,
      cond: kind === "materials" ? "Surplus" : "Rental",
      cat: cats.includes(cat) ? cat : cats[0],
      loc: "Mesa, AZ", dist: 0, seller: "you",
      thumb: "shingle-charcoal", photoOf, kind, sold: false, at: Date.now(),
    };
    window.MP_PHOTOS[id] = window.MP_PHOTOS[photoOf];
    rlsSaveMyListings([item, ...rlsMyListings()]);
    setDone(true);
  };

  return (
    <div className="modal-overlay mpx-overlay-in" onClick={onClose}>
      <div className="modal mpx-modal-in" style={{ maxWidth: 460 }} onClick={e => e.stopPropagation()}>
        {done ? (
          <div style={{ padding: "34px 30px 28px", textAlign: "center" }}>
            <div className="rls-check">
              <svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="var(--green)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
            </div>
            <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 24 }}>You're live!</div>
            <div style={{ fontSize: 14, color: "var(--text-2)", marginTop: 8 }}>
              Your listing is on the marketplace with a "JUST LISTED" badge. Buyers within 25 mi will see it first.
            </div>
            <button className="btn gold" style={{ marginTop: 20 }} onClick={() => { onPublished(kind); onClose(); }}>See it in the grid →</button>
          </div>
        ) : (
          <div style={{ padding: "24px 26px 22px" }}>
            <div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
              <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 22 }}>Post a listing</div>
              <button className="btn ghost sm" onClick={onClose} aria-label="Close">✕</button>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 12, marginTop: 16 }}>
              <div className="mpx-roleseg" style={{ alignSelf: "flex-start" }}>
                <button className={kind === "materials" ? "active" : ""} onClick={() => { setKind("materials"); setCat("Shingles"); setPhotoOf("m1"); }}>Sell materials</button>
                <button className={kind === "machinery" ? "active" : ""} onClick={() => { setKind("machinery"); setCat("Lifts"); setPhotoOf("q1"); }}>Rent out machinery</button>
              </div>
              <div className="field">
                <span className="field-label">Title</span>
                <input className="input" placeholder={kind === "materials" ? "e.g. Architectural shingles — Charcoal" : "e.g. Ladder hoist — 28 ft"}
                       value={title} onChange={e => setTitle(e.target.value)} autoFocus />
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
                <div className="field">
                  <span className="field-label">Price ({unit})</span>
                  <input className="input" type="number" min="1" placeholder="28" value={price} onChange={e => setPrice(e.target.value)} />
                </div>
                <div className="field">
                  <span className="field-label">Category</span>
                  <select className="select" value={cat} onChange={e => setCat(e.target.value)}>
                    {cats.map(c => <option key={c}>{c}</option>)}
                  </select>
                </div>
              </div>
              <div className="field">
                <span className="field-label">Details (optional)</span>
                <input className="input" placeholder={kind === "materials" ? "42 bundles · GAF Timberline HDZ" : "400 lb capacity · gas"}
                       value={detail} onChange={e => setDetail(e.target.value)} />
              </div>
              <div className="field">
                <span className="field-label">Photo</span>
                <div className="rls-photo-pick">
                  {RLS_PHOTO_OPTS.map(p => (
                    <button key={p.key} className={photoOf === p.key ? "on" : ""} onClick={() => setPhotoOf(p.key)} aria-label={p.label}>
                      <img src={MP_PHOTOS[p.key]} alt={p.label} loading="lazy" />
                    </button>
                  ))}
                </div>
              </div>
              <button className="btn gold" style={{ justifyContent: "center", padding: "12px", fontSize: 15 }} disabled={!canPost} onClick={publish}>
                Publish listing
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Avatar menu ──────────────────────────────────────────────────────────
function AccountMenu({ user, onGoTab }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    const close = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", close);
    return () => document.removeEventListener("mousedown", close);
  }, []);
  const initials = user.name.split(" ").map(w => w[0]).slice(0, 2).join("").toUpperCase();
  return (
    <div ref={ref} style={{ position: "relative" }}>
      <button className="rls-avatar" onClick={() => setOpen(o => !o)} aria-label="Account menu">{initials}</button>
      {open && (
        <div className="rls-menu mpx-modal-in">
          <div style={{ padding: "8px 12px 6px", borderBottom: "1px solid var(--border-soft)", marginBottom: 4 }}>
            <div style={{ fontWeight: 600, fontSize: 14 }}>{user.name}</div>
            {user.company !== user.name && <div style={{ fontSize: 12, color: "var(--text-3)" }}>{user.company}</div>}
          </div>
          <a href="account.html">📊 My dashboard</a>
          <a href="account.html">🧰 My tools</a>
          <button onClick={() => { setOpen(false); onGoTab("inbox"); }}>💬 Messages</button>
          <button onClick={() => { setOpen(false); onGoTab("saved"); }}>♡ Saved items</button>
          <button onClick={() => { setOpen(false); onGoTab("mine"); }}>🏷 My listings</button>
          <div style={{ borderTop: "1px solid var(--border-soft)", margin: "4px 0" }}></div>
          <button onClick={() => { localStorage.removeItem("rl-user"); window.location.reload(); }}>Sign out</button>
        </div>
      )}
    </div>
  );
}

// ── Incoming requests on YOUR listings ──
function rlsIncoming() { return rlsRead("rl-incoming", []); }
function rlsSaveIncoming(v) { rlsWrite("rl-incoming", v); }
function rlsEnsureIncoming() {
  const buyers = ["cardenas", "halcon", "summit", "torres", "diaz"];
  const notes = {
    job: "I'd like to apply — 6 yrs on residential crews.",
    crew: "Do you have availability the week of the 20th?",
    work: "We're hiring — can you start Monday?",
    wanted: "I've got these in my yard — want photos?",
  };
  const inc = rlsIncoming();
  let changed = false;
  rlsMyListings().filter(l => !l.sold).forEach((l, i) => {
    if (!inc.some(r => r.listingId === l.id)) {
      const qty = l.unit === "/day" ? 2 : 8;
      inc.push({
        id: "in-" + l.id, listingId: l.id, from: buyers[i % buyers.length],
        qty, total: (l.price || 0) * qty,
        note: notes[l.postType] || "Is this still available?",
        at: Date.now() - 1000 * 60 * (7 + i * 13), status: "new",
      });
      changed = true;
    }
  });
  if (changed) rlsSaveIncoming(inc);
  return inc;
}
function rlsSetIncomingStatus(id, status) {
  const inc = rlsIncoming().map(r => r.id === id ? { ...r, status } : r);
  rlsSaveIncoming(inc);
  return inc;
}
function rlsTimeAgo(ts) {
  const m = Math.max(1, Math.round((Date.now() - ts) / 60000));
  if (m < 60) return m + " min";
  const h = Math.round(m / 60);
  return h < 24 ? h + " hr" : Math.round(h / 24) + " d";
}

// ── Saved tab ────────────────────────────────────────────────────────────
function SavedTab({ onOpen, onGoTab }) {
  const [ids, setIds] = useState(rlsSavedIds());
  useEffect(() => { setIds(rlsSavedIds()); }, []);
  const all = rlsAllItems();
  const items = ids.map(id => all.find(it => it.id === id)).filter(Boolean);
  const Card = window.ListingCardGrid;
  if (items.length === 0) return (
    <div style={{ textAlign: "center", padding: "70px 20px", color: "var(--text-2)" }}>
      <div style={{ fontSize: 40 }}>♡</div>
      <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 24, marginTop: 8 }}>Nothing saved yet</div>
      <div style={{ fontSize: 14, marginTop: 6 }}>Tap the heart on any listing and it'll live here.</div>
      <button className="btn gold" style={{ marginTop: 18 }} onClick={() => onGoTab("materials")}>Browse materials</button>
    </div>
  );
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(240px, 1fr))", gap: 16 }}>
      {items.map((it, i) => <Card key={it.id} item={it} onOpen={onOpen} onGate={() => {}} index={i} />)}
    </div>
  );
}

// ── Messages / inbox tab ──
function InboxTab({ onOpenChat, onGoTab }) {
  const threads = Object.entries(rlsThreads()).filter(([, m]) => m.length > 0)
    .sort((a, b) => b[1][b[1].length - 1].at - a[1][a[1].length - 1].at);
  if (threads.length === 0) return (
    <div style={{ textAlign: "center", padding: "70px 20px", color: "var(--text-2)" }}>
      <div style={{ fontSize: 40 }}>💬</div>
      <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 24, marginTop: 8 }}>No conversations yet</div>
      <div style={{ fontSize: 14, marginTop: 6 }}>Message any seller from a listing — it lands here.</div>
      <button className="btn gold" style={{ marginTop: 18 }} onClick={() => onGoTab("materials")}>Browse listings</button>
    </div>
  );
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10, maxWidth: 720 }}>
      {threads.map(([sid, msgs], i) => {
        const s = MP_SELLERS[sid];
        if (!s) return null;
        const last = msgs[msgs.length - 1];
        return (
          <div key={sid} className="mpx-row mpx-click mpx-enter" style={{ alignItems: "center", animationDelay: (i * 45) + "ms" }}
               onClick={() => onOpenChat(sid)}>
            <SellerAvatar seller={s} size={46} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: "flex", gap: 8, alignItems: "baseline" }}>
                <span style={{ fontSize: 15.5, fontWeight: 600 }}>{s.name}</span>
                <span style={{ fontSize: 12, color: "var(--text-3)", marginLeft: "auto", flexShrink: 0 }}>{rlsTimeAgo(last.at)} ago</span>
              </div>
              <div style={{ fontSize: 13.5, color: "var(--text-2)", marginTop: 3, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                {last.from === "me" ? "You: " : ""}{last.text}
              </div>
            </div>
            <span style={{ color: "var(--text-3)", flexShrink: 0 }}>›</span>
          </div>
        );
      })}
    </div>
  );
}

// ── My listing detail: view / edit / incoming requests ──
function MyListingModal({ item, onClose, onSaved, onChat }) {
  const [editing, setEditing] = useState(false);
  const [title, setTitle] = useState(item.title);
  const [price, setPrice] = useState(item.price);
  const [detail, setDetail] = useState(item.detail);
  const [inc, setInc] = useState(() => rlsEnsureIncoming().filter(r => r.listingId === item.id));
  const views = 14 + (parseInt(item.id.replace(/\D/g, "").slice(-3)) || 0) % 87;
  const saves = 1 + views % 7;

  const save = () => {
    const next = rlsMyListings().map(l => l.id === item.id
      ? { ...l, title: title.trim() || l.title, price: Math.round(parseFloat(price)) || 0, detail: detail.trim() }
      : l);
    rlsSaveMyListings(next);
    setEditing(false);
    onSaved(next);
  };

  const act = (rid, status, from) => {
    setInc(rlsSetIncomingStatus(rid, status).filter(r => r.listingId === item.id));
    if (status === "accepted" && onChat) {
      rlsAppendMsg(from, { from: "me", text: "Request accepted — " + item.title + ". When works for pickup?", at: Date.now() });
    }
  };

  return (
    <div className="modal-overlay mpx-overlay-in" onClick={onClose}>
      <div className="modal mpx-modal-in" style={{ maxWidth: 560, maxHeight: "92vh", overflowY: "auto" }} onClick={e => e.stopPropagation()}>
        <div style={{ height: 180, position: "relative", background: "var(--bg-card-soft)" }}>
          <MPPhoto item={item} />
          <button className="btn sm" style={{ position: "absolute", top: 12, right: 12 }} onClick={onClose} aria-label="Close">✕</button>
          <span className="chip gold" style={{ position: "absolute", left: 12, top: 12 }}>{item.chip || (item.cond === "Rental" ? "Rental" : "For sale")}</span>
        </div>
        <div style={{ padding: "18px 24px 22px" }}>
          {editing ? (
            <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
              <div className="field"><span className="field-label">Title</span>
                <input className="input" value={title} onChange={e => setTitle(e.target.value)} autoFocus /></div>
              <div className="field" style={{ maxWidth: 180 }}><span className="field-label">Price ({item.unit || "each"})</span>
                <input className="input" type="number" min="0" value={price} onChange={e => setPrice(e.target.value)} /></div>
              <div className="field"><span className="field-label">Details</span>
                <textarea className="textarea" rows="2" value={detail} onChange={e => setDetail(e.target.value)}></textarea></div>
              <div style={{ display: "flex", gap: 8 }}>
                <button className="btn gold" onClick={save}>Save changes</button>
                <button className="btn" onClick={() => setEditing(false)}>Cancel</button>
              </div>
            </div>
          ) : (
            <React.Fragment>
              <div style={{ display: "flex", justifyContent: "space-between", gap: 12, alignItems: "flex-start" }}>
                <div>
                  <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 24, lineHeight: 1.15 }}>{item.title}</div>
                  {item.price > 0 && <div style={{ fontSize: 18, fontWeight: 700, marginTop: 6 }}>${item.price}<span style={{ fontSize: 13, color: "var(--text-3)", fontWeight: 400 }}>{item.unit}</span></div>}
                  <div style={{ fontSize: 13.5, color: "var(--text-2)", marginTop: 6 }}>{item.detail}</div>
                </div>
                <button className="btn sm" onClick={() => setEditing(true)}>✎ Edit</button>
              </div>
              <div style={{ display: "flex", gap: 18, marginTop: 14, padding: "10px 0", borderTop: "1px solid var(--border-soft)", borderBottom: "1px solid var(--border-soft)" }}>
                {[[views, "views"], [saves, "saves"], [inc.length, "requests"]].map(([n, l]) => (
                  <span key={l} style={{ fontSize: 13, color: "var(--text-2)" }}>
                    <b style={{ fontSize: 17, fontFamily: "var(--serif)", fontStyle: "italic" }}>{n}</b> {l}
                  </span>
                ))}
              </div>
            </React.Fragment>
          )}

          {!editing && (
            <div style={{ marginTop: 14 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: "var(--text-2)", marginBottom: 8 }}>Requests on this listing</div>
              {inc.length === 0 && <div style={{ fontSize: 13, color: "var(--text-3)" }}>None yet — buyers nearby will see it first.</div>}
              <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                {inc.map(r => {
                  const buyer = MP_SELLERS[r.from];
                  return (
                    <div key={r.id} className="mpx-row rls-msg" style={{ alignItems: "center", padding: "10px 12px" }}>
                      <SellerAvatar seller={buyer} size={36} />
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 14, fontWeight: 600 }}>{buyer.name}
                          {r.total > 0 && <span style={{ fontWeight: 400, color: "var(--text-2)" }}> · ${r.total.toLocaleString()}</span>}
                          <span style={{ fontWeight: 400, fontSize: 12, color: "var(--text-3)" }}> · {rlsTimeAgo(r.at)} ago</span>
                        </div>
                        <div style={{ fontSize: 12.5, color: "var(--text-2)", marginTop: 2 }}>{r.note}</div>
                      </div>
                      <div style={{ display: "flex", gap: 6, flexShrink: 0 }}>
                        {r.status === "new" ? (
                          <React.Fragment>
                            <button className="btn gold sm" onClick={() => act(r.id, "accepted", r.from)}>Accept</button>
                            <button className="btn sm" onClick={() => act(r.id, "declined")}>Decline</button>
                          </React.Fragment>
                        ) : r.status === "accepted" ? (
                          <React.Fragment>
                            <span className="chip green">Accepted</span>
                            <button className="btn sm" onClick={() => { onClose(); onChat && onChat(r.from); }}>Message</button>
                          </React.Fragment>
                        ) : <span className="chip">Declined</span>}
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ── My listings tab ──────────────────────────────────────────────────────
function MyListingsTab({ onPost, onChat }) {
  const [ls, setLs] = useState(rlsMyListings());
  const [open, setOpen] = useState(null);
  const incAll = rlsEnsureIncoming();
  const update = next => { rlsSaveMyListings(next); setLs(next); };
  if (ls.length === 0) return (
    <div style={{ textAlign: "center", padding: "70px 20px", color: "var(--text-2)" }}>
      <div style={{ fontSize: 40 }}>🏷</div>
      <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 24, marginTop: 8 }}>You haven't listed anything yet</div>
      <div style={{ fontSize: 14, marginTop: 6 }}>Surplus shingles? A lift sitting idle? Turn it into money.</div>
      <button className="btn gold" style={{ marginTop: 18 }} onClick={onPost}>+ Post your first listing</button>
    </div>
  );
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 4 }}>
        <span style={{ fontSize: 14, color: "var(--text-2)" }}>{ls.filter(l => !l.sold).length} active · {ls.filter(l => l.sold).length} sold</span>
        <button className="btn primary sm" onClick={onPost}>+ Post a listing</button>
      </div>
      {ls.map(l => {
        const newReq = incAll.filter(r => r.listingId === l.id && r.status === "new").length;
        return (
        <div key={l.id} className="mpx-row mpx-click" style={{ alignItems: "center", opacity: l.sold ? 0.55 : 1 }} onClick={() => setOpen(l)}>
          <div style={{ width: 110, borderRadius: 8, overflow: "hidden", flexShrink: 0, aspectRatio: "16/11", position: "relative" }}><MPPhoto item={l} /></div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 15.5, fontWeight: 600 }}>{l.title}</div>
            <div style={{ fontSize: 13, color: "var(--text-3)", marginTop: 2 }}>{l.price > 0 ? "$" + l.price + l.unit : (l.chip || "")}{l.cat ? " · " + l.cat : ""}</div>
            <div style={{ display: "flex", gap: 6, marginTop: 6 }}>
              <span className={"chip " + (l.sold ? "" : "green")}>{l.sold ? (l.kind === "board" ? "Closed" : "Sold") : "Active"}</span>
              {newReq > 0 && <span className="chip gold">{newReq} new request{newReq > 1 ? "s" : ""}</span>}
            </div>
          </div>
          <div style={{ display: "flex", gap: 6, flexShrink: 0 }} onClick={e => e.stopPropagation()}>
            <button className="btn sm" onClick={() => update(ls.map(x => x.id === l.id ? { ...x, sold: !x.sold } : x))}>
              {l.sold ? "Relist" : (l.kind === "board" ? "Close" : "Mark sold")}
            </button>
            <button className="btn sm danger" onClick={() => update(ls.filter(x => x.id !== l.id))}>Delete</button>
          </div>
        </div>
        );
      })}
      {open && <MyListingModal item={ls.find(x => x.id === open.id) || open} onClose={() => setOpen(null)}
                               onSaved={next => setLs(next)} onChat={onChat} />}
    </div>
  );
}

window.RLS = {
  user: RLS_USER,
  read: rlsRead, write: rlsWrite,
  isSaved: rlsIsSaved, toggleSaved: rlsToggleSaved, savedIds: rlsSavedIds,
  myListings: rlsMyListings, saveMyListings: rlsSaveMyListings, withMine: rlsWithMine, allItems: rlsAllItems,
  threads: rlsThreads, thread: rlsThread,
  requests: rlsRequests,
  incoming: rlsIncoming, ensureIncoming: rlsEnsureIncoming,
  ChatDrawer, RequestModal, PostListingModal, AccountMenu, SavedTab, MyListingsTab, InboxTab, MyListingModal,
};
