// daygig-sales.js — Sales: orders, customers, shipments, events, campaigns

// ── Shared helpers ────────────────────────────────────────────────────────
  let _dgOrderProducts = [];   // cached for order item picker
  let _dgOrderList     = [];   // cached for shipment order picker

  function _todayISO() {
    return new Date().toISOString().slice(0,10);
  }

  // ── Add Order ─────────────────────────────────────────────────────────────
  function toggleOrderForm() {
    const body = document.getElementById('orderFormBody');
    if (!body) return;
    const open = body.style.display !== 'none';
    body.style.display = open ? 'none' : '';
    if (!open) {
      // Set today's date and pre-add one item row
      const dateEl = document.getElementById('order-date');
      if (dateEl && !dateEl.value) dateEl.value = _todayISO();
      const tbody = document.getElementById('order-items-tbody');
      if (tbody && !tbody.children.length) addOrderItem();
      _loadOrderProducts();
    }
  }

  async function _loadOrderProducts() {
    if (_dgOrderProducts.length) { _renderOrderProductOptions(); return; }
    try {
      const res  = await fetch('/api/products?active_only=1&limit=200');
      const data = await res.json();
      _dgOrderProducts = Array.isArray(data) ? data : (data.products || []);
      _renderOrderProductOptions();
    } catch(e) { /* non-fatal */ }
  }

  function _renderOrderProductOptions() {
    document.querySelectorAll('.order-item-product').forEach(sel => {
      _fillProductSelect(sel);
    });
  }

  function _fillProductSelect(sel) {
    const cur = sel.value;
    sel.innerHTML = '<option value="">— pick product —</option>' +
      _dgOrderProducts.map(p =>
        `<option value="${p.id}" data-price="${p.sale_price||0}" data-sku="${p.sku||''}">${p.name}${p.sku ? ' ('+p.sku+')' : ''} — ${dgMoney(p.sale_price||0)}</option>`
      ).join('');
    if (cur) sel.value = cur;
  }

  function addOrderItem() {
    const tbody = document.getElementById('order-items-tbody');
    if (!tbody) return;
    const tr = document.createElement('tr');
    tr.innerHTML = `
      <td style="padding:4px 6px;">
        <select class="order-item-product" onchange="orderItemProductChange(this)" style="width:100%;background:var(--surface2);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:12px;padding:5px 6px;">
          <option value="">— pick product —</option>
          ${_dgOrderProducts.map(p => `<option value="${p.id}" data-price="${p.sale_price||0}">${p.name}${p.sku ? ' ('+p.sku+')' : ''} — ${dgMoney(p.sale_price||0)}</option>`).join('')}
        </select>
      </td>
      <td style="padding:4px 6px;"><input type="number" class="order-item-qty" min="1" value="1" style="width:60px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:12px;padding:5px 6px;"></td>
      <td style="padding:4px 6px;"><input type="number" class="order-item-price" min="0" step="0.01" placeholder="0.00" style="width:80px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:12px;padding:5px 6px;"></td>
      <td style="padding:4px 6px;text-align:center;"><button type="button" onclick="this.closest('tr').remove()" style="background:transparent;border:none;color:var(--err);cursor:pointer;font-size:14px;padding:2px 6px;">✕</button></td>`;
    tbody.appendChild(tr);
  }

  function orderItemProductChange(sel) {
    const opt = sel.options[sel.selectedIndex];
    const price = parseFloat(opt.dataset.price || 0);
    const row = sel.closest('tr');
    const priceInput = row.querySelector('.order-item-price');
    if (priceInput && price > 0) priceInput.value = price.toFixed(2);
  }

  async function submitOrder() {
    const msg = document.getElementById('order-msg');
    const channel        = document.getElementById('order-channel').value;
    const status         = document.getElementById('order-status').value;
    const payment_method = document.getElementById('order-payment').value;
    const order_date     = document.getElementById('order-date').value || _todayISO();
    const customer_name  = document.getElementById('order-cust-name').value.trim() || 'In-person';
    const customer_email = document.getElementById('order-cust-email').value.trim() || null;
    const discount       = parseFloat(document.getElementById('order-discount').value || 0);
    const shipping       = parseFloat(document.getElementById('order-shipping').value || 0);
    const notes          = document.getElementById('order-notes').value.trim() || null;

    if (!payment_method) {
      msg.style.color = 'var(--err)'; msg.style.display = '';
      msg.textContent = 'Payment method is required.'; return;
    }

    // Collect items
    const itemRows = document.querySelectorAll('#order-items-tbody tr');
    const items = [];
    for (const row of itemRows) {
      const pid   = parseInt(row.querySelector('.order-item-product')?.value || 0, 10);
      const qty   = parseInt(row.querySelector('.order-item-qty')?.value || 0, 10);
      const price = parseFloat(row.querySelector('.order-item-price')?.value || 0);
      if (!pid || qty <= 0) continue;
      items.push({ product_id: pid, quantity: qty, unit_price: price });
    }
    if (!items.length) {
      msg.style.color = 'var(--err)'; msg.style.display = '';
      msg.textContent = 'Add at least one item.'; return;
    }

    msg.style.display = ''; msg.style.color = 'var(--text-soft)'; msg.textContent = 'Saving…';
    try {
      const res = await fetch('/api/orders', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({ channel, status, payment_method, order_date, customer_name,
          customer_email, discount, shipping_charged: shipping, notes, items }),
      });
      const data = await res.json();
      if (data.id || data.ok) {
        msg.style.color = 'var(--accent)'; msg.textContent = '✓ Order saved.';
        document.getElementById('orderFormBody').style.display = 'none';
        ordersLoad();
      } else {
        msg.style.color = 'var(--err)'; msg.textContent = data.error || 'Error saving order.';
      }
    } catch(e) { msg.style.color = 'var(--err)'; msg.textContent = 'Network error: ' + e.message; }
  }

  // ── Add Customer ──────────────────────────────────────────────────────────
  function toggleCustForm() {
    const body = document.getElementById('custFormBody');
    if (!body) return;
    body.style.display = body.style.display === 'none' ? '' : 'none';
  }

  async function submitCustomer() {
    const msg   = document.getElementById('cust-msg');
    const name  = document.getElementById('new-cust-name').value.trim();
    if (!name) {
      msg.style.display = ''; msg.style.color = 'var(--err)';
      msg.textContent = 'Name is required.'; return;
    }
    msg.style.display = ''; msg.style.color = 'var(--text-soft)'; msg.textContent = 'Saving…';
    try {
      const res = await fetch('/api/customers', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({
          name,
          email:  document.getElementById('new-cust-email').value.trim() || null,
          phone:  document.getElementById('new-cust-phone').value.trim() || null,
          city:   document.getElementById('new-cust-city').value.trim()  || null,
          state:  document.getElementById('new-cust-state').value.trim().toUpperCase() || null,
          notes:  document.getElementById('new-cust-notes').value.trim() || null,
        }),
      });
      const data = await res.json();
      if (data.id || data.ok) {
        msg.style.color = 'var(--accent)'; msg.textContent = '✓ Customer saved.';
        ['new-cust-name','new-cust-email','new-cust-phone','new-cust-city','new-cust-state','new-cust-notes']
          .forEach(id => { const el = document.getElementById(id); if (el) el.value = ''; });
        document.getElementById('custFormBody').style.display = 'none';
        customersLoad();
      } else {
        msg.style.color = 'var(--err)'; msg.textContent = data.error || 'Error saving customer.';
      }
    } catch(e) { msg.style.color = 'var(--err)'; msg.textContent = 'Network error: ' + e.message; }
  }

  // ── Add Shipment ──────────────────────────────────────────────────────────
  function toggleShipForm() {
    const body = document.getElementById('shipFormBody');
    if (!body) return;
    const open = body.style.display !== 'none';
    body.style.display = open ? 'none' : '';
    if (!open) {
      const dateEl = document.getElementById('ship-date');
      if (dateEl && !dateEl.value) dateEl.value = _todayISO();
      _loadOrdersForShipment();
    }
  }

  async function _loadOrdersForShipment() {
    const sel = document.getElementById('ship-order-select');
    if (!sel) return;
    if (_dgOrderList.length) { _fillShipOrderSelect(sel); return; }
    try {
      const res  = await fetch('/api/orders?limit=200');
      const data = await res.json();
      _dgOrderList = Array.isArray(data) ? data : (data.orders || []);
      _fillShipOrderSelect(sel);
    } catch(e) { /* non-fatal */ }
  }

  function _fillShipOrderSelect(sel) {
    sel.innerHTML = '<option value="">— select order —</option>' +
      _dgOrderList.map(o =>
        `<option value="${o.id}">${o.order_number} — ${o.customer_name||'?'} (${dgMoney(o.total||0)})</option>`
      ).join('');
  }

  async function submitShipment() {
    const msg      = document.getElementById('ship-msg');
    const order_id = parseInt(document.getElementById('ship-order-select').value || 0, 10);
    const carrier  = document.getElementById('ship-carrier').value;
    const ship_date = document.getElementById('ship-date').value || _todayISO();
    const tracking = document.getElementById('ship-tracking').value.trim() || null;
    const postage  = parseFloat(document.getElementById('ship-postage').value || 0);
    const notes    = document.getElementById('ship-notes').value.trim() || null;

    if (!order_id) {
      msg.style.display = ''; msg.style.color = 'var(--err)';
      msg.textContent = 'Select an order.'; return;
    }
    if (!carrier) {
      msg.style.display = ''; msg.style.color = 'var(--err)';
      msg.textContent = 'Select a carrier.'; return;
    }

    msg.style.display = ''; msg.style.color = 'var(--text-soft)'; msg.textContent = 'Saving…';
    try {
      const res = await fetch('/api/shipments', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({ order_id, ship_date, carrier, tracking_number: tracking,
          postage_dollars: postage, notes }),
      });
      const data = await res.json();
      if (data.id || data.ok) {
        msg.style.color = 'var(--accent)'; msg.textContent = '✓ Shipment logged.';
        ['ship-tracking','ship-postage','ship-notes'].forEach(id => {
          const el = document.getElementById(id); if (el) el.value = '';
        });
        document.getElementById('ship-order-select').value = '';
        document.getElementById('ship-carrier').value = 'usps';
        document.getElementById('ship-date').value = _todayISO();
        document.getElementById('shipFormBody').style.display = 'none';
        _dgOrderList = [];  // bust cache so re-opening refreshes order list
        shipmentsLoad();
      } else {
        msg.style.color = 'var(--err)'; msg.textContent = data.error || 'Error logging shipment.';
      }
    } catch(e) { msg.style.color = 'var(--err)'; msg.textContent = 'Network error: ' + e.message; }
  }

