// Design 1: LEDGER — Clean B2B SaaS, spreadsheet-style dense catalog.
// Navy + cool-gray palette, Inter, single blue accent.

const L = {
  bg: '#f7f8fa',
  surface: '#ffffff',
  border: '#e4e7ec',
  borderStrong: '#d0d5dd',
  text: '#101828',
  textMid: '#475467',
  textDim: '#667085',
  accent: '#2e5dff',
  accentDim: '#eaf0ff',
  discount: '#067647',
  discountBg: '#ecfdf3',
  warn: '#b54708',
  warnBg: '#fffaeb',
  row: '#fafbfc',
  font: '"Inter", system-ui, sans-serif',
  mono: '"JetBrains Mono", ui-monospace, monospace',
};

// Shares the signed-in reseller + top-nav state with the (duplicated) top bars.
const LedgerNav = React.createContext(null);

function LedgerApp({ catalog, warehouses }) {
  const [screen, setScreen] = React.useState('login'); // login | warehouse | catalog | review | confirm
  const [tab, setTab] = React.useState('catalog');     // catalog | orders (post-login nav)
  const [user, setUser] = React.useState(null);        // { token, name, company, resellerId }
  const [orders, setOrders] = React.useState([]);
  const [ordersLoading, setOrdersLoading] = React.useState(false);
  const [warehouse, setWarehouse] = React.useState(null);
  const [detailSku, setDetailSku] = React.useState(null);
  const cart = useCart();
  const [confirmation, setConfirmation] = React.useState(null);
  const [warehouseSwitchWarning, setWarehouseSwitchWarning] = React.useState(false);
  const [stockMap, setStockMap] = React.useState(null); // sku → live available for current warehouse

  // Pull server-authoritative availability (on_hand − active holds) for the
  // selected warehouse, so ordering reflects real stock and reservations.
  React.useEffect(() => {
    if (!warehouse) { setStockMap(null); return undefined; }
    let cancelled = false;
    setStockMap(null);
    fetch(`/api/inventory?resource=stock&warehouse=${encodeURIComponent(warehouse.name)}`)
      .then((r) => (r.ok ? r.json() : Promise.reject(new Error('stock'))))
      .then((d) => {
        if (cancelled) return;
        const m = {};
        (d.stock || []).forEach((s) => { m[s.sku] = s.available; });
        setStockMap(m);
      })
      .catch(() => { if (!cancelled) setStockMap(null); });
    return () => { cancelled = true; };
  }, [warehouse]);

  // Catalog with live availability overlaid onto the current warehouse's stock.
  const liveCatalog = React.useMemo(() => {
    if (!warehouse || !stockMap) return catalog;
    // Real availability only: a SKU with no stock record in this warehouse is 0,
    // not the catalog's placeholder number.
    return catalog.map((p) => ({ ...p, stock: { ...p.stock, [warehouse.name]: stockMap[p.sku] ?? 0 } }));
  }, [catalog, warehouse, stockMap]);

  const loadOrders = React.useCallback(async (token) => {
    if (!token) return;
    setOrdersLoading(true);
    try {
      const res = await fetch('/api/orders', { headers: { Authorization: `Bearer ${token}` } });
      const data = await res.json().catch(() => ({}));
      if (res.ok) setOrders(data.orders || []);
    } catch (_) { /* offline — keep whatever we have */ }
    setOrdersLoading(false);
  }, []);

  const handleLogin = (u) => {
    setUser(u);
    setTab('catalog');
    setScreen('warehouse');
    loadOrders(u?.token);
  };

  const doSubmit = async (shipping) => {
    const items = cart.lineItems(liveCatalog, warehouse, user?.discountPercent);
    const subtotal = items.reduce((a, b) => a + b.subtotal, 0);
    const retail = items.reduce((a, b) => a + b.retailSubtotal, 0);
    const exportFee = subtotal > 0 ? exportLicenseFee(warehouse) : 0;
    const totals = summarizeOrderItems(items, exportFee);
    const poNumber = 'PO-' + Date.now().toString().slice(-7);
    setConfirmation({
      id: poNumber,
      date: new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }),
      customer: user?.company || user?.name || 'Reseller account',
      warehouse, shipping, items, subtotal, retail, exportFee, totals,
      savings: retail - subtotal,
      token: user?.token || null,
      serverId: null,
      invoice: { state: user?.token ? 'creating' : 'skipped' },
    });
    setScreen('confirm');
    if (!user?.token) return;
    // Persist the order, then create + email the real QuickBooks invoice.
    try {
      const res = await fetch('/api/orders', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${user.token}` },
        body: JSON.stringify({
          poNumber, warehouse: warehouse?.name, shipTo: shipping,
          items: items.map((it) => ({ sku: it.sku, name: it.name, qty: it.qty, buy: it.buy, subtotal: it.subtotal })),
          subtotal, retail, exportFee, total: totals.grandTotal,
        }),
      });
      const data = await res.json().catch(() => ({}));
      loadOrders(user.token);
      const serverId = data?.order?.id;
      if (!serverId) {
        setConfirmation((c) => (c ? { ...c, invoice: { state: 'error' } } : c));
        return;
      }
      // Reconcile the in-stock/backorder split with what the server actually
      // held vs. routed to production (authoritative).
      const bySku = {};
      (data?.fulfillment?.lines || []).forEach((l) => { bySku[l.sku] = l; });
      setConfirmation((c) => {
        if (!c) return c;
        const merged = c.items.map((it) => {
          const l = bySku[it.sku];
          return l ? { ...it, inStockQty: l.inStock, additionalQty: l.backorder } : it;
        });
        return { ...c, serverId, items: merged, totals: summarizeOrderItems(merged, c.exportFee || 0) };
      });
      const inv = await fetch(`/api/orders/${serverId}/invoice`, {
        method: 'POST',
        headers: { Authorization: `Bearer ${user.token}` },
      });
      const invData = await inv.json().catch(() => ({}));
      setConfirmation((c) => {
        if (!c) return c;
        return inv.ok
          ? { ...c, invoice: { state: 'ready', docNumber: invData.qbo_doc_number, emailedTo: invData.invoice_emailed_to } }
          : { ...c, invoice: { state: 'error', detail: invData.error } };
      });
    } catch (_) {
      setConfirmation((c) => (c ? { ...c, invoice: { state: 'error' } } : c));
    }
  };

  const requestWarehouseSwitch = () => {
    if (cart.totalUnits > 0) {
      setWarehouseSwitchWarning(true);
      return;
    }
    setScreen('warehouse');
  };

  const confirmWarehouseSwitch = () => {
    cart.clear();
    setDetailSku(null);
    setWarehouseSwitchWarning(false);
    setScreen('warehouse');
  };

  const detailProduct = detailSku ? liveCatalog.find(p => p.sku === detailSku) : null;

  const reorder = (order) => {
    const wh = warehouses.find((w) => w.name === order.warehouse) || warehouses[0];
    setWarehouse(wh);
    cart.clear();
    (order.items || []).forEach((it) => { if (it.sku) cart.setQty(it.sku, Number(it.qty) || 0); });
    setTab('catalog');
    setScreen('review');
  };

  const nav = {
    user, tab,
    onNav: (t) => {
      setTab(t);
      if (t === 'orders') loadOrders(user?.token);
      if (t === 'catalog' && screen !== 'login' && !warehouse) setScreen('warehouse');
    },
  };

  return (
    <LedgerNav.Provider value={nav}>
    <div style={{
      width: '100%', height: '100%', background: L.bg, color: L.text,
      fontFamily: L.font, fontSize: 13, overflow: 'hidden', display: 'flex', flexDirection: 'column', position: 'relative',
    }}>
      {screen === 'login' && <LedgerLogin onLogin={handleLogin} />}
      {screen !== 'login' && tab === 'orders' && <LedgerOrders orders={orders} loading={ordersLoading} onReorder={reorder} />}
      {screen !== 'login' && tab === 'catalog' && <>
        {screen === 'warehouse' && <LedgerWarehousePick warehouses={warehouses} onPick={(w) => { setWarehouse(w); setScreen('catalog'); }} />}
        {screen === 'catalog' && <LedgerCatalog
          catalog={liveCatalog} warehouse={warehouse} cart={cart}
          discountPercent={user?.discountPercent}
          onSwitchWarehouse={requestWarehouseSwitch}
          onReview={() => setScreen('review')}
          onOpenDetail={setDetailSku}
        />}
        {screen === 'review' && <LedgerReview
          catalog={liveCatalog} warehouse={warehouse} cart={cart}
          discountPercent={user?.discountPercent}
          onBack={() => setScreen('catalog')}
          onConfirm={doSubmit}
        />}
        {screen === 'confirm' && <LedgerConfirmation
          order={confirmation}
          onNew={() => { cart.clear(); setScreen('warehouse'); }}
        />}
      </>}
      {detailProduct && <LedgerProductDetail
        product={detailProduct} warehouse={warehouse} cart={cart}
        discountPercent={user?.discountPercent}
        onClose={() => setDetailSku(null)}
      />}
      {cart.qtyChoice && <LedgerQtyChoice choice={cart.qtyChoice} cart={cart} />}
      {cart.requestMoreChoice && (
        <LedgerConfirmDialog
          title="Add to backorder?"
          message={`This will add ${fmtInt(cart.requestMoreChoice.requested - cart.requestMoreChoice.available)} unit(s) on backorder, pending review by your account manager.`}
          confirmLabel="Confirm backorder"
          cancelLabel="Cancel"
          onConfirm={cart.confirmRequestMore}
          onCancel={cart.cancelRequestMore}
        />
      )}
      {cart.removeChoice && (
        <LedgerConfirmDialog
          title="Remove item?"
          message="Are you sure you want to remove this item from your order?"
          confirmLabel="Remove item"
          cancelLabel="Keep item"
          destructive
          onConfirm={cart.confirmRemove}
          onCancel={cart.cancelRemove}
        />
      )}
      {warehouseSwitchWarning && (
        <LedgerConfirmDialog
          title="Switch warehouse?"
          message="Are you sure you want to switch warehouse locations? Your current selections will be cleared."
          confirmLabel="Switch warehouse"
          cancelLabel="Keep current order"
          destructive
          onConfirm={confirmWarehouseSwitch}
          onCancel={() => setWarehouseSwitchWarning(false)}
        />
      )}
    </div>
    </LedgerNav.Provider>
  );
}

function LedgerConfirmDialog({ title, message, confirmLabel, cancelLabel, destructive, onConfirm, onCancel }) {
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 60, background: 'rgba(16,24,40,0.42)', display: 'grid', placeItems: 'center', padding: 16 }} onClick={onCancel}>
      <div onClick={(e) => e.stopPropagation()} style={{ width: 430, maxWidth: 'calc(100vw - 32px)', background: L.surface, border: `1px solid ${L.border}`, borderRadius: 12, boxShadow: '0 24px 70px rgba(0,0,0,.22)', padding: 24, maxHeight: '88dvh', overflowY: 'auto' }}>
        <div style={{ fontSize: 18, fontWeight: 700, marginBottom: 8 }}>{title}</div>
        <div style={{ fontSize: 13, color: L.textMid, lineHeight: 1.55, marginBottom: 18 }}>{message}</div>
        <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10, flexWrap: 'wrap' }}>
          <button onClick={onCancel} style={secondaryBtn}>{cancelLabel}</button>
          <button onClick={onConfirm} style={{ ...secondaryBtn, background: destructive ? L.warn : L.accent, color: '#fff', border: 'none' }}>{confirmLabel}</button>
        </div>
      </div>
    </div>
  );
}

function LedgerQtyChoice({ choice, cart }) {
  const isOutOfStock = choice.available === 0;
  const backorderUnits = choice.requested - choice.available;
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 40, background: 'rgba(16,24,40,0.42)', display: 'grid', placeItems: 'center', padding: 16 }}>
      <div style={{ width: 440, maxWidth: 'calc(100vw - 32px)', background: L.surface, border: `1px solid ${L.border}`, borderRadius: 12, boxShadow: '0 24px 70px rgba(0,0,0,.22)', padding: 24, maxHeight: '88dvh', overflowY: 'auto' }}>
        <div style={{ fontSize: 18, fontWeight: 700, marginBottom: 6 }}>Not enough inventory</div>
        <div style={{ fontSize: 13, color: L.textMid, lineHeight: 1.55, marginBottom: 18 }}>
          {isOutOfStock ? (
            <>This item is out of stock in this warehouse. You requested <b>{fmtInt(choice.requested)}</b> units.<br/>Request more will add <b>{fmtInt(choice.requested)}</b> units on backorder, pending review.</>
          ) : (
            <>Only <b>{fmtInt(choice.available)}</b> units are available in this warehouse. You requested <b>{fmtInt(choice.requested)}</b> units.<br/>Request more will add <b>{fmtInt(backorderUnits)}</b> units on backorder, pending review. Add available qty will limit the quantity to the current inventory.</>
          )}
        </div>
        <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10, flexWrap: 'wrap' }}>
          <button onClick={() => cart.resolveQtyChoice('more')} style={{ ...secondaryBtn, background: L.accent, color: '#fff', border: 'none' }}>Request more</button>
          {!isOutOfStock && (
            <button onClick={() => cart.resolveQtyChoice('available')} style={secondaryBtn}>Add available qty</button>
          )}
        </div>
      </div>
    </div>
  );
}

function LedgerImage({ src, inset = '88%' }) {
  return (
    <div style={{
      width: inset,
      height: inset,
      backgroundImage: `url("${src}")`,
      backgroundSize: 'contain',
      backgroundPosition: 'center',
      backgroundRepeat: 'no-repeat',
    }} />
  );
}

function useLedgerViewportWidth() {
  const [width, setWidth] = React.useState(() => window.innerWidth || 1440);
  React.useEffect(() => {
    const onResize = () => setWidth(window.innerWidth || 1440);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);
  return width;
}

// ── LOGIN ────────────────────────────────────────────────────────────────
// Single centered card — the layout is fluid (clamp + max-width), so there is no
// phone breakpoint to track here.
function LedgerLogin({ onLogin }) {
  const [username, setUsername] = React.useState('');
  const [pw, setPw] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState('');
  const [captcha, setCaptcha] = React.useState('');
  // A captcha token is single-use, so every rejected attempt has to reset the
  // widget or the next submit fails with a stale token.
  const [captchaReset, setCaptchaReset] = React.useState(0);

  const submit = async (e) => {
    e?.preventDefault?.();
    if (busy) return;
    setBusy(true);
    setError('');
    try {
      const res = await fetch('/api/resellers/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username: username.trim(), password: pw, recaptchaToken: captcha }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || `Login failed (${res.status})`);
      onLogin(data);
    } catch (err) {
      setError(err.message);
      setCaptchaReset((n) => n + 1);
      setBusy(false);
    }
  };
  // Card colors only — AuthShell paints its own dark navy ground.
  const authPalette = { surface: L.surface, border: L.borderStrong, text: L.text, font: L.font, mono: L.mono };
  return (
    <AuthShell
      palette={authPalette}
      label="Reseller Portal"
      footer={<>
        New distributor? Contact <a href="mailto:jb@gruvgear.com" style={AUTH_LINK}>jb@gruvgear.com</a>
        <div style={{ marginTop: 6 }}><SupportLine /></div>
      </>}
    >
      <form onSubmit={submit}>
        <div style={{ fontSize: 20, fontWeight: 700, letterSpacing: -0.4, marginBottom: 6, textAlign: 'center' }}>Sign in</div>
        <div style={{ fontSize: 13, lineHeight: 1.5, color: L.textDim, marginBottom: 24, textAlign: 'center' }}>
          Use the username and password provided by your account manager.
        </div>

        <AuthField palette={authPalette} label="Username" value={username} onChange={setUsername} autoComplete="username" />
        <div style={{ height: 16 }} />
        <AuthField palette={authPalette} label="Password" value={pw} onChange={setPw} type="password" autoComplete="current-password" />

        {error ? (
          <div style={{ marginTop: 14, padding: '8px 12px', borderRadius: 8, background: '#fef3f2', color: '#b42318', fontSize: 12 }}>{error}</div>
        ) : null}

        <label style={{ display: 'flex', gap: 8, alignItems: 'center', marginTop: 14, minHeight: 24, fontSize: 13, color: L.textMid, cursor: 'pointer' }}>
          <input type="checkbox" defaultChecked style={{ width: 16, height: 16, accentColor: L.accent }} /> Keep me signed in
        </label>

        <Recaptcha onToken={setCaptcha} resetSignal={captchaReset} />

        <button type="submit" disabled={busy || (recaptchaEnabled() && !captcha)} style={{
          marginTop: 22, width: '100%', height: 46, border: 'none', borderRadius: 10,
          background: L.accent, color: '#fff', fontSize: 15, fontWeight: 600,
          cursor: busy ? 'wait' : 'pointer', fontFamily: L.font,
          opacity: busy || (recaptchaEnabled() && !captcha) ? 0.7 : 1,
        }}>{busy ? 'Signing in…' : 'Sign in'}</button>
      </form>
    </AuthShell>
  );
}

function LedgerField({ label, value, onChange, type = 'text', mono }) {
  return (
    <label style={{ display: 'block' }}>
      <div style={{ fontSize: 12, color: L.textMid, marginBottom: 6, fontWeight: 500 }}>{label}</div>
      <input type={type} value={value} onChange={e => onChange(e.target.value)} style={{
        width: '100%', height: 40, padding: '0 12px',
        border: `1px solid ${L.borderStrong}`, borderRadius: 8,
        fontSize: 14, fontFamily: mono ? L.mono : L.font,
        background: '#fff', color: L.text, outline: 'none', boxSizing: 'border-box',
      }} />
    </label>
  );
}

// ── WAREHOUSE PICKER ─────────────────────────────────────────────────────
function LedgerWarehousePick({ warehouses, onPick }) {
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  return (
    <>
      <LedgerTopBar />
      <div style={{ flex: 1, overflow: 'auto', padding: isPhone ? '24px 14px' : '48px 48px' }}>
        <div style={{ maxWidth: 1100, margin: '0 auto' }}>
          <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim, letterSpacing: 1.5, marginBottom: 8 }}>STEP 1 / 3</div>
          <div style={{ fontSize: isPhone ? 24 : 28, fontWeight: 600, letterSpacing: -0.5, marginBottom: 6 }}>Choose a shipping warehouse</div>
          <div style={{ fontSize: 14, color: L.textMid, marginBottom: 32 }}>
            Each order ships from a single warehouse. Pricing and availability vary by region.
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: isPhone ? '1fr' : 'repeat(3, 1fr)', gap: isPhone ? 12 : 20 }}>
            {warehouses.map((w, i) => {
              const stats = [
                { label: 'SKUs available', v: i === 0 ? '1,284' : i === 1 ? '962' : '741' },
                { label: 'Currency', v: w.currency },
                { label: 'Ships to', v: i === 0 ? 'Global' : i === 1 ? 'US / CA / MX' : 'EU / UK' },
              ];
              return (
                <button key={w.id} onClick={() => onPick(w)} style={{
                  textAlign: 'left', background: L.surface,
                  border: `1px solid ${L.border}`, borderRadius: 12, padding: 24,
                  cursor: 'pointer', fontFamily: L.font, transition: 'all .15s',
                }} onMouseOver={e => { e.currentTarget.style.borderColor = L.accent; e.currentTarget.style.boxShadow = `0 0 0 3px ${L.accentDim}`; }}
                  onMouseOut={e => { e.currentTarget.style.borderColor = L.border; e.currentTarget.style.boxShadow = 'none'; }}
                >
                  <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 24 }}>
                    <div style={{ fontSize: 32 }}>{w.flag}</div>
                    <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim, letterSpacing: 1 }}>{w.code}</div>
                  </div>
                  <div style={{ fontSize: 20, fontWeight: 600, marginBottom: 2 }}>{w.name}</div>
                  <div style={{ fontSize: 13, color: L.textDim, marginBottom: 20 }}>{w.country}</div>
                  <div style={{ borderTop: `1px solid ${L.border}`, paddingTop: 16, display: 'grid', gridTemplateColumns: '1fr 1fr', rowGap: 10, columnGap: 8 }}>
                    {stats.map(s => (
                      <div key={s.label}>
                        <div style={{ fontSize: 10, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 2 }}>{s.label}</div>
                        <div style={{ fontSize: 13, fontWeight: 500, fontFamily: L.mono }}>{s.v}</div>
                      </div>
                    ))}
                  </div>
                </button>
              );
            })}
          </div>
        </div>
      </div>
    </>
  );
}

// ── TOP BAR ──────────────────────────────────────────────────────────────
function ledgerInitials(text) {
  const parts = String(text || '').trim().split(/\s+/).filter(Boolean);
  if (!parts.length) return 'GG';
  return (parts[0][0] + (parts[1] ? parts[1][0] : '')).toUpperCase();
}

function LedgerTopBar({ warehouse, onSwitch }) {
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  const isCompact = width < 1040;
  const nav = React.useContext(LedgerNav) || {};
  const user = nav.user;
  const tab = nav.tab || 'catalog';
  const onNav = nav.onNav || (() => {});
  const navLink = (key, label) => (
    <a onClick={() => onNav(key)} style={{ color: tab === key ? L.text : L.textMid, fontWeight: tab === key ? 600 : 400, cursor: 'pointer' }}>{label}</a>
  );
  return (
    <div style={{
      flex: '0 0 auto', minHeight: 56, background: L.surface,
      borderBottom: `1px solid ${L.border}`,
      display: 'flex', alignItems: 'center', padding: isPhone ? '8px 12px' : '0 24px', gap: isPhone ? 10 : 20,
      flexWrap: isPhone ? 'wrap' : 'nowrap',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <BrandLogo size={26} radius={6} />
        <div style={{ fontSize: 14, fontWeight: 600, letterSpacing: -0.3 }}>Gruv Gear | Krane Reseller Portal</div>
      </div>
      {!isPhone && <div style={{ width: 1, height: 22, background: L.border }} />}
      {!isCompact && <div style={{ display: 'flex', gap: 20, fontSize: 13, color: L.textMid }}>
        {navLink('catalog', 'Catalog')}
        {navLink('orders', 'Orders')}
      </div>}
      <div style={{ flex: 1 }} />
      {warehouse && (
        <button onClick={onSwitch} style={{
          display: 'flex', alignItems: 'center', gap: 8,
          height: 32, padding: '0 10px 0 10px', maxWidth: isPhone ? '100%' : 'none',
          background: L.accentDim, border: `1px solid ${L.accent}33`, borderRadius: 6,
          fontSize: 12, fontWeight: 500, color: L.accent, cursor: onSwitch ? 'pointer' : 'default', fontFamily: L.font,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>
          <span>{warehouse.flag}</span> {isPhone ? warehouse.name : `Shipping from ${warehouse.name}`} <span style={{ opacity: 0.6 }}>⇄</span>
        </button>
      )}
      {!isPhone && user && <div style={{ display: 'flex', alignItems: 'center', gap: 10, paddingLeft: 8 }}>
        <div style={{ textAlign: 'right' }}>
          <div style={{ fontSize: 12, fontWeight: 500 }}>{user.name}</div>
          <div style={{ fontSize: 10, color: L.textDim, fontFamily: L.mono }}>{user.company || 'Reseller'}</div>
        </div>
        <div style={{ width: 32, height: 32, borderRadius: 16, background: L.accentDim, display: 'grid', placeItems: 'center', fontSize: 11, fontWeight: 700, color: L.accent }}>{ledgerInitials(user.name || user.company)}</div>
      </div>}
    </div>
  );
}

// ── ORDERS (per-reseller history) ─────────────────────────────────────────
const ledgerOrdTh = { padding: '11px 16px', fontWeight: 600 };
const ledgerOrdTd = { padding: '12px 16px', color: L.text };

function ledgerOrderDate(iso) {
  if (!iso) return '—';
  const d = new Date(iso);
  if (isNaN(d.getTime())) return '—';
  return d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' });
}

function ledgerOrderUnits(order) {
  return Array.isArray(order.items) ? order.items.reduce((a, it) => a + (Number(it.qty) || 0), 0) : 0;
}

function LedgerOrderCard({ order, onClick }) {
  return (
    <div onClick={onClick} style={{ background: L.surface, border: `1px solid ${L.border}`, borderRadius: 10, padding: 14, cursor: onClick ? 'pointer' : 'default' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8, gap: 8 }}>
        <div style={{ fontFamily: L.mono, fontWeight: 600 }}>{order.po_number}</div>
        <span style={{ padding: '2px 10px', borderRadius: 999, background: L.accentDim, color: L.accent, fontSize: 11, fontWeight: 600, whiteSpace: 'nowrap' }}>{order.status}</span>
      </div>
      <div style={{ fontSize: 12, color: L.textMid, display: 'grid', gap: 3 }}>
        <div>{ledgerOrderDate(order.created_at)} · {order.warehouse || '—'}</div>
        <div>{fmtInt(ledgerOrderUnits(order))} units · <span style={{ fontWeight: 600, color: L.text }}>{fmt(Number(order.total) || 0)}</span></div>
      </div>
    </div>
  );
}

function LedgerOrders({ orders, loading, onReorder }) {
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  const [selected, setSelected] = React.useState(null);
  return (
    <>
      <LedgerTopBar />
      <div style={{ flex: 1, overflow: 'auto', padding: isPhone ? '24px 14px' : '40px 48px' }}>
        <div style={{ maxWidth: 1100, margin: '0 auto' }}>
          <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim, letterSpacing: 1.5, marginBottom: 8 }}>ORDER HISTORY</div>
          <div style={{ fontSize: isPhone ? 24 : 28, fontWeight: 600, letterSpacing: -0.5, marginBottom: 6 }}>Your orders</div>
          <div style={{ fontSize: 14, color: L.textMid, marginBottom: 28 }}>Every wholesale order placed on your account.</div>

          {loading && orders.length === 0 ? (
            <div style={{ padding: '40px 0', textAlign: 'center', color: L.textDim }}>Loading orders…</div>
          ) : orders.length === 0 ? (
            <div style={{ padding: '40px 20px', textAlign: 'center', color: L.textDim, background: L.surface, border: `1px solid ${L.border}`, borderRadius: 10 }}>
              No orders yet. Place your first order from the Catalog.
            </div>
          ) : isPhone ? (
            <div style={{ display: 'grid', gap: 12 }}>
              {orders.map((o) => <LedgerOrderCard key={o.id} order={o} onClick={() => setSelected(o)} />)}
            </div>
          ) : (
            <div style={{ background: L.surface, border: `1px solid ${L.border}`, borderRadius: 10, overflow: 'hidden' }}>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
                <thead>
                  <tr style={{ background: L.bg, color: L.textDim, fontSize: 11, textTransform: 'uppercase', letterSpacing: 0.5 }}>
                    <th style={{ ...ledgerOrdTh, textAlign: 'left' }}>PO #</th>
                    <th style={{ ...ledgerOrdTh, textAlign: 'left' }}>Date</th>
                    <th style={{ ...ledgerOrdTh, textAlign: 'left' }}>Warehouse</th>
                    <th style={{ ...ledgerOrdTh, textAlign: 'right' }}>Units</th>
                    <th style={{ ...ledgerOrdTh, textAlign: 'right' }}>Total</th>
                    <th style={{ ...ledgerOrdTh, textAlign: 'left' }}>Status</th>
                  </tr>
                </thead>
                <tbody>
                  {orders.map((o) => (
                    <tr key={o.id} onClick={() => setSelected(o)}
                      onMouseOver={(e) => { e.currentTarget.style.background = L.bg; }}
                      onMouseOut={(e) => { e.currentTarget.style.background = 'transparent'; }}
                      style={{ borderTop: `1px solid ${L.border}`, cursor: 'pointer' }}>
                      <td style={{ ...ledgerOrdTd, fontFamily: L.mono, fontWeight: 600 }}>{o.po_number}</td>
                      <td style={ledgerOrdTd}>{ledgerOrderDate(o.created_at)}</td>
                      <td style={ledgerOrdTd}>{o.warehouse || '—'}</td>
                      <td style={{ ...ledgerOrdTd, textAlign: 'right', fontFamily: L.mono }}>{fmtInt(ledgerOrderUnits(o))}</td>
                      <td style={{ ...ledgerOrdTd, textAlign: 'right', fontFamily: L.mono, fontWeight: 600 }}>{fmt(Number(o.total) || 0)}</td>
                      <td style={ledgerOrdTd}><span style={{ padding: '2px 10px', borderRadius: 999, background: L.accentDim, color: L.accent, fontSize: 11, fontWeight: 600 }}>{o.status}</span></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </div>
      {selected && <LedgerOrderDetail order={selected} onClose={() => setSelected(null)} onReorder={onReorder ? () => { onReorder(selected); setSelected(null); } : null} />}
    </>
  );
}

function LedgerOrderDetail({ order, onClose, onReorder }) {
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  const items = Array.isArray(order.items) ? order.items : [];
  const ship = order.ship_to || null;
  const row = (label, value) => (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, fontSize: 13, padding: '3px 0' }}>
      <span style={{ color: L.textDim }}>{label}</span>
      <span style={{ fontWeight: 600, textAlign: 'right' }}>{value}</span>
    </div>
  );
  return (
    <LedgerDrawer side="right" width={isPhone ? '92vw' : 460} onClose={onClose}>
      <div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
        <div style={{ padding: isPhone ? '16px' : '18px 22px', borderBottom: `1px solid ${L.border}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
          <div>
            <div style={{ fontFamily: L.mono, fontSize: 16, fontWeight: 700 }}>{order.po_number}</div>
            <div style={{ fontSize: 12, color: L.textDim, marginTop: 2 }}>{ledgerOrderDate(order.created_at)} · {order.warehouse || '—'}</div>
          </div>
          <button onClick={onClose} style={iconBtn}>×</button>
        </div>
        <div style={{ flex: 1, overflowY: 'auto', padding: isPhone ? '16px' : '18px 22px' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 16 }}>
            <span style={{ padding: '2px 10px', borderRadius: 999, background: L.accentDim, color: L.accent, fontSize: 11, fontWeight: 600 }}>{order.status}</span>
            <span style={{ fontSize: 12, color: L.textDim }}>{fmtInt(ledgerOrderUnits(order))} units</span>
          </div>

          {ship && (ship.location || ship.method) && (
            <div style={{ marginBottom: 16, padding: 12, background: L.bg, border: `1px solid ${L.border}`, borderRadius: 8, fontSize: 12, color: L.textMid, lineHeight: 1.5 }}>
              <div style={{ fontSize: 11, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 4 }}>Ship to</div>
              {ship.location?.label && <div style={{ fontWeight: 600, color: L.text }}>{ship.location.label}</div>}
              {ship.location?.address && <div>{ship.location.address}</div>}
              {ship.method && <div style={{ marginTop: 4 }}>Via {ship.method}</div>}
            </div>
          )}

          <div style={{ fontSize: 11, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 8 }}>Items</div>
          <div style={{ border: `1px solid ${L.border}`, borderRadius: 8, overflow: 'hidden', marginBottom: 16 }}>
            {items.length === 0 && <div style={{ padding: 12, fontSize: 13, color: L.textDim }}>No line items recorded.</div>}
            {items.map((it, i) => (
              <div key={i} style={{ display: 'flex', justifyContent: 'space-between', gap: 10, padding: '10px 12px', borderTop: i ? `1px solid ${L.border}` : 'none' }}>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{it.name || it.sku}</div>
                  <div style={{ fontSize: 11, color: L.textDim, fontFamily: L.mono }}>{it.sku} · {fmtInt(Number(it.qty) || 0)} units</div>
                </div>
                <div style={{ fontFamily: L.mono, fontSize: 13, fontWeight: 600, whiteSpace: 'nowrap' }}>{fmt(Number(it.subtotal) || 0)}</div>
              </div>
            ))}
          </div>

          <div style={{ padding: 12, background: L.bg, border: `1px solid ${L.border}`, borderRadius: 8 }}>
            {row('Subtotal', fmt(Number(order.subtotal) || 0))}
            {Number(order.export_fee) > 0 && row('Export license fee', fmt(Number(order.export_fee)))}
            <div style={{ borderTop: `1px solid ${L.border}`, marginTop: 6, paddingTop: 6 }}>
              {row('Total', fmt(Number(order.total) || 0))}
            </div>
            {order.qbo_doc_number && row('QuickBooks invoice', `INV-${order.qbo_doc_number}`)}
          </div>
        </div>
        {onReorder && (
          <div style={{ padding: isPhone ? '12px 16px' : '14px 22px', borderTop: `1px solid ${L.border}` }}>
            <button onClick={onReorder} style={{
              width: '100%', height: 44, border: 'none', borderRadius: 8, background: L.accent, color: '#fff',
              fontSize: 14, fontWeight: 600, cursor: 'pointer', fontFamily: L.font,
            }}>Reorder these items →</button>
          </div>
        )}
      </div>
    </LedgerDrawer>
  );
}

