// screens_settle.jsx — per-person Share/Tip/Total, You special-cased,
// REAL money requests (deep links into Venmo / Cash App / PayPal, copy-to-paste
// for Zelle / Apple Cash), save to history. -> window.

function PayGlyph({ app }) {
  const m = {
    venmo: <span style={{ fontWeight: 800, fontSize: 20, fontStyle: 'italic' }}>V</span>,
    cashapp: <IconDollar s={20} />,
    apple: <svg width="19" height="19" viewBox="0 0 24 24" fill="currentColor"><path d="M16.4 12.6c0-2.3 1.9-3.4 2-3.5-1.1-1.6-2.8-1.8-3.4-1.8-1.4-.1-2.8.8-3.5.8s-1.8-.8-3-.8c-1.5 0-3 .9-3.8 2.3-1.6 2.8-.4 7 1.2 9.3.8 1.1 1.7 2.4 2.9 2.3 1.2 0 1.6-.7 3-.7s1.8.7 3 .7 2-1.1 2.8-2.2c.9-1.3 1.2-2.5 1.3-2.6-.1 0-2.5-1-2.5-3.8zM14.2 5.4c.6-.8 1-1.9.9-3-.9 0-2 .6-2.7 1.4-.6.7-1.1 1.8-.9 2.9 1 .1 2-.5 2.7-1.3z"/></svg>,
    zelle: <span style={{ fontWeight: 800, fontSize: 19 }}>Z</span>,
  };
  return m[app.glyph] || <span style={{ fontWeight: 800 }}>{app.name[0]}</span>;
}

// ── Per-app request behaviour ─────────────────────────────────
// 'open'  → open the app's CHARGE screen pre-filled (Venmo).
// 'share' → build a payment LINK to your own handle and share/open it.
// 'copy'  → no public link (Zelle / Apple Cash) → copy the details to paste.
// need: 'their' = their handle required · 'mine' = your handle required ·
//       'optional' = a handle helps but isn't required · 'none' = no handle.
function reqConfig(appId) {
  switch (appId) {
    case 'venmo':     return { need: 'optional', prefix: '@', label: 'Their Venmo username (optional)', placeholder: 'leave blank to pick in Venmo', mode: 'open',
      blurb: (n, amt) => `Opens Venmo to charge ${amt}. Leave the username blank to choose ${n} inside Venmo — or have them scan the code above to pay you. We don’t save a copy here, so no double requests.` };
    case 'cashapp':   return { need: 'mine', prefix: '$', label: 'Your $Cashtag', placeholder: 'cashtag', mode: 'share',
      blurb: (n) => `Shares a Cash App link to your $Cashtag — or have ${n} scan the code above to pay you.` };
    case 'zelle':     return { need: 'mine', prefix: '', label: 'Your Zelle email or phone', placeholder: 'email or phone', mode: 'copy',
      blurb: (n) => `Zelle has no link — we copy the details so ${n} can pay you from their bank app.` };
    case 'applecash': return { need: 'none', prefix: '', label: '', placeholder: '', mode: 'copy',
      blurb: (n) => `Apple Cash sends in Messages — we copy the amount for you to paste to ${n}.` };
    default:          return { need: 'none', prefix: '', label: '', placeholder: '', mode: 'copy', blurb: () => '' };
  }
}

function buildPayUrl(appId, handle, amt, note) {
  const h = (handle || '').trim();
  if (!h) return null;
  if (appId === 'venmo')   return `https://venmo.com/${encodeURIComponent(h.replace(/^@/, ''))}?txn=charge&amount=${amt}&note=${encodeURIComponent(note)}`;
  if (appId === 'cashapp') return `https://cash.app/$${encodeURIComponent(h.replace(/^\$/, ''))}/${amt}`;
  return null;
}

// Scan-to-PAY link (the other person scans and pays YOU). Venmo: txn=pay to your
// username; Cash App: cash.app/$tag/amount. Only these two expose a public link
// a phone camera can open, so only they get a QR.
function buildQrUrl(appId, handle, amt, note) {
  const h = (handle || '').trim().replace(/^[@$]/, '');
  if (!h) return null;
  if (appId === 'venmo')   return `https://venmo.com/${encodeURIComponent(h)}?txn=pay&amount=${amt}&note=${encodeURIComponent(note)}`;
  if (appId === 'cashapp') return `https://cash.app/$${encodeURIComponent(h)}/${amt}`;
  return null;
}

