// ════════════ MONEY · accounting cluster ════════════
const { Icon, Spark, Pex, Avatar, Card, Btn, Pill, Label, Num, Spark2, Toggle, Field, Tabs, money } = window;

// Controlled input shell (same look as Field, but supports onChange for local forms/modals in this file)
function MoneyField({ label, value, onChange, placeholder, icon, sub, suffix, mono, type = 'text', style = {} }) {
  const P = window.PX;
  return (
    <label style={{ display: 'block', ...style }}>
      {label && <div style={{ fontSize: 12, color: P.ink3, marginBottom: 5, fontWeight: 500 }}>{label}</div>}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, background: P.card, border: `1px solid ${P.lineStrong}`, borderRadius: P.rCtl, padding: '9px 11px' }}>
        {icon && <Icon name={icon} size={15} color={P.ink3}/>}
        <input type={type} value={value} onChange={e => onChange(e.target.value)} placeholder={placeholder}
          style={{ flex: 1, border: 'none', background: 'transparent', outline: 'none', fontSize: 13.5, color: P.ink, fontFamily: mono ? P.mono : P.sans, minWidth: 0 }}/>
        {suffix && <span style={{ fontSize: 12, color: P.ink3 }}>{suffix}</span>}
      </div>
      {sub && <div style={{ fontSize: 11, color: P.ink3, marginTop: 4 }}>{sub}</div>}
    </label>
  );
}

// Controlled select, styled to match MoneyField
function MoneySelect({ label, value, onChange, options, style = {} }) {
  const P = window.PX;
  return (
    <label style={{ display: 'block', ...style }}>
      {label && <div style={{ fontSize: 12, color: P.ink3, marginBottom: 5, fontWeight: 500 }}>{label}</div>}
      <select value={value} onChange={e => onChange(e.target.value)}
        style={{ width: '100%', background: P.card, border: `1px solid ${P.lineStrong}`, borderRadius: P.rCtl, padding: '9px 11px', fontSize: 13.5, color: P.ink, fontFamily: P.sans, outline: 'none' }}>
        {options.map(o => <option key={o} value={o}>{o}</option>)}
      </select>
    </label>
  );
}

// Secondary nav layout used across Money/People/Website/Settings
window.SubLayout = function SubLayout({ title, nav, active, onNav, children, foot }) {
  const P = window.PX;
  return (
    <div style={{ display: 'flex', height: '100%', fontFamily: P.sans }}>
      <div style={{ width: 210, borderRight: `1px solid ${P.line}`, background: P.canvas, flexShrink: 0, display: 'flex', flexDirection: 'column', overflow: 'auto' }}>
        <div style={{ padding: '16px 16px 8px' }}>
          <div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 22, color: P.ink, letterSpacing: -0.4 }}>{title}</div>
        </div>
        <div style={{ padding: '4px 10px', flex: 1 }}>
          {nav.map((g, i) => (
            <div key={i} style={{ marginBottom: 10 }}>
              {g.label && <Label style={{ padding: '8px 8px 4px' }}>{g.label}</Label>}
              {g.items.map(it => {
                const on = active === it.k;
                return (
                  <div key={it.k} onClick={() => onNav(it.k)} style={{ display: 'flex', alignItems: 'center', gap: 9, padding: '7px 9px', borderRadius: 8, margin: '1px 0', cursor: 'pointer',
                    background: on ? P.card : 'transparent', border: `1px solid ${on ? P.line : 'transparent'}`, boxShadow: on ? P.shSm : 'none',
                    color: on ? P.ink : P.ink2, fontSize: 13, fontWeight: on ? 600 : 500 }}
                    onMouseEnter={e => { if (!on) e.currentTarget.style.background = P.hover; }} onMouseLeave={e => { if (!on) e.currentTarget.style.background = 'transparent'; }}>
                    <Icon name={it.icon} size={16} color={on ? P.spark : P.ink3} stroke={on ? 2 : 1.75}/>
                    <span style={{ flex: 1 }}>{it.label}</span>
                    {it.badge != null && <span style={{ fontSize: 11, color: it.tone ? P[it.tone] : P.ink3, fontWeight: 600 }}>{it.badge}</span>}
                  </div>
                );
              })}
            </div>
          ))}
        </div>
        {foot && <div style={{ padding: 12, borderTop: `1px solid ${P.line}` }}>{foot}</div>}
      </div>
      <div style={{ flex: 1, overflow: 'auto', minWidth: 0 }}>{children}</div>
    </div>
  );
};

window.SCREENS['money'] = function Money({ sub }) {
  const P = window.PX; const { go } = window.useApp();
  const seg = (sub || '').split('/');
  const active = seg[0] || 'overview';
  const nav = [
    { label: 'Banking', items: [
      { k: 'overview', icon: 'home', label: 'Overview' },
      { k: 'accounts', icon: 'building', label: 'Accounts' },
      { k: 'cards', icon: 'card', label: 'Cards' },
      { k: 'send', icon: 'send', label: 'Send money' },
      { k: 'transactions', icon: 'activity', label: 'Transactions', badge: 847 },
    ]},
    { label: 'Get paid', items: [
      { k: 'invoices', icon: 'receipt', label: 'Invoices', badge: 3, tone: 'rose' },
      { k: 'payments', icon: 'dollar', label: 'Accept payments' },
      { k: 'products', icon: 'tag', label: 'Products & prices' },
    ]},
    { label: 'Spending', items: [
      { k: 'bills', icon: 'fileText', label: 'Bill Pay', badge: 2, tone: 'amber' },
      { k: 'expenses', icon: 'percent', label: 'Expenses' },
      { k: 'payroll', icon: 'users', label: 'Payroll' },
    ]},
    { label: 'Accounting', items: [
      { k: 'reports', icon: 'pie', label: 'Reports' },
      { k: 'tax', icon: 'shield', label: 'Tax' },
      { k: 'reconcile', icon: 'refresh', label: 'Reconcile', badge: 6, tone: 'sky' },
    ]},
  ];
  const onNav = (k) => go('money' + (k === 'overview' ? '' : '/' + k));

  return (
    <window.SubLayout title="Money" nav={nav} active={active} onNav={onNav}>
      {active === 'overview' && <MoneyOverview/>}
      {active === 'accounts' && <window.MoneyAccounts/>}
      {active === 'cards' && <window.MoneyCards/>}
      {active === 'send' && <window.MoneySend/>}
      {active === 'transactions' && <MoneyTransactions/>}
      {active === 'invoices' && (seg[1] === 'new' ? <window.InvoiceEditor/> : seg[1] ? <InvoiceDetail id={seg[1]}/> : <InvoiceList/>)}
      {active === 'payments' && <MoneyPayments/>}
      {active === 'products' && <MoneyProducts/>}
      {active === 'bills' && <MoneyBills/>}
      {active === 'expenses' && <MoneyExpenses/>}
      {active === 'payroll' && <MoneyPayroll/>}
      {active === 'reports' && <MoneyReports/>}
      {active === 'tax' && <MoneyTax/>}
      {active === 'reconcile' && <MoneyReconcile/>}
    </window.SubLayout>
  );
};

// ── Overview ────────────────────────────────────────────────
function MoneyOverview() {
  const P = window.PX; const { go, toast, sparks, setSparks, openOverlay } = window.useApp();
  const [deposit, setDeposit] = React.useState(false);
  const chase = () => {
    const cost = 2;
    if (cost > sparks) { openOverlay('creditGate', { needed: cost, balance: sparks }); return; }
    setSparks(s => Math.max(0, s - cost));
    toast('Pex is chasing 3 overdue invoices — warm nudges, your voice.', { tone: 'sage', icon: 'check' });
  };
  const op = window.PXBank ? window.PXBank.acct('op') : { balance: 12408.22 };
  const tax = window.PXBank ? window.PXBank.acct('tax') : { balance: 3820 };
  const sav = window.PXBank ? window.PXBank.acct('save') : { balance: 8100 };
  return (
    <div style={{ padding: 22, fontFamily: P.sans }}>
      {/* balance hero */}
      <div style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: 14, marginBottom: 14 }}>
        <Card pad={0} style={{ background: P.card, border: `1px solid ${P.line}`, boxShadow: P.shMd }}>
          <div style={{ padding: 22, display: 'flex', gap: 20, height: '100%' }}>
            <div style={{ flex: 1 }}>
              <Label>Operating · USD</Label>
              <div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 50, letterSpacing: -1.5, lineHeight: 1, marginTop: 6, color: P.ink }}>{window.money(op.balance).split('.')[0]}<span style={{ fontSize: 26, color: P.ink3 }}>.{window.money(op.balance).split('.')[1]}</span></div>
              <div style={{ fontSize: 13, color: P.ink3, marginTop: 8 }}>+$842 this week · <span style={{ color: P.sage, fontWeight: 600 }}>+22%</span> vs last month · <span onClick={() => go('money/accounts')} style={{ color: P.spark, cursor: 'pointer' }}>Accounts →</span></div>
              <div style={{ display: 'flex', gap: 8, marginTop: 16 }}>
                <Btn kind="spark" size="sm" icon="send" onClick={() => go('money/invoices/new')}>Send invoice</Btn>
                <Btn kind="default" size="sm" icon="arrowDown" onClick={() => setDeposit(true)}>Add money</Btn>
                <Btn kind="default" size="sm" icon="arrowUp" onClick={() => go('money/send')}>Pay</Btn>
              </div>
            </div>
            <svg width="180" height="120" viewBox="0 0 180 120" style={{ alignSelf: 'flex-end' }}>
              <path d="M0,90 L20,84 L40,92 L60,72 L80,78 L100,58 L120,64 L140,44 L160,38 L180,22" fill="none" stroke={P.spark} strokeWidth="2"/>
              <path d="M0,90 L20,84 L40,92 L60,72 L80,78 L100,58 L120,64 L140,44 L160,38 L180,22 L180,120 L0,120 Z" fill={P.spark} opacity="0.12"/>
            </svg>
          </div>
        </Card>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {[{ l: 'Tax reserve', v: window.money(tax.balance), d: '18% of revenue', tone: 'sky' }, { l: 'Savings', v: window.money(sav.balance), d: 'Earning 4.10% APY', tone: 'sage' }].map((b, i) => (
            <Card key={i} pad={16} hover onClick={() => go('money/accounts')} style={{ flex: 1 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}><Label>{b.l}</Label><span style={{ fontSize: 11, color: P.ink3 }}>USD</span></div>
              <Num size={26} style={{ marginTop: 6 }}>{b.v}</Num>
              <div style={{ fontSize: 11.5, color: P.ink3, marginTop: 5 }}>{b.d}</div>
            </Card>
          ))}
        </div>
      </div>

      {/* stat strip */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14, marginBottom: 14 }}>
        {[['Revenue · MTD', '$18,640', '+22%', 'sage', 'reports'], ['Expenses · MTD', '$9,420', '+8%', 'ink', 'expenses'], ['Receivables', '$4,280', '1 overdue', 'rose', 'invoices'], ['Payables', '$2,140', '2 due', 'amber', 'bills']].map((c, i) => (
          <Card key={i} pad={16} hover onClick={() => go('money/' + c[4])}><Label>{c[0]}</Label><Num size={24} style={{ marginTop: 6 }}>{c[1]}</Num><div style={{ fontSize: 11.5, color: c[3] === 'ink' ? P.ink3 : P[c[3]], marginTop: 4 }}>{c[2]}</div></Card>
        ))}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: 14 }}>
        <Card>
          <div style={{ padding: '14px 18px', borderBottom: `1px solid ${P.line}`, display: 'flex' }}>
            <span style={{ fontSize: 14, fontWeight: 600, color: P.ink, flex: 1 }}>Recent transactions</span>
            <span onClick={() => go('money/transactions')} style={{ fontSize: 12, color: P.spark, cursor: 'pointer' }}>All 847 →</span>
          </div>
          {window.TXNS.slice(0, 7).map((t, i) => <TxnRow key={i} t={t} last={i === 6} onClick={() => go('money/transactions')}/>)}
        </Card>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <Card pad={16}>
            <div style={{ fontSize: 14, fontWeight: 600, color: P.ink, marginBottom: 10 }}>Outstanding · $4,280</div>
            {[['#1024 Café Bleu', '$1,420', '11d late', 'rose', '1024'], ['#1026 Greenpoint', '$2,400', 'due 4d', 'amber', '1026'], ['#1027 BK Co-op', '$460', 'Apr 2', 'ink3', '1027']].map((r, i) => (
              <div key={i} onClick={() => go('money/invoices/' + r[4])} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 0', borderBottom: i < 2 ? `1px solid ${P.line}` : 'none', cursor: 'pointer' }}
                onMouseEnter={e => e.currentTarget.style.opacity = 0.6} onMouseLeave={e => e.currentTarget.style.opacity = 1}>
                <div style={{ flex: 1 }}><div style={{ fontSize: 12.5, color: P.ink }}>{r[0]}</div><div style={{ fontSize: 10.5, color: r[3] === 'ink3' ? P.ink3 : P[r[3]] }}>{r[2]}</div></div>
                <span style={{ fontFamily: P.mono, fontSize: 12.5, fontWeight: 500, color: P.ink }}>{r[1]}</span>
                <Icon name="chevR" size={14} color={P.ink4}/>
              </div>
            ))}
            <Btn kind="spark" size="sm" full style={{ marginTop: 10 }} onClick={chase}>Let Pex chase · 2 ⚡</Btn>
          </Card>
          <Card pad={16}>
            <div style={{ fontSize: 14, fontWeight: 600, color: P.ink, marginBottom: 4 }}>Where money goes</div>
            <div style={{ fontSize: 11.5, color: P.ink3, marginBottom: 12 }}>This month · by category</div>
            {[['Ingredients', 38, 'spark'], ['Payroll', 31, 'sky'], ['Rent', 16, 'sage'], ['Marketing', 9, 'amber'], ['Other', 6, 'plum']].map((c, i) => (
              <div key={i} style={{ marginBottom: 9 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, color: P.ink2, marginBottom: 3 }}><span>{c[0]}</span><span>{c[1]}%</span></div>
                <div style={{ height: 6, background: P.sunk, borderRadius: 6, overflow: 'hidden' }}><div style={{ width: c[1] + '%', height: '100%', background: P[c[2]] }}/></div>
              </div>
            ))}
          </Card>
        </div>
      </div>
      {deposit && <AddMoneyModal onClose={() => setDeposit(false)}/>}
    </div>
  );
}