// ── CATALOG ──────────────────────────────────────────────────────────────
function LedgerCatalog({ catalog, warehouse, cart, discountPercent, onSwitchWarehouse, onReview, onOpenDetail }) {
  const disc = Number(discountPercent) || 0;
  const [category, setCategory] = React.useState('All');
  const [search, setSearch] = React.useState('');
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  const isTablet = width >= 760 && width < 1180;
  const isCompact = width < 1180;
  const [categoriesOpen, setCategoriesOpen] = React.useState(false);
  const [cartOpen, setCartOpen] = React.useState(false);

  const categories = ['All', ...new Set(catalog.map(p => p.category))];
  const searchTerm = search.trim().toLowerCase();
  const filtered = catalog.filter(p => {
    const matchesSearch = searchTerm === '' || p.name.toLowerCase().includes(searchTerm) || p.sku.toLowerCase().includes(searchTerm);
    if (searchTerm) return matchesSearch;
    return (category === 'All' || p.category === category) && matchesSearch;
  });

  const items = cart.lineItems(catalog, warehouse, discountPercent);
  const subtotal = items.reduce((a, b) => a + b.subtotal, 0);
  const retail = items.reduce((a, b) => a + b.retailSubtotal, 0);
  const exportFee = subtotal > 0 ? exportLicenseFee(warehouse) : 0;
  const orderTotal = subtotal + exportFee;

  const categoryPanel = (
    <div style={{ height: '100%', background: L.surface, padding: '20px 0', overflow: 'auto' }}>
      <div style={{ padding: '0 20px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
        <div style={{ fontSize: 11, fontWeight: 600, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.8 }}>Categories</div>
        <button onClick={() => setCategoriesOpen(false)} style={iconBtn} aria-label="Close categories">×</button>
      </div>
      {categories.map(c => {
        const count = c === 'All' ? catalog.length : catalog.filter(p => p.category === c).length;
        const active = c === category;
        return (
          <button key={c} onClick={() => { setCategory(c); setCategoriesOpen(false); }} style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            width: '100%', padding: '8px 20px', border: 'none',
            background: active ? L.accentDim : 'transparent',
            borderLeft: `3px solid ${active ? L.accent : 'transparent'}`,
            color: active ? L.accent : L.text, fontFamily: L.font,
            fontSize: 13, fontWeight: active ? 600 : 400,
            cursor: 'pointer', textAlign: 'left',
          }}>
            <span>{c}</span>
            <span style={{ fontSize: 11, color: L.textDim, fontFamily: L.mono }}>{count}</span>
          </button>
        );
      })}
    </div>
  );

  const cartPanel = (
    <div style={{ height: '100%', background: L.surface, display: 'flex', flexDirection: 'column' }}>
      <div style={{ padding: 20, borderBottom: `1px solid ${L.border}` }}>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 4 }}>
          <div style={{ fontSize: 15, fontWeight: 600 }}>Order summary</div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim }}>{items.length} SKU{items.length !== 1 ? 's' : ''}</div>
            <button onClick={() => setCartOpen(false)} style={iconBtn} aria-label="Close order summary">×</button>
          </div>
        </div>
        <div style={{ fontSize: 12, color: L.textDim }}>Ship from {warehouse.flag} {warehouse.name}</div>
      </div>
      <div style={{ flex: 1, overflow: 'auto', padding: '8px 0' }}>
        {items.length === 0 && (
          <div style={{ padding: '60px 24px', textAlign: 'center', color: L.textDim, fontSize: 13 }}>
            Add products to build your order.
            <div style={{ fontSize: 11, marginTop: 6, fontFamily: L.mono }}>Qty · Retail × discount = line</div>
          </div>
        )}
        {items.map(it => (
          <div key={it.sku} style={{ padding: '10px 20px', display: 'flex', gap: 10, alignItems: 'center', borderBottom: `1px dashed ${L.border}` }}>
            <div style={{ width: 32, height: 32, background: L.bg, borderRadius: 4, display: 'grid', placeItems: 'center', overflow: 'hidden', flexShrink: 0 }}>
              <LedgerImage src={it.image} />
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{it.name}</div>
              <div style={{ fontSize: 11, color: L.textDim, fontFamily: L.mono }}>{it.qty} × {fmt(it.buy)}</div>
            </div>
            <div style={{ fontFamily: L.mono, fontSize: 12, fontWeight: 600 }}>{fmt(it.subtotal)}</div>
          </div>
        ))}
      </div>
      <div style={{ padding: 20, borderTop: `1px solid ${L.border}`, background: L.row }}>
        <Row label="Retail value" value={fmt(retail)} dim />
        <Row label={`Trade discount (${disc}%)`} value={'−' + fmt(retail - subtotal)} discount />
        {exportFee > 0 && <Row label="Shanghai export license fee" value={fmt(exportFee, warehouse.currency)} dim />}
        <Row label="Units" value={fmtInt(cart.totalUnits)} dim mono />
        <div style={{ height: 8 }} />
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', borderTop: `1px solid ${L.border}`, paddingTop: 10 }}>
          <div style={{ fontSize: 14, fontWeight: 600 }}>Order total</div>
          <div style={{ fontFamily: L.mono, fontSize: 20, fontWeight: 700, letterSpacing: -0.5 }}>{fmt(orderTotal, warehouse.currency)}</div>
        </div>
        <button onClick={onReview} disabled={subtotal === 0} style={{
          width: '100%', marginTop: 14, height: 42,
          background: subtotal === 0 ? L.border : L.accent, color: '#fff',
          border: 'none', borderRadius: 8, fontSize: 14, fontWeight: 600,
          cursor: subtotal === 0 ? 'not-allowed' : 'pointer', fontFamily: L.font,
        }}>Review order →</button>
      </div>
    </div>
  );

  return (
    <>
      <LedgerTopBar warehouse={warehouse} onSwitch={onSwitchWarehouse} />
      <div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
        {/* Sidebar */}
        {!isCompact && categoriesOpen && <div style={{ flex: '0 0 220px', borderRight: `1px solid ${L.border}`, overflow: 'hidden' }}>{categoryPanel}</div>}
        {isCompact && categoriesOpen && <LedgerDrawer side="left" width={isPhone ? '86vw' : 260} onClose={() => setCategoriesOpen(false)}>{categoryPanel}</LedgerDrawer>}

        {/* Main spreadsheet */}
        <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
          <div style={{
            padding: isPhone ? '10px 12px' : '16px 24px', background: L.surface, borderBottom: `1px solid ${L.border}`,
            display: 'flex', alignItems: 'center', gap: 10, flexWrap: isPhone ? 'wrap' : 'nowrap',
          }}>
            <button onClick={() => setCategoriesOpen(true)} style={{
              ...panelToggleBtn,
              display: 'inline-flex', alignItems: 'center',
              border: `1px solid ${L.border}`, borderRadius: 7, color: L.textMid,
              fontSize: 12, fontWeight: 600, whiteSpace: 'nowrap',
            }}>
              Category: <span style={{ color: L.text, marginLeft: 4 }}>{category}</span>
              {category !== 'All' && (
                <span
                  onClick={e => { e.stopPropagation(); setCategory('All'); }}
                  aria-label="Clear category filter"
                  style={{ marginLeft: 6, fontSize: 15, lineHeight: 1, opacity: 0.55, cursor: 'pointer' }}
                >×</span>
              )}
            </button>
            <div style={{ position: 'relative', flex: isPhone ? '1 0 100%' : '0 1 320px', minWidth: isPhone ? 0 : 220, order: isPhone ? 2 : 0 }}>
              <input value={search} onChange={e => setSearch(e.target.value)} placeholder="Search SKU or product name…" style={{
                width: '100%', height: 34, padding: '0 12px 0 34px', boxSizing: 'border-box',
                border: `1px solid ${L.border}`, borderRadius: 6, fontSize: 13, fontFamily: L.font,
                background: L.bg, color: L.text, outline: 'none',
              }} />
              <svg width="14" height="14" style={{ position: 'absolute', left: 12, top: 10, color: L.textDim }} fill="none" stroke="currentColor" strokeWidth="2"><circle cx="6" cy="6" r="5"/><path d="M10 10l3 3"/></svg>
            </div>
            <div style={{ fontSize: 12, color: L.textDim, fontFamily: L.mono, order: isPhone ? 3 : 0 }}>{filtered.length} of {catalog.length} SKUs</div>
            <div style={{ flex: 1, ...(isPhone ? { display: 'none' } : {}) }} />
            <div style={{ fontSize: 11, color: L.textDim, ...(isPhone ? { flex: '1', order: 4 } : {}) }}>
              Your reseller price is <b style={{ color: L.discount }}>{disc}% off retail</b>
            </div>
            <button onClick={() => setCartOpen(true)} aria-label={`Cart, ${fmtInt(cart.totalUnits)} items`} style={{
              ...panelToggleBtn,
              background: L.accent, color: '#fff', border: 'none',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 7,
              minWidth: 70, ...(isPhone ? { order: 4 } : {}),
            }}>
              <CartIcon />
              <span>{fmtInt(cart.totalUnits)}</span>
            </button>
          </div>

          <div style={{ flex: 1, overflow: 'auto', background: L.surface }}>
            {isPhone ? (
              <div style={{ padding: 10, display: 'grid', gap: 10 }}>
                {filtered.map((raw) => {
                  const p = regionalProduct(raw, warehouse, discountPercent);
                  const qty = cart.cart[p.sku] || 0;
                  const stock = p.stock[warehouse.name];
                  const lineSubtotal = qty * p.buy;
                  return (
                    <div key={p.sku} onClick={() => onOpenDetail(p.sku)} style={{ border: `1px solid ${L.border}`, borderRadius: 10, background: qty > 0 ? L.accentDim + '80' : L.surface, padding: 12 }}>
                      <div style={{ display: 'grid', gridTemplateColumns: '58px minmax(0,1fr)', gap: 12, marginBottom: 12 }}>
                        <div style={{ width: 58, height: 58, background: L.bg, borderRadius: 8, display: 'grid', placeItems: 'center', overflow: 'hidden' }}>
                          <LedgerImage src={p.image} />
                        </div>
                        <div style={{ minWidth: 0 }}>
                          <div style={{ fontSize: 13, fontWeight: 700, lineHeight: 1.25, color: L.accent }}>{p.name}</div>
                          <div style={{ fontSize: 11, color: L.textDim, marginTop: 4 }}>{p.sku}</div>
                          <div style={{ fontSize: 11, color: L.textDim, marginTop: 2 }}>{p.category} · {p.color}{p.size !== '—' ? ' · ' + p.size : ''}</div>
                        </div>
                      </div>
                      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 8, alignItems: 'end' }}>
                        <MiniLineStat label="Stock" value={stock === 0 ? 'Backorder' : fmtInt(stock)} color={stock === 0 || stock < 100 ? L.warn : undefined} />
                        <MiniLineStat label="Price" value={fmt(p.buy)} />
                        <div onClick={e => e.stopPropagation()} style={{ textAlign: 'right' }}>
                          <div style={{ fontSize: 10, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 5 }}>Qty</div>
                          <QtyStepper value={qty} moq={p.moq} max={stock} onInc={() => cart.inc(p.sku, p.moq, p.moq, stock)} onDec={() => cart.dec(p.sku, p.moq, p.moq, stock)} onSet={(v) => cart.setQty(p.sku, v, stock, p.moq)} disabled={false} />
                        </div>
                      </div>
                      {qty > 0 && <div style={{ marginTop: 10, paddingTop: 10, borderTop: `1px solid ${L.border}`, display: 'flex', justifyContent: 'space-between', fontFamily: L.mono, fontSize: 12 }}><span>Subtotal</span><b>{fmt(lineSubtotal)}</b></div>}
                    </div>
                  );
                })}
              </div>
            ) : <table style={{ width: '100%', minWidth: isTablet ? 760 : 0, borderCollapse: 'collapse', fontSize: 13 }}>
              <thead style={{ position: 'sticky', top: 0, background: L.surface, zIndex: 1 }}>
                <tr style={{ borderBottom: `1px solid ${L.borderStrong}`, fontSize: 11, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5 }}>
                  <th style={th(60)}></th>
                  <th style={{...th(), textAlign: 'left'}}>Product</th>
                  <th style={{...th(110), textAlign: 'left'}}>SKU</th>
                  <th style={{...th(70), textAlign: 'right'}}>Stock</th>
                  <th style={{...th(80), textAlign: 'right'}}>Retail</th>
                  <th style={{...th(80), textAlign: 'right'}}>Your price</th>
                  <th style={{...th(140), textAlign: 'center'}}>Quantity</th>
                  <th style={{...th(100), textAlign: 'right', paddingRight: 24}}>Subtotal</th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((p, i) => {
                  p = regionalProduct(p, warehouse, discountPercent);
                  const qty = cart.cart[p.sku] || 0;
                  const stock = p.stock[warehouse.name];
                  const lineSubtotal = qty * p.buy;
                  return (
                    <tr key={p.sku} style={{
                      borderBottom: `1px solid ${L.border}`,
                      background: qty > 0 ? L.accentDim + '80' : (i % 2 ? L.row : 'transparent'),
                      cursor: 'pointer',
                    }} onClick={() => onOpenDetail(p.sku)}>
                      <td style={{ padding: '10px 0 10px 24px' }}>
                        <div style={{ width: 44, height: 44, background: L.bg, borderRadius: 6, display: 'grid', placeItems: 'center', overflow: 'hidden' }}>
                          <LedgerImage src={p.image} />
                        </div>
                      </td>
                      <td style={{ padding: '10px 12px' }}>
                        <div style={{ fontWeight: 500, fontSize: 13, marginBottom: 2, color: L.accent, textDecoration: 'none' }}>{p.name}</div>
                        <div style={{ fontSize: 11, color: L.textDim }}>{p.category} · {p.color}{p.size !== '—' ? ' · ' + p.size : ''}</div>
                      </td>
                      <td style={{ padding: '10px 12px', fontFamily: L.mono, fontSize: 11, color: L.textMid }}>{p.sku}</td>
                      <td style={{ padding: '10px 12px', textAlign: 'right', fontFamily: L.mono, fontSize: 12 }}>
                        {stock === 0 ? <span style={{ color: L.warn }}>Backorder</span> : <span style={{ color: stock < 100 ? L.warn : L.textMid }}>{fmtInt(stock)}</span>}
                      </td>
                      <td style={{ padding: '10px 12px', textAlign: 'right', fontFamily: L.mono, fontSize: 12, color: L.textDim, textDecoration: 'line-through' }}>{fmt(p.retail)}</td>
                      <td style={{ padding: '10px 12px', textAlign: 'right', fontFamily: L.mono, fontSize: 13, fontWeight: 600 }}>
                        {fmt(p.buy)}
                        <div style={{
                          display: 'inline-block', marginLeft: 6, padding: '1px 5px',
                          background: L.discountBg, color: L.discount, borderRadius: 3,
                          fontSize: 10, fontWeight: 600, fontFamily: L.font,
                        }}>−{disc}%</div>
                      </td>
                      <td style={{ padding: '10px 12px', textAlign: 'center' }} onClick={e => e.stopPropagation()}>
                        <QtyStepper value={qty} moq={p.moq} max={stock} onInc={() => cart.inc(p.sku, p.moq, p.moq, stock)} onDec={() => cart.dec(p.sku, p.moq, p.moq, stock)} onSet={(v) => cart.setQty(p.sku, v, stock, p.moq)} disabled={false} />
                      </td>
                      <td style={{ padding: '10px 24px 10px 12px', textAlign: 'right', fontFamily: L.mono, fontSize: 13, fontWeight: qty > 0 ? 600 : 400, color: qty > 0 ? L.text : L.textDim }}>
                        {fmt(lineSubtotal)}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>}
          </div>
        </div>

        {/* Cart rail */}
        {!isCompact && cartOpen && <div style={{ flex: '0 0 320px', borderLeft: `1px solid ${L.border}`, overflow: 'hidden' }}>{cartPanel}</div>}
        {isCompact && cartOpen && <LedgerDrawer side="right" width={isPhone ? '92vw' : 340} onClose={() => setCartOpen(false)}>{cartPanel}</LedgerDrawer>}
      </div>
    </>
  );
}

