// ===== panels.jsx — Breakdown, Settle, PersonDetail, Export, TripMenu =====

// ---------- Spending breakdown (donut) ----------
function Breakdown({ txns, people }) {
  const cats = useMemo(() => categoryTotals(txns), [txns]);
  const total = txns.reduce((s, t) => s + (Number(t.amount) || 0), 0);
  return (
    <div className="card" style={{ padding: 20 }}>
      <div className="label" style={{ marginBottom: 16 }}>Spending</div>
      {txns.length === 0 ? (
        <div style={{ fontSize: 13.5, color: "var(--faint)" }}>Log charges to see where the money goes.</div>
      ) : (
        <>
          <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
            <Donut segments={cats} total={total} size={140} thickness={18} centerLabel={money(total)} centerSub="total spend" />
            <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 9 }}>
              {cats.map((c) => (
                <div key={c.id} style={{ display: "flex", alignItems: "center", gap: 9 }}>
                  <span style={{ width: 9, height: 9, borderRadius: 3, background: c.color, flex: "none" }} />
                  <span style={{ flex: 1, minWidth: 0, fontSize: 12.5, color: "var(--muted)", lineHeight: 1.25 }}>{c.label}</span>
                  <span className="mono" style={{ fontSize: 12.5, fontWeight: 600, flex: "none", whiteSpace: "nowrap" }}>{money(c.value)}</span>
                  <span className="mono" style={{ fontSize: 11.5, color: "var(--faint)", minWidth: 38, textAlign: "right", flex: "none" }}>{pctOf(c.value, total)}%</span>
                </div>
              ))}
            </div>
          </div>
          <hr className="divider" style={{ margin: "16px 0 14px" }} />
          <div style={{ display: "flex", gap: 20, fontSize: 13, color: "var(--muted)" }}>
            <span><b className="mono" style={{ color: "var(--text)", fontWeight: 600 }}>{txns.length}</b> charges</span>
            <span><b className="mono" style={{ color: "var(--text)", fontWeight: 600 }}>{people.length}</b> people</span>
            {people.length > 0 && <span><b className="mono" style={{ color: "var(--text)", fontWeight: 600 }}>{money(total / people.length)}</b> / person</span>}
          </div>
        </>
      )}
    </div>
  );
}