// Deposit into Operating — real balance + activity mutation on PXBank
function AddMoneyModal({ onClose }) {
  const P = window.PX; const { toast } = window.useApp();
  const [amount, setAmount] = React.useState('');
  const [source, setSource] = React.useState('Bank transfer · ACH');
  const sources = ['Bank transfer · ACH', 'Debit card', 'Wire transfer', 'Cash / check deposit'];
  const canSave = Number(amount) > 0;
  const submit = () => {
    const amt = Number(amount) || 0;
    if (window.PXBank) {
      window.PXBank.set(s => ({
        ...s,
        accounts: s.accounts.map(a => a.id === 'op' ? { ...a, balance: window.PXBank.round(a.balance + amt), current: window.PXBank.round(a.current + amt) } : a),
        activity: [{ id: window.pxid('dep'), acct: 'op', dir: 'in', desc: 'Deposit · ' + source, sub: 'Deposit · Operating', amt, date: 'Today', status: amt > 5000 ? 'pending' : 'settled' }, ...s.activity],
      }));
    }
    toast(`Added ${money(amt)} to Operating ••4290.`, { tone: 'sage', icon: 'check' });
    onClose();
  };
  return (
    <window.Modal title="Add money" sub="Deposit into your Operating account" onClose={onClose}
      foot={<>
        <Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn>
        <Btn kind="primary" size="md" disabled={!canSave} onClick={submit}>Add money</Btn>
      </>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <MoneyField label="Amount" value={amount} onChange={setAmount} placeholder="0.00" type="number" icon="dollar"/>
        <MoneySelect label="Source" value={source} onChange={setSource} options={sources}/>
        <div style={{ fontSize: 11.5, color: P.ink3, lineHeight: 1.5 }}>Deposits under $5,000 land instantly here; larger amounts show as pending review.</div>
      </div>
    </window.Modal>
  );
}

function TxnRow({ t, last, onClick }) {
  const P = window.PX;
  const tones = { in: P.sage, out: P.ink, spark: P.spark, pending: P.rose };
  const c = t.k === 'in' ? P.sage : t.k === 'spark' ? P.spark : t.k === 'pending' ? P.rose : P.ink;
  return (
    <div onClick={onClick} onMouseEnter={e => { if (onClick) e.currentTarget.style.background = P.hover; }} onMouseLeave={e => { if (onClick) e.currentTarget.style.background = 'transparent'; }}
      style={{ padding: '10px 18px', display: 'grid', gridTemplateColumns: '32px 1fr auto', gap: 11, alignItems: 'center', borderBottom: last ? 'none' : `1px solid ${P.line}`, cursor: onClick ? 'pointer' : 'default' }}>
      <div style={{ width: 30, height: 30, borderRadius: 8, background: t.k === 'out' ? P.sunk : P[(t.k === 'in' ? 'sage' : t.k === 'spark' ? 'spark' : 'rose') + 'Tint'], color: t.k === 'out' ? P.ink2 : c, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <Icon name={t.k === 'in' ? 'arrowDown' : t.k === 'spark' ? 'sparkles' : t.k === 'pending' ? 'clock' : 'arrowUp'} size={14}/>
      </div>
      <div style={{ minWidth: 0 }}><div style={{ fontSize: 13, color: P.ink, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{t.r}</div><div style={{ fontSize: 11, color: P.ink3 }}>{t.d} · {t.cat}</div></div>
      <span style={{ fontFamily: P.mono, fontSize: 13, fontWeight: 500, color: c }}>{t.a}</span>
    </div>
  );
}

window.TXNS = [
  { k: 'in', r: 'Shopify payout · Mar 11 batch', cat: 'Revenue', d: 'Today', a: '+$842.30' },
  { k: 'spark', r: 'Pexxie · Sparks usage', cat: 'Pexxie', d: 'Today', a: '−$4.00' },
  { k: 'in', r: 'Invoice #1025 · Lila Events', cat: 'Revenue', d: 'Today', a: '+$1,850.00' },
  { k: 'out', r: 'King Arthur Baking · flour', cat: 'Ingredients', d: 'Mar 11', a: '−$340.00' },
  { k: 'out', r: 'Con Edison · electricity', cat: 'Utilities', d: 'Mar 10', a: '−$218.40' },
  { k: 'out', r: 'Stripe processing fees', cat: 'Fees', d: 'Mar 10', a: '−$24.18' },
  { k: 'in', r: 'Class ticket · Sofia Martins', cat: 'Classes', d: 'Mar 9', a: '+$80.00' },
  { k: 'out', r: 'Google Ads', cat: 'Marketing', d: 'Mar 9', a: '−$145.00' },
  { k: 'pending', r: 'Invoice #1024 · Café Bleu', cat: 'Pending', d: 'Mar 8', a: '$1,420.00' },
  { k: 'out', r: 'Whole Foods · supplies', cat: 'Ingredients', d: 'Mar 8', a: '−$92.30' },
  { k: 'in', r: 'Square · in-store sales', cat: 'Revenue', d: 'Mar 7', a: '+$1,240.50' },
  { k: 'out', r: 'Payroll · Rosa Kim', cat: 'Payroll', d: 'Mar 7', a: '−$1,840.00' },
];

// ── Transactions (ledger) ────────────────────────────────────
function MoneyTransactions() {
  const P = window.PX; const { toast } = window.useApp();
  const [q, setQ] = React.useState('');
  const [filter, setFilter] = React.useState('All');
  const [txns, setTxns] = React.useState(() => window.TXNS.concat(window.TXNS));
  const [showFilter, setShowFilter] = React.useState(false);
  const [acct, setAcct] = React.useState('All accounts');
  const [minAmt, setMinAmt] = React.useState('');
  const [exporting, setExporting] = React.useState(false);
  const [adding, setAdding] = React.useState(false);
  const pills = ['All', 'Money in', 'Money out', 'Uncategorized', 'Pexxie'];
  const accounts = ['All accounts', 'Operating ••4290', 'Tax reserve ••5512', 'Savings ••7733'];
  const matchesFilter = (t) => {
    switch (filter) {
      case 'Money in': return t.k === 'in';
      case 'Money out': return t.k === 'out';
      case 'Uncategorized': return t.cat === 'Uncategorized';
      case 'Pexxie': return t.cat === 'Pexxie';
      default: return true;
    }
  };
  const parseAmt = (a) => Math.abs(parseFloat(String(a).replace(/[^0-9.]/g, '')) || 0);
  const needle = q.trim().toLowerCase();
  const min = Number(minAmt) || 0;
  const rows = txns.filter(t => matchesFilter(t)
    && (!needle || t.r.toLowerCase().includes(needle) || t.cat.toLowerCase().includes(needle))
    && (acct === 'All accounts' || (t.acct || 'Operating ••4290') === acct)
    && (!min || parseAmt(t.a) >= min));
  const filtersOn = acct !== 'All accounts' || min > 0;
  const exportCsv = () => {
    if (exporting) return;
    setExporting(true);
    setTimeout(() => { setExporting(false); toast(`Exported ${rows.length} transactions to CSV.`, { tone: 'sage', icon: 'download' }); }, 900);
  };
  const addTxn = (t) => {
    setTxns(ts => [t, ...ts]);
    toast(`Added ${t.r} — ${t.a}.`, { tone: 'sage', icon: 'check' });
    setAdding(false);
  };
  return (
    <div style={{ fontFamily: P.sans }}>
      <div style={{ padding: '18px 22px', borderBottom: `1px solid ${P.line}`, display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{ flex: 1 }}>
          <div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink, letterSpacing: -0.4 }}>Transactions</div>
          <div style={{ fontSize: 12.5, color: P.ink3, marginTop: 2 }}>847 total · showing {rows.length} · 6 uncategorized · $24.18 in fees this month</div>
        </div>
        <Btn kind={showFilter || filtersOn ? 'soft' : 'default'} size="sm" icon="filter" onClick={() => setShowFilter(v => !v)}>Filter{filtersOn ? ' · on' : ''}</Btn>
        <Btn kind="default" size="sm" icon="download" loading={exporting} onClick={exportCsv}>Export CSV</Btn>
        <Btn kind="primary" size="sm" icon="plus" onClick={() => setAdding(true)}>Add</Btn>
      </div>
      {showFilter && (
        <div style={{ padding: '12px 22px', borderBottom: `1px solid ${P.line}`, background: P.canvas, display: 'flex', alignItems: 'flex-end', gap: 12 }}>
          <MoneySelect label="Account" value={acct} onChange={setAcct} options={accounts} style={{ width: 210 }}/>
          <MoneyField label="Min amount" value={minAmt} onChange={setMinAmt} placeholder="0.00" type="number" icon="dollar" style={{ width: 150 }}/>
          <div style={{ flex: 1 }}/>
          <Btn kind="ghost" size="sm" onClick={() => { setAcct('All accounts'); setMinAmt(''); }}>Clear</Btn>
        </div>
      )}
      <div style={{ padding: '10px 22px', display: 'flex', gap: 8, borderBottom: `1px solid ${P.line}`, alignItems: 'center' }}>
        <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: 8, padding: '7px 11px', background: P.card, border: `1px solid ${P.line}`, borderRadius: 9, fontSize: 12.5, color: P.ink3 }}>
          <Icon name="search" size={15}/>
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search transactions…"
            style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent', fontSize: 12.5, color: P.ink, fontFamily: P.sans }}/>
        </div>
        {pills.map((t, i) => (
          <span key={i} onClick={() => setFilter(t)} style={{ cursor: 'pointer' }}>
            <Pill tone={filter === t ? 'spark' : 'neutral'} style={{ padding: '5px 11px' }}>{t}</Pill>
          </span>
        ))}
      </div>
      <div style={{ padding: '0 22px' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '90px 1fr 150px 130px 110px', gap: 12, padding: '12px 4px', borderBottom: `1px solid ${P.line}` }}>
          {['Date', 'Description', 'Category', 'Account', 'Amount'].map((h, i) => <Label key={i} style={{ textAlign: i === 4 ? 'right' : 'left' }}>{h}</Label>)}
        </div>
        {rows.length === 0 && <div style={{ padding: '30px 4px', textAlign: 'center', fontSize: 12.5, color: P.ink3 }}>No transactions match "{q}".</div>}
        {rows.map((t, i) => {
          const c = t.k === 'in' ? P.sage : t.k === 'spark' ? P.spark : t.k === 'pending' ? P.rose : P.ink;
          return (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: '90px 1fr 150px 130px 110px', gap: 12, padding: '11px 4px', borderBottom: `1px solid ${P.line}`, alignItems: 'center', fontSize: 13 }}>
              <span style={{ color: P.ink3, fontSize: 12 }}>{t.d}</span>
              <span style={{ color: P.ink, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{t.r}</span>
              <span><Pill tone={t.cat === 'Pending' ? 'rose' : 'neutral'} style={{ fontSize: 10.5 }}>{t.cat}</Pill></span>
              <span style={{ color: P.ink3, fontSize: 12 }}>{t.acct || 'Operating ••4290'}</span>
              <span style={{ fontFamily: P.mono, fontWeight: 500, color: c, textAlign: 'right' }}>{t.a}</span>
            </div>
          );
        })}
      </div>
      {adding && <AddTxnModal onClose={() => setAdding(false)} onSave={addTxn}/>}
    </div>
  );
}

function AddTxnModal({ onClose, onSave }) {
  const [desc, setDesc] = React.useState('');
  const [amount, setAmount] = React.useState('');
  const [dir, setDir] = React.useState('out');
  const [cat, setCat] = React.useState('Uncategorized');
  const [acct, setAcct] = React.useState('Operating ••4290');
  const cats = ['Revenue', 'Ingredients', 'Utilities', 'Payroll', 'Marketing', 'Fees', 'Classes', 'Uncategorized'];
  const accts = ['Operating ••4290', 'Tax reserve ••5512', 'Savings ••7733'];
  const canSave = desc.trim().length > 0 && Number(amount) > 0;
  const submit = () => {
    const n = Number(amount) || 0;
    const a = (dir === 'in' ? '+' : '−') + money(n);
    onSave({ k: dir, r: desc.trim(), cat, d: 'Today', a, acct });
  };
  return (
    <window.Modal title="Add transaction" sub="Record a manual transaction" onClose={onClose}
      foot={<>
        <Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn>
        <Btn kind="primary" size="md" disabled={!canSave} onClick={submit}>Add transaction</Btn>
      </>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <MoneyField label="Description" value={desc} onChange={setDesc} placeholder="e.g. Farmers market · retail sales" icon="fileText"/>
        <div style={{ display: 'flex', gap: 12 }}>
          <MoneyField label="Amount" value={amount} onChange={setAmount} placeholder="0.00" type="number" icon="dollar" style={{ flex: 1 }}/>
          <MoneySelect label="Direction" value={dir === 'in' ? 'Money in' : 'Money out'} onChange={v => setDir(v === 'Money in' ? 'in' : 'out')} options={['Money out', 'Money in']} style={{ flex: 1 }}/>
        </div>
        <div style={{ display: 'flex', gap: 12 }}>
          <MoneySelect label="Category" value={cat} onChange={setCat} options={cats} style={{ flex: 1 }}/>
          <MoneySelect label="Account" value={acct} onChange={setAcct} options={accts} style={{ flex: 1 }}/>
        </div>
      </div>
    </window.Modal>
  );
}

// ── Invoices list ────────────────────────────────────────────
function InvoiceList() {
  const P = window.PX; const { go } = window.useApp();
  const [tab, setTab] = React.useState('all');
  const invs = window.useStore(window.PXInvoices).invoices;
  const $0 = (v) => '$' + Math.round(v).toLocaleString();
  const sum = (f) => invs.filter(f).reduce((a, i) => a + i.amt, 0);
  const cnt = (st) => invs.filter(i => i.status === st).length;
  const outstanding = sum(i => i.status === 'sent' || i.status === 'overdue');
  const stTone = { draft: 'neutral', sent: 'sky', paid: 'sage', overdue: 'rose', void: 'outline' };
  const filtered = tab === 'all' ? invs : invs.filter(i => i.status === tab);
  return (
    <div style={{ fontFamily: P.sans }}>
      <div style={{ padding: '18px 22px 0', display: 'flex', alignItems: 'flex-start' }}>
        <div style={{ flex: 1 }}>
          <div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink, letterSpacing: -0.4 }}>Invoices</div>
          <div style={{ fontSize: 12.5, color: P.ink3, marginTop: 2 }}>{$0(outstanding)} outstanding · {$0(sum(i => i.status === 'paid'))} paid this month</div>
        </div>
        <Btn kind="primary" size="md" icon="plus" onClick={() => go('money/invoices/new')}>New invoice</Btn>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 14, padding: '16px 22px' }}>
        {[['Outstanding', $0(outstanding), 'rose'], ['Overdue', $0(sum(i => i.status === 'overdue')), 'rose'], ['Draft', $0(sum(i => i.status === 'draft')), 'neutral'], ['Paid · 30d', $0(sum(i => i.status === 'paid')), 'sage']].map((c, i) => (
          <Card key={i} pad={14}><Label>{c[0]}</Label><Num size={22} style={{ marginTop: 5 }} color={c[2] === 'rose' ? P.rose : c[2] === 'sage' ? P.sage : P.ink}>{c[1]}</Num></Card>
        ))}
      </div>
      <div style={{ padding: '0 22px' }}>
        <Tabs tabs={[{ k: 'all', label: 'All', count: invs.length }, { k: 'draft', label: 'Draft', count: cnt('draft') }, { k: 'sent', label: 'Sent', count: cnt('sent') }, { k: 'overdue', label: 'Overdue', count: cnt('overdue') }, { k: 'paid', label: 'Paid', count: cnt('paid') }]} active={tab} onChange={setTab}/>
        <div style={{ display: 'grid', gridTemplateColumns: '70px 1fr 110px 100px 90px 30px', gap: 12, padding: '12px 4px', borderBottom: `1px solid ${P.line}` }}>
          {['Invoice', 'Customer', 'Issued', 'Due', 'Amount', ''].map((h, i) => <Label key={i} style={{ textAlign: i === 4 ? 'right' : 'left' }}>{h}</Label>)}
        </div>
        {filtered.map((iv, i) => (
          <div key={iv.id} onClick={() => go('money/invoices/' + iv.id)} style={{ display: 'grid', gridTemplateColumns: '70px 1fr 110px 100px 90px 30px', gap: 12, padding: '12px 4px', borderBottom: `1px solid ${P.line}`, alignItems: 'center', cursor: 'pointer' }}
            onMouseEnter={e => e.currentTarget.style.background = P.hover} onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
            <span style={{ fontFamily: P.mono, fontSize: 12.5, color: P.ink2 }}>#{iv.id}</span>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}><Avatar name={iv.who} size={26}/><span style={{ fontSize: 13.5, color: P.ink, fontWeight: 500 }}>{iv.who}</span><Pill tone={stTone[iv.status]} style={{ fontSize: 10 }}>{iv.status}</Pill></div>
            <span style={{ fontSize: 12.5, color: P.ink3 }}>{iv.date}</span>
            <span style={{ fontSize: 12.5, color: iv.status === 'overdue' ? P.rose : P.ink3 }}>{iv.due}</span>
            <span style={{ fontFamily: P.mono, fontSize: 13, fontWeight: 500, color: P.ink, textAlign: 'right' }}>{money(iv.amt)}</span>
            <Icon name="chevR" size={15} color={P.ink4}/>
          </div>
        ))}
        {filtered.length === 0 && (
          <div style={{ padding: '36px 0', textAlign: 'center', fontSize: 13, color: P.ink3 }}>No {tab === 'all' ? '' : tab + ' '}invoices yet.</div>
        )}
      </div>
    </div>
  );
}