function LedgerSelect({ value, onChange, options, placeholder, error }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, [open]);
  const selected = options.find((o) => o.id === value);
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button onClick={() => setOpen((v) => !v)} style={{
        width: '100%', minHeight: 36, padding: '0 10px', fontFamily: L.font, fontSize: 13,
        color: selected ? L.text : L.textDim,
        border: `1.5px solid ${error ? '#ef4444' : L.borderStrong}`,
        borderRadius: 7, outline: 'none', boxSizing: 'border-box',
        background: L.surface, cursor: 'pointer',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8,
        boxShadow: error ? '0 0 0 3px rgba(239,68,68,0.12)' : 'none',
        textAlign: 'left',
      }}>
        <span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{selected ? selected.label : placeholder}</span>
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" style={{ flexShrink: 0, transition: 'transform .15s', transform: open ? 'rotate(180deg)' : 'none' }}>
          <path d="M6 9l6 6 6-6" />
        </svg>
      </button>
      {open && (
        <div style={{
          position: 'absolute', top: '100%', left: 0, right: 0, marginTop: 4,
          background: L.surface, border: `1px solid ${L.border}`,
          borderRadius: 8, zIndex: 999,
          boxShadow: '0 8px 24px rgba(15,23,42,0.16)', overflow: 'hidden',
        }}>
          {options.map((opt) => (
            <button key={opt.id} onClick={() => { onChange(opt.id); setOpen(false); }} style={{
              width: '100%', padding: '10px 12px', border: 'none', cursor: 'pointer', textAlign: 'left',
              background: opt.id === value ? L.accentDim : 'transparent',
              fontFamily: L.font, fontSize: 13, color: L.text,
              display: 'flex', alignItems: 'center', gap: 8,
            }}>
              <span style={{ width: 14, color: L.accent, flexShrink: 0 }}>{opt.id === value ? '✓' : ''}</span>
              {opt.label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function LedgerDrawer({ side, width, onClose, children }) {
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 30, background: 'rgba(15,23,42,0.38)' }} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()} style={{
        position: 'absolute', top: 0, bottom: 0, [side]: 0,
        width, maxWidth: '100%', background: L.surface,
        boxShadow: side === 'left' ? '18px 0 46px rgba(15,23,42,0.24)' : '-18px 0 46px rgba(15,23,42,0.24)',
      }}>
        {children}
      </div>
    </div>
  );
}

const th = (w) => ({ padding: '12px', fontWeight: 500, width: w, whiteSpace: 'nowrap' });
const iconBtn = {
  width: 28, height: 28, border: `1px solid ${L.border}`, borderRadius: 6,
  background: L.surface, color: L.textMid, cursor: 'pointer', fontFamily: L.font, fontSize: 18, lineHeight: 1,
};
const panelToggleBtn = {
  height: 34, padding: '0 10px', border: `1px solid ${L.borderStrong}`, borderRadius: 7,
  background: L.surface, color: L.text, cursor: 'pointer', fontFamily: L.font, fontSize: 12, fontWeight: 700,
  whiteSpace: 'nowrap',
};

function CartIcon() {
  return (
    <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <circle cx="9" cy="20" r="1.6" />
      <circle cx="18" cy="20" r="1.6" />
      <path d="M3 4h2l2.4 11.2a2 2 0 0 0 2 1.6h7.8a2 2 0 0 0 2-1.5L21 8H7" />
    </svg>
  );
}

function Row({ label, value, dim, discount, mono }) {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, padding: '3px 0' }}>
      <span style={{ color: L.textMid }}>{label}</span>
      <span style={{
        color: discount ? L.discount : (dim ? L.textMid : L.text),
        fontFamily: mono ? L.mono : L.mono, fontWeight: 500,
      }}>{value}</span>
    </div>
  );
}