// ── QR generator (lazy, once) ─────────────────────────────────
let _qrPromise = null;
function loadQR() {
  if (window.qrcode) return Promise.resolve(window.qrcode);
  if (_qrPromise) return _qrPromise;
  _qrPromise = new Promise((resolve, reject) => {
    const sc = document.createElement('script');
    sc.src = 'https://cdn.jsdelivr.net/npm/qrcode-generator@1.4.4/qrcode.js';
    sc.onload = () => window.qrcode ? resolve(window.qrcode) : reject(new Error('QR unavailable'));
    sc.onerror = () => { _qrPromise = null; reject(new Error('QR offline')); };
    document.head.appendChild(sc);
  });
  return _qrPromise;
}

function QRImage({ text, size = 188 }) {
  const [src, setSrc] = React.useState('');
  const [err, setErr] = React.useState(false);
  React.useEffect(() => {
    let alive = true; setSrc(''); setErr(false);
    loadQR().then((qrcode) => {
      try { const qr = qrcode(0, 'M'); qr.addData(text); qr.make(); if (alive) setSrc(qr.createDataURL(6, 10)); }
      catch (e) { if (alive) setErr(true); }
    }).catch(() => { if (alive) setErr(true); });
    return () => { alive = false; };
  }, [text]);
  if (err) return <div style={{ width: size, height: size, display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center', fontSize: 12, color: 'var(--on-surface-var)', padding: 12 }}>Couldn’t load the scan code — use the button below.</div>;
  if (!src) return <div style={{ width: size, height: size, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><div style={{ width: 26, height: 26, borderRadius: 99, border: '3px solid var(--outline)', borderTopColor: 'var(--primary)', animation: 'taSpin .8s linear infinite' }} /></div>;
  return <img src={src} width={size} height={size} alt="Scan to pay" style={{ display: 'block', width: size, height: size, imageRendering: 'pixelated', borderRadius: 6 }} />;
}

// Robust copy: Clipboard API in secure contexts, execCommand fallback otherwise
// (older browsers, non-secure origins, some embedded/desktop webviews).
function fallbackCopy(text) {
  try {
    const ta = document.createElement('textarea');
    ta.value = text; ta.setAttribute('readonly', '');
    ta.style.cssText = 'position:fixed;top:0;left:0;width:1px;height:1px;opacity:0;';
    document.body.appendChild(ta);
    ta.focus(); ta.select(); ta.setSelectionRange(0, text.length);
    const ok = document.execCommand('copy');
    document.body.removeChild(ta);
    return ok;
  } catch (e) { return false; }
}
function copyToClipboard(text) {
  return new Promise((resolve) => {
    if (navigator.clipboard && navigator.clipboard.writeText && window.isSecureContext) {
      navigator.clipboard.writeText(text).then(() => resolve(true)).catch(() => resolve(fallbackCopy(text)));
    } else {
      resolve(fallbackCopy(text));
    }
  });
}

// ── Reusable request sheet ────────────────────────────────────
// Drives the whole "request money" flow (method picker → QR / deep-link / copy)
// for ONE person. Used from both Settle-up (live bill) and History (past split)
// so requesting works from either place. A name is never required — it only
// personalises the message; the request still goes through without it.
function RequestSheet({ open, person, merchant, currency, settings, setSettings, toast, onClose, onRequested }) {
  const [sheetApp, setSheetApp] = React.useState(null);   // null = app picker, else = detail
  const [handle, setHandle] = React.useState('');
  const myHandles = settings.myHandles || {};
  const contacts = settings.contacts || {};
  const enabledApps = PAYMENT_APPS.filter((a) => (settings.payApps || PAYMENT_APPS.map((x) => x.id)).includes(a.id));

  React.useEffect(() => { if (!open) { setSheetApp(null); setHandle(''); } }, [open]);

  const nameKey = (p) => (p && p.name ? p.name.trim().toLowerCase() : '');
  // Venmo is no longer prefilled from a saved per-person handle — you either
  // pick the person inside Venmo or type it fresh — so the same person can't end
  // up requested twice (typed handle + stale saved contact).
  const savedHandle = (app) => {
    if (!app) return '';
    if (app.id === 'venmo') return '';
    return myHandles[app.id] || '';
  };
  const pickApp = (app) => { setSheetApp(app); setHandle(savedHandle(app)); };
  const close = () => { setSheetApp(null); setHandle(''); onClose(); };

  const persistHandle = (app, val) => {
    const v = (val || '').trim();
    if (!v) return;
    // Only your own handles persist; we never auto-save someone else's Venmo.
    if (['cashapp', 'zelle'].includes(app.id)) {
      setSettings({ ...settings, myHandles: { ...myHandles, [app.id]: v } });
    }
  };

  // Plain-text request message (also shown in copy-mode so it can be selected
  // by hand if the programmatic copy is blocked).
  const buildMessage = (app, cfg, amtStr) => {
    const cleanH = handle.trim().replace(/^[@$]/, '');
    const where = app.id === 'applecash'
      ? ' Send it to me on Apple Cash in Messages.'
      : (cfg.prefix && cleanH) ? ` Send it to me at ${cfg.prefix}${cleanH} on ${app.name}.`
      : cleanH ? ` Send it to ${cleanH} on ${app.name}.`
      : ` Pay me via ${app.name}.`;
    const who = person && person.name ? person.name : '';
    const lead = `${who ? who + ', y' : 'Y'}our share of ${merchant || 'the bill'} is ${amtStr}.`;
    return lead + where;
  };

  const submit = (app) => {
    if (!person) return;
    const cfg = reqConfig(app.id);
    const required = cfg.need === 'their' || cfg.need === 'mine';
    if (required && !handle.trim()) return;
    persistHandle(app, handle);

    const amt = (person.total / 100).toFixed(2);
    const amtStr = fmt(person.total, currency);
    const who = person.name || 'them';
    const note = merchant ? `${merchant} — your share` : 'Your share of the bill';
    let url = buildPayUrl(app.id, handle, amt, note);
    // Venmo with no username: open Venmo itself so you pick the person there.
    if (app.id === 'venmo' && !url) url = 'https://venmo.com/';
    const record = () => onRequested({ method: app.id, at: new Date().toISOString(), amount: person.total });

    if (cfg.mode === 'open' && url) {
      try { window.open(url, '_blank', 'noopener'); } catch (e) {}
      record(); close();
      toast(`Requested ${amtStr} · ${who} on ${app.name}`, <IconCheckCircle s={18} />);
    } else if (cfg.mode === 'share' && url) {
      const msg = buildMessage(app, cfg, amtStr);
      try {
        if (navigator.share) navigator.share({ title: 'DivvyTab request', text: msg, url }).catch(() => {});
        else window.open(url, '_blank', 'noopener');
      } catch (e) {}
      record(); close();
      toast(`Requested ${amtStr} · ${who} on ${app.name}`, <IconCheckCircle s={18} />);
    } else {
      const msg = buildMessage(app, cfg, amtStr);
      copyToClipboard(msg).then((ok) => {
        record(); close();
        toast(ok ? `Copied request · ${who}` : `Couldn’t auto-copy — select the text to copy`, <IconCheckCircle s={18} />);
      });
    }
  };

  const fieldInput = {
    height: 48, width: '100%', borderRadius: 12, border: 'none', background: 'transparent',
    color: 'var(--on-surface)', fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 16, padding: '0 4px', outline: 'none', minWidth: 0,
  };

  return (
    <Sheet open={open} onClose={close}
      title={person ? (sheetApp ? sheetApp.name : `Request ${fmt(person.total, currency)}`) : ''}>
      {person && !sheetApp && (
        <React.Fragment>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14, padding: '0 2px' }}>
            <Avatar person={person} size={34} /><span style={{ fontWeight: 600, color: 'var(--on-surface-var)' }}>from <b style={{ color: 'var(--on-surface)' }}>{person.name || 'this person'}</b> · pick a method</span>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {enabledApps.map((a) => (
              <button key={a.id} className="ta-press" onClick={() => pickApp(a)} style={{ display: 'flex', alignItems: 'center', gap: 13, padding: '12px 14px', borderRadius: 'var(--radius-sm)', border: 'none', cursor: 'pointer', background: 'var(--surface-variant)', textAlign: 'left' }}>
                <div style={{ width: 40, height: 40, borderRadius: 11, background: a.color, color: a.fg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><PayGlyph app={a} /></div>
                <span style={{ flex: 1, fontWeight: 700, fontSize: 15.5, color: 'var(--on-surface)' }}>{a.name}</span>
                <IconChevron s={20} style={{ color: 'var(--on-surface-var)' }} />
              </button>
            ))}
          </div>
        </React.Fragment>
      )}

      {person && sheetApp && (() => {
        const cfg = reqConfig(sheetApp.id);
        const amtStr = fmt(person.total, currency);
        const amt = (person.total / 100).toFixed(2);
        const note = merchant ? `${merchant} — your share` : 'Your share of the bill';
        const disabled = (cfg.need === 'their' || cfg.need === 'mine') && !handle.trim();
        const ModeIcon = cfg.mode === 'open' ? IconExternal : cfg.mode === 'share' ? IconShare : IconCopy;
        // Scan-to-pay: Venmo uses YOUR saved username; Cash App uses the cashtag
        // being entered here. Apple Cash / Zelle have no scannable link.
        const myVenmo = (myHandles.venmo || '').trim();
        const qrHandle = sheetApp.id === 'venmo' ? myVenmo : handle;
        const qrUrl = (sheetApp.id === 'venmo' || sheetApp.id === 'cashapp') ? buildQrUrl(sheetApp.id, qrHandle, amt, note) : null;
        const copyMsg = buildMessage(sheetApp, cfg, amtStr);
        const selectAll = (e) => { try { const r = document.createRange(); r.selectNodeContents(e.currentTarget); const s = window.getSelection(); s.removeAllRanges(); s.addRange(r); } catch (_) {} };
        return (
          <div className="ta-fade">
            <button className="ta-press" onClick={() => setSheetApp(null)} style={{ display: 'flex', alignItems: 'center', gap: 5, border: 'none', background: 'transparent', cursor: 'pointer', color: 'var(--on-surface-var)', fontWeight: 700, fontSize: 13, padding: '0 2px 12px' }}>
              <IconBack s={17} /> All methods
            </button>

            <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '0 2px 14px' }}>
              <div style={{ width: 44, height: 44, borderRadius: 12, background: sheetApp.color, color: sheetApp.fg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><PayGlyph app={sheetApp} /></div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 700, fontSize: 15, overflowWrap: 'anywhere' }}>{person.name || 'This person'}</div>
                <div style={{ fontSize: 12.5, color: 'var(--on-surface-var)' }}>owes you</div>
              </div>
              <span className="ta-num" style={{ fontFamily: 'var(--font-display)', fontWeight: 'var(--num-weight)', fontSize: 22, flexShrink: 0 }}>{amtStr}</span>
            </div>

            {qrUrl && (
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10, padding: '2px 0 16px' }}>
                <div style={{ padding: 12, background: '#fff', borderRadius: 16, boxShadow: 'var(--shadow-soft)' }}>
                  <QRImage text={qrUrl} size={184} />
                </div>
                <div style={{ fontSize: 12.5, color: 'var(--on-surface-var)', textAlign: 'center', maxWidth: 270, lineHeight: 1.5 }}>
                  Have <b style={{ color: 'var(--on-surface)' }}>{person.name || 'them'}</b> scan to pay you {amtStr} in {sheetApp.name}.
                </div>
              </div>
            )}
            {sheetApp.id === 'venmo' && !myVenmo && (
              <div style={{ fontSize: 12.5, color: 'var(--on-surface-var)', lineHeight: 1.5, background: 'var(--surface-variant)', borderRadius: 12, padding: '11px 13px', marginBottom: 14 }}>
                Add your Venmo username in <b style={{ color: 'var(--on-surface)' }}>Settings → Your payment handles</b> to show a scan-to-pay code here.
              </div>
            )}

            {cfg.need !== 'none' && (
              <React.Fragment>
                <Label style={{ margin: '2px 2px 7px' }}>{cfg.label}</Label>
                <div style={{ display: 'flex', alignItems: 'center', borderRadius: 12, border: '1.5px solid var(--outline)', background: 'var(--surface-variant)', padding: '0 13px', marginBottom: 12 }}>
                  {cfg.prefix && <span style={{ fontWeight: 700, color: 'var(--on-surface-var)', fontSize: 16, flexShrink: 0 }}>{cfg.prefix}</span>}
                  <input value={handle} onChange={(e) => setHandle(e.target.value)} placeholder={cfg.placeholder} autoCapitalize="none" autoCorrect="off" spellCheck={false} style={fieldInput} />
                </div>
              </React.Fragment>
            )}

            {cfg.mode === 'copy' && (
              <React.Fragment>
                <Label style={{ margin: '2px 2px 7px' }}>Message to send</Label>
                <div onClick={selectAll} style={{ userSelect: 'text', WebkitUserSelect: 'text', cursor: 'text', borderRadius: 12, border: '1.5px solid var(--outline)', background: 'var(--surface-variant)', padding: '11px 13px', marginBottom: 12, fontSize: 13.5, lineHeight: 1.5, color: 'var(--on-surface)' }}>{copyMsg}</div>
              </React.Fragment>
            )}

            <div style={{ fontSize: 12.5, color: 'var(--on-surface-var)', lineHeight: 1.5, padding: '0 2px 14px' }}>{cfg.blurb(person.name || 'them', amtStr)}</div>

            <Button disabled={disabled} onClick={() => submit(sheetApp)} leading={<ModeIcon s={20} />}>
              {cfg.mode === 'open' ? `Open ${sheetApp.name}` : cfg.mode === 'share' ? `Send ${sheetApp.name} request` : 'Copy request details'}
            </Button>
          </div>
        );
      })()}
    </Sheet>
  );
}