// ── Invoice detail ───────────────────────────────────────────
function InvoiceDetail({ id }) {
  const P = window.PX; const { go, toast } = window.useApp();
  const inv = window.useStore(window.PXInvoices).invoices.find(i => i.id === String(id));
  const [voidArm, setVoidArm] = React.useState(false);
  if (!inv) {
    return (
      <div style={{ fontFamily: P.sans, padding: 22 }}>
        <Btn kind="ghost" size="sm" icon="chevL" onClick={() => go('money/invoices')}>Invoices</Btn>
        <Card pad={28} style={{ marginTop: 14, textAlign: 'center' }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: P.ink }}>Invoice #{id} not found</div>
          <div style={{ fontSize: 12.5, color: P.ink3, marginTop: 6 }}>It may have been removed, or the link is stale.</div>
        </Card>
      </div>
    );
  }
  const open = inv.status === 'sent' || inv.status === 'overdue';
  const stPill = { draft: ['neutral', 'Draft'], sent: ['sky', 'Sent'], paid: ['sage', 'Paid'], overdue: ['rose', 'Overdue'], void: ['outline', 'Void'] }[inv.status] || ['neutral', inv.status];
  const crmLinked = inv.contact && (window.PEOPLE || []).some(p => p.id === inv.contact);
  const markPaid = () => {
    window.PXInvoices.update(inv.id, { status: 'paid' });
    window.PXInvoices.logEvent(inv.id, 'Payment recorded', 'Just now · to Operating', 'check');
    if (window.PXBank) {
      window.PXBank.set(s => ({
        ...s,
        accounts: s.accounts.map(a => a.id === 'op' ? { ...a, balance: window.PXBank.round(a.balance + inv.amt), current: window.PXBank.round(a.current + inv.amt) } : a),
        activity: [{ id: 'inv' + inv.id, acct: 'op', dir: 'in', desc: `Invoice #${inv.id} paid · ${inv.who}`, sub: 'Deposit · Operating', amt: inv.amt, date: 'Today', status: 'settled' }, ...s.activity],
      }));
    }
    toast(`Marked as paid — ${money(inv.amt)} recorded to Operating.`, { tone: 'sage', icon: 'check' });
  };
  const remind = () => {
    window.PXInvoices.logEvent(inv.id, 'Reminder sent', 'Just now · by email', 'send');
    toast(`Reminder sent to ${inv.who}.`, { tone: 'sage', icon: 'send' });
  };
  const sendDraft = () => {
    window.PXInvoices.update(inv.id, { status: 'sent' });
    window.PXInvoices.logEvent(inv.id, `Sent to ${inv.who}`, 'Just now', 'send');
    toast(`Invoice #${inv.id} sent to ${inv.who}.`, { tone: 'sage', icon: 'send' });
  };
  const doVoid = () => {
    if (!voidArm) { setVoidArm(true); return; }
    window.PXInvoices.update(inv.id, { status: 'void' });
    window.PXInvoices.logEvent(inv.id, 'Voided', 'Just now', 'x');
    setVoidArm(false);
    toast(`Invoice #${inv.id} voided.`, { icon: 'x' });
  };
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 18 }}>
        <Btn kind="ghost" size="sm" icon="chevL" onClick={() => go('money/invoices')}>Invoices</Btn>
        <div style={{ flex: 1 }}/>
        <Btn kind="default" size="sm" icon="download" onClick={() => toast('Invoice PDF downloaded.', { icon: 'download' })}>PDF</Btn>
        {(open || inv.status === 'draft') && <Btn kind="danger" size="sm" onClick={doVoid}>{voidArm ? 'Confirm void?' : 'Void'}</Btn>}
        {open && <Btn kind="default" size="sm" onClick={markPaid}>Mark as paid</Btn>}
        {open && <Btn kind="primary" size="sm" icon="send" onClick={remind}>Send reminder</Btn>}
        {inv.status === 'draft' && <Btn kind="primary" size="sm" icon="send" onClick={sendDraft}>Send invoice</Btn>}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 320px', gap: 20 }}>
        <Card pad={0}>
          <div style={{ padding: 36 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', paddingBottom: 22, borderBottom: `2px solid ${P.ink}` }}>
              <div>
                <div style={{ width: 38, height: 38, background: '#3A2A1C', borderRadius: 7, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontFamily: P.serif, color: '#F5D8A8', fontSize: 20, fontStyle: 'italic', marginBottom: 10 }}>hl</div>
                <div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 24, color: P.ink, letterSpacing: -0.4 }}>Honest Loaves</div>
                <div style={{ fontSize: 11, color: P.ink3, marginTop: 4, lineHeight: 1.5 }}>241 Metropolitan Ave<br/>Brooklyn, NY 11211</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <Pill tone={stPill[0]}>{stPill[1]}</Pill>
                <div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 30, color: P.ink, marginTop: 8 }}>#{inv.id}</div>
                <div style={{ fontSize: 11, color: P.ink3, marginTop: 8 }}>Issued {inv.date}</div>
                <div style={{ fontSize: 11, color: inv.status === 'overdue' ? P.rose : P.ink3 }}>Due {inv.due}</div>
              </div>
            </div>
            <div style={{ padding: '18px 0', borderBottom: `1px solid ${P.line}` }}>
              <Label>Bill to</Label>
              <div onClick={crmLinked ? () => go('people/' + inv.contact) : undefined}
                style={{ fontSize: 14, fontWeight: 600, color: P.ink, marginTop: 4, cursor: crmLinked ? 'pointer' : 'default', display: 'inline-flex', alignItems: 'center', gap: 5 }}>
                {inv.who} {crmLinked && <Icon name="arrowRight" size={13} color={P.ink4}/>}
              </div>
              <div style={{ fontSize: 11.5, color: P.ink3 }}>{[inv.email, inv.addr].filter(Boolean).join(' · ')}</div>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '3fr 1fr 1fr 1fr', gap: 8, padding: '12px 0', borderBottom: `1px solid ${P.line}` }}>
              {['Item', 'Qty', 'Rate', 'Amount'].map((h, i) => <Label key={i} style={{ textAlign: i ? 'right' : 'left' }}>{h}</Label>)}
            </div>
            {(inv.items || []).map((r, i) => (
              <div key={i} style={{ display: 'grid', gridTemplateColumns: '3fr 1fr 1fr 1fr', gap: 8, padding: '10px 0', fontSize: 13, color: P.ink }}>
                <span>{r.desc}</span><span style={{ textAlign: 'right' }}>{r.qty}</span><span style={{ textAlign: 'right' }}>{money(r.rate)}</span><span style={{ textAlign: 'right', fontFamily: P.mono }}>{money(r.qty * r.rate)}</span>
              </div>
            ))}
            <div style={{ display: 'flex', justifyContent: 'flex-end', paddingTop: 14 }}>
              <div style={{ width: 220 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12.5, color: P.ink3, padding: '3px 0' }}><span>Subtotal</span><span style={{ fontFamily: P.mono }}>{money(inv.subtotal != null ? inv.subtotal : inv.amt)}</span></div>
                {inv.discount > 0 && <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12.5, color: P.ink3, padding: '3px 0' }}><span>Discount</span><span style={{ fontFamily: P.mono }}>−{money(inv.discount)}</span></div>}
                {inv.tax > 0 && <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12.5, color: P.ink3, padding: '3px 0' }}><span>Tax · {inv.taxRate}%</span><span style={{ fontFamily: P.mono }}>{money(inv.tax)}</span></div>}
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', paddingTop: 8, borderTop: `1px solid ${P.line}`, marginTop: 6 }}><span style={{ fontSize: 13, fontWeight: 600, color: P.ink }}>Total due</span><Num size={22}>{money(inv.amt)}</Num></div>
              </div>
            </div>
          </div>
        </Card>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <Card pad={16}>
            <div style={{ fontSize: 13, fontWeight: 600, color: P.ink, marginBottom: 12 }}>Timeline</div>
            {(inv.timeline || []).map((e, i) => (
              <div key={i} style={{ display: 'flex', gap: 10, paddingBottom: 12 }}>
                <div style={{ width: 24, height: 24, borderRadius: 7, background: P.sunk, color: P.ink2, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Icon name={e.icon} size={13}/></div>
                <div><div style={{ fontSize: 12.5, color: P.ink, fontWeight: 500 }}>{e.t}</div><div style={{ fontSize: 11, color: P.ink3 }}>{e.d}</div></div>
              </div>
            ))}
            {(!inv.timeline || inv.timeline.length === 0) && <div style={{ fontSize: 12, color: P.ink3 }}>No activity yet.</div>}
          </Card>
          {inv.note && (
          <Card pad={16} style={{ background: P.skyWash, border: `1px solid ${P.skyTint}` }}>
            <div style={{ fontSize: 12, fontWeight: 600, color: P.sky, marginBottom: 6 }}>Update</div>
            <div style={{ fontSize: 12.5, color: P.ink2, lineHeight: 1.5 }}>{inv.note}</div>
          </Card>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Bills ────────────────────────────────────────────────────
function MoneyBills() {
  const P = window.PX; const { toast } = window.useApp();
  const [bills, setBills] = React.useState([
    { v: 'King Arthur Baking', cat: 'Ingredients', amt: 340, due: 'Due in 2 days', tone: 'amber' },
    { v: 'Con Edison', cat: 'Utilities', amt: 218.40, due: 'Due in 5 days', tone: 'neutral' },
    { v: 'Greenpoint Rent LLC', cat: 'Rent', amt: 3200, due: 'Due Apr 1', tone: 'neutral' },
    { v: 'Cintas · linens', cat: 'Services', amt: 120, due: 'Paid Mar 8', tone: 'sage' },
  ]);
  const [open, setOpen] = React.useState(false);
  const addBill = (b) => {
    setBills(bs => [{ v: b.vendor, cat: b.category, amt: Number(b.amount) || 0, due: b.due ? `Due ${b.due}` : 'Due date TBD', tone: 'amber' }, ...bs]);
    toast(`Added bill for ${b.vendor} — ${money(Number(b.amount) || 0)}.`, { tone: 'sage', icon: 'check' });
    setOpen(false);
  };
  const payBill = (idx) => {
    const b = bills[idx];
    if (!b || b.tone === 'sage') return;
    setBills(bs => bs.map((x, i) => i === idx ? { ...x, tone: 'sage', due: 'Paid just now' } : x));
    if (window.PXBank) {
      window.PXBank.set(s => ({
        ...s,
        accounts: s.accounts.map(a => a.id === 'op' ? { ...a, balance: window.PXBank.round(a.balance - b.amt), current: window.PXBank.round(a.current - b.amt) } : a),
        activity: [{ id: window.pxid('bill'), acct: 'op', dir: 'out', desc: `Bill payment · ${b.v}`, sub: b.cat, amt: -b.amt, date: 'Today', status: 'settled' }, ...s.activity],
      }));
    }
    toast(`Paid ${b.v} — ${money(b.amt)}.`, { tone: 'sage', icon: 'check' });
  };
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 18 }}>
        <div style={{ flex: 1 }}><div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink }}>Bill Pay</div><div style={{ fontSize: 12.5, color: P.ink3 }}>$2,140 due this week · $3,200 next month</div></div>
        <Btn kind="primary" size="sm" icon="plus" onClick={() => setOpen(true)}>Add bill</Btn>
      </div>
      <Card>
        {bills.map((b, i) => (
          <div key={i} style={{ padding: '14px 18px', display: 'flex', alignItems: 'center', gap: 14, borderBottom: i < bills.length - 1 ? `1px solid ${P.line}` : 'none' }}>
            <div style={{ width: 36, height: 36, borderRadius: 9, background: P.sunk, display: 'flex', alignItems: 'center', justifyContent: 'center', color: P.ink2 }}><Icon name="fileText" size={17}/></div>
            <div style={{ flex: 1 }}><div style={{ fontSize: 14, color: P.ink, fontWeight: 500 }}>{b.v}</div><div style={{ fontSize: 11.5, color: P.ink3 }}>{b.cat}</div></div>
            <Pill tone={b.tone}>{b.due}</Pill>
            <Num size={20}>{money(b.amt)}</Num>
            <Btn kind={b.tone === 'sage' ? 'soft' : 'default'} size="sm" disabled={b.tone === 'sage'} onClick={() => payBill(i)}>{b.tone === 'sage' ? 'Paid' : 'Pay'}</Btn>
          </div>
        ))}
      </Card>
      {open && <AddBillModal onClose={() => setOpen(false)} onSave={addBill}/>}
    </div>
  );
}

function AddBillModal({ onClose, onSave }) {
  const [vendor, setVendor] = React.useState('');
  const [amount, setAmount] = React.useState('');
  const [due, setDue] = React.useState('');
  const [category, setCategory] = React.useState('Ingredients');
  const cats = ['Ingredients', 'Utilities', 'Rent', 'Services', 'Marketing', 'Other'];
  const canSave = vendor.trim().length > 0 && Number(amount) > 0;
  return (
    <window.Modal title="Add bill" sub="Record a bill to pay" onClose={onClose}
      foot={<>
        <Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn>
        <Btn kind="primary" size="md" disabled={!canSave} onClick={() => onSave({ vendor, amount, due, category })}>Add bill</Btn>
      </>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <MoneyField label="Vendor" value={vendor} onChange={setVendor} placeholder="e.g. King Arthur Baking" icon="building"/>
        <MoneyField label="Amount" value={amount} onChange={setAmount} placeholder="0.00" type="number" icon="dollar"/>
        <MoneyField label="Due date" value={due} onChange={setDue} placeholder="e.g. Apr 1 or in 5 days" icon="calendar"/>
        <MoneySelect label="Category" value={category} onChange={setCategory} options={cats}/>
      </div>
    </window.Modal>
  );
}

// ── Expenses ─────────────────────────────────────────────────
const EXPENSE_CATS = ['Ingredients', 'Payroll', 'Rent', 'Marketing', 'Utilities', 'Other'];

function MoneyExpenses() {
  const P = window.PX; const { toast } = window.useApp();
  const [receipts, setReceipts] = React.useState([
    ['King Arthur · flour', '$340.00', 'Mar 11'], ['Whole Foods', '$92.30', 'Mar 8'], ['Uline · packaging', '$148.00', 'Mar 5'], ['Adobe', '$54.99', 'Mar 3'],
  ]);
  const [modal, setModal] = React.useState(null); // 'record' | 'upload' | null
  const addExpense = (vendor, amount, date, category) => {
    setReceipts(rs => [[vendor, money(Number(amount) || 0), date || 'Today'], ...rs]);
    toast(`Recorded ${vendor} — ${money(Number(amount) || 0)} · ${category}.`, { tone: 'sage', icon: 'check' });
    setModal(null);
  };
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 18 }}>
        <div style={{ flex: 1 }}><div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink }}>Expenses</div><div style={{ fontSize: 12.5, color: P.ink3 }}>$9,420 this month across 6 categories</div></div>
        <Btn kind="default" size="sm" icon="upload" onClick={() => setModal('upload')}>Upload receipt</Btn>
        <Btn kind="primary" size="sm" icon="plus" style={{ marginLeft: 8 }} onClick={() => setModal('record')}>Record</Btn>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Card pad={18}>
          <div style={{ fontSize: 14, fontWeight: 600, color: P.ink, marginBottom: 14 }}>By category · March</div>
          {[['Ingredients', 3580, 38, 'spark'], ['Payroll', 2920, 31, 'sky'], ['Rent', 1510, 16, 'sage'], ['Marketing', 850, 9, 'amber'], ['Utilities', 360, 4, 'plum'], ['Other', 200, 2, 'neutral']].map((c, i) => (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '8px 0' }}>
              <span style={{ width: 10, height: 10, borderRadius: 3, background: c[3] === 'neutral' ? P.ink4 : P[c[3]] }}/>
              <span style={{ flex: 1, fontSize: 13, color: P.ink }}>{c[0]}</span>
              <span style={{ fontSize: 12, color: P.ink3 }}>{c[2]}%</span>
              <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink, width: 70, textAlign: 'right' }}>{money(c[1])}</span>
            </div>
          ))}
        </Card>
        <Card pad={18}>
          <div style={{ fontSize: 14, fontWeight: 600, color: P.ink, marginBottom: 14 }}>Recent receipts</div>
          {receipts.map((r, i) => (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '9px 0', borderBottom: i < receipts.length - 1 ? `1px solid ${P.line}` : 'none' }}>
              <div style={{ width: 32, height: 32, borderRadius: 8, background: P.sunk, display: 'flex', alignItems: 'center', justifyContent: 'center', color: P.ink2 }}><Icon name="receipt" size={15}/></div>
              <span style={{ flex: 1, fontSize: 13, color: P.ink }}>{r[0]}</span>
              <span style={{ fontSize: 11, color: P.ink3 }}>{r[2]}</span>
              <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink }}>{r[1]}</span>
            </div>
          ))}
        </Card>
      </div>
      {modal === 'record' && <RecordExpenseModal onClose={() => setModal(null)} onSave={addExpense}/>}
      {modal === 'upload' && <UploadReceiptModal onClose={() => setModal(null)} onSave={addExpense}/>}
    </div>
  );
}