function summarizeOrderItems(items, exportFee = 0) {
  const inStockSubtotal = items.reduce((a, b) => a + (b.inStockSubtotal || 0), 0);
  const additionalSubtotal = items.reduce((a, b) => a + (b.additionalSubtotal || 0), 0);
  const inStockUnits = items.reduce((a, b) => a + (b.inStockQty || 0), 0);
  const additionalUnits = items.reduce((a, b) => a + (b.additionalQty || 0), 0);
  return {
    inStockSubtotal,
    additionalSubtotal,
    inStockUnits,
    additionalUnits,
    exportFee,
    grandTotal: inStockSubtotal + additionalSubtotal + exportFee,
  };
}

function ReviewOrderSection({ title, items, qtyKey, subtotalKey, empty, cart }) {
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  const totalUnits = items.reduce((a, b) => a + (b[qtyKey] || 0), 0);
  const totalAmount = items.reduce((a, b) => a + (b[subtotalKey] || 0), 0);
  return (
    <div style={{ background: L.surface, border: `1px solid ${L.border}`, borderRadius: 10, overflow: 'hidden', marginBottom: 14 }}>
      <div style={{ padding: isPhone ? '12px 14px' : '14px 22px', borderBottom: `1px solid ${L.border}`, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
        <div style={{ fontSize: 14, fontWeight: 600 }}>{title}</div>
        <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim }}>
          {fmtInt(totalUnits)} units · {fmt(totalAmount)}
        </div>
      </div>
      {items.length === 0 ? (
        <div style={{ padding: isPhone ? '14px' : '18px 22px', color: L.textDim, fontSize: 13 }}>{empty}</div>
      ) : isPhone ? (
        <div>
          {items.map((it, i) => (
            <div key={`${title}-${it.sku}`} style={{ padding: '12px 14px', borderTop: i === 0 ? 'none' : `1px solid ${L.border}`, display: 'grid', gridTemplateColumns: '44px 1fr', gap: 12 }}>
              <div style={{ width: 44, height: 44, background: L.bg, borderRadius: 6, display: 'grid', placeItems: 'center', overflow: 'hidden' }}>
                <LedgerImage src={it.image} />
              </div>
              <div style={{ minWidth: 0 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 }}>
                  <div style={{ fontSize: 13, fontWeight: 600, lineHeight: 1.3 }}>{it.name}</div>
                  <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim, flexShrink: 0 }}>{String(i + 1).padStart(2, '0')}</div>
                </div>
                <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim, marginTop: 2 }}>{it.sku} · {it.color}</div>
                <div style={{ marginTop: 10, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
                  {cart ? (
                    <QtyStepper
                      value={it[qtyKey] || 0}
                      moq={it.moq}
                      max={it.warehouseStock}
                      onInc={() => cart.inc(it.sku, it.moq, it.moq, it.warehouseStock)}
                      onDec={() => cart.dec(it.sku, it.moq, it.moq, it.warehouseStock)}
                      onSet={(v) => cart.setQty(it.sku, v, it.warehouseStock, it.moq)}
                      disabled={false}
                    />
                  ) : (
                    <span style={{ fontFamily: L.mono, fontSize: 13, fontWeight: 600 }}>{fmtInt(it[qtyKey] || 0)} units</span>
                  )}
                  <div style={{ textAlign: 'right' }}>
                    <div style={{ fontFamily: L.mono, fontSize: 13, fontWeight: 700 }}>{fmt(it[subtotalKey] || 0)}</div>
                    <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim }}>
                      <span style={{ textDecoration: 'line-through' }}>{fmt(it.retail)}</span> → {fmt(it.buy)}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          ))}
        </div>
      ) : (
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
          <tbody>
            {items.map((it, i) => (
              <tr key={`${title}-${it.sku}`} style={{ borderTop: i === 0 ? 'none' : `1px solid ${L.border}` }}>
                <td style={{ padding: '12px 12px 12px 22px', fontFamily: L.mono, fontSize: 11, color: L.textDim, width: 40 }}>{String(i + 1).padStart(2, '0')}</td>
                <td style={{ padding: '10px 0', width: 60 }}>
                  <div style={{ width: 44, height: 44, background: L.bg, borderRadius: 6, display: 'grid', placeItems: 'center', overflow: 'hidden' }}>
                    <LedgerImage src={it.image} />
                  </div>
                </td>
                <td style={{ padding: '10px 12px' }}>
                  <div style={{ fontSize: 13, fontWeight: 500 }}>{it.name}</div>
                  <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim }}>{it.sku} · {it.color}</div>
                </td>
                <td style={{ padding: '10px 12px', textAlign: 'right', width: 150 }}>
                  {cart ? (
                    <QtyStepper
                      value={it[qtyKey] || 0}
                      moq={it.moq}
                      max={it.warehouseStock}
                      onInc={() => cart.inc(it.sku, it.moq, it.moq, it.warehouseStock)}
                      onDec={() => cart.dec(it.sku, it.moq, it.moq, it.warehouseStock)}
                      onSet={(v) => cart.setQty(it.sku, v, it.warehouseStock, it.moq)}
                      disabled={false}
                    />
                  ) : (
                    <span style={{ fontFamily: L.mono, fontSize: 12, fontWeight: 600 }}>{fmtInt(it[qtyKey] || 0)}</span>
                  )}
                </td>
                <td style={{ padding: '10px 12px', textAlign: 'right', fontFamily: L.mono, fontSize: 12, color: L.textDim, textDecoration: 'line-through', width: 80 }}>{fmt(it.retail)}</td>
                <td style={{ padding: '10px 12px', textAlign: 'right', fontFamily: L.mono, fontSize: 12, fontWeight: 500, width: 80 }}>{fmt(it.buy)}</td>
                <td style={{ padding: '10px 22px 10px 12px', textAlign: 'right', fontFamily: L.mono, fontSize: 13, fontWeight: 600, width: 100 }}>{fmt(it[subtotalKey] || 0)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
    </div>
  );
}

function QtyStepper({ value, moq, max, onInc, onDec, onSet, disabled }) {
  if (disabled) return <div style={{ fontSize: 11, color: L.textDim, fontStyle: 'italic' }}>Unavailable</div>;
  return (
    <div style={{ display: 'inline-flex', alignItems: 'center', border: `1px solid ${L.border}`, borderRadius: 6, background: '#fff' }}>
      <button onClick={onDec} style={stepBtn(value === 0)}>−</button>
      <input
        key={value}
        defaultValue={value}
        onBlur={e => { const n = parseInt(e.target.value) || 0; onSet(n); }}
        style={{
          width: 58, height: 26, border: 'none', textAlign: 'center',
          fontFamily: L.mono, fontSize: 13, fontWeight: value > 0 ? 600 : 400,
          color: value > 0 ? L.text : L.textDim,
          background: 'transparent', outline: 'none',
        }}
      />
      <button onClick={onInc} style={stepBtn(false)}>+</button>
    </div>
  );
}
const stepBtn = (dim) => ({
  width: 24, height: 26, border: 'none', background: 'transparent',
  color: dim ? L.textDim : L.textMid, fontSize: 15, cursor: 'pointer',
  fontFamily: L.font,
});

// ── CONFIRMATION ─────────────────────────────────────────────────────────
function LedgerConfirmation({ order, onNew }) {
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  const [payOpen, setPayOpen] = React.useState(false);
  const [paymentStatus, setPaymentStatus] = React.useState('ready');
  const invState = order.invoice?.state || 'ready';
  const invoiceId = order.invoice?.docNumber
    ? `INV-${order.invoice.docNumber}`
    : `QB-${order.id.replace(/[^0-9A-Z]/gi, '')}`;
  const invoiceHeight = isPhone ? 320 : 420;

  const badge =
    invState === 'creating' ? { text: 'Connecting QuickBooks…', bg: L.row, fg: L.textMid }
    : invState === 'error' ? { text: 'QuickBooks offline', bg: L.row, fg: L.textMid }
    : { text: 'QuickBooks connected', bg: L.discountBg, fg: L.discount };
  const subline = order.invoice?.emailedTo
    ? `Invoice ${invoiceId} emailed to ${order.invoice.emailedTo}. Your distributor account manager will confirm availability within one business day.`
    : 'Email confirmation with PDF invoice sent. Your distributor account manager will confirm availability within one business day.';

  return (
    <>
      <LedgerTopBar />
      <div style={{ flex: 1, overflow: 'auto', padding: isPhone ? '18px 12px' : '28px 32px' }}>
        <div style={{ maxWidth: 900, margin: '0 auto' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 20, flexWrap: 'wrap' }}>
            <div style={{ width: 36, height: 36, borderRadius: 18, background: L.discountBg, color: L.discount, display: 'grid', placeItems: 'center', flexShrink: 0 }}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M4 12l5 5L20 6"/></svg>
            </div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 22, fontWeight: 600, letterSpacing: -0.5 }}>Order submitted</div>
              <div style={{ fontSize: 13, color: L.textDim }}>{subline}</div>
              <div style={{ marginTop: 7, display: 'flex', gap: 8, alignItems: 'center' }}>
                <span style={{ padding: '4px 8px', borderRadius: 999, background: badge.bg, color: badge.fg, fontSize: 11, fontWeight: 700 }}>{badge.text}</span>
                <span style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim }}>{invoiceId} · {paymentStatus === 'paid' ? 'Payment received' : invState === 'ready' ? 'Payment link ready' : '…'}</span>
              </div>
            </div>
            <button onClick={onNew} style={{ ...secondaryBtn, background: L.accent, color: '#fff', border: 'none' }}>New order</button>
          </div>

          <div style={{ display: 'grid', gap: 12 }}>
            <ConfirmationTotals order={order} />
            <div style={{ minWidth: 0 }}>
              <QuickBooksInvoicePreview order={order} height={invoiceHeight} />
              <div style={{ marginTop: 10 }}>
                <button onClick={() => setPayOpen(true)} style={{
                  ...secondaryBtn,
                  width: '100%', height: 54,
                  background: '#108000', color: '#fff', border: 'none',
                  fontSize: 16, fontWeight: 800,
                }}>Pay now</button>
              </div>
            </div>
          </div>
        </div>
      </div>
      {payOpen && (
        <QuickBooksPaymentDemo
          order={order}
          invoiceId={invoiceId}
          status={paymentStatus}
          onClose={() => setPayOpen(false)}
          onPaid={() => setPaymentStatus('paid')}
        />
      )}
    </>
  );
}