function SettleScreen({ state, set, derived, currency, nav, toast, onComplete, settings, setSettings }) {
  const [reqFor, setReqFor] = React.useState(null);
  const person = derived.rows.find((r) => r.id === reqFor);
  const requested = state.requested || {};
  const paid = state.paid || {};
  const owing = derived.rows.filter((r) => r.you || r.total > 0);

  const markPaid = (id) => set({ paid: { ...paid, [id]: !paid[id] } });
  const others = owing.filter((r) => !r.you);
  const allDone = others.every((r) => paid[r.id]);
  const save = () => { onComplete(); };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      <ScreenHeader title="Settle up" onBack={() => nav('tip')} sub={state.merchant || null} />
      <Steps active="Settle" />

      <div className="ta-scroll" style={{ flex: 1, minHeight: 0, padding: '10px 18px 8px' }}>
        {/* totals */}
        <Card style={{ marginBottom: 14, padding: '15px 18px' }}>
          {[['Subtotal', derived.subtotal], derived.tax ? [`Tax`, derived.tax] : null, [`Tip · ${state.tipPct}%`, derived.tip], derived.roundingAdj ? ['Rounding', derived.roundingAdj] : null].filter(Boolean).map(([l, v]) => (
            <div key={l} style={{ display: 'flex', justifyContent: 'space-between', fontSize: 14, marginBottom: 7 }}>
              <span style={{ color: 'var(--on-surface-var)', whiteSpace: 'nowrap' }}>{l}</span>
              <span className="ta-num" style={{ fontWeight: 700 }}>{l === 'Rounding' && v > 0 ? '+' : ''}{fmt(v, currency)}</span>
            </div>
          ))}
          <div style={{ height: 1, background: 'var(--outline-faint)', margin: '4px 0 10px' }} />
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
            <span style={{ fontWeight: 700 }}>Total due</span>
            <span className="ta-num" style={{ fontFamily: 'var(--font-display)', fontWeight: 'var(--num-weight)', fontSize: 24 }}>{fmt(derived.grand, currency)}</span>
          </div>
        </Card>

        <Label style={{ marginBottom: 10, padding: '0 2px' }}>Who owes what</Label>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 9 }}>
          {owing.map((r) => {
            const isPaid = paid[r.id];
            const req = requested[r.id];
            const reqApp = req && PAYMENT_APPS.find((a) => a.id === req.method);
            return (
              <div key={r.id} style={{ background: r.you ? 'var(--surface-alt)' : 'var(--surface)', borderRadius: 'var(--radius)', padding: '12px 14px',
                boxShadow: r.you ? 'none' : 'var(--shadow-soft)', border: r.you ? '1.5px solid var(--outline-faint)' : 'none', opacity: isPaid ? 0.62 : 1 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                  <Avatar person={r} size={42} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 700, display: 'flex', alignItems: 'center', gap: 7, flexWrap: 'wrap' }}>
                      <span style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '100%' }}>{r.you ? 'You' : r.name}</span>
                      {r.you && <span style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: 0.4, color: 'var(--on-surface-var)', background: 'var(--surface-variant)', borderRadius: 99, padding: '2px 7px', whiteSpace: 'nowrap', flexShrink: 0 }}>YOUR SHARE</span>}
                      {isPaid && <span style={{ fontSize: 11, fontWeight: 800, color: 'var(--good)', display: 'inline-flex', alignItems: 'center', gap: 3, flexShrink: 0 }}><IconCheck s={13} />PAID</span>}
                    </div>
                    <div className="ta-num" style={{ fontSize: 12.5, color: 'var(--on-surface-var)', marginTop: 1 }}>
                      {fmt(r.share, currency)} + {fmt(r.tip, currency)} tip{reqApp && !isPaid ? ` · via ${reqApp.name}` : ''}
                    </div>
                  </div>
                  <span className="ta-num" style={{ fontFamily: 'var(--font-display)', fontWeight: 'var(--num-weight)', fontSize: 19, flexShrink: 0, textDecoration: isPaid ? 'line-through' : 'none' }}>{fmt(r.total, currency)}</span>
                </div>
                {!r.you && !isPaid && (
                  <div style={{ display: 'flex', gap: 8, marginTop: 11 }}>
                    <button className="ta-press" onClick={() => setReqFor(r.id)} style={{ flex: 1, height: 42, borderRadius: 99, border: 'none', cursor: 'pointer', background: reqApp ? 'var(--primary-container)' : 'var(--primary)', color: reqApp ? 'var(--on-primary-container)' : 'var(--on-primary)', fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 14, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7 }}>
                      <IconDollar s={16} /> {reqApp ? 'Requested · resend' : 'Request'}
                    </button>
                    <button className="ta-press" onClick={() => markPaid(r.id)} title="Mark as paid" style={{ width: 46, height: 42, borderRadius: 99, cursor: 'pointer', border: '1.5px solid var(--outline)', background: 'transparent', color: 'var(--on-surface)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><IconCheck s={20} /></button>
                  </div>
                )}
                {!r.you && isPaid && (
                  <button className="ta-press" onClick={() => markPaid(r.id)} style={{ marginTop: 10, width: '100%', height: 38, borderRadius: 99, cursor: 'pointer', border: '1.5px solid var(--outline)', background: 'transparent', color: 'var(--on-surface-var)', fontWeight: 700, fontSize: 13 }}>Mark as unpaid</button>
                )}
              </div>
            );
          })}
        </div>
      </div>

      <div style={{ background: 'var(--surface)', borderTopLeftRadius: 28, borderTopRightRadius: 28, padding: '12px 18px 14px', boxShadow: '0 -6px 24px rgba(0,0,0,0.05)' }}>
        <Button onClick={save} variant={allDone ? 'filled' : 'tonal'} leading={allDone ? <IconCheck s={20} /> : <IconClock s={19} />}>
          {allDone ? 'Done · save to history' : 'Save to history'}
        </Button>
      </div>

      <RequestSheet open={!!reqFor} person={person} merchant={state.merchant} currency={currency}
        settings={settings} setSettings={setSettings} toast={toast}
        onClose={() => setReqFor(null)}
        onRequested={(req) => { if (person) set({ requested: { ...requested, [person.id]: req } }); }} />
    </div>
  );
}

Object.assign(window, { SettleScreen, RequestSheet, PayGlyph, reqConfig, buildPayUrl, buildQrUrl, QRImage, copyToClipboard });