function RecordExpenseModal({ onClose, onSave }) {
  const [vendor, setVendor] = React.useState('');
  const [amount, setAmount] = React.useState('');
  const [date, setDate] = React.useState('');
  const [category, setCategory] = React.useState(EXPENSE_CATS[0]);
  const canSave = vendor.trim().length > 0 && Number(amount) > 0;
  return (
    <window.Modal title="Record expense" sub="Log a purchase or cost" onClose={onClose}
      foot={<>
        <Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn>
        <Btn kind="primary" size="md" disabled={!canSave} onClick={() => onSave(vendor, amount, date, category)}>Add expense</Btn>
      </>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <MoneyField label="Vendor" value={vendor} onChange={setVendor} placeholder="e.g. Restaurant Depot" icon="building"/>
        <MoneyField label="Amount" value={amount} onChange={setAmount} placeholder="0.00" type="number" icon="dollar"/>
        <MoneyField label="Date" value={date} onChange={setDate} placeholder="e.g. Mar 12" icon="calendar"/>
        <MoneySelect label="Category" value={category} onChange={setCategory} options={EXPENSE_CATS}/>
      </div>
    </window.Modal>
  );
}

// Simulated dropzone → mocked OCR extraction → editable category → add
function UploadReceiptModal({ onClose, onSave }) {
  const P = window.PX;
  const [scanned, setScanned] = React.useState(false);
  const [extracted, setExtracted] = React.useState(null);
  const [category, setCategory] = React.useState(EXPENSE_CATS[0]);
  const simulateScan = () => {
    const mocks = [
      { vendor: 'Restaurant Depot', amount: '187.42', date: 'Today', category: 'Ingredients' },
      { vendor: 'Uline · packaging', amount: '96.15', date: 'Today', category: 'Ingredients' },
      { vendor: 'Staples', amount: '41.28', date: 'Today', category: 'Other' },
    ];
    const pick = mocks[Math.floor(Math.random() * mocks.length)];
    setExtracted(pick);
    setCategory(pick.category);
    setScanned(true);
  };
  return (
    <window.Modal title="Upload receipt" sub={scanned ? 'Confirm the extracted details' : 'Pex reads it and fills in the details'} onClose={onClose}
      foot={scanned ? <>
        <Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn>
        <Btn kind="primary" size="md" onClick={() => onSave(extracted.vendor, extracted.amount, extracted.date, category)}>Add expense</Btn>
      </> : <Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn>}>
      {!scanned && (
        <label style={{ display: 'block', border: `1.5px dashed ${P.lineStrong}`, borderRadius: 12, padding: '40px 20px', textAlign: 'center', cursor: 'pointer', background: P.sunk }}
          onMouseEnter={e => e.currentTarget.style.background = P.hover} onMouseLeave={e => e.currentTarget.style.background = P.sunk}>
          <input type="file" accept="image/*,application/pdf" onChange={simulateScan} style={{ display: 'none' }}/>
          <div style={{ width: 42, height: 42, borderRadius: 11, background: P.card, border: `1px solid ${P.line}`, display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 12px', color: P.ink3 }}><Icon name="upload" size={19}/></div>
          <div style={{ fontSize: 13.5, color: P.ink, fontWeight: 500, marginBottom: 4 }}>Drop a receipt image, or click to browse</div>
          <div style={{ fontSize: 11.5, color: P.ink3 }}>JPG, PNG, or PDF · Pex extracts vendor, amount &amp; date</div>
        </label>
      )}
      {scanned && extracted && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px', background: P.sparkWash, border: `1px solid ${P.sparkTint}`, borderRadius: 9, fontSize: 11.5, color: P.ink2 }}>
            <Spark size={12}/>Extracted from receipt.jpg — review before saving.
          </div>
          <MoneyField label="Vendor" value={extracted.vendor} onChange={v => setExtracted(x => ({ ...x, vendor: v }))} icon="building"/>
          <MoneyField label="Amount" value={extracted.amount} onChange={v => setExtracted(x => ({ ...x, amount: v }))} type="number" icon="dollar"/>
          <MoneyField label="Date" value={extracted.date} onChange={v => setExtracted(x => ({ ...x, date: v }))} icon="calendar"/>
          <MoneySelect label="Category" value={category} onChange={setCategory} options={EXPENSE_CATS}/>
        </div>
      )}
    </window.Modal>
  );
}

// ── Payroll ──────────────────────────────────────────────────
function MoneyPayroll() {
  const P = window.PX; const { toast } = window.useApp();
  const [team, setTeam] = React.useState([
    { name: 'Rosa Kim', role: 'Head baker', gross: 1840, type: 'Salary', status: 'Scheduled' },
    { name: 'Diego Torres', role: 'Baker', gross: 1520, type: 'Hourly · 72h', status: 'Scheduled' },
    { name: 'Ethan Brooks', role: 'Counter', gross: 980, type: 'Hourly · 48h', status: 'Scheduled' },
    { name: 'Priya Venkatesan', role: 'Marketing PT', gross: 1100, type: 'Contract', status: 'Scheduled' },
  ]);
  const [history, setHistory] = React.useState([
    { date: 'Feb 28, 2025', people: 4, gross: 5440, cost: 5856, status: 'Paid' },
    { date: 'Feb 14, 2025', people: 4, gross: 5440, cost: 5856, status: 'Paid' },
    { date: 'Jan 31, 2025', people: 3, gross: 4340, cost: 4672, status: 'Paid' },
  ]);
  const [runModal, setRunModal] = React.useState(false);
  const [histModal, setHistModal] = React.useState(false);
  const [addModal, setAddModal] = React.useState(false);
  const gross = team.reduce((a, t) => a + t.gross, 0);
  const taxes = Math.round(gross * 0.0765);
  const totalCost = gross + taxes;
  const allPaid = team.length > 0 && team.every(t => t.status === 'Paid');
  const runPayroll = () => {
    setTeam(ts => ts.map(t => ({ ...t, status: 'Paid' })));
    setHistory(h => [{ date: 'Mar 14, 2025', people: team.length, gross, cost: totalCost, status: 'Paid' }, ...h]);
    if (window.PXBank) {
      window.PXBank.set(s => ({
        ...s,
        accounts: s.accounts.map(a => a.id === 'op' ? { ...a, balance: window.PXBank.round(a.balance - totalCost), current: window.PXBank.round(a.current - totalCost) } : a),
        activity: [{ id: window.pxid('pay'), acct: 'op', dir: 'out', desc: `Payroll run · ${team.length} people`, sub: 'Payroll', amt: -totalCost, date: 'Today', status: 'settled' }, ...s.activity],
      }));
    }
    setRunModal(false);
    toast(`Payroll run — ${money(totalCost)} paid to ${team.length} people.`, { tone: 'sage', icon: 'check' });
  };
  const addEmployee = (e) => {
    setTeam(ts => [...ts, { name: e.name, role: e.role || 'Team', gross: Number(e.gross) || 0, type: e.type === 'Salary' ? 'Salary' : e.type + ' · new', status: allPaid ? 'Paid' : 'Scheduled' }]);
    toast(`Added ${e.name} to payroll.`, { tone: 'sage', icon: 'check' });
    setAddModal(false);
  };
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 16 }}>
        <div style={{ flex: 1 }}><div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink }}>Payroll</div><div style={{ fontSize: 12.5, color: P.ink3 }}>{allPaid ? 'Run complete · next run in 2 weeks' : 'Next run: Friday Mar 14'} · {team.length} people · semi-monthly</div></div>
        <Btn kind="default" size="sm" icon="userPlus" onClick={() => setAddModal(true)}>Add person</Btn>
        <Btn kind="default" size="sm" icon="clock" style={{ marginLeft: 8 }} onClick={() => setHistModal(true)}>History</Btn>
        <Btn kind="spark" size="sm" icon="play" style={{ marginLeft: 8 }} disabled={allPaid} onClick={() => setRunModal(true)}>{allPaid ? 'Paid' : 'Run payroll'}</Btn>
      </div>

      {/* run summary */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 14, marginBottom: 14 }}>
        {[['Gross pay', money(gross)], ['Employer taxes', money(taxes)], ['Total cost', money(totalCost)], ['Pay date', 'Mar 14']].map((c, i) => (
          <Card key={i} pad={16}><Label>{c[0]}</Label><Num size={22} style={{ marginTop: 5 }} color={P.ink}>{c[1]}</Num>{i === 1 && <div style={{ fontSize: 11, color: P.ink3, marginTop: 4 }}>FICA + FUTA/SUTA</div>}</Card>
        ))}
      </div>

      <Card pad={0}>
        <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 120px 110px 110px 90px', gap: 12, padding: '12px 18px', borderBottom: `1px solid ${P.line}` }}>
          {['Employee', 'Type', 'Gross', 'Net', 'Status'].map((h, i) => <Label key={i} style={{ textAlign: i >= 2 && i <= 3 ? 'right' : 'left' }}>{h}</Label>)}
        </div>
        {team.map((t, i) => (
          <div key={i} style={{ display: 'grid', gridTemplateColumns: '1.4fr 120px 110px 110px 90px', gap: 12, padding: '12px 18px', borderBottom: i < team.length - 1 ? `1px solid ${P.line}` : 'none', alignItems: 'center' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 11 }}><Avatar name={t.name} size={30}/><div><div style={{ fontSize: 13.5, color: P.ink, fontWeight: 500 }}>{t.name}</div><div style={{ fontSize: 11, color: P.ink3 }}>{t.role}</div></div></div>
            <span style={{ fontSize: 12, color: P.ink3 }}>{t.type}</span>
            <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink, textAlign: 'right' }}>{money(t.gross)}</span>
            <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink2, textAlign: 'right' }}>{money(t.gross * 0.78)}</span>
            <span><Pill tone={t.status === 'Paid' ? 'sage' : 'sky'}>{t.status}</Pill></span>
          </div>
        ))}
      </Card>

      {runModal && (
        <window.Modal title="Run payroll" sub="Review before you run" onClose={() => setRunModal(false)}
          foot={<><Btn kind="ghost" size="md" onClick={() => setRunModal(false)}>Cancel</Btn><Btn kind="spark" size="md" icon="play" onClick={runPayroll}>Run · {money(totalCost)}</Btn></>}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            <div style={{ fontSize: 13, color: P.ink2, lineHeight: 1.5 }}>You're about to pay <b style={{ color: P.ink }}>{team.length} people</b> for the period ending Mar 14. {money(totalCost)} will be debited from Operating ••4290.</div>
            {[['Gross pay', money(gross)], ['Employer taxes', money(taxes)], ['Total cost', money(totalCost)]].map((r, i) => (
              <div key={i} style={{ display: 'flex', justifyContent: 'space-between', padding: '7px 0', borderTop: i === 2 ? `1px solid ${P.lineStrong}` : `1px solid ${P.line}` }}>
                <span style={{ fontSize: 13, color: P.ink2, fontWeight: i === 2 ? 600 : 400 }}>{r[0]}</span>
                <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink, fontWeight: i === 2 ? 600 : 400 }}>{r[1]}</span>
              </div>
            ))}
          </div>
        </window.Modal>
      )}
      {histModal && (
        <window.Modal title="Payroll history" sub="Past runs" onClose={() => setHistModal(false)}
          foot={<Btn kind="ghost" size="md" onClick={() => setHistModal(false)}>Close</Btn>}>
          <div>
            {history.map((h, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '11px 0', borderBottom: i < history.length - 1 ? `1px solid ${P.line}` : 'none' }}>
                <div style={{ width: 34, height: 34, borderRadius: 9, background: P.sunk, color: P.ink2, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="check" size={16}/></div>
                <div style={{ flex: 1 }}><div style={{ fontSize: 13.5, color: P.ink, fontWeight: 500 }}>{h.date}</div><div style={{ fontSize: 11.5, color: P.ink3 }}>{h.people} people · gross {money(h.gross)}</div></div>
                <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink }}>{money(h.cost)}</span>
                <Pill tone="sage">{h.status}</Pill>
              </div>
            ))}
          </div>
        </window.Modal>
      )}
      {addModal && <AddEmployeeModal onClose={() => setAddModal(false)} onSave={addEmployee}/>}
    </div>
  );
}

function AddEmployeeModal({ onClose, onSave }) {
  const [name, setName] = React.useState('');
  const [role, setRole] = React.useState('');
  const [gross, setGross] = React.useState('');
  const [type, setType] = React.useState('Salary');
  const types = ['Salary', 'Hourly', 'Contract'];
  const canSave = name.trim().length > 0 && Number(gross) > 0;
  return (
    <window.Modal title="Add to payroll" sub="Add an employee or contractor" onClose={onClose}
      foot={<><Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn><Btn kind="primary" size="md" disabled={!canSave} onClick={() => onSave({ name: name.trim(), role: role.trim(), gross, type })}>Add person</Btn></>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <MoneyField label="Name" value={name} onChange={setName} placeholder="e.g. Sam Rivera" icon="user"/>
        <MoneyField label="Role" value={role} onChange={setRole} placeholder="e.g. Baker" icon="briefcase"/>
        <div style={{ display: 'flex', gap: 12 }}>
          <MoneyField label="Gross / period" value={gross} onChange={setGross} placeholder="0.00" type="number" icon="dollar" style={{ flex: 1 }}/>
          <MoneySelect label="Pay type" value={type} onChange={setType} options={types} style={{ flex: 1 }}/>
        </div>
      </div>
    </window.Modal>
  );
}

// ── Reports (P&L / Balance sheet / Cash flow) ────────────────
const REPORT_PERIODS = [
  { v: 'March 2025', f: 1 },
  { v: 'February 2025', f: 0.86 },
  { v: 'Q1 2025', f: 2.94 },
  { v: 'YTD 2025', f: 5.4 },
];
const rMoney = (n) => (n < 0 ? '−$' + Math.abs(n).toLocaleString() : '$' + n.toLocaleString());

function MoneyReports() {
  const P = window.PX; const { toast } = window.useApp();
  const [tab, setTab] = React.useState('pnl');
  const [period, setPeriod] = React.useState('March 2025');
  const [exporting, setExporting] = React.useState(false);
  const f = (REPORT_PERIODS.find(p => p.v === period) || {}).f || 1;
  const k = (n) => Math.round(n * f);
  const tabLabel = { pnl: 'Profit & Loss', bs: 'Balance sheet', cf: 'Cash flow', coa: 'Chart of accounts', je: 'Journal entries', ar: 'AR aging' }[tab];
  const exportReport = () => {
    if (exporting) return;
    setExporting(true);
    setTimeout(() => { setExporting(false); toast(`${tabLabel} · ${period} exported to PDF.`, { tone: 'sage', icon: 'download' }); }, 900);
  };
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'center', marginBottom: 14 }}>
        <div style={{ flex: 1 }}><div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink }}>Reports</div><div style={{ fontSize: 12.5, color: P.ink3 }}>{period} · in plain English</div></div>
        <MoneySelect value={period} onChange={setPeriod} options={REPORT_PERIODS.map(p => p.v)} style={{ width: 170 }}/>
        <Btn kind="default" size="sm" icon="download" loading={exporting} style={{ marginLeft: 8 }} onClick={exportReport}>Export</Btn>
      </div>
      <Tabs tabs={[{ k: 'pnl', label: 'Profit & Loss' }, { k: 'bs', label: 'Balance sheet' }, { k: 'cf', label: 'Cash flow' }, { k: 'coa', label: 'Chart of accounts' }, { k: 'je', label: 'Journal entries' }, { k: 'ar', label: 'AR aging' }]} active={tab} onChange={setTab} style={{ marginBottom: 18 }}/>
      {tab === 'pnl' && <PnlStatement k={k} period={period}/>}
      {tab === 'bs' && <BalanceSheet k={k} period={period}/>}
      {tab === 'cf' && <CashFlow k={k} period={period}/>}
      {tab === 'coa' && <ChartOfAccounts/>}
      {tab === 'je' && <JournalEntries/>}
      {tab === 'ar' && <ARAging/>}
    </div>
  );
}