// ---------- Settle up (with payment tracking) ----------
function SettlePanel({ people, txns, payments, canEdit, onAddPayment, onRemovePayment, onOpenPerson, onExport }) {
  const balances = useMemo(() => computeBalances(people, txns, payments), [people, txns, payments]);
  const transfers = useMemo(() => settle(balances), [balances]);
  const sorted = [...people].map((p, i) => ({ ...p, idx: i, bal: fromCents(balances[p.id] || 0) })).sort((a, b) => b.bal - a.bal);
  const anyActivity = txns.length > 0;
  const remaining = transfers.reduce((s, t) => s + t.amt, 0);
  const settledTotal = payments.reduce((s, p) => s + p.amt, 0);
  const grand = remaining + settledTotal;
  const pct = grand > 0 ? (settledTotal / grand) * 100 : (anyActivity ? 100 : 0);
  const maxAbs = Math.max(1, ...sorted.map((p) => Math.abs(p.bal)));
  const [showPaid, setShowPaid] = useState(false);

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
      {/* net balances */}
      <div className="card" style={{ padding: "18px 20px" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14 }}>
          <div className="label">Net balances</div>
          {anyActivity && <span style={{ fontSize: 11.5, color: "var(--faint)" }}>tap for detail</span>}
        </div>
        {!anyActivity ? (
          <div style={{ fontSize: 13.5, color: "var(--faint)" }}>Add charges to see who's up and who's down.</div>
        ) : (
          <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
            {sorted.map((p) => {
              const settled = Math.abs(p.bal) < 0.005;
              const col = settled ? "var(--muted)" : p.bal > 0 ? "var(--pos)" : "var(--neg)";
              const w = (Math.abs(p.bal) / maxAbs) * 100;
              return (
                <button key={p.id} onClick={() => onOpenPerson(p.id)} className="person-row"
                  style={{ display: "flex", alignItems: "center", gap: 12, padding: "7px 8px", borderRadius: 10, width: "100%", textAlign: "left" }}>
                  <Avatar person={p} idx={p.idx} size={32} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 5 }}>
                      <span style={{ fontWeight: 500, fontSize: 14.5 }}>{p.name}</span>
                      <span className="mono" style={{ fontWeight: 700, fontSize: 14.5, color: col, whiteSpace: "nowrap", marginLeft: 10 }}>
                        {settled ? "settled" : money(p.bal, { sign: true })}
                      </span>
                    </div>
                    <div style={{ height: 5, background: "var(--bg-2)", borderRadius: 99, overflow: "hidden" }}>
                      <div style={{ height: "100%", width: w + "%", background: col, borderRadius: 99, transition: "width 0.4s var(--ease)" }} />
                    </div>
                  </div>
                </button>
              );
            })}
            <div style={{ display: "flex", gap: 16, marginTop: 8, padding: "0 8px", fontSize: 12, color: "var(--faint)" }}>
              <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}><i style={{ width: 8, height: 8, borderRadius: 2, background: "var(--pos)" }} /> is owed</span>
              <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}><i style={{ width: 8, height: 8, borderRadius: 2, background: "var(--neg)" }} /> owes</span>
            </div>
          </div>
        )}
      </div>

      {/* settle up */}
      <div className="card" style={{ padding: "18px 20px" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 14 }}>
          <span style={{ color: "var(--accent)", display: "inline-flex" }}><Icon name="wallet" size={18} /></span>
          <span className="label" style={{ color: "var(--text)", fontSize: 12.5 }}>Settle up</span>
          {transfers.length > 0 && <span className="tag mono" style={{ marginLeft: "auto", color: "var(--accent)", borderColor: "var(--accent-line)", background: "var(--accent-quiet)" }}>{transfers.length} left</span>}
        </div>

        {!anyActivity ? (
          <div style={{ fontSize: 13.5, color: "var(--faint)" }}>The fewest-payments plan to zero everyone out will appear here.</div>
        ) : (
          <>
            {grand > 0 && (
              <div style={{ marginBottom: 16 }}>
                <div style={{ display: "flex", justifyContent: "space-between", fontSize: 12.5, marginBottom: 7 }}>
                  <span style={{ color: "var(--muted)" }}><b className="mono" style={{ color: "var(--pos)" }}>{money(settledTotal)}</b> settled</span>
                  <span style={{ color: "var(--muted)" }}><b className="mono" style={{ color: "var(--text)" }}>{money(remaining)}</b> to go</span>
                </div>
                <div style={{ height: 7, background: "var(--bg-2)", borderRadius: 99, overflow: "hidden" }}>
                  <div style={{ height: "100%", width: pct + "%", background: "var(--pos)", borderRadius: 99, transition: "width 0.45s var(--ease)" }} />
                </div>
              </div>
            )}

            {transfers.length === 0 ? (
              <div style={{ display: "flex", alignItems: "center", gap: 10, color: "var(--pos)", fontWeight: 600, fontSize: 14.5, padding: "4px 0 6px" }}>
                <Icon name="checkCircle" size={20} /> All square — everyone's paid up.
              </div>
            ) : (
              <div style={{ display: "flex", flexDirection: "column", gap: 9 }}>
                {transfers.map((t, i) => {
                  const from = people.find((p) => p.id === t.from), to = people.find((p) => p.id === t.to);
                  const fi = people.findIndex((p) => p.id === t.from), ti = people.findIndex((p) => p.id === t.to);
                  return (
                    <div key={i} className="rise" style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", background: "var(--bg-2)", border: "1px solid var(--border)", borderRadius: 11 }}>
                      <Avatar person={from} idx={fi} size={28} />
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 14, flexWrap: "wrap" }}>
                          <span style={{ fontWeight: 600 }}>{from?.name}</span>
                          <span style={{ color: "var(--accent)", display: "inline-flex" }}><Icon name="arrow" size={15} /></span>
                          <span style={{ fontWeight: 600 }}>{to?.name}</span>
                        </div>
                      </div>
                      <span className="mono display" style={{ fontWeight: 700, fontSize: 15.5 }}>{money(t.amt)}</span>
                      {canEdit && (
                        <button className="btn btn-icon" title="Mark as paid"
                          onClick={() => onAddPayment({ from: t.from, to: t.to, amt: t.amt })}
                          style={{ color: "var(--pos)", background: "var(--pos-quiet)" }}>
                          <Icon name="check" size={17} />
                        </button>
                      )}
                    </div>
                  );
                })}
              </div>
            )}

            {payments.length > 0 && (
              <div style={{ marginTop: 14 }}>
                <button className="btn btn-quiet btn-sm" style={{ width: "100%", justifyContent: "space-between", padding: "0 4px" }} onClick={() => setShowPaid((s) => !s)}>
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 7, color: "var(--muted)" }}>
                    <Icon name="checkCircle" size={16} /> Paid ({payments.length})
                  </span>
                  <span style={{ color: "var(--faint)", display: "inline-flex" }}><Icon name={showPaid ? "chevronUp" : "chevron"} size={16} /></span>
                </button>
                {showPaid && (
                  <div style={{ display: "flex", flexDirection: "column", gap: 7, marginTop: 9 }}>
                    {payments.map((pm) => {
                      const from = people.find((p) => p.id === pm.from), to = people.find((p) => p.id === pm.to);
                      return (
                        <div key={pm.id} style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 11px", borderRadius: 10, background: "var(--pos-quiet)", border: "1px solid transparent" }}>
                          <span style={{ color: "var(--pos)", display: "inline-flex" }}><Icon name="checkCircle" size={17} /></span>
                          <span style={{ flex: 1, fontSize: 13.5, color: "var(--muted)" }}>
                            <b style={{ color: "var(--text)", fontWeight: 600 }}>{from?.name}</b> paid <b style={{ color: "var(--text)", fontWeight: 600 }}>{to?.name}</b>
                          </span>
                          <span className="mono" style={{ fontWeight: 700, fontSize: 13.5 }}>{money(pm.amt)}</span>
                          {canEdit && <button className="btn btn-icon btn-quiet" style={{ width: 28, height: 28 }} title="Undo" onClick={() => onRemovePayment(pm.id)}><Icon name="undo" size={15} /></button>}
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>
            )}

            <button className="btn btn-ghost" style={{ width: "100%", marginTop: 16 }} onClick={onExport}>
              <Icon name="share" size={16} /> Export summary
            </button>
          </>
        )}
      </div>
    </div>
  );
}