function ConfirmationTotals({ order }) {
  const totals = order.totals || summarizeOrderItems(order.items, order.exportFee || 0);
  return (
    <div style={{ background: L.surface, border: `1px solid ${L.border}`, borderRadius: 10, padding: 18 }}>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))', gap: 12 }}>
        <MiniLineStat label={`In-stock order · ${fmtInt(totals.inStockUnits)} units`} value={fmt(totals.inStockSubtotal, order.warehouse.currency)} strong />
        <MiniLineStat label={`Backorder · ${fmtInt(totals.additionalUnits)} units`} value={fmt(totals.additionalSubtotal, order.warehouse.currency)} strong />
        <MiniLineStat label="Grand total" value={fmt(totals.grandTotal, order.warehouse.currency)} strong />
      </div>
      {totals.exportFee > 0 && <div style={{ marginTop: 10, fontSize: 12, color: L.textDim }}>Includes {fmt(totals.exportFee, order.warehouse.currency)} Shanghai export license fee.</div>}
    </div>
  );
}

function QuickBooksInvoicePreview({ order, height = 540 }) {
  const { serverId, token } = order;
  const state = order.invoice?.state || 'ready';
  const ready = state === 'ready';
  const [realUrl, setRealUrl] = React.useState(null);
  const [loadError, setLoadError] = React.useState(false);
  // Pull the real QuickBooks invoice PDF once the invoice exists (needs the
  // Bearer token, so we fetch → blob rather than pointing the frame at the URL).
  React.useEffect(() => {
    if (!serverId || !token || !ready) return undefined;
    let objectUrl = null; let cancelled = false;
    setLoadError(false);
    fetch(`/api/orders/${serverId}/invoice?pdf=1`, { headers: { Authorization: `Bearer ${token}` } })
      .then((r) => (r.ok ? r.blob() : Promise.reject(new Error('pdf'))))
      .then((blob) => { if (!cancelled) { objectUrl = URL.createObjectURL(blob); setRealUrl(objectUrl); } })
      .catch(() => { if (!cancelled) setLoadError(true); });
    return () => { cancelled = true; if (objectUrl) URL.revokeObjectURL(objectUrl); };
  }, [serverId, token, ready]);

  const shell = (children) => (
    <div style={{
      background: L.surface, border: `1px solid ${L.border}`, borderRadius: 10, overflow: 'hidden',
      boxShadow: '0 18px 40px rgba(15, 23, 42, 0.08)', position: 'relative',
    }}>{children}</div>
  );

  // Only ever render the real QuickBooks invoice — a loader while it's being
  // generated, an error note if it can't be loaded. Never a placeholder PDF.
  if (!realUrl) {
    const errored = loadError || state === 'error';
    return shell(
      <div style={{ height, display: 'grid', placeItems: 'center', background: '#f8fafc', padding: 24, textAlign: 'center' }}>
        {errored ? (
          <div>
            <div style={{ fontSize: 14, fontWeight: 600, color: L.text, marginBottom: 4 }}>Invoice unavailable</div>
            <div style={{ fontSize: 12, color: L.textDim }}>We couldn’t load the QuickBooks invoice — it was still emailed to you.</div>
          </div>
        ) : (
          <div>
            <svg width="34" height="34" viewBox="0 0 50 50" style={{ display: 'block', margin: '0 auto 12px' }}>
              <circle cx="25" cy="25" r="20" fill="none" stroke={L.border} strokeWidth="5" />
              <circle cx="25" cy="25" r="20" fill="none" stroke={L.accent} strokeWidth="5" strokeLinecap="round" strokeDasharray="80 150">
                <animateTransform attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.9s" repeatCount="indefinite" />
              </circle>
            </svg>
            <div style={{ fontSize: 13, color: L.textMid }}>Generating your QuickBooks invoice…</div>
          </div>
        )}
      </div>
    );
  }

  const viewerUrl = `${realUrl}#toolbar=0&navpanes=0&scrollbar=0`;
  return shell(
    <>
      <button
        onClick={() => { const a = document.createElement('a'); a.href = realUrl; a.download = `${order.id}-invoice.pdf`; a.click(); }}
        title="Download invoice PDF"
        aria-label="Download invoice PDF"
        style={{
          position: 'absolute', top: 12, right: 12, zIndex: 2,
          width: 38, height: 38, borderRadius: 19, border: '1px solid rgba(255,255,255,0.5)',
          background: 'rgba(15, 23, 42, 0.82)', color: '#fff', cursor: 'pointer',
          display: 'grid', placeItems: 'center', boxShadow: '0 10px 24px rgba(15, 23, 42, 0.22)',
        }}
      >
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M12 3v12" />
          <path d="M7 10l5 5 5-5" />
          <path d="M5 21h14" />
        </svg>
      </button>
      <object data={viewerUrl} type="application/pdf" style={{ display: 'block', width: '100%', height, border: 0, background: '#f8fafc' }}>
        <iframe src={viewerUrl} title="QuickBooks invoice PDF" style={{ display: 'block', width: '100%', height, border: 0, background: '#f8fafc' }} />
      </object>
    </>
  );
}