function StatementCard({ title, rows }) {
  const P = window.PX;
  return (
    <Card pad={22}>
      <div style={{ fontSize: 15, fontWeight: 600, color: P.ink, marginBottom: 14 }}>{title}</div>
      {rows.map((r, i) => (
        <div key={i} style={{ display: 'flex', justifyContent: 'space-between', padding: r[2] ? '12px 0 4px' : '5px 0', borderTop: r[3] ? `1px solid ${P.lineStrong}` : 'none', marginTop: r[3] ? 6 : 0 }}>
          <span style={{ fontSize: r[2] ? 11 : 13, fontWeight: r[2] || r[3] ? 600 : 400, color: r[2] ? P.ink3 : P.ink, textTransform: r[2] ? 'uppercase' : 'none', letterSpacing: r[2] ? 0.6 : 0, paddingLeft: r[0].startsWith('  ') ? 4 : 0 }}>{r[0].trim()}</span>
          {r[1] != null && <span style={{ fontFamily: P.mono, fontSize: 13, fontWeight: r[3] ? 600 : 400, color: r[1] < 0 ? P.ink2 : r[3] ? P.sage : P.ink }}>{rMoney(r[1])}</span>}
        </div>
      ))}
    </Card>
  );
}

function PnlStatement({ k, period }) {
  const P = window.PX;
  const [compare, setCompare] = React.useState(false);
  const rows = [['Revenue', null, true], ['  Wholesale', k(9240)], ['  Classes', k(4800)], ['  Retail / shop', k(3100)], ['  Events', k(1500)], ['Total revenue', k(18640), false, true], ['Cost of goods', null, true], ['  Ingredients', k(-3580)], ['  Packaging', k(-640)], ['Gross profit', k(14420), false, true], ['Operating expenses', null, true], ['  Payroll', k(-2920)], ['  Rent', k(-1510)], ['  Marketing', k(-850)], ['  Utilities', k(-360)], ['Net profit', k(9220), false, true]];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 18 }}>
      <StatementCard title={`Profit & Loss · ${period}`} rows={rows}/>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <Card pad={18} style={{ background: P.sageWash, border: `1px solid ${P.sageTint}` }}>
          <Label style={{ color: P.sage }}>Net margin</Label>
          <Num size={44} style={{ marginTop: 6 }} color={P.sage}>49.5%</Num>
          <div style={{ fontSize: 12.5, color: P.ink2, marginTop: 6 }}>Up from 41% in February. Strong for a bakery — industry average is 4–9%.</div>
        </Card>
        <Card pad={16}>
          <div style={{ fontSize: 13, fontWeight: 600, color: P.ink, marginBottom: 6 }}>Watch-item</div>
          <div style={{ fontSize: 12.5, color: P.ink2, lineHeight: 1.5 }}>You're profitable and growing. The one thing to watch: ingredient cost rose 11% this quarter. Two suppliers offer the same protein rating for less.</div>
          <Btn kind="default" size="sm" full style={{ marginTop: 10 }} onClick={() => setCompare(true)}>Compare suppliers</Btn>
        </Card>
      </div>
      {compare && <SupplierCompareModal onClose={() => setCompare(false)}/>}
    </div>
  );
}

function BalanceSheet({ k, period }) {
  const P = window.PX;
  const assets = [['  Operating cash ••4290', k(12408)], ['  Tax reserve ••5512', k(3820)], ['  Savings ••7733', k(8100)], ['  Accounts receivable', k(4280)], ['  Inventory · ingredients', k(2140)]];
  const liabs = [['  Accounts payable', k(2140)], ['  Sales tax payable', k(640)], ['  Payroll liabilities', k(1840)]];
  const equity = [['  Owner’s equity', k(16908)], ['  Retained earnings', k(9220)]];
  const sum = (a) => a.reduce((t, r) => t + r[1], 0);
  const totalAssets = sum(assets), totalLiabs = sum(liabs), totalEquity = sum(equity);
  const rows = [['Assets', null, true], ...assets, ['Total assets', totalAssets, false, true], ['Liabilities', null, true], ...liabs, ['Total liabilities', totalLiabs, false, true], ['Equity', null, true], ...equity, ['Total equity', totalEquity, false, true]];
  const balanced = totalAssets === totalLiabs + totalEquity;
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 18 }}>
      <StatementCard title={`Balance sheet · ${period}`} rows={rows}/>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <Card pad={18} style={{ background: balanced ? P.sageWash : P.roseWash, border: `1px solid ${balanced ? P.sageTint : P.roseTint}` }}>
          <Label style={{ color: balanced ? P.sage : P.rose }}>{balanced ? 'Balanced' : 'Out of balance'}</Label>
          <Num size={30} style={{ marginTop: 6 }} color={P.ink}>{rMoney(totalAssets)}</Num>
          <div style={{ fontSize: 12.5, color: P.ink2, marginTop: 6 }}>Assets equal liabilities plus equity — {rMoney(totalLiabs)} owed + {rMoney(totalEquity)} owner value. Your books tie out.</div>
        </Card>
        <Card pad={16}>
          <div style={{ fontSize: 13, fontWeight: 600, color: P.ink, marginBottom: 6 }}>What this means</div>
          <div style={{ fontSize: 12.5, color: P.ink2, lineHeight: 1.5 }}>You own {rMoney(totalAssets)} and owe {rMoney(totalLiabs)}, so the business is worth {rMoney(totalEquity)} to you. Cash makes up the bulk of assets — healthy liquidity.</div>
        </Card>
      </div>
    </div>
  );
}

function CashFlow({ k, period }) {
  const P = window.PX;
  const op = [['  Net profit', k(9220)], ['  + Depreciation', k(320)], ['  − Increase in receivables', k(-640)], ['  + Increase in payables', k(210)]];
  const inv = [['  Equipment purchase', k(-1200)]];
  const fin = [['  Owner draw', k(-800)]];
  const sum = (a) => a.reduce((t, r) => t + r[1], 0);
  const netOp = sum(op), netInv = sum(inv), netFin = sum(fin);
  const netChange = netOp + netInv + netFin;
  const beginning = k(17218);
  const ending = beginning + netChange;
  const rows = [['Operating activities', null, true], ...op, ['Cash from operations', netOp, false, true], ['Investing activities', null, true], ...inv, ['Cash from investing', netInv, false, true], ['Financing activities', null, true], ...fin, ['Cash from financing', netFin, false, true], ['Net change in cash', netChange, false, true], ['  Beginning cash', beginning], ['Ending cash', ending, false, true]];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 18 }}>
      <StatementCard title={`Cash flow · ${period}`} rows={rows}/>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <Card pad={18} style={{ background: netChange >= 0 ? P.sageWash : P.roseWash, border: `1px solid ${netChange >= 0 ? P.sageTint : P.roseTint}` }}>
          <Label style={{ color: netChange >= 0 ? P.sage : P.rose }}>Net cash flow</Label>
          <Num size={40} style={{ marginTop: 6 }} color={netChange >= 0 ? P.sage : P.rose}>{rMoney(netChange)}</Num>
          <div style={{ fontSize: 12.5, color: P.ink2, marginTop: 6 }}>You generated {rMoney(netOp)} from operations and ended with {rMoney(ending)} in the bank.</div>
        </Card>
        <Card pad={16}>
          <div style={{ fontSize: 13, fontWeight: 600, color: P.ink, marginBottom: 6 }}>Where cash went</div>
          <div style={{ fontSize: 12.5, color: P.ink2, lineHeight: 1.5 }}>Operations threw off healthy cash; you reinvested {rMoney(Math.abs(netInv))} in equipment and drew {rMoney(Math.abs(netFin))} as owner pay. Net, cash still grew.</div>
        </Card>
      </div>
    </div>
  );
}

function SupplierCompareModal({ onClose }) {
  const P = window.PX; const { toast } = window.useApp();
  const suppliers = [
    { name: 'King Arthur Baking', price: 0.68, protein: '12.7%', lead: '2 days', current: true },
    { name: 'Central Milling', price: 0.61, protein: '12.7%', lead: '3 days' },
    { name: 'Ardent Mills', price: 0.59, protein: '12.5%', lead: '4 days' },
  ];
  return (
    <window.Modal title="Compare flour suppliers" sub="Same protein rating · $ per lb" w={560} onClose={onClose}
      foot={<Btn kind="ghost" size="md" onClick={onClose}>Close</Btn>}>
      <div>
        <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 80px 80px 80px 90px', gap: 10, padding: '8px 0', borderBottom: `1px solid ${P.line}` }}>
          {['Supplier', 'Price/lb', 'Protein', 'Lead', ''].map((h, i) => <Label key={i} style={{ textAlign: i >= 1 && i <= 2 ? 'right' : 'left' }}>{h}</Label>)}
        </div>
        {suppliers.map((s, i) => (
          <div key={i} style={{ display: 'grid', gridTemplateColumns: '1.4fr 80px 80px 80px 90px', gap: 10, padding: '11px 0', borderBottom: i < suppliers.length - 1 ? `1px solid ${P.line}` : 'none', alignItems: 'center' }}>
            <div><span style={{ fontSize: 13, color: P.ink, fontWeight: 500 }}>{s.name}</span>{s.current && <Pill tone="sky" style={{ fontSize: 9.5, marginLeft: 6 }}>current</Pill>}</div>
            <span style={{ fontFamily: P.mono, fontSize: 12.5, color: s.price < 0.68 ? P.sage : P.ink, textAlign: 'right' }}>${s.price.toFixed(2)}</span>
            <span style={{ fontFamily: P.mono, fontSize: 12.5, color: P.ink3, textAlign: 'right' }}>{s.protein}</span>
            <span style={{ fontSize: 12, color: P.ink3, textAlign: 'right' }}>{s.lead}</span>
            {s.current ? <span style={{ fontSize: 11.5, color: P.ink4, textAlign: 'right' }}>—</span>
              : <Btn kind="soft" size="sm" onClick={() => { toast(`Switched flour supplier to ${s.name} — saves ~$${((0.68 - s.price) * 1400).toFixed(0)}/mo.`, { tone: 'sage', icon: 'check' }); onClose(); }}>Switch</Btn>}
          </div>
        ))}
        <div style={{ fontSize: 11.5, color: P.ink3, marginTop: 12, lineHeight: 1.5 }}>Central Milling matches your protein rating at $0.07/lb less — about $98/month at current volume.</div>
      </div>
    </window.Modal>
  );
}

// ── Chart of accounts ───────────────────────────────────────
const COA_GROUPS = [
  { group: 'Assets', tone: 'sky', accounts: [
    { code: '1010', name: 'Operating ••4290', balance: 12408.22 },
    { code: '1020', name: 'Tax reserve ••5512', balance: 3820.00 },
    { code: '1030', name: 'Savings ••7788', balance: 8100.00 },
    { code: '1200', name: 'Accounts receivable', balance: 4280.00 },
    { code: '1300', name: 'Inventory · ingredients', balance: 2140.00 },
  ]},
  { group: 'Liabilities', tone: 'amber', accounts: [
    { code: '2010', name: 'Accounts payable', balance: 2140.00 },
    { code: '2020', name: 'Sales tax payable', balance: 640.00 },
    { code: '2030', name: 'Payroll liabilities', balance: 1840.00 },
  ]},
  { group: 'Equity', tone: 'plum', accounts: [
    { code: '3010', name: "Owner's equity", balance: 24500.00 },
    { code: '3020', name: 'Retained earnings', balance: 18200.00 },
  ]},
  { group: 'Income', tone: 'sage', accounts: [
    { code: '4010', name: 'Wholesale revenue', balance: 9240.00 },
    { code: '4020', name: 'Class revenue', balance: 4800.00 },
    { code: '4030', name: 'Retail / shop revenue', balance: 3100.00 },
    { code: '4040', name: 'Event revenue', balance: 1500.00 },
  ]},
  { group: 'Expenses', tone: 'rose', accounts: [
    { code: '5010', name: 'Ingredients', balance: 3580.00 },
    { code: '5020', name: 'Payroll', balance: 2920.00 },
    { code: '5030', name: 'Rent', balance: 1510.00 },
    { code: '5040', name: 'Marketing', balance: 850.00 },
    { code: '5050', name: 'Utilities', balance: 360.00 },
  ]},
];

const COA_TONE = { Assets: 'sky', Liabilities: 'amber', Equity: 'plum', Income: 'sage', Expenses: 'rose' };
const COA_ORDER = ['Assets', 'Liabilities', 'Equity', 'Income', 'Expenses'];

function ChartOfAccounts() {
  const P = window.PX; const { toast } = window.useApp();
  const [accounts, setAccounts] = React.useState(() =>
    COA_GROUPS.flatMap(g => g.accounts.map(a => ({ id: window.pxid('acc'), code: a.code, name: a.name, balance: a.balance, group: g.group }))));
  const [modal, setModal] = React.useState(null); // { account } — null account = add
  const save = (data) => {
    if (data.id) { setAccounts(as => as.map(a => a.id === data.id ? { ...a, code: data.code, name: data.name, group: data.group, balance: Number(data.balance) || 0 } : a)); toast(`Updated ${data.name}.`, { tone: 'sage', icon: 'check' }); }
    else { setAccounts(as => [...as, { id: window.pxid('acc'), code: data.code, name: data.name, group: data.group, balance: Number(data.balance) || 0 }]); toast(`Added account ${data.name}.`, { tone: 'sage', icon: 'check' }); }
    setModal(null);
  };
  const del = (id) => { setAccounts(as => as.filter(a => a.id !== id)); toast('Account deleted.', { icon: 'trash' }); };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <Btn kind="primary" size="sm" icon="plus" onClick={() => setModal({ account: null })}>Add account</Btn>
      </div>
      {COA_ORDER.map((group) => {
        const rows = accounts.filter(a => a.group === group);
        if (rows.length === 0) return null;
        return (
          <Card key={group} pad={0}>
            <div style={{ padding: '13px 18px', borderBottom: `1px solid ${P.line}`, display: 'flex', alignItems: 'center', gap: 10 }}>
              <span style={{ fontSize: 14, fontWeight: 600, color: P.ink, flex: 1 }}>{group}</span>
              <Pill tone={COA_TONE[group]}>{rows.length} accounts</Pill>
            </div>
            {rows.map((a, i) => (
              <div key={a.id} style={{ display: 'grid', gridTemplateColumns: '70px 1fr 120px 58px', gap: 12, padding: '11px 18px', borderBottom: i < rows.length - 1 ? `1px solid ${P.line}` : 'none', alignItems: 'center' }}
                onMouseEnter={e => { const el = e.currentTarget.querySelector('.coa-actions'); if (el) el.style.opacity = 1; }}
                onMouseLeave={e => { const el = e.currentTarget.querySelector('.coa-actions'); if (el) el.style.opacity = 0; }}>
                <span style={{ fontFamily: P.mono, fontSize: 11.5, color: P.ink4 }}>{a.code}</span>
                <span style={{ fontSize: 13, color: P.ink }}>{a.name}</span>
                <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink, textAlign: 'right' }}>{money(a.balance)}</span>
                <span className="coa-actions" style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', opacity: 0, transition: 'opacity .12s' }}>
                  <span onClick={() => setModal({ account: a })} style={{ cursor: 'pointer', display: 'inline-flex' }}><Icon name="pencil" size={14} color={P.ink3}/></span>
                  <span onClick={() => del(a.id)} style={{ cursor: 'pointer', display: 'inline-flex' }}><Icon name="trash" size={14} color={P.ink3}/></span>
                </span>
              </div>
            ))}
          </Card>
        );
      })}
      {modal && <AccountModal account={modal.account} onClose={() => setModal(null)} onSave={save}/>}
    </div>
  );
}