// ---------- Per-person detail ----------
function PersonDetail({ personId, people, txns, payments, onClose }) {
  const idx = people.findIndex((p) => p.id === personId);
  const person = people[idx];
  const balances = useMemo(() => computeBalances(people, txns, payments), [people, txns, payments]);
  const transfers = useMemo(() => settle(balances), [balances]);
  const roll = useMemo(() => personRollup(personId, people, txns, payments), [personId, people, txns, payments]);
  const bal = fromCents(balances[personId] || 0);
  const settled = Math.abs(bal) < 0.005;
  const col = settled ? "var(--muted)" : bal > 0 ? "var(--pos)" : "var(--neg)";

  const mine = transfers.filter((t) => t.from === personId || t.to === personId);

  useEffect(() => {
    const h = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, []);

  return (
    <div className="modal-backdrop" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={{ maxWidth: 560 }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "20px 24px" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 13 }}>
            <Avatar person={person} idx={idx} size={42} />
            <div>
              <h2 className="display" style={{ fontSize: 19, fontWeight: 600 }}>{person?.name}</h2>
              <div className="mono" style={{ fontSize: 13.5, fontWeight: 600, color: col }}>
                {settled ? "All settled up" : bal > 0 ? `is owed ${money(bal)}` : `owes ${money(-bal)}`}
              </div>
            </div>
          </div>
          <button className="btn btn-icon btn-quiet" onClick={onClose} aria-label="Close"><Icon name="close" size={18} /></button>
        </div>
        <hr className="divider" />

        <div style={{ padding: 24, display: "flex", flexDirection: "column", gap: 22, maxHeight: "62vh", overflowY: "auto" }}>
          {/* stat trio */}
          <div className="stat-trio" style={{ display: "grid", gridTemplateColumns: "minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr)", gap: 10 }}>
            {[["Paid out", money(roll.paid), "var(--text)"], ["Their share", money(roll.owed), "var(--text)"], ["Net", settled ? "—" : money(bal, { sign: true }), col]].map(([k, v, c], i) => (
              <div key={i} style={{ background: "var(--bg-2)", border: "1px solid var(--border)", borderRadius: 12, padding: "13px 14px" }}>
                <div className="label" style={{ fontSize: 10.5, marginBottom: 6 }}>{k}</div>
                <div className="mono display" style={{ fontSize: 18, fontWeight: 700, color: c }}>{v}</div>
              </div>
            ))}
          </div>

          {/* share of total spend */}
          {(() => {
            const total = txns.reduce((s, t) => s + (Number(t.amount) || 0), 0);
            const pct = pctOf(roll.owed, total);
            return (
              <div style={{ marginTop: -12, fontSize: 13, color: "var(--muted)" }}>
                Covers <b className="mono" style={{ color: "var(--text)" }}>{money(roll.owed)}</b> of the {money(total)} trip — <b style={{ color: "var(--accent)" }}>{pct}%</b> of total spend.
              </div>
            );
          })()}

          {/* to settle */}
          {mine.length > 0 && (
            <div>
              <div className="label" style={{ marginBottom: 10 }}>To settle</div>
              <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                {mine.map((t, i) => {
                  const isPayer = t.from === personId;
                  const other = people.find((p) => p.id === (isPayer ? t.to : t.from));
                  const oi = people.findIndex((p) => p.id === other.id);
                  return (
                    <div key={i} style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", background: "var(--bg-2)", border: "1px solid var(--border)", borderRadius: 11 }}>
                      <Avatar person={other} idx={oi} size={28} />
                      <span style={{ flex: 1, fontSize: 14 }}>
                        {isPayer ? <>Pay <b style={{ fontWeight: 600 }}>{other?.name}</b></> : <><b style={{ fontWeight: 600 }}>{other?.name}</b> pays you</>}
                      </span>
                      <span className="mono display" style={{ fontWeight: 700, fontSize: 15, color: isPayer ? "var(--neg)" : "var(--pos)" }}>{money(t.amt)}</span>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* charges */}
          <div>
            <div className="label" style={{ marginBottom: 10 }}>In these charges ({roll.inCharges.length})</div>
            {roll.inCharges.length === 0 ? (
              <div style={{ fontSize: 13.5, color: "var(--faint)" }}>Not part of any charge yet.</div>
            ) : (
              <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
                {roll.inCharges.map(({ txn, share, paid }) => (
                  <div key={txn.id} style={{ display: "flex", alignItems: "center", gap: 12, padding: "10px 4px", borderBottom: "1px solid var(--border)" }}>
                    <span style={{ width: 34, height: 34, borderRadius: 9, background: "var(--bg-2)", display: "flex", alignItems: "center", justifyContent: "center", flex: "none" }}><CatIcon id={txn.category} size={17} /></span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontWeight: 500, fontSize: 14, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{txn.description}</div>
                      <div style={{ fontSize: 12, color: "var(--faint)", display: "flex", gap: 8, alignItems: "center" }}>
                        <span>{fmtDate(txn.date)}</span>
                        {paid > 0 && <span className="tag" style={{ height: 18, fontSize: 10.5, padding: "0 6px", color: "var(--accent)", background: "var(--accent-quiet)", borderColor: "transparent" }}>paid {money(paid)}</span>}
                      </div>
                    </div>
                    <div style={{ textAlign: "right" }}>
                      <div className="mono" style={{ fontWeight: 600, fontSize: 14 }}>{money(share)}</div>
                      <div style={{ fontSize: 11, color: "var(--faint)" }}>their share</div>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

// ---------- Charge detail (read-only, tap a charge) ----------
function ChargeDetail({ txn, people, onClose }) {
  useEffect(() => {
    const h = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, []);
  const SPLIT_LABEL = { equal: "Split equally", exact: "Custom amounts", percent: "By percentage", shares: "By shares" };
  const total = toCents(txn.amount);
  const shares = computeShares(txn, people);
  const parts = txn.participants.filter((id) => people.some((p) => p.id === id));
  const cat = catOf(txn.category);
  const idxOf = (id) => people.findIndex((p) => p.id === id);
  const multi = txn.payers.length > 1;

  return (
    <div className="modal-backdrop" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={{ maxWidth: 560 }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "20px 24px", gap: 12 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 13, minWidth: 0 }}>
            <span style={{ width: 42, height: 42, borderRadius: 11, background: "var(--bg-2)", border: "1px solid var(--border)", display: "flex", alignItems: "center", justifyContent: "center", flex: "none" }}>
              <CatIcon id={txn.category} size={21} />
            </span>
            <div style={{ minWidth: 0 }}>
              <h2 className="display" style={{ fontSize: 19, fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{txn.description}</h2>
              <div style={{ fontSize: 13, color: "var(--faint)" }}>{fmtDate(txn.date)} · {cat.label}</div>
            </div>
          </div>
          <button className="btn btn-icon btn-quiet" onClick={onClose} aria-label="Close" style={{ flex: "none" }}><Icon name="close" size={18} /></button>
        </div>
        <hr className="divider" />

        <div style={{ padding: 24, display: "flex", flexDirection: "column", gap: 20, maxHeight: "66vh", overflowY: "auto" }}>
          <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 12, flexWrap: "wrap" }}>
            <div className="mono display" style={{ fontSize: 30, fontWeight: 700, letterSpacing: "-0.02em" }}>{money(txn.amount)}</div>
            <span className="tag">{SPLIT_LABEL[txn.splitMode] || "Split equally"} · {parts.length} {parts.length === 1 ? "person" : "people"}</span>
          </div>

          {txn.note && (
            <div style={{ background: "var(--accent-quiet)", border: "1px solid var(--accent-line)", borderRadius: 12, padding: "12px 14px", fontSize: 14, color: "var(--text)", lineHeight: 1.5, whiteSpace: "pre-wrap", wordBreak: "break-word" }}>
              {txn.note}
            </div>
          )}

          {/* paid by */}
          <div>
            <div className="label" style={{ marginBottom: 10 }}>Paid by</div>
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              {txn.payers.map((pay, i) => {
                const p = people.find((x) => x.id === pay.personId);
                return (
                  <div key={i} style={{ display: "flex", alignItems: "center", gap: 11, padding: "9px 12px", background: "var(--bg-2)", border: "1px solid var(--border)", borderRadius: 11 }}>
                    <Avatar person={p} idx={idxOf(pay.personId)} size={28} />
                    <span style={{ flex: 1, fontWeight: 500 }}>{p?.name || "—"}</span>
                    <span className="mono display" style={{ fontWeight: 700, fontSize: 15 }}>{money(multi ? pay.amount : txn.amount)}</span>
                  </div>
                );
              })}
            </div>
          </div>

          {/* split breakdown */}
          <div>
            <div className="label" style={{ marginBottom: 10 }}>Split between</div>
            <div className="card" style={{ background: "var(--bg-2)", padding: 6 }}>
              {parts.length === 0 ? (
                <div style={{ padding: "10px 12px", fontSize: 13.5, color: "var(--faint)" }}>Nobody is on this charge.</div>
              ) : parts.map((id) => {
                const p = people.find((x) => x.id === id);
                const c = shares[id] || 0;
                const pct = pctOf(c, total);
                return (
                  <div key={id} style={{ display: "flex", alignItems: "center", gap: 11, padding: "9px 10px" }}>
                    <Avatar person={p} idx={idxOf(id)} size={26} />
                    <span style={{ flex: 1, fontWeight: 500 }}>{p?.name}</span>
                    <span className="mono" style={{ fontSize: 12, color: "var(--faint)", marginRight: 8 }}>{pct}%</span>
                    <span className="mono" style={{ fontWeight: 700 }}>{money(fromCents(c))}</span>
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ---------- Export summary ----------
function ExportModal({ trip, onClose }) {
  const text = useMemo(() => buildSummary(trip), [trip]);
  const [copied, setCopied] = useState(false);

  const copy = async () => {
    try {
      await navigator.clipboard.writeText(text);
    } catch (e) {
      const ta = document.createElement("textarea");
      ta.value = text; ta.style.position = "fixed"; ta.style.opacity = "0";
      document.body.appendChild(ta); ta.select();
      try { document.execCommand("copy"); } catch (e2) {}
      document.body.removeChild(ta);
    }
    setCopied(true);
    setTimeout(() => setCopied(false), 1800);
  };
  const download = () => {
    const blob = new Blob([text], { type: "text/plain" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url; a.download = (trip.name || "trip").replace(/[^\w]+/g, "-").toLowerCase() + "-summary.txt";
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  };

  useEffect(() => {
    const h = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, []);

  return (
    <div className="modal-backdrop" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={{ maxWidth: 560 }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "20px 24px" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <span style={{ color: "var(--accent)", display: "inline-flex" }}><Icon name="share" size={20} /></span>
            <h2 className="display" style={{ fontSize: 19, fontWeight: 600 }}>Trip summary</h2>
          </div>
          <button className="btn btn-icon btn-quiet" onClick={onClose} aria-label="Close"><Icon name="close" size={18} /></button>
        </div>
        <hr className="divider" />
        <div style={{ padding: 24 }}>
          <pre className="mono" style={{ background: "var(--bg-2)", border: "1px solid var(--border)", borderRadius: 12, padding: 18, fontSize: 12.5, lineHeight: 1.7, color: "var(--text)", whiteSpace: "pre-wrap", wordBreak: "break-word", maxHeight: "50vh", overflowY: "auto", fontFamily: '"Space Grotesk", monospace' }}>{text}</pre>
        </div>
        <hr className="divider" />
        <div className="modal-foot foot-actions" style={{ display: "flex", justifyContent: "flex-end", gap: 10, padding: "16px 24px" }}>
          <button className="btn btn-ghost" onClick={download}><Icon name="download" size={16} /> Download .txt</button>
          <button className="btn btn-accent" onClick={copy} style={copied ? { background: "var(--pos)" } : undefined}>
            <Icon name={copied ? "check" : "copy"} size={16} /> {copied ? "Copied!" : "Copy summary"}
          </button>
        </div>
      </div>
    </div>
  );
}

// ---------- Trip switcher menu ----------
function TripMenu({ trips, activeId, onSwitch, onNew, onJoin, onDelete, onLeave, admin, adminEnabled, onAdmin, onExitAdmin }) {
  return (
    <Dropdown width={300} align="right"
      trigger={(open, toggle) => (
        <button className="btn btn-ghost" onClick={toggle}>
          <Icon name="folder" size={17} /> Trips
          <span style={{ display: "inline-flex", color: "var(--faint)" }}><Icon name={open ? "chevronUp" : "chevron"} size={15} /></span>
        </button>
      )}
    >
      {(close) => (
        <>
          {trips.map((t) => {
            const total = t.txns.reduce((s, x) => s + (Number(x.amount) || 0), 0);
            return (
              <div key={t.id} className="menu-item" style={{ background: t.id === activeId ? "var(--surface-2)" : "transparent", gap: 10 }}>
                <button style={{ display: "flex", alignItems: "center", gap: 10, flex: 1, minWidth: 0, textAlign: "left", background: "none" }} onClick={() => { onSwitch(t.id); close(); }}>
                  <span style={{ width: 30, height: 30, borderRadius: 8, background: t.id === activeId ? "var(--accent)" : "var(--surface-3)", color: t.id === activeId ? "var(--accent-ink)" : "var(--muted)", display: "flex", alignItems: "center", justifyContent: "center", flex: "none" }}>
                    <Icon name="folder" size={16} />
                  </span>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 600, fontSize: 14, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{t.name}</div>
                    <div className="mono" style={{ fontSize: 11.5, color: "var(--faint)" }}>{money(total)} · {t.people.length} people</div>
                  </div>
                  {t.id === activeId && <span style={{ color: "var(--accent)", flex: "none" }}><Icon name="check" size={16} /></span>}
                </button>
                {t.owner ? (
                  <button className="btn btn-icon btn-quiet" style={{ width: 28, height: 28, flex: "none" }} title="Delete trip"
                    onClick={() => { if (confirm(`Delete "${t.name}" and all its charges? This deletes it for everyone and can't be undone.`)) onDelete(t.id); }}>
                    <Icon name="trash" size={15} />
                  </button>
                ) : (
                  <button className="btn btn-icon btn-quiet" style={{ width: 28, height: 28, flex: "none" }} title="Leave trip"
                    onClick={() => { if (confirm(`Remove "${t.name}" from this device? You can rejoin later with the code.`)) onLeave(t.id); }}>
                    <Icon name="undo" size={15} />
                  </button>
                )}
              </div>
            );
          })}
          <hr className="divider" style={{ margin: "6px 4px" }} />
          <button className="menu-item" style={{ color: "var(--accent)", fontWeight: 600 }} onClick={() => { onJoin(); close(); }}>
            <span style={{ width: 30, display: "flex", justifyContent: "center" }}><Icon name="arrow" size={17} /></span>
            Join with code
          </button>
          <button className="menu-item" style={{ color: "var(--accent)", fontWeight: 600 }} onClick={() => { onNew(); close(); }}>
            <span style={{ width: 30, display: "flex", justifyContent: "center" }}><Icon name="plus" size={17} /></span>
            New trip
          </button>
          {admin ? (
            <button className="menu-item" onClick={() => { onExitAdmin(); close(); }}>
              <span style={{ width: 30, display: "flex", justifyContent: "center" }}><Icon name="undo" size={16} /></span>
              Exit admin
            </button>
          ) : adminEnabled ? (
            <button className="menu-item" onClick={() => { onAdmin(); close(); }}>
              <span style={{ width: 30, display: "flex", justifyContent: "center" }}><Icon name="wallet" size={16} /></span>
              Admin sign-in
            </button>
          ) : null}
        </>
      )}
    </Dropdown>
  );
}

Object.assign(window, { Breakdown, SettlePanel, PersonDetail, ChargeDetail, ExportModal, TripMenu });