function MiniLineStat({ label, value, strong, color }) {
  return (
    <div>
      <div style={{ fontSize: 10, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 3 }}>{label}</div>
      <div style={{ fontFamily: L.mono, fontSize: 12, fontWeight: strong ? 700 : 500, ...(color ? { color } : {}) }}>{value}</div>
    </div>
  );
}

// One-shot download of the paid QuickBooks invoice, which doubles as the
// printable receipt — once the charge lands, that PDF shows the payment applied.
// The PDF viewer above keeps a live object URL for its <object> embed; this
// revokes immediately, so the two do not share a helper.
async function downloadInvoicePdf(order, invoiceId) {
  const res = await fetch(`/api/orders/${order.serverId}/invoice?pdf=1`, {
    headers: { Authorization: `Bearer ${order.token}` },
  });
  if (!res.ok) throw new Error('pdf');
  const url = URL.createObjectURL(await res.blob());
  const a = document.createElement('a');
  a.href = url;
  a.download = `${invoiceId || order.id}-receipt.pdf`;
  a.click();
  URL.revokeObjectURL(url);
}

// Payment receipt. Intuit's app assessment asks which details a receipt carries
// and how it reaches the payer, so every row here maps to one of the fields on
// that list — amount, date, payment method with the account number masked,
// transaction id — plus the processor disclosure they require verbatim.
function PaymentReceipt({ order, invoiceId, total, payResult, isPhone }) {
  const [pdfError, setPdfError] = React.useState(false);
  const paidAt = payResult?.processedAt ? new Date(payResult.processedAt) : new Date();
  const card = payResult?.card;

  const rows = [
    ['Amount paid', fmt(payResult?.amount ?? total, order.warehouse.currency)],
    ['Date', Number.isNaN(paidAt.getTime()) ? '—' : paidAt.toLocaleString()],
    card?.last4 ? ['Payment method', `${card.type || 'Card'} ···· ${card.last4}`] : null,
    ['Invoice', invoiceId],
    payResult?.chargeId ? ['Transaction ID', payResult.chargeId] : null,
    payResult?.paymentId ? ['QuickBooks payment', `#${payResult.paymentId}`] : null,
  ].filter(Boolean);

  return (
    <div style={{ marginTop: 22, padding: isPhone ? 14 : 18, borderRadius: 10, background: L.discountBg, color: L.discount }}>
      <div style={{ fontSize: 17, fontWeight: 800, marginBottom: 4 }}>Payment received</div>
      <div style={{ fontSize: 13, lineHeight: 1.45, marginBottom: 14 }}>
        QuickBooks has linked this payment back to the invoice for reconciliation.
      </div>

      <div style={{ display: 'grid', gap: 6 }}>
        {rows.map(([label, value]) => (
          <div key={label} style={{
            display: 'grid',
            gridTemplateColumns: isPhone ? '1fr' : 'minmax(120px, auto) 1fr',
            gap: isPhone ? 0 : 12, fontSize: 12, lineHeight: 1.5,
          }}>
            <div style={{ opacity: 0.75 }}>{label}</div>
            <div style={{ fontFamily: L.mono, fontWeight: 600, wordBreak: 'break-all' }}>{value}</div>
          </div>
        ))}
      </div>

      <button
        onClick={() => { setPdfError(false); downloadInvoicePdf(order, invoiceId).catch(() => setPdfError(true)); }}
        style={{
          marginTop: 16, minHeight: 44, padding: '0 16px', borderRadius: 8,
          border: `1px solid ${L.discount}`, background: 'transparent', color: L.discount,
          fontFamily: L.font, fontSize: 13, fontWeight: 700, cursor: 'pointer',
        }}
      >Download receipt (PDF)</button>
      {pdfError ? (
        <div style={{ marginTop: 8, fontSize: 12 }}>
          Could not fetch the PDF just now — it is also on the order once QuickBooks finishes generating it.
        </div>
      ) : null}

      {/* Required disclosure, wording supplied by Intuit — do not paraphrase. */}
      <div style={{ marginTop: 16, paddingTop: 12, borderTop: `1px solid ${L.discount}33`, fontSize: 11, lineHeight: 1.5, opacity: 0.8 }}>
        Payment is processed by: Intuit Payments Inc., 2700 Coast Avenue, Mountain View, CA 94043,
        Phone number 1-888-536-4801, NMLS #1098819
        <div style={{ marginTop: 6 }}>
          <SupportLine linkStyle={{ color: L.discount, textDecoration: 'underline', textUnderlineOffset: 2 }} />
        </div>
      </div>
    </div>
  );
}