function AccountModal({ account, onClose, onSave }) {
  const [code, setCode] = React.useState(account ? account.code : '');
  const [name, setName] = React.useState(account ? account.name : '');
  const [group, setGroup] = React.useState(account ? account.group : 'Assets');
  const [balance, setBalance] = React.useState(account ? String(account.balance) : '');
  const canSave = code.trim().length > 0 && name.trim().length > 0;
  return (
    <window.Modal title={account ? 'Edit account' : 'Add account'} sub="Chart of accounts entry" onClose={onClose}
      foot={<><Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn><Btn kind="primary" size="md" disabled={!canSave} onClick={() => onSave({ id: account ? account.id : null, code: code.trim(), name: name.trim(), group, balance })}>{account ? 'Save changes' : 'Add account'}</Btn></>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div style={{ display: 'flex', gap: 12 }}>
          <MoneyField label="Code" value={code} onChange={setCode} placeholder="e.g. 5060" mono style={{ width: 120 }}/>
          <MoneySelect label="Type" value={group} onChange={setGroup} options={COA_ORDER} style={{ flex: 1 }}/>
        </div>
        <MoneyField label="Account name" value={name} onChange={setName} placeholder="e.g. Delivery vehicles"/>
        <MoneyField label="Balance" value={balance} onChange={setBalance} placeholder="0.00" type="number" icon="dollar"/>
      </div>
    </window.Modal>
  );
}

// ── Journal entries ──────────────────────────────────────────
const JOURNAL = [
  { date: 'Mar 11', desc: 'Recorded Shopify payout', debit: 'Operating ••4290', credit: 'Wholesale revenue', amt: 842.30 },
  { date: 'Mar 11', desc: 'Pexxie Sparks usage', debit: 'Software & subscriptions', credit: 'Operating ••4290', amt: 4.00 },
  { date: 'Mar 10', desc: 'Paid Con Edison electric bill', debit: 'Utilities', credit: 'Operating ••4290', amt: 218.40 },
  { date: 'Mar 9', desc: 'Invoice #1025 payment received · Lila Events', debit: 'Operating ••4290', credit: 'Accounts receivable', amt: 1850.00 },
  { date: 'Mar 8', desc: 'Payroll run · Rosa Kim', debit: 'Payroll', credit: 'Operating ••4290', amt: 1840.00 },
  { date: 'Mar 7', desc: 'Recorded Square in-store sales', debit: 'Operating ••4290', credit: 'Retail / shop revenue', amt: 1240.50 },
  { date: 'Mar 5', desc: 'Purchased packaging · Uline', debit: 'Ingredients', credit: 'Operating ••4290', amt: 148.00 },
];

const ACCOUNT_NAMES = COA_GROUPS.flatMap(g => g.accounts.map(a => a.name)).concat(['Software & subscriptions']);

function JournalEntries() {
  const P = window.PX; const { toast } = window.useApp();
  const [entries, setEntries] = React.useState(() => JOURNAL.map(j => ({ ...j })));
  const [modal, setModal] = React.useState(false);
  const addEntry = (e) => {
    setEntries(es => [{ date: e.date.trim() || 'Today', desc: e.desc.trim(), debit: e.debit, credit: e.credit, amt: Number(e.amt) || 0 }, ...es]);
    toast('Journal entry added.', { tone: 'sage', icon: 'check' });
    setModal(false);
  };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
      <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <Btn kind="primary" size="sm" icon="plus" onClick={() => setModal(true)}>New entry</Btn>
      </div>
      <Card pad={0}>
        <div style={{ display: 'grid', gridTemplateColumns: '80px 1.6fr 1fr 1fr 100px', gap: 12, padding: '12px 18px', borderBottom: `1px solid ${P.line}` }}>
          {['Date', 'Description', 'Debit', 'Credit', 'Amount'].map((h, i) => <Label key={i} style={{ textAlign: i === 4 ? 'right' : 'left' }}>{h}</Label>)}
        </div>
        {entries.map((j, i) => (
          <div key={i} style={{ display: 'grid', gridTemplateColumns: '80px 1.6fr 1fr 1fr 100px', gap: 12, padding: '12px 18px', borderBottom: i < entries.length - 1 ? `1px solid ${P.line}` : 'none', alignItems: 'center' }}>
            <span style={{ fontSize: 12, color: P.ink3 }}>{j.date}</span>
            <span style={{ fontSize: 13, color: P.ink }}>{j.desc}</span>
            <span style={{ fontSize: 12, color: P.ink2 }}>{j.debit}</span>
            <span style={{ fontSize: 12, color: P.ink2 }}>{j.credit}</span>
            <span style={{ fontFamily: P.mono, fontSize: 13, fontWeight: 500, color: P.ink, textAlign: 'right' }}>{money(j.amt)}</span>
          </div>
        ))}
      </Card>
      {modal && <JournalModal onClose={() => setModal(false)} onSave={addEntry}/>}
    </div>
  );
}

function JournalModal({ onClose, onSave }) {
  const P = window.PX;
  const [date, setDate] = React.useState('');
  const [desc, setDesc] = React.useState('');
  const [debit, setDebit] = React.useState(ACCOUNT_NAMES[0]);
  const [credit, setCredit] = React.useState(ACCOUNT_NAMES[1]);
  const [amt, setAmt] = React.useState('');
  const balanced = debit !== credit;
  const canSave = desc.trim().length > 0 && Number(amt) > 0 && balanced;
  return (
    <window.Modal title="New journal entry" sub="Manual double-entry adjustment" onClose={onClose}
      foot={<><Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn><Btn kind="primary" size="md" disabled={!canSave} onClick={() => onSave({ date, desc, debit, credit, amt })}>Post entry</Btn></>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <MoneyField label="Description" value={desc} onChange={setDesc} placeholder="e.g. Reclassify March supplies" icon="fileText"/>
        <div style={{ display: 'flex', gap: 12 }}>
          <MoneySelect label="Debit" value={debit} onChange={setDebit} options={ACCOUNT_NAMES} style={{ flex: 1 }}/>
          <MoneySelect label="Credit" value={credit} onChange={setCredit} options={ACCOUNT_NAMES} style={{ flex: 1 }}/>
        </div>
        <div style={{ display: 'flex', gap: 12 }}>
          <MoneyField label="Amount" value={amt} onChange={setAmt} placeholder="0.00" type="number" icon="dollar" style={{ flex: 1 }}/>
          <MoneyField label="Date" value={date} onChange={setDate} placeholder="e.g. Mar 12" icon="calendar" style={{ flex: 1 }}/>
        </div>
        {!balanced && <div style={{ fontSize: 11.5, color: P.rose }}>Debit and credit accounts must differ.</div>}
      </div>
    </window.Modal>
  );
}

// ── AR aging ─────────────────────────────────────────────────
const AR_INVOICES = [
  { id: '1024', who: 'Café Bleu', amt: 1420.00, daysPastDue: 11 },
  { id: '1026', who: 'Greenpoint Market', amt: 2400.00, daysPastDue: -4 },
  { id: '1027', who: 'BK Food Co-op', amt: 460.00, daysPastDue: 0 },
  { id: '1019', who: 'Slate & Stone', amt: 800.00, daysPastDue: 45 },
  { id: '1012', who: 'Park Bros. Hotel', amt: 3200.00, daysPastDue: 72 },
  { id: '1005', who: 'Lila Events', amt: 610.00, daysPastDue: 95 },
];
const AR_BUCKETS = [['0–30', 'sage'], ['30–60', 'amber'], ['60–90', 'rose'], ['90+', 'plum']];
function arBucket(d) {
  if (d <= 30) return '0–30';
  if (d <= 60) return '30–60';
  if (d <= 90) return '60–90';
  return '90+';
}

function ARAging() {
  const P = window.PX; const { go } = window.useApp();
  const totals = Object.fromEntries(AR_BUCKETS.map(([b]) => [b, 0]));
  AR_INVOICES.forEach(iv => { totals[arBucket(iv.daysPastDue)] += iv.amt; });
  const grand = Object.values(totals).reduce((a, b) => a + b, 0) || 1;
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.2fr', gap: 18, alignItems: 'start' }}>
      <Card pad={18}>
        <div style={{ fontSize: 14, fontWeight: 600, color: P.ink, marginBottom: 14 }}>Outstanding by age · {money(grand)}</div>
        {AR_BUCKETS.map(([b, tone]) => {
          const pct = Math.round((totals[b] / grand) * 100);
          return (
            <div key={b} style={{ marginBottom: 12 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12.5, color: P.ink2, marginBottom: 4 }}>
                <span>{b} days</span><span style={{ fontFamily: P.mono }}>{money(totals[b])}</span>
              </div>
              <div style={{ height: 8, background: P.sunk, borderRadius: 6, overflow: 'hidden' }}><div style={{ width: pct + '%', height: '100%', background: P[tone] }}/></div>
            </div>
          );
        })}
      </Card>
      <Card pad={0}>
        <div style={{ display: 'grid', gridTemplateColumns: '70px 1fr 90px 90px', gap: 12, padding: '12px 18px', borderBottom: `1px solid ${P.line}` }}>
          {['Invoice', 'Customer', 'Bucket', 'Amount'].map((h, i) => <Label key={i} style={{ textAlign: i === 3 ? 'right' : 'left' }}>{h}</Label>)}
        </div>
        {AR_INVOICES.map((iv, i) => {
          const b = arBucket(iv.daysPastDue);
          const tone = AR_BUCKETS.find(x => x[0] === b)[1];
          return (
            <div key={i} onClick={() => go('money/invoices/' + iv.id)} style={{ display: 'grid', gridTemplateColumns: '70px 1fr 90px 90px', gap: 12, padding: '11px 18px', borderBottom: i < AR_INVOICES.length - 1 ? `1px solid ${P.line}` : 'none', alignItems: 'center', cursor: 'pointer' }}
              onMouseEnter={e => e.currentTarget.style.background = P.hover} onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
              <span style={{ fontFamily: P.mono, fontSize: 12.5, color: P.ink2 }}>#{iv.id}</span>
              <span style={{ fontSize: 13, color: P.ink }}>{iv.who}</span>
              <span><Pill tone={tone} style={{ fontSize: 10 }}>{b}d</Pill></span>
              <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink, textAlign: 'right' }}>{money(iv.amt)}</span>
            </div>
          );
        })}
      </Card>
    </div>
  );
}