// ── Orders ────────────────────────────────────────────────────────────────
  async function ordersLoad() {
    const tbody = document.getElementById('orders-tbody');
    const sub   = document.getElementById('orders-sub');
    tbody.innerHTML = '<tr><td colspan="7" style="padding:32px;text-align:center;color:var(--text-dim);">Loading…</td></tr>';
    try {
      const res  = await fetch('/api/orders?limit=100');
      const data = await res.json();
      const orders = Array.isArray(data) ? data : (data.orders || []);
      if (!orders.length) {
        tbody.innerHTML = '<tr><td colspan="7" style="padding:32px;text-align:center;color:var(--text-dim);">No orders yet.</td></tr>';
        sub.textContent = '0 orders';
        return;
      }
      sub.textContent = `${orders.length} order${orders.length !== 1 ? 's' : ''}`;
      const statusColor = { completed:'var(--accent)', draft:'var(--text-dim)', refunded:'var(--err)', cancelled:'var(--err)', pending:'var(--warn)' };
      tbody.innerHTML = orders.map(o => `
        <tr style="border-bottom:1px solid var(--border);">
          <td style="padding:7px 10px;font-family:var(--mono);font-size:11px;color:var(--text-soft);">${o.order_number}</td>
          <td style="padding:7px 10px;font-family:var(--mono);font-size:12px;color:var(--text-soft);">${o.order_date}</td>
          <td style="padding:7px 10px;font-size:13px;color:var(--text);">${o.customer_name || '—'}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text-soft);">${o.channel || '—'}</td>
          <td style="padding:7px 10px;"><span style="font-family:var(--mono);font-size:10px;color:${statusColor[o.status]||'var(--text-dim)'};">${o.status}</span>${o.status === 'completed' ? ` <button onclick="openReturnPanel(${o.id})" title="Record a return/refund" style="background:transparent;border:1px solid var(--border);border-radius:5px;color:var(--text-dim);font-size:10px;padding:2px 7px;margin-left:6px;cursor:pointer;">↔ Return</button>` : ''}${(o.status === 'invoice' || o.status === 'draft') ? ` <button onclick="markOrderPaid(${o.id})" title="Mark this invoice paid" style="background:var(--accent-bg);border:1px solid var(--accent-ring);border-radius:5px;color:var(--accent);font-size:10px;padding:2px 7px;margin-left:6px;cursor:pointer;">Mark Paid</button>` : ''}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--text);">${dgMoney(o.total||0)}</td>
          <td style="padding:7px 10px;text-align:center;font-size:12px;"><a href="/api/orders/${o.id}/invoice.pdf" target="_blank" title="Download invoice PDF" style="color:var(--text-soft);text-decoration:none;margin-right:8px;">${dgIcon('receipt', 14)}</a>${o.has_shipment ? '✓' : '—'}</td>
        </tr>`).join('');
    } catch(e) { tbody.innerHTML = `<tr><td colspan="7" style="padding:20px;color:var(--err);">Error: ${e.message}</td></tr>`; }
  }

  async function refundOrderUI(orderId) {
    if (!orderId) return;
    // Step 1: confirm the refund itself (Cancel aborts).
    if (!confirm(
      'Refund this order?\n\n' +
      'This reverses the sale in your ledger (revenue, sales tax, and COGS) and ' +
      'marks the order Refunded.'
    )) return;
    // Step 2: separate yes/no for restocking.
    const restock = confirm(
      'Restock the items to inventory?\n\n' +
      'OK = put the items back in stock\n' +
      'Cancel = do not restock (e.g. the goods came back damaged)'
    );
    try {
      const res = await fetch('/api/orders/refund/' + orderId, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ restock }),
      });
      const data = await res.json();
      if (data.error) { alert('Refund failed: ' + data.error); return; }
      if (data.warnings && data.warnings.length) {
        alert('Refunded, with notes:\n• ' + data.warnings.join('\n• '));
      }
      ordersLoad();
    } catch (e) { alert('Refund failed: ' + e.message); }
  }
  if (typeof window !== 'undefined') window.refundOrderUI = refundOrderUI;

  async function markOrderPaid(orderId) {
    if (!orderId) return;
    if (!confirm('Mark this invoice as paid? It will be set to Completed.')) return;
    try {
      const res = await fetch('/api/orders/mark-paid/' + orderId, {
        method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}',
      });
      const data = await res.json();
      if (data.error) { alert('Failed: ' + data.error); return; }
      ordersLoad();
      if (typeof loadDashboard === 'function') loadDashboard();
    } catch (e) { alert('Failed: ' + e.message); }
  }
  if (typeof window !== 'undefined') window.markOrderPaid = markOrderPaid;

  // ── Returns / refunds ─────────────────────────────────────────────────────
  async function openReturnPanel(orderId) {
    const modal = document.getElementById('return-modal');
    const linesEl = document.getElementById('return-lines');
    if (!modal || !linesEl) return;
    linesEl.dataset.orderId = orderId;
    linesEl.innerHTML = 'Loading…';
    modal.style.display = 'flex';
    try {
      const res = await fetch('/api/orders/' + orderId);
      const order = await res.json();
      document.getElementById('return-title').textContent = 'Return / Refund — ' + (order.order_number || '');
      const items = (order.items || []).filter(i => (i.returnable_qty || 0) > 0);
      if (!items.length) { linesEl.innerHTML = '<div style="color:var(--text-dim);">Every item on this order has already been returned.</div>'; return; }
      const esc = (s) => String(s == null ? '' : s).replace(/[&<>"]/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[m]));
      linesEl.innerHTML = items.map(i => `
        <div class="return-line" data-item="${i.id}" style="display:flex;gap:10px;align-items:center;border-bottom:1px solid var(--border);padding:8px 0;">
          <div style="flex:1;font-size:13px;">${esc(i.product_name_snapshot || i.sku_snapshot)} <span style="color:var(--text-dim);">(${dgMoney(i.unit_price)} · ${i.returnable_qty} returnable)</span></div>
          <input type="number" class="return-qty" min="0" max="${i.returnable_qty}" value="0" style="width:64px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:12px;padding:5px 8px;">
          <select class="return-disp" style="background:var(--surface2);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:12px;padding:5px 8px;">
            <option value="restock">Restock</option><option value="scrap">Scrap</option><option value="replace">Replace</option>
          </select>
        </div>`).join('');
    } catch (e) { linesEl.innerHTML = 'Could not load order: ' + e.message; }
  }
  function closeReturnPanel() {
    const modal = document.getElementById('return-modal');
    if (modal) modal.style.display = 'none';
  }
  async function submitReturn() {
    const linesEl = document.getElementById('return-lines');
    const orderId = linesEl && linesEl.dataset.orderId;
    const msg = document.getElementById('return-msg');
    const show = (t) => { if (msg) { msg.textContent = t; msg.style.display = 'inline'; } };
    if (msg) msg.style.display = 'none';
    const lines = [];
    document.querySelectorAll('#return-lines .return-line').forEach(row => {
      const qty = parseInt(row.querySelector('.return-qty').value || '0', 10);
      if (qty > 0) lines.push({
        order_item_id: parseInt(row.dataset.item, 10),
        quantity: qty,
        disposition: row.querySelector('.return-disp').value,
      });
    });
    if (!lines.length) { show('Enter a quantity for at least one item.'); return; }
    const payload = {
      lines,
      refund_shipping: document.getElementById('return-shipping').checked,
      fee_lost: parseFloat(document.getElementById('return-fee').value || '0'),
      reason: document.getElementById('return-reason').value || '',
    };
    try {
      const res = await fetch('/api/orders/return/' + orderId, {
        method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload),
      });
      const data = await res.json();
      if (data.error) { show('Failed: ' + data.error); return; }
      if (data.warnings && data.warnings.length) alert('Recorded, with notes:\n• ' + data.warnings.join('\n• '));
      closeReturnPanel();
      ordersLoad();
      if (typeof loadDashboard === 'function') loadDashboard();
    } catch (e) { show('Failed: ' + e.message); }
  }
  if (typeof window !== 'undefined') {
    window.openReturnPanel = openReturnPanel;
    window.closeReturnPanel = closeReturnPanel;
    window.submitReturn = submitReturn;
  }

  // ── Customers ─────────────────────────────────────────────────────────────
  async function customersLoad() {
    const tbody  = document.getElementById('cust-tbody');
    const sub    = document.getElementById('cust-sub');
    const search = document.getElementById('cust-search')?.value.trim() || '';
    tbody.innerHTML = '<tr><td colspan="5" style="padding:32px;text-align:center;color:var(--text-dim);">Loading…</td></tr>';
    try {
      const url  = '/api/customers' + (search ? `?search=${encodeURIComponent(search)}` : '');
      const res  = await fetch(url);
      const data = await res.json();
      const custs = Array.isArray(data) ? data : [];
      if (!custs.length) {
        tbody.innerHTML = '<tr><td colspan="5" style="padding:32px;text-align:center;color:var(--text-dim);">No customers found.</td></tr>';
        sub.textContent = '0 customers';
        return;
      }
      sub.textContent = `${custs.length} customer${custs.length !== 1 ? 's' : ''}`;
      tbody.innerHTML = custs.map(c => `
        <tr style="border-bottom:1px solid var(--border);">
          <td style="padding:7px 10px;font-size:13px;color:var(--text);font-weight:500;">${c.name}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text-soft);">${c.email || '—'}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text-soft);">${[c.city, c.state].filter(Boolean).join(', ') || '—'}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;">${c.order_count || 0}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--accent);">${dgMoney(c.lifetime_value||0)}</td>
        </tr>`).join('');
    } catch(e) { tbody.innerHTML = `<tr><td colspan="5" style="padding:20px;color:var(--err);">Error: ${e.message}</td></tr>`; }
  }

  // ── Shipments ─────────────────────────────────────────────────────────────
  async function shipmentsLoad() {
    const tbody = document.getElementById('ship-tbody');
    const sub   = document.getElementById('ship-sub');
    tbody.innerHTML = '<tr><td colspan="5" style="padding:32px;text-align:center;color:var(--text-dim);">Loading…</td></tr>';
    try {
      const res  = await fetch('/api/shipments?limit=100');
      const data = await res.json();
      const ships = Array.isArray(data) ? data : [];
      if (!ships.length) {
        tbody.innerHTML = '<tr><td colspan="5" style="padding:32px;text-align:center;color:var(--text-dim);">No shipments yet.</td></tr>';
        sub.textContent = '0 shipments';
        return;
      }
      sub.textContent = `${ships.length} shipment${ships.length !== 1 ? 's' : ''}`;
      tbody.innerHTML = ships.map(s => {
        const tn   = s.tracking_number || '—';
        const tnEl = s.tracking_url
          ? `<a href="${s.tracking_url}" target="_blank" style="color:var(--blue);font-family:var(--mono);font-size:11px;">${tn}</a>`
          : `<span style="font-family:var(--mono);font-size:11px;color:var(--text-soft);">${tn}</span>`;
        return `<tr style="border-bottom:1px solid var(--border);">
          <td style="padding:7px 10px;font-family:var(--mono);font-size:11px;color:var(--text-soft);">${s.order_number || '—'}</td>
          <td style="padding:7px 10px;font-family:var(--mono);font-size:12px;color:var(--text-soft);">${s.ship_date || '—'}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text);">${(s.carrier||'').toUpperCase()}</td>
          <td style="padding:7px 10px;">${tnEl}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--text);">${dgMoney(s.postage||0)}</td>
        </tr>`;
      }).join('');
    } catch(e) { tbody.innerHTML = `<tr><td colspan="5" style="padding:20px;color:var(--err);">Error: ${e.message}</td></tr>`; }
  }

  // ── Events ────────────────────────────────────────────────────────────────
  async function eventsLoad() {
    const tbody = document.getElementById('events-tbody');
    const sub   = document.getElementById('events-sub');
    tbody.innerHTML = '<tr><td colspan="7" style="padding:32px;text-align:center;color:var(--text-dim);">Loading…</td></tr>';
    try {
      const res  = await fetch('/api/events?limit=100');
      const data = await res.json();
      const events = Array.isArray(data) ? data : (data.events || []);
      if (!events.length) {
        tbody.innerHTML = '<tr><td colspan="7" style="padding:32px;text-align:center;color:var(--text-dim);">No events yet.</td></tr>';
        sub.textContent = 'Conventions, shows, pop-ups, and live gigs';
        return;
      }
      sub.textContent = `${events.length} event${events.length !== 1 ? 's' : ''}`;
      const statusColor = { upcoming:'var(--blue)', active:'var(--accent)', completed:'var(--text-dim)', cancelled:'var(--err)' };
      tbody.innerHTML = events.map(e => `
        <tr style="border-bottom:1px solid var(--border);">
          <td style="padding:7px 10px;font-size:13px;color:var(--text);font-weight:500;">${e.name || '—'}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text-soft);">${e.event_type || '—'}</td>
          <td style="padding:7px 10px;font-family:var(--mono);font-size:12px;color:var(--text-soft);">${e.start_date || '—'}</td>
          <td style="padding:7px 10px;"><span style="font-family:var(--mono);font-size:10px;color:${statusColor[e.status]||'var(--text-dim)'};">${e.status||'—'}</span></td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--accent);">${dgMoney(e.actual_revenue||e.total_revenue||0)}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--err);">${dgMoney(e.actual_expense||e.total_expenses||0)}</td>
          <td style="padding:7px 10px;text-align:right;white-space:nowrap;"><a href="/api/events/${e.id}/load-pack.json" title="Export this event's Load Pack for the phone" style="color:var(--text-soft);text-decoration:none;font-size:11px;">↑ Load Pack</a></td>
        </tr>`).join('');
    } catch(e) { tbody.innerHTML = `<tr><td colspan="7" style="padding:20px;color:var(--err);">Error: ${e.message}</td></tr>`; }
  }

  // ── Field-capture: import a Results Pack from the phone ─────────────────────
  async function importEventResults(input) {
    const file = input && input.files && input.files[0];
    if (!file) return;
    try {
      const text = await file.text();
      const pack = JSON.parse(text);
      const res = await fetch('/api/events/import-results', {
        method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(pack),
      });
      const r = await res.json();
      if (r.error) { alert('Import failed: ' + r.error); }
      else if (r.already_imported) { alert('This results pack was already imported — nothing to do.'); }
      else {
        const parts = [`Imported event results:`,
          `• ${r.orders_created} cash order(s) — ${r.cash_sales}`,
          `• ${r.comps_units} comp unit(s)`,
          `• ${r.mileage_entries} mileage trip(s)`,
          `• ${r.cash_out_entries} cash expense(s) → Receipts "needs a receipt" queue`];
        if (r.skipped && r.skipped.length) parts.push(`Skipped (already in): ${r.skipped.length}`);
        if (r.errors && r.errors.length) parts.push(`Errors:\n  ${r.errors.join('\n  ')}`);
        alert(parts.join('\n'));
      }
      eventsLoad();
      if (typeof loadDashboard === 'function') loadDashboard();
    } catch (e) { alert('Could not read that file as a Results Pack: ' + e.message); }
    finally { input.value = ''; }
  }
  if (typeof window !== 'undefined') window.importEventResults = importEventResults;

  // ── Campaigns ─────────────────────────────────────────────────────────────
  async function campaignsLoad() {
    const tbody = document.getElementById('campaigns-tbody');
    const sub   = document.getElementById('campaigns-sub');
    tbody.innerHTML = '<tr><td colspan="5" style="padding:32px;text-align:center;color:var(--text-dim);">Loading…</td></tr>';
    try {
      const res  = await fetch('/api/funding?limit=100');
      const data = await res.json();
      const camps = Array.isArray(data) ? data : (data.campaigns || []);
      if (!camps.length) {
        tbody.innerHTML = '<tr><td colspan="5" style="padding:32px;text-align:center;color:var(--text-dim);">No campaigns yet.</td></tr>';
        sub.textContent = 'Kickstarters, grants, and crowdfunding';
        return;
      }
      sub.textContent = `${camps.length} campaign${camps.length !== 1 ? 's' : ''}`;
      const statusColor = { active:'var(--accent)', completed:'var(--text-dim)', cancelled:'var(--err)', draft:'var(--text-soft)' };
      tbody.innerHTML = camps.map(c => `
        <tr style="border-bottom:1px solid var(--border);">
          <td style="padding:7px 10px;font-size:13px;color:var(--text);font-weight:500;">${c.name || '—'}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text-soft);">${c.funding_type || c.campaign_type || '—'}</td>
          <td style="padding:7px 10px;"><span style="font-family:var(--mono);font-size:10px;color:${statusColor[c.status]||'var(--text-dim)'};">${c.status||'—'}</span></td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--text-soft);">${c.goal_cents ? dgMoneyC(c.goal_cents) : '—'}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--accent);">${c.raised_cents ? dgMoneyC(c.raised_cents) : '—'}</td>
        </tr>`).join('');
    } catch(e) { tbody.innerHTML = `<tr><td colspan="5" style="padding:20px;color:var(--err);">Error: ${e.message}</td></tr>`; }
  }