function QuickBooksPaymentDemo({ order, invoiceId, status, onClose, onPaid }) {
  const totals = order.totals || summarizeOrderItems(order.items, order.exportFee || 0);
  const total = totals.grandTotal;
  const paid = status === 'paid';
  const vw = useLedgerViewportWidth();
  const isPhone = vw < 760;
  const [processing, setProcessing] = React.useState(false);
  const [error, setError] = React.useState(null);
  const [payResult, setPayResult] = React.useState(null);
  const [captcha, setCaptcha] = React.useState('');
  const [captchaReset, setCaptchaReset] = React.useState(0);
  const live = order.serverId && order.token;

  const handlePay = async () => {
    setError(null);
    if (!live) { onPaid(); return; } // no backend order (offline) → simulate
    setProcessing(true);
    try {
      const r = await fetch(`/api/orders/${order.serverId}/pay`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${order.token}` },
        body: JSON.stringify({ recaptchaToken: captcha }),
      });
      const d = await r.json().catch(() => ({}));
      if (r.ok && (d.status === 'CAPTURED' || d.status === 'AUTHORIZED' || d.alreadyPaid)) {
        setPayResult(d);
        onPaid(d);
      } else {
        setError(d.error || 'Payment could not be processed.');
        setCaptchaReset((n) => n + 1);
      }
    } catch (_) {
      setError('Payment could not be processed.');
      setCaptchaReset((n) => n + 1);
    }
    setProcessing(false);
  };

  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 50, background: 'rgba(15,23,42,0.48)', display: 'grid', placeItems: 'center', padding: isPhone ? 10 : 32 }} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()} style={{ width: 520, maxWidth: 'calc(100vw - 20px)', background: '#fff', borderRadius: 12, overflow: 'hidden', boxShadow: '0 28px 80px rgba(15,23,42,0.28)', maxHeight: '92dvh', display: 'flex', flexDirection: 'column' }}>
        <div style={{ padding: '18px 22px', background: '#123b22', color: '#fff', display: 'flex', alignItems: 'center', gap: 12 }}>
          <div style={{ width: 38, height: 38, borderRadius: 9, background: '#2ca01c', display: 'grid', placeItems: 'center', fontWeight: 800 }}>qb</div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 16, fontWeight: 700 }}>QuickBooks Payments</div>
            <div style={{ fontSize: 12, opacity: 0.72 }}>{live ? 'Sandbox test card · real QuickBooks charge' : 'Payment demo'}</div>
          </div>
          <button onClick={onClose} style={{ width: 30, height: 30, border: '1px solid rgba(255,255,255,0.28)', background: 'transparent', color: '#fff', borderRadius: 6, cursor: 'pointer', fontSize: 18 }}>×</button>
        </div>

        <div style={{ padding: isPhone ? 16 : 24, overflowY: 'auto', flex: 1 }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: 16, alignItems: 'start', paddingBottom: 18, borderBottom: `1px solid ${L.border}` }}>
            <div>
              <div style={{ fontSize: 12, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 4 }}>Invoice</div>
              <div style={{ fontFamily: L.mono, fontSize: 15, fontWeight: 700 }}>{invoiceId}</div>
              <div style={{ fontSize: 12, color: L.textDim, marginTop: 4 }}>{order.customer || 'Reseller account'}</div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ fontSize: 12, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 4 }}>Amount due</div>
              <div style={{ fontFamily: L.mono, fontSize: 24, fontWeight: 800 }}>{fmt(total, order.warehouse.currency)}</div>
            </div>
          </div>

          {paid ? (
            <PaymentReceipt
              order={order}
              invoiceId={invoiceId}
              total={total}
              payResult={payResult}
              isPhone={isPhone}
            />
          ) : (
            <>
              <div style={{ marginTop: 22, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
                <div style={{ border: `1px solid ${L.borderStrong}`, borderRadius: 9, padding: 14 }}>
                  <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 3 }}>Credit card</div>
                  <div style={{ fontSize: 12, color: L.textDim }}>Visa, Mastercard, Amex</div>
                </div>
                <div style={{ border: `1px solid ${L.border}`, borderRadius: 9, padding: 14, background: L.row }}>
                  <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 3 }}>Bank transfer</div>
                  <div style={{ fontSize: 12, color: L.textDim }}>ACH payment option</div>
                </div>
              </div>
              <div style={{ marginTop: 18, padding: 14, borderRadius: 9, background: L.bg, border: `1px solid ${L.border}`, fontSize: 12, color: L.textDim, lineHeight: 1.5 }}>
                {live
                  ? 'Charged securely through QuickBooks Payments (sandbox test card — no real funds move) and recorded against the invoice automatically.'
                  : 'In production, this button charges the card through QuickBooks Payments and records it against the invoice.'}
              </div>
              {error && <div style={{ marginTop: 12, padding: 12, borderRadius: 9, background: '#fef2f2', border: '1px solid #f4c9c9', color: '#b42318', fontSize: 12 }}>{error}</div>}
              {/* Intuit requires a captcha in front of the transaction itself. */}
              <Recaptcha onToken={setCaptcha} resetSignal={captchaReset} />
            </>
          )}
        </div>

        <div style={{ padding: '16px 24px', borderTop: `1px solid ${L.border}`, display: 'flex', justifyContent: 'flex-end', gap: 10 }}>
          <button onClick={onClose} disabled={processing} style={secondaryBtn}>{paid ? 'Close' : 'Cancel'}</button>
          {!paid && (() => {
            const blocked = processing || (recaptchaEnabled() && !captcha);
            return (
              <button onClick={handlePay} disabled={blocked} style={{ ...secondaryBtn, background: '#108000', color: '#fff', border: 'none', opacity: blocked ? 0.7 : 1, cursor: blocked ? 'default' : 'pointer' }}>
                {processing ? 'Processing…' : `Pay ${fmt(total, order.warehouse.currency)}`}
              </button>
            );
          })()}
        </div>
      </div>
    </div>
  );
}

function createQuickBooksDemoPdfBlob(order) {
  const totals = order.totals || summarizeOrderItems(order.items, order.exportFee || 0);
  const inStockItems = order.items.filter((it) => it.inStockQty > 0);
  const additionalItems = order.items.filter((it) => it.additionalQty > 0);
  const lines = [
    'Gruv Gear / QuickBooks Invoice',
    `Invoice: ${order.id}`,
    `Date: ${order.date}`,
    `Customer: ${order.customer || 'Reseller account'}`,
    `Ship to: ${order.shipping?.location?.label || ''}`,
    `Address: ${order.shipping?.location?.address || ''}`,
    `Shipping method: ${order.shipping?.method || ''}`,
    `Warehouse: ${order.warehouse.name}`,
    '',
    'In-stock order',
    ...(inStockItems.length ? inStockItems.slice(0, 10).map((it) => `${it.sku}  ${it.inStockQty} x ${fmt(it.buy)}  ${fmt(it.inStockSubtotal)}`) : ['None']),
    '',
    'Additional unit order',
    ...(additionalItems.length ? additionalItems.slice(0, 10).map((it) => `${it.sku}  ${it.additionalQty} x ${fmt(it.buy)}  ${fmt(it.additionalSubtotal)}`) : ['None']),
    '',
    `In-stock total: ${fmt(totals.inStockSubtotal, order.warehouse.currency)}`,
    `Additional unit total: ${fmt(totals.additionalSubtotal, order.warehouse.currency)}`,
    ...(order.exportFee ? [`Shanghai export license fee: ${fmt(order.exportFee, order.warehouse.currency)}`] : []),
    `Grand total: ${fmt(totals.grandTotal, order.warehouse.currency)}`,
  ];
  const escape = (s) => String(s).replace(/[\\()]/g, '\\$&');
  const content = ['BT', '/F1 12 Tf', '50 760 Td', ...lines.flatMap((line, i) => [`(${escape(line)}) Tj`, i === lines.length - 1 ? '' : '0 -18 Td']), 'ET'].join('\n');
  const objects = [
    '<< /Type /Catalog /Pages 2 0 R >>',
    '<< /Type /Pages /Kids [3 0 R] /Count 1 >>',
    '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >>',
    '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>',
    `<< /Length ${content.length} >>\nstream\n${content}\nendstream`,
  ];
  let pdf = '%PDF-1.4\n';
  const offsets = [0];
  objects.forEach((obj, i) => {
    offsets.push(pdf.length);
    pdf += `${i + 1} 0 obj\n${obj}\nendobj\n`;
  });
  const xref = pdf.length;
  pdf += `xref\n0 ${objects.length + 1}\n0000000000 65535 f \n`;
  offsets.slice(1).forEach((off) => { pdf += `${String(off).padStart(10, '0')} 00000 n \n`; });
  pdf += `trailer\n<< /Size ${objects.length + 1} /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF`;
  return new Blob([pdf], { type: 'application/pdf' });
}

function downloadQuickBooksDemoPdf(order) {
  const a = document.createElement('a');
  a.href = URL.createObjectURL(createQuickBooksDemoPdfBlob(order));
  a.download = `${order.id}-quickbooks-invoice.pdf`;
  a.click();
  URL.revokeObjectURL(a.href);
}

function Meta({ label, value, mono }) {
  return (
    <div>
      <div style={{ fontSize: 10, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 3 }}>{label}</div>
      <div style={{ fontSize: 13, fontWeight: 500, fontFamily: mono ? L.mono : L.font }}>{value}</div>
    </div>
  );
}

function TotalRow({ label, value, dim, accent }) {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13, padding: '4px 0' }}>
      <span style={{ color: dim ? 'rgba(255,255,255,0.55)' : '#fff' }}>{label}</span>
      <span style={{ fontFamily: L.mono, color: accent || '#fff', fontWeight: 500 }}>{value}</span>
    </div>
  );
}

const secondaryBtn = {
  height: 38, padding: '0 16px', background: '#fff',
  border: `1px solid ${L.borderStrong}`, borderRadius: 8,
  fontSize: 13, fontWeight: 500, fontFamily: L.font,
  color: L.text, cursor: 'pointer',
};

// ── REVIEW ───────────────────────────────────────────────────────────────
function LedgerReview({ catalog, warehouse, cart, discountPercent, onBack, onConfirm }) {
  const disc = Number(discountPercent) || 0;
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  const items = cart.lineItems(catalog, warehouse, discountPercent);
  const subtotal = items.reduce((a, b) => a + b.subtotal, 0);
  const retail = items.reduce((a, b) => a + b.retailSubtotal, 0);
  const exportFee = subtotal > 0 ? exportLicenseFee(warehouse) : 0;
  const totals = summarizeOrderItems(items, exportFee);
  const inStockItems = items.filter((it) => it.inStockQty > 0);
  const additionalItems = items.filter((it) => it.additionalQty > 0);
  const nav = React.useContext(LedgerNav) || {};
  // Prefer the signed-in reseller's own ship-to destinations from the DB; fall
  // back to the generic list only if none are on file for their account.
  const dbLocations = nav.user?.shipTo || [];
  const usingDbLocations = dbLocations.length > 0;
  const shipLocations = usingDbLocations ? dbLocations : SHIPPING_LOCATIONS;
  const availableShipMethods = SHIPPING_METHODS;
  const lastShipMethod = availableShipMethods.find((m) => m.lastUsed) || availableShipMethods[0];
  const defaultLoc = usingDbLocations ? (dbLocations.find((l) => l.isDefault) || dbLocations[0]) : null;
  const [shipLocation, setShipLocation] = React.useState(defaultLoc ? defaultLoc.id : '');
  const [shipMethod, setShipMethod] = React.useState(lastShipMethod?.id || '');
  const selectedLocation = shipLocations.find((l) => l.id === shipLocation);
  // For DB locations the carrier + account travel with the destination.
  const locationCarrier = usingDbLocations && selectedLocation?.carrier
    ? `${selectedLocation.carrier}${selectedLocation.account ? ` (${selectedLocation.account})` : ''}`
    : '';
  const selectedShipMethod = availableShipMethods.find((m) => m.id === shipMethod);
  const confirmedMethod = usingDbLocations ? locationCarrier : shippingMethodLabel(selectedShipMethod);
  const canConfirm = Boolean(shipLocation && (usingDbLocations || selectedShipMethod));
  return (
    <>
      <LedgerTopBar warehouse={warehouse} />
      <div style={{ flex: 1, overflow: 'auto', padding: isPhone ? '18px 12px' : '32px 48px' }}>
        <div style={{ maxWidth: 980, margin: '0 auto' }}>
          <button onClick={onBack} style={{
            background: 'transparent', border: 'none', color: L.textMid,
            fontFamily: L.font, fontSize: 13, cursor: 'pointer', marginBottom: 12, padding: 0,
          }}>← Back to catalog</button>
          <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim, letterSpacing: 1.5, marginBottom: 6 }}>STEP 3 / 3 · REVIEW</div>
          <div style={{ fontSize: 28, fontWeight: 600, letterSpacing: -0.5, marginBottom: 6 }}>Review your order</div>
          <div style={{ fontSize: 14, color: L.textMid, marginBottom: 24 }}>
            Check line items, quantities and ship-to address. Nothing is submitted until you confirm.
          </div>

          <ReviewOrderSection title="In-stock order" items={inStockItems} qtyKey="inStockQty" subtotalKey="inStockSubtotal" empty="No in-stock units in this order." cart={cart} catalog={catalog} warehouse={warehouse} />
          <ReviewOrderSection title="Backorder" items={additionalItems} qtyKey="additionalQty" subtotalKey="additionalSubtotal" empty="No items on backorder." cart={cart} catalog={catalog} warehouse={warehouse} />

          <div style={{ display: 'grid', gridTemplateColumns: isPhone ? '1fr' : '1fr 1fr', gap: 20 }}>
            <div style={{ background: L.surface, border: `1px solid ${L.border}`, borderRadius: 10, padding: 22 }}>
              <div style={{ fontSize: 12, fontWeight: 600, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 14 }}>Shipping</div>
              <div style={{ marginBottom: 12 }}>
                <div style={{ fontSize: 11, color: L.textDim, marginBottom: 5 }}>
                  Ship-to location <span style={{ color: '#ef4444' }}>*</span>
                </div>
                <LedgerSelect
                  value={shipLocation}
                  onChange={setShipLocation}
                  placeholder="Choose shipping location"
                  error={!shipLocation}
                  options={shipLocations.map((loc) => ({ id: loc.id, label: loc.label }))}
                />
                {!shipLocation && <div style={{ fontSize: 11, color: '#ef4444', marginTop: 4 }}>Required to submit order</div>}
              </div>
              {selectedLocation && <div style={{ margin: '-2px 0 14px', fontSize: 12, color: L.textMid, lineHeight: 1.45 }}>{selectedLocation.address}</div>}
              {usingDbLocations ? (
                locationCarrier ? (
                  <div>
                    <div style={{ fontSize: 11, color: L.textDim, marginBottom: 5 }}>Shipping method</div>
                    <div style={{ fontSize: 13, color: L.text }}>{locationCarrier}</div>
                    <div style={{ fontSize: 11, color: L.textDim, marginTop: 2 }}>Your carrier account on file for this destination.</div>
                  </div>
                ) : null
              ) : (
                <div>
                  <div style={{ fontSize: 11, color: L.textDim, marginBottom: 5 }}>Shipping method</div>
                  <LedgerSelect
                    value={shipMethod}
                    onChange={setShipMethod}
                    placeholder="Choose shipping method"
                    options={availableShipMethods.map((m) => ({ id: m.id, label: shippingMethodLabel(m) }))}
                  />
                </div>
              )}
              <div style={{ marginTop: 14, paddingTop: 14, borderTop: `1px solid ${L.border}`, fontSize: 12, color: L.textDim }}>
                <span>From {warehouse.flag} {warehouse.name}</span>
              </div>
            </div>
            <div style={{ background: '#0b1220', color: '#fff', borderRadius: 10, padding: 22 }}>
              <div style={{ fontSize: 12, fontWeight: 600, color: 'rgba(255,255,255,0.5)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 14 }}>Totals</div>
              <TotalRow label="Retail value" value={fmt(retail)} dim />
              <TotalRow label={`Trade discount (${disc}%)`} value={'−' + fmt(retail - subtotal)} accent="#7ce3a3" />
              <TotalRow label="In-stock order" value={fmt(totals.inStockSubtotal)} dim />
              <TotalRow label="Backorder" value={fmt(totals.additionalSubtotal)} dim />
              {exportFee > 0 && <TotalRow label="Shanghai export license fee" value={fmt(exportFee)} dim />}
              <div style={{ borderTop: '1px solid rgba(255,255,255,0.15)', marginTop: 10, paddingTop: 10, display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                <div style={{ fontSize: 14 }}>Grand total</div>
                <div style={{ fontFamily: L.mono, fontSize: 24, fontWeight: 700, letterSpacing: -0.5 }}>{fmt(totals.grandTotal, warehouse.currency)}</div>
              </div>
            </div>
          </div>

          <div style={{ display: 'flex', gap: 10, marginTop: 24, justifyContent: 'flex-end', alignItems: 'center', flexWrap: 'wrap' }}>
            <div style={{ fontSize: 12, color: L.textDim, marginRight: 'auto' }}>By confirming, you agree to Net 30 payment terms.</div>
            <button onClick={onBack} style={secondaryBtn}>Keep editing</button>
            <button onClick={() => onConfirm({ location: selectedLocation, method: confirmedMethod })} disabled={!canConfirm} style={{ ...secondaryBtn, background: canConfirm ? L.accent : L.borderStrong, color: '#fff', border: 'none', cursor: canConfirm ? 'pointer' : 'not-allowed' }}>Confirm order →</button>
          </div>
        </div>
      </div>
    </>
  );
}

// ── PRODUCT DETAIL ───────────────────────────────────────────────────────
function LedgerProductDetail({ product, warehouse, cart, discountPercent, onClose }) {
  const disc = Number(discountPercent) || 0;
  const width = useLedgerViewportWidth();
  const isPhone = width < 760;
  product = regionalProduct(product, warehouse, discountPercent);
  const qty = cart.cart[product.sku] || 0;
  const stock = product.stock[warehouse.name];
  const desc = product.description || `Wholesale item available at ${disc}% off retail.`;
  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 20,
      background: 'rgba(16, 24, 40, 0.5)', display: 'flex', justifyContent: 'flex-end',
    }} onClick={onClose}>
      <div onClick={e => e.stopPropagation()} style={{
        width: isPhone ? '100%' : 720, maxWidth: '100%', background: L.surface, display: 'flex', flexDirection: 'column',
        boxShadow: '-20px 0 40px rgba(0,0,0,0.1)',
      }}>
        <div style={{ padding: isPhone ? '12px 14px' : '16px 24px', borderBottom: `1px solid ${L.border}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <div style={{ fontFamily: L.mono, fontSize: 11, color: L.textDim }}>{product.sku}</div>
            <span style={{ color: L.border }}>·</span>
            <div style={{ fontSize: 12, color: L.textMid }}>{product.category}</div>
          </div>
          <button onClick={onClose} style={{
            width: 30, height: 30, border: `1px solid ${L.border}`, borderRadius: 6,
            background: '#fff', fontSize: 16, cursor: 'pointer', color: L.textMid,
          }}>×</button>
        </div>
        <div style={{ flex: 1, overflow: 'auto', padding: isPhone ? 14 : 28 }}>
          <div style={{ display: 'grid', gridTemplateColumns: isPhone ? '1fr' : '280px 1fr', gap: isPhone ? 16 : 28, marginBottom: 24 }}>
            <div style={{
              aspectRatio: '1', background: L.bg, borderRadius: 10, border: `1px solid ${L.border}`,
              display: 'grid', placeItems: 'center', overflow: 'hidden',
            }}>
              <LedgerImage src={product.image} inset="86%" />
            </div>
            <div>
              <div style={{ fontSize: 22, fontWeight: 600, letterSpacing: -0.3, lineHeight: 1.2, marginBottom: 6 }}>{product.name}</div>
              <div style={{ fontSize: 13, color: L.textDim, marginBottom: 18 }}>{product.color}{product.size !== '—' ? ' · ' + product.size : ''}</div>

              <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 4 }}>
                <div style={{ fontFamily: L.mono, fontSize: 24, fontWeight: 700 }}>{fmt(product.buy)}</div>
                <div style={{ fontSize: 13, color: L.textDim, textDecoration: 'line-through', fontFamily: L.mono }}>{fmt(product.retail)}</div>
                <div style={{ padding: '2px 7px', background: L.discountBg, color: L.discount, borderRadius: 3, fontSize: 11, fontWeight: 600 }}>−{disc}%</div>
              </div>
              <div style={{ fontSize: 12, color: L.textMid, marginBottom: 20 }}>Your reseller price per unit</div>

              <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 12, padding: '14px 16px', background: L.bg, borderRadius: 8, border: `1px solid ${L.border}`, marginBottom: 18 }}>
                <div>
                  <div style={{ fontSize: 10, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 3 }}>Stock in {warehouse.name}</div>
                  <div style={{ fontFamily: L.mono, fontSize: 14, fontWeight: 600, color: stock === 0 ? L.warn : stock < 100 ? L.warn : L.text }}>{stock === 0 ? 'Backorder' : fmtInt(stock) + ' units'}</div>
                </div>
              </div>

              <div style={{ display: 'grid', gap: 10, justifyItems: isPhone ? 'stretch' : 'start' }}>
                <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
                  <QtyStepper value={qty} moq={product.moq} max={stock} onInc={() => cart.inc(product.sku, product.moq, product.moq, stock)} onDec={() => cart.dec(product.sku, product.moq, product.moq, stock)} onSet={(v) => cart.setQty(product.sku, v, stock, product.moq)} disabled={false} />
                  {qty > 0 && <div style={{ fontFamily: L.mono, fontSize: 13, color: L.textMid }}>Line total <b style={{ color: L.text }}>{fmt(qty * product.buy)}</b></div>}
                </div>
                <button
                  onClick={onClose}
                  disabled={qty <= 0}
                  style={{
                    ...secondaryBtn,
                    width: isPhone ? '100%' : 'auto',
                    background: qty > 0 ? L.accent : L.border,
                    color: '#fff',
                    border: 'none',
                    cursor: qty > 0 ? 'pointer' : 'not-allowed',
                  }}
                >Add to cart</button>
              </div>
            </div>
          </div>

          <div style={{ borderTop: `1px solid ${L.border}`, paddingTop: 22 }}>
            <div style={{ fontSize: 12, fontWeight: 600, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 10 }}>Description</div>
            <div style={{ fontSize: 13, lineHeight: 1.65, color: L.text, whiteSpace: 'pre-wrap' }}>{desc}</div>
            {(product.upc || product.dimensions || product.weight || product.brand) && (
              <div style={{ marginTop: 16, display: 'grid', gridTemplateColumns: isPhone ? 'repeat(2, 1fr)' : 'repeat(4, 1fr)', gap: 10, fontFamily: L.mono, fontSize: 11, color: L.textMid }}>
                {product.brand && <div><b style={{ color: L.textDim }}>Brand</b><br/>{product.brand}</div>}
                {product.upc && <div><b style={{ color: L.textDim }}>UPC</b><br/>{product.upc}</div>}
                {product.dimensions && <div><b style={{ color: L.textDim }}>Size</b><br/>{product.dimensions}</div>}
                {product.weight && <div><b style={{ color: L.textDim }}>Weight</b><br/>{product.weight} lb</div>}
              </div>
            )}
          </div>

          {product.bullets && product.bullets.length > 0 && (
            <div style={{ marginTop: 22 }}>
              <div style={{ fontSize: 12, fontWeight: 600, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 10 }}>Features</div>
              <ul style={{ padding: 0, margin: 0, listStyle: 'none' }}>
                {product.bullets.map((b, i) => (
                  <li key={i} style={{ display: 'flex', gap: 10, fontSize: 13, lineHeight: 1.5, padding: '4px 0', color: L.textMid }}>
                    <span style={{ color: L.accent, marginTop: 1 }}>—</span><span>{b}</span>
                  </li>
                ))}
              </ul>
            </div>
          )}

          <div style={{ marginTop: 22, display: 'grid', gridTemplateColumns: isPhone ? '1fr' : 'repeat(3, 1fr)', gap: 14, paddingTop: 22, borderTop: `1px solid ${L.border}` }}>
            <Spec label="SKU" value={product.sku} mono />
            <Spec label="UPC" value={product.upc || '—'} mono />
            <Spec label="Country of origin" value={product.origin || '—'} />
          </div>
        </div>
      </div>
    </div>
  );
}

function Spec({ label, value, mono }) {
  return (
    <div>
      <div style={{ fontSize: 10, color: L.textDim, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 3 }}>{label}</div>
      <div style={{ fontSize: 12, fontWeight: 500, fontFamily: mono ? L.mono : L.font }}>{value}</div>
    </div>
  );
}

window.LedgerApp = LedgerApp;