// ── Tax ──────────────────────────────────────────────────────
function MoneyTax() {
  const P = window.PX; const { toast } = window.useApp();
  const quarters = [
    { q: 'Q4 2024', due: 'Jan 15', amt: 4180, status: 'paid' },
    { q: 'Q1 2025', due: 'Apr 15', amt: 4610, status: 'upcoming' },
    { q: 'Q2 2025', due: 'Jun 16', amt: '—', status: 'future' },
    { q: 'Q3 2025', due: 'Sep 15', amt: '—', status: 'future' },
  ];
  const stTone = { paid: 'sage', upcoming: 'amber', future: 'neutral' };
  const [autoReserve, setAutoReserve] = React.useState(false);
  const [docLoading, setDocLoading] = React.useState(false);
  const downloadDocs = () => {
    if (docLoading) return;
    setDocLoading(true);
    setTimeout(() => { setDocLoading(false); toast('Tax document package downloaded (3 files).', { tone: 'sage', icon: 'download' }); }, 900);
  };
  const setupAutoReserve = () => {
    if (window.PXBank) {
      window.PXBank.set(s => ({
        ...s,
        accounts: s.accounts.map(a =>
          a.id === 'op' ? { ...a, balance: window.PXBank.round(a.balance - 790), current: window.PXBank.round(a.current - 790) }
          : a.id === 'tax' ? { ...a, balance: window.PXBank.round(a.balance + 790), current: window.PXBank.round(a.current + 790) } : a),
        activity: [{ id: window.pxid('tax'), acct: 'op', dir: 'sweep', desc: 'Tax reserve top-up', sub: 'Operating → Tax reserve', amt: -790, date: 'Today', status: 'settled' }, ...s.activity],
      }));
    }
    setAutoReserve(true);
    toast('Auto-reserve on — $790 moved and 25% of every deposit now sweeps to tax reserve.', { tone: 'sage', icon: 'check' });
  };
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 16 }}>
        <div style={{ flex: 1 }}><div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink }}>Tax</div><div style={{ fontSize: 12.5, color: P.ink3 }}>Estimated quarterly taxes · Schedule C · EIN ••-•••4821</div></div>
        <Btn kind="default" size="sm" icon="download" loading={docLoading} onClick={downloadDocs}>Tax documents</Btn>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 14, marginBottom: 14 }}>
        {[['Set aside', '$3,820', 'In tax reserve ••5512', 'sky'], ['Estimated Q1 owed', '$4,610', 'Due Apr 15 · 17 days', 'amber'], ['Shortfall', '$790', 'Pex suggests a transfer', 'rose']].map((c, i) => (
          <Card key={i} pad={16}><Label>{c[0]}</Label><Num size={26} style={{ marginTop: 6 }} color={P[c[3]]}>{c[1]}</Num><div style={{ fontSize: 11.5, color: P.ink3, marginTop: 4 }}>{c[2]}</div></Card>
        ))}
      </div>

      {!autoReserve ? (
        <Card pad={18} style={{ background: P.amberWash, border: `1px solid ${P.amberTint}`, display: 'flex', gap: 14, alignItems: 'center', marginBottom: 14 }}>
          <div style={{ width: 40, height: 40, borderRadius: 10, background: P.amberTint, color: P.amber, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Icon name="alert" size={20}/></div>
          <div style={{ flex: 1 }}><div style={{ fontSize: 14, fontWeight: 600, color: P.ink }}>You're $790 short for Q1 estimated taxes.</div><div style={{ fontSize: 12.5, color: P.ink2, marginTop: 2 }}>Move $790 to your tax reserve and auto-reserve 25% of revenue going forward.</div></div>
          <Btn kind="spark" size="sm" onClick={setupAutoReserve}>Set up auto-reserve</Btn>
        </Card>
      ) : (
        <Card pad={18} style={{ background: P.sageWash, border: `1px solid ${P.sageTint}`, display: 'flex', gap: 14, alignItems: 'center', marginBottom: 14 }}>
          <div style={{ width: 40, height: 40, borderRadius: 10, background: P.sageTint, color: P.sage, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}><Icon name="check" size={20}/></div>
          <div style={{ flex: 1 }}><div style={{ fontSize: 14, fontWeight: 600, color: P.ink }}>Auto-reserve is on.</div><div style={{ fontSize: 12.5, color: P.ink2, marginTop: 2 }}>$790 moved to your tax reserve · 25% of every deposit now sweeps automatically.</div></div>
          <Toggle on={autoReserve} onClick={() => { setAutoReserve(false); toast('Auto-reserve turned off.', { icon: 'alert' }); }}/>
        </Card>
      )}

      <div style={{ display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 14, alignItems: 'start' }}>
        {/* quarterly schedule */}
        <Card pad={0}>
          <div style={{ padding: '13px 18px', borderBottom: `1px solid ${P.line}`, fontSize: 14, fontWeight: 600, color: P.ink }}>2025 quarterly schedule</div>
          {quarters.map((q, i) => (
            <div key={i} style={{ padding: '13px 18px', display: 'flex', alignItems: 'center', gap: 12, borderBottom: i < quarters.length - 1 ? `1px solid ${P.line}` : 'none' }}>
              <div style={{ width: 36, height: 36, borderRadius: 9, background: q.status === 'upcoming' ? P.amberTint : P.sunk, color: q.status === 'upcoming' ? P.amber : P.ink3, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="calendar" size={16}/></div>
              <div style={{ flex: 1 }}><div style={{ fontSize: 13.5, color: P.ink, fontWeight: 500 }}>{q.q}</div><div style={{ fontSize: 11.5, color: P.ink3 }}>Due {q.due}</div></div>
              <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink }}>{q.amt === '—' ? '—' : money(q.amt)}</span>
              <Pill tone={stTone[q.status]} style={{ fontSize: 10 }}>{q.status}</Pill>
            </div>
          ))}
        </Card>

        {/* deductions + documents */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <Card pad={18}>
            <div style={{ display: 'flex', alignItems: 'baseline', marginBottom: 12 }}><span style={{ fontSize: 14, fontWeight: 600, color: P.ink, flex: 1 }}>Deductions tracked</span><span style={{ fontFamily: P.mono, fontSize: 13, color: P.sage }}>$11,240</span></div>
            {[['Ingredients & supplies', 7180], ['Equipment & depreciation', 1860], ['Vehicle / delivery', 920], ['Home office', 680], ['Software & subscriptions', 600]].map((d, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '7px 0', borderBottom: i < 4 ? `1px solid ${P.line}` : 'none' }}>
                <Icon name="check" size={14} color={P.sage}/>
                <span style={{ flex: 1, fontSize: 12.5, color: P.ink2 }}>{d[0]}</span>
                <span style={{ fontFamily: P.mono, fontSize: 12.5, color: P.ink }}>{money(d[1])}</span>
              </div>
            ))}
            <div style={{ fontSize: 11, color: P.ink3, marginTop: 10, lineHeight: 1.5 }}>Pex categorizes deductible expenses automatically and flags anything that looks personal.</div>
          </Card>
          <Card pad={18}>
            <div style={{ fontSize: 14, fontWeight: 600, color: P.ink, marginBottom: 10 }}>Documents</div>
            {[['2024 Schedule C', 'Ready', 'sage'], ['Q4 2024 · 1040-ES', 'Filed Jan 15', 'sage'], ['1099-NEC · 2 contractors', 'Draft', 'amber']].map((d, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 0', borderBottom: i < 2 ? `1px solid ${P.line}` : 'none' }}>
                <div style={{ width: 30, height: 30, borderRadius: 8, background: P.sunk, color: P.ink2, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="fileText" size={15}/></div>
                <div style={{ flex: 1 }}><div style={{ fontSize: 12.5, color: P.ink, fontWeight: 500 }}>{d[0]}</div><div style={{ fontSize: 10.5, color: P[d[2]] }}>{d[1]}</div></div>
                <span onClick={() => toast(`${d[0]} downloaded.`, { icon: 'download' })} style={{ cursor: 'pointer', display: 'inline-flex' }}><Icon name="download" size={15} color={P.ink3}/></span>
              </div>
            ))}
          </Card>
        </div>
      </div>
    </div>
  );
}

// ── Reconcile ────────────────────────────────────────────────
function MoneyReconcile() {
  const P = window.PX; const { toast, sparks, setSparks, openOverlay } = window.useApp();
  const [rows, setRows] = React.useState([
    { id: 'r1', name: 'Square deposit', amt: '$1,240.50', note: 'Matches: in-store sales Mar 7', tone: 'sage' },
    { id: 'r2', name: 'ACH credit', amt: '$842.30', note: 'Matches: Shopify payout', tone: 'sage' },
    { id: 'r3', name: 'Card · UNKNOWN MERCHANT', amt: '$54.99', note: 'Pex guesses: Adobe subscription', tone: 'amber' },
    { id: 'r4', name: 'Check #1043', amt: '$320.00', note: 'No match found', tone: 'rose' },
  ]);
  const resolve = (id) => { setRows(rs => rs.filter(r => r.id !== id)); toast('Transaction matched and reconciled.', { tone: 'sage', icon: 'check' }); };
  const autoMatch = () => {
    const cost = 1;
    if (cost > sparks) { openOverlay('creditGate', { needed: cost, balance: sparks }); return; }
    const matchable = rows.filter(r => r.tone !== 'rose');
    if (matchable.length === 0) { toast('Nothing to auto-match — the remaining item needs a manual match.', { icon: 'alert' }); return; }
    setSparks(s => Math.max(0, s - cost));
    setRows(rs => rs.filter(r => r.tone === 'rose'));
    toast(`Pex matched ${matchable.length} transactions automatically.`, { tone: 'sage', icon: 'sparkles' });
  };
  const remaining = rows.length;
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 16 }}>
        <div style={{ flex: 1 }}><div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink }}>Reconcile</div><div style={{ fontSize: 12.5, color: P.ink3 }}>{remaining === 0 ? 'All caught up · Operating ••4290' : `${remaining} transaction${remaining === 1 ? '' : 's'} to match · Operating ••4290`}</div></div>
        {remaining > 0 && <Btn kind="spark" size="sm" icon="sparkles" onClick={autoMatch}>Auto-match all · 1 ⚡</Btn>}
      </div>
      {remaining === 0 ? (
        <Card pad={40} style={{ textAlign: 'center' }}>
          <div style={{ width: 46, height: 46, borderRadius: 12, background: P.sageTint, color: P.sage, display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 12px' }}><Icon name="check" size={22}/></div>
          <div style={{ fontSize: 15, fontWeight: 600, color: P.ink }}>Everything's reconciled</div>
          <div style={{ fontSize: 12.5, color: P.ink3, marginTop: 4 }}>Your books match the bank down to the penny.</div>
        </Card>
      ) : (
        <Card>
          {rows.map((r, i) => (
            <div key={r.id} style={{ padding: '14px 18px', display: 'flex', alignItems: 'center', gap: 14, borderBottom: i < rows.length - 1 ? `1px solid ${P.line}` : 'none' }}>
              <div style={{ width: 8, height: 8, borderRadius: 8, background: P[r.tone], flexShrink: 0 }}/>
              <div style={{ flex: 1 }}><div style={{ fontSize: 13.5, color: P.ink, fontWeight: 500 }}>{r.name}</div><div style={{ fontSize: 11.5, color: r.tone === 'rose' ? P.rose : P.ink3, marginTop: 2 }}>{r.note}</div></div>
              <span style={{ fontFamily: P.mono, fontSize: 13.5, color: P.ink }}>{r.amt}</span>
              <Btn kind={r.tone === 'sage' ? 'soft' : 'default'} size="sm" onClick={() => resolve(r.id)}>{r.tone === 'sage' ? 'Confirm' : 'Match'}</Btn>
            </div>
          ))}
        </Card>
      )}
    </div>
  );
}

// ── Payments ─────────────────────────────────────────────────
function MoneyPayments() {
  const P = window.PX; const { toast } = window.useApp();
  const [methods, setMethods] = React.useState([
    { label: 'Card · Visa, MC, Amex', on: true },
    { label: 'ACH bank transfer', on: true },
    { label: 'Apple Pay / Google Pay', on: true },
    { label: 'Cash / check (manual)', on: false },
  ]);
  const [linkModal, setLinkModal] = React.useState(false);
  const [manageModal, setManageModal] = React.useState(false);
  const [disputeSubmitted, setDisputeSubmitted] = React.useState(false);
  const toggleMethod = (i) => setMethods(ms => ms.map((m, j) => {
    if (j !== i) return m;
    toast(`${m.label} ${m.on ? 'disabled' : 'enabled'}.`, { tone: m.on ? 'neutral' : 'sage', icon: m.on ? 'x' : 'check' });
    return { ...m, on: !m.on };
  }));
  const payouts = [
    { d: 'Tomorrow', amt: 842.30, gross: 866.48, fee: 24.18, status: 'scheduled' },
    { d: 'Mar 10', amt: 1216.32, gross: 1240.50, fee: 24.18, status: 'paid' },
    { d: 'Mar 7', amt: 1809.40, gross: 1850.00, fee: 40.60, status: 'paid' },
    { d: 'Mar 4', amt: 1184.55, gross: 1210.00, fee: 25.45, status: 'paid' },
  ];
  const stTone = { scheduled: 'sky', paid: 'sage' };
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 16 }}>
        <div style={{ flex: 1 }}><div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink }}>Accept payments</div><div style={{ fontSize: 12.5, color: P.ink3 }}>How customers pay you · where the money lands</div></div>
        <Btn kind="default" size="sm" icon="link" onClick={() => setLinkModal(true)}>Payment link</Btn>
      </div>

      {/* stat strip */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 14, marginBottom: 14 }}>
        {[['Volume · MTD', '$8,420', '142 payments', 'ink'], ['Processing fees', '$114.41', '1.36% effective', 'ink'], ['Avg. payment', '$59.30', '+$4 vs Feb', 'sage'], ['Disputes', '1 open', '$54.99 held', 'rose']].map((c, i) => (
          <Card key={i} pad={16}><Label>{c[0]}</Label><Num size={22} style={{ marginTop: 5 }} color={c[3] === 'rose' ? P.rose : P.ink}>{c[1]}</Num><div style={{ fontSize: 11.5, color: c[3] === 'sage' ? P.sage : c[3] === 'rose' ? P.rose : P.ink3, marginTop: 4 }}>{c[2]}</div></Card>
        ))}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: 14, alignItems: 'start' }}>
        {/* payouts */}
        <Card pad={0}>
          <div style={{ padding: '13px 18px', borderBottom: `1px solid ${P.line}`, display: 'flex', alignItems: 'center' }}>
            <div style={{ flex: 1 }}><span style={{ fontSize: 14, fontWeight: 600, color: P.ink }}>Payouts</span><div style={{ fontSize: 11.5, color: P.ink3, marginTop: 1 }}>Daily · to Operating ••4290</div></div>
            <Pill tone="sage" dot>Auto</Pill>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 110px 90px 90px', gap: 10, padding: '10px 18px', borderBottom: `1px solid ${P.line}` }}>
            {['Date', 'Gross', 'Fees', 'Net'].map((h, i) => <Label key={i} style={{ textAlign: i ? 'right' : 'left' }}>{h}</Label>)}
          </div>
          {payouts.map((p, i) => (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: '1fr 110px 90px 90px', gap: 10, padding: '12px 18px', borderBottom: i < payouts.length - 1 ? `1px solid ${P.line}` : 'none', alignItems: 'center' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}><span style={{ fontSize: 13, color: P.ink }}>{p.d}</span><Pill tone={stTone[p.status]} style={{ fontSize: 10 }}>{p.status}</Pill></div>
              <span style={{ fontFamily: P.mono, fontSize: 12.5, color: P.ink3, textAlign: 'right' }}>{money(p.gross)}</span>
              <span style={{ fontFamily: P.mono, fontSize: 12.5, color: P.ink3, textAlign: 'right' }}>−{money(p.fee)}</span>
              <span style={{ fontFamily: P.mono, fontSize: 13, fontWeight: 500, color: P.ink, textAlign: 'right' }}>{money(p.amt)}</span>
            </div>
          ))}
        </Card>

        {/* right column */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <Card pad={18}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
              <div style={{ width: 40, height: 28, background: '#635BFF', borderRadius: 5, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 10, fontWeight: 700 }}>stripe</div>
              <div style={{ flex: 1 }}><div style={{ fontSize: 14, fontWeight: 600, color: P.ink }}>Stripe</div><div style={{ fontSize: 11.5, color: P.sage }}>Connected · payouts daily</div></div>
              <Btn kind="soft" size="sm" onClick={() => setManageModal(true)}>Manage</Btn>
            </div>
            <div style={{ fontSize: 12, color: P.ink3, lineHeight: 1.5 }}>2.9% + 30¢ per card charge · 0.8% for ACH (capped $5). Next payout <b style={{ color: P.ink }}>$842.30</b> arrives tomorrow.</div>
          </Card>
          <Card pad={18}>
            <div style={{ fontSize: 14, fontWeight: 600, color: P.ink, marginBottom: 10 }}>Accepted methods</div>
            {methods.map((m, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 0', borderBottom: i < methods.length - 1 ? `1px solid ${P.line}` : 'none' }}><Icon name="card" size={15} color={P.ink3}/><span style={{ flex: 1, fontSize: 13, color: P.ink }}>{m.label}</span><Toggle on={m.on} size="sm" onClick={() => toggleMethod(i)}/></div>
            ))}
          </Card>
          {!disputeSubmitted ? (
            <Card pad={16} style={{ background: P.roseWash, border: `1px solid ${P.roseTint}` }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}><Icon name="alert" size={16} color={P.rose}/><span style={{ fontSize: 13, fontWeight: 600, color: P.rose }}>1 dispute needs evidence</span></div>
              <div style={{ fontSize: 12, color: P.ink2, lineHeight: 1.5 }}>$54.99 charge on Mar 3 disputed as "not recognized." Respond by Mar 18 — Pex drafted the evidence from your receipt and delivery log.</div>
              <Btn kind="default" size="sm" full style={{ marginTop: 10 }} onClick={() => { setDisputeSubmitted(true); toast('Evidence submitted to Stripe. Most disputes resolve in 5–7 days.', { tone: 'sage', icon: 'check' }); }}>Review &amp; submit evidence</Btn>
            </Card>
          ) : (
            <Card pad={16} style={{ background: P.sageWash, border: `1px solid ${P.sageTint}` }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}><Icon name="check" size={16} color={P.sage}/><span style={{ fontSize: 13, fontWeight: 600, color: P.sage }}>Evidence submitted</span></div>
              <div style={{ fontSize: 12, color: P.ink2, lineHeight: 1.5 }}>Pex sent your receipt and delivery log to Stripe for the $54.99 dispute. You'll hear back in 5–7 days — no action needed.</div>
            </Card>
          )}
        </div>
      </div>
      {linkModal && <PaymentLinkModal onClose={() => setLinkModal(false)}/>}
      {manageModal && <StripeManageModal onClose={() => setManageModal(false)}/>}
    </div>
  );
}

function PaymentLinkModal({ onClose }) {
  const P = window.PX; const { toast } = window.useApp();
  const [amount, setAmount] = React.useState('');
  const [desc, setDesc] = React.useState('');
  const [link, setLink] = React.useState('');
  const generate = () => {
    const slug = Math.random().toString(36).slice(2, 8);
    setLink(`https://pay.honestloaves.com/${slug}${Number(amount) > 0 ? '?amt=' + amount : ''}`);
  };
  const copy = () => {
    try { if (navigator.clipboard) navigator.clipboard.writeText(link); } catch (e) {}
    toast('Payment link copied to clipboard.', { icon: 'copy' });
  };
  return (
    <window.Modal title="Create payment link" sub="Share a hosted checkout — no invoice needed" w={520} onClose={onClose}
      foot={link
        ? <><Btn kind="ghost" size="md" onClick={onClose}>Done</Btn><Btn kind="primary" size="md" icon="copy" onClick={copy}>Copy link</Btn></>
        : <><Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn><Btn kind="primary" size="md" icon="link" onClick={generate}>Generate link</Btn></>}>
      {!link ? (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <MoneyField label="Amount (optional)" value={amount} onChange={setAmount} placeholder="Leave blank for buyer-entered" type="number" icon="dollar"/>
          <MoneyField label="Description" value={desc} onChange={setDesc} placeholder="e.g. Sourdough class · 1 seat" icon="tag"/>
        </div>
      ) : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px', background: P.sageWash, border: `1px solid ${P.sageTint}`, borderRadius: 9, fontSize: 11.5, color: P.ink2 }}><Icon name="check" size={13} color={P.sage}/>Link ready — live and shareable.</div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 12px', background: P.sunk, border: `1px solid ${P.line}`, borderRadius: 9 }}>
            <Icon name="link" size={14} color={P.ink3}/>
            <span style={{ flex: 1, fontFamily: P.mono, fontSize: 12, color: P.ink, wordBreak: 'break-all' }}>{link}</span>
          </div>
          {(desc || Number(amount) > 0) && <div style={{ fontSize: 11.5, color: P.ink3 }}>{desc ? `For: ${desc}` : 'Buyer-entered amount'}{Number(amount) > 0 ? ` · ${money(Number(amount))}` : ''}</div>}
        </div>
      )}
    </window.Modal>
  );
}

function StripeManageModal({ onClose }) {
  const P = window.PX; const { toast } = window.useApp();
  const [schedule, setSchedule] = React.useState('Daily');
  const [statementDesc, setStatementDesc] = React.useState('HONEST LOAVES');
  return (
    <window.Modal title="Manage Stripe" sub="Connected · payouts to Operating ••4290" onClose={onClose}
      foot={<><Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn><Btn kind="primary" size="md" onClick={() => { toast('Stripe settings saved.', { tone: 'sage', icon: 'check' }); onClose(); }}>Save changes</Btn></>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <MoneySelect label="Payout schedule" value={schedule} onChange={setSchedule} options={['Daily', 'Weekly', 'Monthly', 'Manual']}/>
        <MoneyField label="Statement descriptor" value={statementDesc} onChange={setStatementDesc} icon="card"/>
        <div style={{ fontSize: 11.5, color: P.ink3, lineHeight: 1.5 }}>2.9% + 30¢ per card · 0.8% ACH (capped $5). Next payout $842.30 arrives tomorrow.</div>
      </div>
    </window.Modal>
  );
}

function MoneyProducts() {
  const P = window.PX; const { toast } = window.useApp();
  const [cat, setCat] = React.useState('all');
  const [products, setProducts] = React.useState([
    { name: 'Country bâtard', sku: 'BRD-001', cat: 'Bread', unit: 'each', price: 8.00, cost: 2.10, used: 64, on: true },
    { name: 'Baguette', sku: 'BRD-002', cat: 'Bread', unit: 'each', price: 4.50, cost: 1.05, used: 88, on: true },
    { name: 'Pain de mie', sku: 'BRD-003', cat: 'Bread', unit: 'loaf', price: 7.00, cost: 1.80, used: 41, on: true },
    { name: 'Seeded rye', sku: 'BRD-004', cat: 'Bread', unit: 'loaf', price: 9.00, cost: 2.40, used: 22, on: false },
    { name: 'Sourdough class', sku: 'CLS-001', cat: 'Class', unit: 'seat', price: 80.00, cost: 18.00, used: 36, on: true },
    { name: 'Private workshop', sku: 'CLS-002', cat: 'Class', unit: 'group', price: 450.00, cost: 90.00, used: 4, on: true },
    { name: 'Wholesale delivery', sku: 'SVC-001', cat: 'Service', unit: 'trip', price: 200.00, cost: 45.00, used: 28, on: true },
    { name: 'Gift box', sku: 'RTL-001', cat: 'Retail', unit: 'box', price: 36.00, cost: 11.00, used: 17, on: true },
  ].map(p => ({ ...p, id: window.pxid('prod') })));
  const [modal, setModal] = React.useState(null); // { product } — null product = add
  const [importOpen, setImportOpen] = React.useState(false);
  const [menuId, setMenuId] = React.useState(null);
  const cats = ['all', 'Bread', 'Class', 'Service', 'Retail'];
  const counts = {}; products.forEach(p => { counts[p.cat] = (counts[p.cat] || 0) + 1; });
  const filtered = cat === 'all' ? products : products.filter(p => p.cat === cat);
  const catTone = { Bread: 'spark', Class: 'sky', Service: 'sage', Retail: 'plum' };
  const saveProduct = (data) => {
    if (data.id) { setProducts(ps => ps.map(p => p.id === data.id ? { ...p, name: data.name, sku: data.sku, cat: data.cat, unit: data.unit, price: data.price, cost: data.cost } : p)); toast(`Updated ${data.name}.`, { tone: 'sage', icon: 'check' }); }
    else { setProducts(ps => [{ ...data, id: window.pxid('prod'), used: 0, on: true }, ...ps]); toast(`Added ${data.name} — ${money(data.price)}.`, { tone: 'sage', icon: 'check' }); }
    setModal(null);
  };
  const toggleProduct = (id) => { const p = products.find(x => x.id === id); setProducts(ps => ps.map(x => x.id === id ? { ...x, on: !x.on } : x)); if (p) toast(`${p.name} ${p.on ? 'disabled' : 'enabled'}.`, { icon: p.on ? 'x' : 'check', tone: p.on ? 'neutral' : 'sage' }); };
  const deleteProduct = (id) => { const p = products.find(x => x.id === id); setProducts(ps => ps.filter(x => x.id !== id)); toast(`${p ? p.name : 'Product'} deleted.`, { icon: 'trash' }); };
  const importProducts = (list) => {
    setProducts(ps => [...list.map(p => ({ ...p, id: window.pxid('prod'), used: 0, on: true })), ...ps]);
    toast(`Imported ${list.length} products.`, { tone: 'sage', icon: 'check' });
    setImportOpen(false);
  };
  return (
    <div style={{ fontFamily: P.sans, padding: 22 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 16 }}>
        <div style={{ flex: 1 }}><div style={{ fontFamily: P.serif, fontStyle: 'italic', fontSize: 26, color: P.ink }}>Products &amp; prices</div><div style={{ fontSize: 12.5, color: P.ink3 }}>{products.length} items · reusable across invoices, your shop, and classes</div></div>
        <Btn kind="default" size="sm" icon="upload" onClick={() => setImportOpen(true)}>Import</Btn>
        <Btn kind="primary" size="sm" icon="plus" style={{ marginLeft: 8 }} onClick={() => setModal({ product: null })}>Add product</Btn>
      </div>

      <div style={{ display: 'flex', gap: 8, marginBottom: 14 }}>
        {cats.map(c => (
          <span key={c} onClick={() => setCat(c)} style={{ fontSize: 12.5, fontWeight: 500, padding: '5px 12px', borderRadius: 999, cursor: 'pointer',
            background: cat === c ? P.sparkTint : P.sunk, color: cat === c ? P.sparkDim : P.ink2, border: `1px solid ${cat === c ? P.sparkTint : 'transparent'}`, textTransform: c === 'all' ? 'capitalize' : 'none' }}>{c === 'all' ? 'All' : c}{c !== 'all' && <span style={{ opacity: 0.6, marginLeft: 5 }}>{counts[c] || 0}</span>}</span>
        ))}
      </div>

      <Card pad={0}>
        <div style={{ display: 'grid', gridTemplateColumns: '1.6fr 90px 80px 80px 80px 70px 40px', gap: 10, padding: '11px 18px', borderBottom: `1px solid ${P.line}` }}>
          {['Product', 'Category', 'Price', 'Cost', 'Margin', 'Used 30d', ''].map((h, i) => <Label key={i} style={{ textAlign: i >= 2 && i <= 5 ? 'right' : 'left' }}>{h}</Label>)}
        </div>
        {filtered.length === 0 && <div style={{ padding: '30px 18px', textAlign: 'center', fontSize: 12.5, color: P.ink3 }}>No products in this category.</div>}
        {filtered.map((p, i) => {
          const margin = Math.round((1 - p.cost / p.price) * 100);
          return (
            <div key={p.id} style={{ display: 'grid', gridTemplateColumns: '1.6fr 90px 80px 80px 80px 70px 40px', gap: 10, padding: '12px 18px', borderBottom: i < filtered.length - 1 ? `1px solid ${P.line}` : 'none', alignItems: 'center', opacity: p.on ? 1 : 0.55 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 11 }}>
                <div style={{ width: 34, height: 34, borderRadius: 8, background: P[catTone[p.cat] + 'Tint'], display: 'flex', alignItems: 'center', justifyContent: 'center', color: P[catTone[p.cat]] }}><Icon name="tag" size={15}/></div>
                <div><div style={{ fontSize: 13.5, color: P.ink, fontWeight: 500 }}>{p.name}</div><div style={{ fontFamily: P.mono, fontSize: 10.5, color: P.ink4 }}>{p.sku} · per {p.unit}</div></div>
              </div>
              <span><Pill tone={catTone[p.cat]} style={{ fontSize: 10 }}>{p.cat}</Pill></span>
              <span style={{ fontFamily: P.mono, fontSize: 13, color: P.ink, textAlign: 'right' }}>{money(p.price)}</span>
              <span style={{ fontFamily: P.mono, fontSize: 12.5, color: P.ink3, textAlign: 'right' }}>{money(p.cost)}</span>
              <span style={{ fontFamily: P.mono, fontSize: 12.5, color: margin >= 70 ? P.sage : P.ink2, textAlign: 'right' }}>{margin}%</span>
              <span style={{ fontSize: 12.5, color: P.ink3, textAlign: 'right' }}>{p.on ? p.used + '×' : '—'}</span>
              <div style={{ position: 'relative', textAlign: 'right' }}>
                <span onClick={() => setMenuId(menuId === p.id ? null : p.id)} style={{ cursor: 'pointer', display: 'inline-flex' }}><Icon name="dotsV" size={16} color={P.ink4}/></span>
                {menuId === p.id && (
                  <React.Fragment>
                    <div onClick={() => setMenuId(null)} style={{ position: 'fixed', inset: 0, zIndex: 40 }}/>
                    <div style={{ position: 'absolute', top: '100%', right: 0, marginTop: 4, background: P.card, border: `1px solid ${P.line}`, borderRadius: 10, boxShadow: P.shLg, zIndex: 50, overflow: 'hidden', minWidth: 152 }}>
                      {[
                        { label: 'Edit', icon: 'pencil', act: () => { setModal({ product: p }); setMenuId(null); } },
                        { label: p.on ? 'Disable' : 'Enable', icon: p.on ? 'x' : 'check', act: () => { toggleProduct(p.id); setMenuId(null); } },
                        { label: 'Delete', icon: 'trash', tone: P.rose, act: () => { deleteProduct(p.id); setMenuId(null); } },
                      ].map((mi, k) => (
                        <div key={k} onClick={mi.act} style={{ display: 'flex', alignItems: 'center', gap: 9, padding: '9px 12px', cursor: 'pointer', fontSize: 12.5, color: mi.tone || P.ink, textAlign: 'left' }}
                          onMouseEnter={e => e.currentTarget.style.background = P.hover} onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                          <Icon name={mi.icon} size={14} color={mi.tone || P.ink3}/>{mi.label}
                        </div>
                      ))}
                    </div>
                  </React.Fragment>
                )}
              </div>
            </div>
          );
        })}
      </Card>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 12, fontSize: 12, color: P.ink3 }}><Pex size={18}/>Your <b style={{ color: P.ink, margin: '0 3px' }}>Country bâtard</b> carries a 74% margin and is your most-invoiced item — Pex suggests a $0.50 wholesale bump next quarter.</div>
      {modal && <ProductModal product={modal.product} onClose={() => setModal(null)} onSave={saveProduct}/>}
      {importOpen && <ImportProductsModal onClose={() => setImportOpen(false)} onImport={importProducts}/>}
    </div>
  );
}

function ProductModal({ product, onClose, onSave }) {
  const [name, setName] = React.useState(product ? product.name : '');
  const [sku, setSku] = React.useState(product ? product.sku : '');
  const [cat, setCat] = React.useState(product ? product.cat : 'Bread');
  const [unit, setUnit] = React.useState(product ? product.unit : 'each');
  const [price, setPrice] = React.useState(product ? String(product.price) : '');
  const [cost, setCost] = React.useState(product ? String(product.cost) : '');
  const cats = ['Bread', 'Class', 'Service', 'Retail'];
  const canSave = name.trim().length > 0 && Number(price) > 0;
  return (
    <window.Modal title={product ? 'Edit product' : 'Add product'} sub="Reusable across invoices, shop & classes" onClose={onClose}
      foot={<><Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn><Btn kind="primary" size="md" disabled={!canSave} onClick={() => onSave({ id: product ? product.id : null, name: name.trim(), sku: sku.trim() || 'NEW-' + Math.floor(Math.random() * 900 + 100), cat, unit: unit.trim() || 'each', price: Number(price) || 0, cost: Number(cost) || 0 })}>{product ? 'Save changes' : 'Add product'}</Btn></>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <MoneyField label="Name" value={name} onChange={setName} placeholder="e.g. Cinnamon roll" icon="tag"/>
        <div style={{ display: 'flex', gap: 12 }}>
          <MoneyField label="SKU" value={sku} onChange={setSku} placeholder="auto" mono style={{ flex: 1 }}/>
          <MoneySelect label="Category" value={cat} onChange={setCat} options={cats} style={{ flex: 1 }}/>
        </div>
        <div style={{ display: 'flex', gap: 12 }}>
          <MoneyField label="Price" value={price} onChange={setPrice} placeholder="0.00" type="number" icon="dollar" style={{ flex: 1 }}/>
          <MoneyField label="Cost" value={cost} onChange={setCost} placeholder="0.00" type="number" icon="dollar" style={{ flex: 1 }}/>
        </div>
        <MoneyField label="Unit" value={unit} onChange={setUnit} placeholder="e.g. each, loaf, seat"/>
      </div>
    </window.Modal>
  );
}

function ImportProductsModal({ onClose, onImport }) {
  const P = window.PX;
  const [scanned, setScanned] = React.useState(false);
  const preview = [
    { name: 'Focaccia · rosemary', sku: 'BRD-005', cat: 'Bread', unit: 'each', price: 6.5, cost: 1.6 },
    { name: 'Ciabatta', sku: 'BRD-006', cat: 'Bread', unit: 'loaf', price: 5.5, cost: 1.3 },
    { name: 'Croissant · 6-pack', sku: 'RTL-002', cat: 'Retail', unit: 'pack', price: 18, cost: 5.4 },
  ];
  return (
    <window.Modal title="Import products" sub={scanned ? `${preview.length} products found in your file` : 'Upload a CSV — Pex maps the columns'} onClose={onClose}
      foot={scanned
        ? <><Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn><Btn kind="primary" size="md" onClick={() => onImport(preview)}>Import {preview.length}</Btn></>
        : <Btn kind="ghost" size="md" onClick={onClose}>Cancel</Btn>}>
      {!scanned ? (
        <label style={{ display: 'block', border: `1.5px dashed ${P.lineStrong}`, borderRadius: 12, padding: '36px 20px', textAlign: 'center', cursor: 'pointer', background: P.sunk }}
          onMouseEnter={e => e.currentTarget.style.background = P.hover} onMouseLeave={e => e.currentTarget.style.background = P.sunk}>
          <input type="file" accept=".csv,text/csv" onChange={() => setScanned(true)} style={{ display: 'none' }}/>
          <div style={{ width: 42, height: 42, borderRadius: 11, background: P.card, border: `1px solid ${P.line}`, display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 12px', color: P.ink3 }}><Icon name="upload" size={19}/></div>
          <div style={{ fontSize: 13.5, color: P.ink, fontWeight: 500, marginBottom: 4 }}>Drop a CSV, or click to browse</div>
          <div style={{ fontSize: 11.5, color: P.ink3 }}>Columns: name, sku, category, price, cost</div>
        </label>
      ) : (
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px', marginBottom: 10, background: P.sparkWash, border: `1px solid ${P.sparkTint}`, borderRadius: 9, fontSize: 11.5, color: P.ink2 }}>
            <Spark size={12}/>Mapped from products.csv — review before importing.
          </div>
          {preview.map((p, i) => (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 0', borderBottom: i < preview.length - 1 ? `1px solid ${P.line}` : 'none' }}>
              <Icon name="tag" size={15} color={P.ink3}/>
              <span style={{ flex: 1, fontSize: 13, color: P.ink }}>{p.name}</span>
              <span style={{ fontFamily: P.mono, fontSize: 11, color: P.ink4 }}>{p.sku}</span>
              <span style={{ fontFamily: P.mono, fontSize: 12.5, color: P.ink }}>{money(p.price)}</span>
            </div>
          ))}
        </div>
      )}
    </window.Modal>
  );
}
