/* GarageWiz — Estimate (cart): mixed doors / openers / parts on one order */
(function () {
  const e = React.createElement;
  const { useState, useEffect } = React;
  const Icon = window.Icon, Btn = window.Btn, Field = window.Field, Input = window.Input, SectionTitle = window.SectionTitle;

  const GROUP = { door: 'Doors', opener: 'Openers', part: 'Parts & service' };
  const GROUP_ICON = { door: 'door', opener: 'opener', part: 'parts' };
  const STATUS_BADGE = { draft: 'badge-start', approved: 'badge-good', won: 'badge-prem', lost: 'badge-order', expired: 'badge-order' };

  function EstimateScreen() {
    const app = window.useApp();
    const est = app.estimate;
    const result = est ? GW.computeEstimate(est, app.settings) : null;
    const [code, setCode] = useState((est && est.couponCode) || '');
    const [cpErr, setCpErr] = useState('');

    if (!est || !result || result.empty) {
      return e('div', { style: { maxWidth: 760, margin: '0 auto', padding: '60px 24px' } },
        e(window.EmptyState, {
          title: 'Your estimate is empty',
          sub: "Price a door, opener, or parts, then tap 'Add to estimate' to start building an official, signable estimate.",
          action: e('div', { style: { display: 'flex', gap: 10, justifyContent: 'center', flexWrap: 'wrap' } },
            e(Btn, { variant: 'primary', icon: 'door', onClick: () => app.go('#/doors') }, 'Build a door'),
            e(Btn, { variant: 'ghost', icon: 'opener', onClick: () => app.go('#/openers') }, 'Openers'),
            e(Btn, { variant: 'ghost', icon: 'parts', onClick: () => app.go('#/parts') }, 'Parts'),
          ),
        }),
      );
    }

    const cust = est.customer || {};
    const setCust = (patch) => app.updateEstimate({ customer: Object.assign({}, cust, patch) });
    const applyCoupon = () => { const cp = GW.findCoupon(code); if (!cp) { setCpErr('Invalid or inactive code.'); return; } setCpErr(''); app.updateEstimate({ couponCode: cp.code }); };
    const removeCoupon = () => { setCode(''); setCpErr(''); app.updateEstimate({ couponCode: null }); };
    const editDoor = (idx) => {
      const item = est.items[idx];
      if (item && item.type === 'door') { app.setConfig(Object.assign({}, item.config)); app.removeEstimateItem(idx); app.go('#/doors'); }
    };
    const setItemQty = (idx, qty) => {
      const items = est.items.map((it, i) => {
        if (i !== idx) return it;
        if (it.type === 'door') return Object.assign({}, it, { config: Object.assign({}, it.config, { qty: Math.max(1, qty) }) });
        return Object.assign({}, it, { qty: Math.max(1, qty) });
      });
      app.updateEstimate({ items });
    };

    const qBtn = (label, on, dis) => e('button', { onClick: on, disabled: dis, style: { border: '1.5px solid var(--line-2)', background: '#fff', borderRadius: 8, width: 30, height: 30, display: 'grid', placeItems: 'center', cursor: dis ? 'not-allowed' : 'pointer', color: 'var(--ink)', fontWeight: 700, fontSize: 16, opacity: dis ? .4 : 1 } }, label);

    // ---- cloud save / status (Supabase) ----
    const backend = !!(window.GW.db && window.GW.db.configured);
    const saveCloud = async (patch) => {
      if (!backend) { app.toast('Sign in to save estimates to the cloud.'); return null; }
      const merged = patch ? Object.assign({}, est, patch) : est;
      try {
        const id = await GW.db.saveEstimate(merged, GW.computeEstimate(merged, app.settings));
        app.updateEstimate(Object.assign({}, patch || {}, { backendId: id }));
        app.toast('Estimate saved');
        return id;
      } catch (e) { app.toast('Save failed: ' + ((e && e.message) || 'error')); return null; }
    };
    const saveAndNew = async () => { const id = await saveCloud(); if (id) app.clearEstimate(); };
    const setStatus = async (status) => {
      app.updateEstimate({ status: status });
      if (backend) { if (est.backendId) { try { await GW.db.setEstimateStatus(est.backendId, status); } catch (e) {} } else { saveCloud({ status: status }); } }
    };
    const approve = async (sig) => {
      app.updateEstimate({ signature: sig, status: 'approved' });
      if (backend) await saveCloud({ signature: sig, status: 'approved' });
    };
    const STATUSES = ['draft', 'approved', 'won', 'lost'];
    const STATUS_BADGE = { draft: 'badge-start', approved: 'badge-good', won: 'badge-prem', lost: 'badge-order' };

    function downloadPdf() {
      const ns = window.jspdf;
      if (!ns || !ns.jsPDF) { app.toast('PDF tool still loading — try again in a moment.'); return; }
      const doc = new ns.jsPDF({ unit: 'pt', format: 'letter' });
      const W = doc.internal.pageSize.getWidth(), M = 48;
      doc.setFillColor(0, 95, 122); doc.rect(0, 0, W, 96, 'F');
      doc.setTextColor(255, 255, 255); doc.setFont('helvetica', 'bold'); doc.setFontSize(26); doc.text('GarageWiz', M, 50);
      doc.setFont('helvetica', 'normal'); doc.setFontSize(10); doc.setTextColor(245, 224, 65); doc.text('ESTIMATE', M, 68);
      doc.setTextColor(255, 255, 255); doc.setFontSize(11); doc.text('Your estimate', W - M, 44, { align: 'right' });
      doc.setFontSize(10); doc.text(result.validity.issuedLabel, W - M, 62, { align: 'right' });
      doc.setFontSize(9); doc.setTextColor(245, 224, 65); doc.text('Valid through ' + result.validity.expiresLabel, W - M, 77, { align: 'right' });
      let y = 134; doc.setTextColor(25, 25, 25);
      if (cust.name || cust.phone || cust.email || cust.address) {
        doc.setFont('helvetica', 'bold'); doc.setFontSize(10); doc.setTextColor(120, 120, 120); doc.text('PREPARED FOR', M, y); y += 18;
        doc.setTextColor(25, 25, 25); doc.setFontSize(15); if (cust.name) { doc.text(cust.name, M, y); y += 18; }
        doc.setFont('helvetica', 'normal'); doc.setFontSize(11); doc.setTextColor(110, 110, 110);
        const contact = [cust.phone, cust.email].filter(Boolean).join('   ·   ');
        if (contact) { doc.text(contact, M, y); y += 14; }
        if (cust.address) { doc.text(String(cust.address), M, y); y += 14; }
        y += 14;
      }
      doc.setFont('helvetica', 'bold'); doc.setFontSize(10); doc.setTextColor(120, 120, 120); doc.text('ESTIMATE ITEMS', M, y); y += 8;
      doc.setDrawColor(225, 225, 225); doc.line(M, y, W - M, y); y += 22;
      result.lines.forEach(l => {
        doc.setFont('helvetica', 'bold'); doc.setFontSize(12.5); doc.setTextColor(25, 25, 25);
        doc.text((l.qty > 1 ? l.qty + '× ' : '') + String(l.label), M, y);
        doc.text(GW.fmt(l.linePrice), W - M, y, { align: 'right' });
        if (l.sub) { doc.setFont('helvetica', 'normal'); doc.setFontSize(10.5); doc.setTextColor(130, 130, 130); doc.text(String(l.sub), M, y + 15); y += 34; } else { y += 24; }
        doc.setDrawColor(238, 238, 238); doc.line(M, y - 10, W - M, y - 10);
      });
      y += 16;
      doc.setFillColor(0, 95, 122); doc.roundedRect(M, y, W - M * 2, 78, 8, 8, 'F');
      doc.setTextColor(245, 224, 65); doc.setFont('helvetica', 'bold'); doc.setFontSize(10); doc.text('TOTAL · FULLY INSTALLED', M + 22, y + 30);
      doc.setTextColor(255, 255, 255); doc.setFontSize(30); doc.text(GW.fmt(result.price), W - M - 22, y + 44, { align: 'right' });
      doc.setFont('helvetica', 'normal'); doc.setFontSize(9); doc.setTextColor(220, 235, 240); doc.text('Includes professional installation, hardware, and workmanship guarantee.', M + 22, y + 56);
      y += 100;
      if (result.discount > 0) { doc.setFont('helvetica', 'bold'); doc.setFontSize(10.5); doc.setTextColor(34, 150, 94); doc.text((result.coupon ? ('Coupon ' + result.coupon.code + ': ') : 'Discount: ') + '−' + GW.fmt(result.discount) + ' applied.', M, y); y += 22; }
      const sig = result.signature;
      if (sig && sig.dataUrl) {
        doc.setFont('helvetica', 'bold'); doc.setFontSize(10); doc.setTextColor(120, 120, 120); doc.text('CUSTOMER APPROVAL', M, y); y += 6;
        doc.setDrawColor(225, 225, 225); doc.line(M, y, W - M, y); y += 10;
        try { doc.addImage(sig.dataUrl, 'PNG', M, y, 200, 64); } catch (er) {}
        doc.setFont('helvetica', 'normal'); doc.setFontSize(10); doc.setTextColor(25, 25, 25); doc.text('Approved by ' + (sig.name || 'Customer'), M, y + 80);
        doc.setTextColor(130, 130, 130); doc.text('Signed ' + new Date(sig.signedAt || Date.now()).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }), M, y + 95); y += 110;
      }
      const safeName = (cust.name || 'GarageWiz-Estimate').replace(/[^a-z0-9]+/gi, '-');
      doc.save(safeName + '.pdf'); app.toast('Estimate downloaded');
    }

    function shareReview() {
      const snap = { v: 1, estimate: est, note: '', rep: (app.user && app.user.name) || 'Sales rep', ts: Date.now() };
      const link = location.origin + location.pathname + '#/review/' + GW.encodeReview(snap);
      GW.reviews.unshift({ id: 'rv' + Date.now(), rep: snap.rep, note: '', customer: cust.name || '', price: result.price, data: GW.encodeReview(snap), ts: snap.ts, status: 'pending', kind: 'estimate' });
      GW.saveReviews();
      try { navigator.clipboard && navigator.clipboard.writeText(link).then(() => app.toast('Review link copied — send it to your admin.')); } catch (er) {}
    }

    // group line rows
    const byType = { door: [], opener: [], part: [] };
    result.lines.forEach(l => byType[l.type].push(l));

    return e('div', { style: { maxWidth: 1320, margin: '0 auto', padding: '28px 24px 80px' } },
      e('div', { className: 'no-print', style: { display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16, flexWrap: 'wrap' } },
        e(Btn, { variant: 'ghost', icon: 'plus', onClick: () => app.go('#/tools/pricing') }, 'Add more items'),
        backend ? e(Btn, { variant: 'ghost', icon: 'briefcase', onClick: () => app.go('#/estimates') }, 'My estimates') : null,
        e('div', { className: 'grow' }),
        e(Btn, { variant: 'ghost', icon: 'mail', onClick: shareReview }, 'Share for review'),
        e(Btn, { variant: 'ghost', icon: 'print', onClick: () => window.print() }, 'Print'),
        e(Btn, { variant: 'ghost', icon: 'download', onClick: downloadPdf }, 'Download PDF'),
        backend ? e(Btn, { variant: 'primary', icon: 'check', onClick: () => saveCloud() }, est.backendId ? 'Update saved' : 'Save estimate') : null,
        backend ? e(Btn, { variant: 'ghost', icon: 'plus', onClick: saveAndNew }, 'Save & start new') : null,
      ),
      e('div', { style: { display: 'flex', alignItems: 'center', gap: 9, marginBottom: 18, fontSize: 13.5, color: result.validity.expired ? 'var(--danger)' : 'var(--ink-2)' } },
        e(Icon, { name: result.validity.expired ? 'info' : 'check', size: 16, style: { color: result.validity.expired ? 'var(--danger)' : 'var(--good)' } }),
        result.validity.expired ? e('span', null, e('strong', null, 'This estimate has expired'), ' — re-issue to refresh pricing.')
          : e('span', null, 'Estimate valid through ', e('strong', null, result.validity.expiresLabel), ' · ' + result.validity.daysLeft + ' day' + (result.validity.daysLeft === 1 ? '' : 's') + ' left'),
      ),

      e('div', { className: 'parts-sale-grid', style: { display: 'grid', gridTemplateColumns: 'minmax(0,1fr) 380px', gap: 24, alignItems: 'start' } },
        // ---- left: customer + items ----
        e('div', null,
          e('div', { className: 'card', style: { padding: 20, marginBottom: 18 } },
            e('div', { className: 'eyebrow', style: { marginBottom: 12 } }, 'Customer'),
            e('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 } },
              e(Field, { label: 'Name', style: { gridColumn: '1 / -1' } }, e(Input, { placeholder: 'e.g. The Hendersons', value: cust.name || '', onChange: ev => setCust({ name: ev.target.value }) })),
              e(Field, { label: 'Phone' }, e(Input, { placeholder: '(555) 123-4567', value: cust.phone || '', onChange: ev => setCust({ phone: ev.target.value }) })),
              e(Field, { label: 'Email' }, e(Input, { placeholder: 'name@email.com', value: cust.email || '', onChange: ev => setCust({ email: ev.target.value }) })),
              e(Field, { label: 'Address', style: { gridColumn: '1 / -1' } }, e(Input, { placeholder: 'Install address', value: cust.address || '', onChange: ev => setCust({ address: ev.target.value }) })),
            ),
          ),

          ['door', 'opener', 'part'].map(type => byType[type].length ? e('div', { key: type, className: 'card', style: { marginBottom: 18, overflow: 'hidden' } },
            e('div', { style: { background: 'var(--field)', padding: '13px 20px', borderBottom: '1px solid var(--line)', display: 'flex', alignItems: 'center', gap: 10 } },
              e('div', { style: { width: 30, height: 30, borderRadius: 8, background: '#fff', color: 'var(--teal)', display: 'grid', placeItems: 'center', boxShadow: 'var(--sh-1)' } }, e(Icon, { name: GROUP_ICON[type], size: 17 })),
              e('div', { className: 'display', style: { fontSize: 16, fontWeight: 600 } }, GROUP[type]),
            ),
            byType[type].map((l, i) => e('div', { key: l.idx, style: { display: 'flex', alignItems: 'center', gap: 14, padding: '14px 20px', borderTop: i ? '1px solid var(--line)' : 'none' } },
              e('div', { className: 'grow', style: { minWidth: 0 } },
                e('div', { style: { fontWeight: 700, fontSize: 15 } }, l.label),
                e('div', { className: 'muted', style: { fontSize: 13 } }, l.sub),
              ),
              e('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
                qBtn('−', () => setItemQty(l.idx, l.qty - 1), l.qty <= 1),
                e('span', { className: 'num', style: { minWidth: 20, textAlign: 'center', fontWeight: 700 } }, l.qty),
                qBtn('+', () => setItemQty(l.idx, l.qty + 1), false),
              ),
              e('div', { className: 'display num', style: { fontSize: 17, fontWeight: 700, color: 'var(--teal)', minWidth: 80, textAlign: 'right' } }, GW.fmt(l.linePrice)),
              l.type === 'door' ? e('button', { onClick: () => editDoor(l.idx), title: 'Edit door', style: { border: 'none', background: 'var(--field)', color: 'var(--ink-2)', borderRadius: 9, width: 32, height: 32, display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0 } }, e(Icon, { name: 'edit', size: 15 })) : null,
              e('button', { onClick: () => app.removeEstimateItem(l.idx), title: 'Remove', style: { border: 'none', background: 'var(--danger-bg)', color: 'var(--danger)', borderRadius: 9, width: 32, height: 32, display: 'grid', placeItems: 'center', cursor: 'pointer', flexShrink: 0 } }, e(Icon, { name: 'trash', size: 15 })),
            )),
          ) : null),
        ),

        // ---- right: totals / coupon / approval ----
        e('div', { className: 'parts-ticket', style: { position: 'sticky', top: 88, display: 'flex', flexDirection: 'column', gap: 14 } },
          e('div', { className: 'card', style: { padding: 22, textAlign: 'center' } },
            e('div', { className: 'eyebrow' }, 'Total · fully installed'),
            result.discount > 0 ? e('div', { className: 'num', style: { fontSize: 17, color: 'var(--ink-3)', textDecoration: 'line-through', marginTop: 6 } }, GW.fmt(result.listPrice)) : null,
            e('div', { className: 'display num', style: { fontSize: 42, fontWeight: 700, color: 'var(--teal)', lineHeight: 1, margin: '8px 0' } }, GW.fmt(result.price)),
            result.discount > 0 ? e('div', { style: { display: 'inline-flex', alignItems: 'center', gap: 6, background: 'var(--good-bg)', color: 'var(--good)', borderRadius: 999, padding: '5px 12px', fontWeight: 700, fontSize: 13 } }, e(Icon, { name: 'tag', size: 14 }), (result.coupon ? result.coupon.code + ' · ' : '') + 'You save ' + GW.fmt(result.discount)) : null,
            e('div', { className: 'muted', style: { fontSize: 12.5, marginTop: 8 } }, result.itemCount + ' item' + (result.itemCount === 1 ? '' : 's') + ' · installed, no hidden fees'),
          ),

          // status (cloud)
          backend ? e('div', { className: 'card no-print', style: { padding: 16 } },
            e('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' } },
              e('div', { style: { fontSize: 12, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--ink-3)' } }, 'Status'),
              e('span', { className: 'badge ' + (STATUS_BADGE[est.status] || 'badge-start') }, (est.status || 'draft').toUpperCase()),
            ),
            e('div', { style: { display: 'flex', gap: 6, marginTop: 10, flexWrap: 'wrap' } },
              STATUSES.map(st => e('button', { key: st, onClick: () => setStatus(st), style: { border: '1.5px solid ' + (est.status === st ? 'var(--teal)' : 'var(--line-2)'), background: est.status === st ? 'var(--teal)' : '#fff', color: est.status === st ? '#fff' : 'var(--ink-2)', borderRadius: 999, padding: '6px 12px', fontSize: 12.5, fontWeight: 700, cursor: 'pointer', textTransform: 'capitalize' } }, st)),
            ),
            est.backendId ? e('div', { className: 'muted', style: { fontSize: 11.5, marginTop: 8 } }, 'Saved to cloud · syncs across devices') : e('div', { className: 'muted', style: { fontSize: 11.5, marginTop: 8 } }, 'Not saved yet — hit “Save estimate”.'),
          ) : null,

          // coupon
          e('div', { className: 'card no-print', style: { padding: 18 } },
            e('div', { style: { fontSize: 12, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 10, display: 'flex', alignItems: 'center', gap: 7 } }, e(Icon, { name: 'tag', size: 15 }), 'Coupon code'),
            result.couponCode
              ? e('div', { style: { display: 'flex', alignItems: 'center', gap: 10 } },
                  e('div', { className: 'grow' },
                    e('div', { style: { fontWeight: 800, fontFamily: 'var(--display)', letterSpacing: '.05em', fontSize: 16, color: 'var(--good)' } }, result.couponCode),
                    e('div', { className: 'muted', style: { fontSize: 12.5 } }, result.coupon ? (GW.couponLabel(result.coupon) + ' · −' + GW.fmt(result.discount) + ' applied') : 'Applied')),
                  e(Btn, { variant: 'ghost', size: 'sm', onClick: removeCoupon }, 'Remove'))
              : e('div', null,
                  e('div', { style: { display: 'flex', gap: 8 } },
                    e('input', { value: code, onChange: ev => { setCode(ev.target.value.toUpperCase()); setCpErr(''); }, onKeyDown: ev => ev.key === 'Enter' && applyCoupon(), placeholder: 'Enter approved code', style: { flex: 1, minWidth: 0, padding: '10px 12px', borderRadius: 10, border: '1.5px solid var(--line-2)', fontWeight: 700, letterSpacing: '.05em', textTransform: 'uppercase', outline: 'none', fontFamily: 'var(--display)' } }),
                    e(Btn, { variant: 'teal', size: 'sm', onClick: applyCoupon }, 'Apply')),
                  cpErr ? e('div', { style: { color: 'var(--danger)', fontSize: 12.5, fontWeight: 600, marginTop: 8 } }, cpErr) : null,
                ),
          ),

          // approval
          e(window.ApprovalBlock, { signature: est.signature, onApprove: approve, onClear: () => app.updateEstimate({ signature: null }) }),

          e('button', { className: 'no-print', onClick: () => { if (confirm('Clear this estimate?')) app.clearEstimate(); }, style: { border: 'none', background: 'transparent', color: 'var(--ink-3)', fontWeight: 600, fontSize: 13, cursor: 'pointer', padding: 4 } }, 'Clear estimate'),
        ),
      ),
    );
  }
  window.EstimateScreen = EstimateScreen;

  /* ===================== MY ESTIMATES (saved pipeline) ===================== */
  function MyEstimates() {
    const app = window.useApp();
    const backend = !!(window.GW.db && window.GW.db.configured);
    const [list, setList] = useState(null);
    const [err, setErr] = useState('');
    const [filter, setFilter] = useState('all');

    const load = async () => {
      if (!backend) { setErr('Sign in to a backend to save and list estimates.'); setList([]); return; }
      try { setErr(''); setList(await GW.db.listEstimates()); }
      catch (e) { setErr((e && e.message) || 'Could not load estimates.'); setList([]); }
    };
    useEffect(() => { load(); }, []);

    const open = async (id) => { const head = await GW.db.getEstimate(id); const cart = GW.db.toCart(head); if (cart) { app.setEstimate(cart); app.go('#/estimate'); } };
    const duplicate = async (id) => { const head = await GW.db.getEstimate(id); const cart = GW.db.toCart(head); if (cart) { delete cart.backendId; cart.status = 'draft'; cart.signature = null; cart.quoteDate = null; app.setEstimate(cart); app.toast('Duplicated to a new draft'); app.go('#/estimate'); } };
    const remove = async (id) => { if (!confirm('Delete this estimate?')) return; await GW.db.deleteEstimate(id); load(); };

    const rows = (list || []).filter(r => filter === 'all' || r.status === filter);

    return e('div', { style: { maxWidth: 1100, margin: '0 auto', padding: '34px 28px 80px' } },
      e(SectionTitle, { eyebrow: 'Pricing', title: 'My estimates', sub: 'Your saved estimates — synced across devices. Reopen, duplicate, or update status.',
        right: e(Btn, { variant: 'primary', icon: 'plus', onClick: () => { app.clearEstimate(); app.go('#/tools/pricing'); } }, 'New estimate') }),

      e('div', { style: { display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 18 } },
        ['all', 'draft', 'approved', 'won', 'lost'].map(f => e('button', { key: f, onClick: () => setFilter(f), className: 'display', style: { border: 'none', cursor: 'pointer', borderRadius: 999, padding: '8px 16px', fontWeight: 600, fontSize: 14, background: filter === f ? 'var(--teal)' : '#fff', color: filter === f ? '#fff' : 'var(--ink-2)', boxShadow: filter === f ? 'none' : 'var(--sh-1)', textTransform: 'capitalize' } }, f))),

      list === null ? e('div', { className: 'muted', style: { padding: 30, textAlign: 'center' } }, 'Loading…')
        : err ? e('div', { className: 'card', style: { padding: 30, textAlign: 'center', color: 'var(--ink-3)' } }, err)
        : rows.length === 0 ? e('div', { className: 'card', style: { padding: 40, textAlign: 'center', color: 'var(--ink-3)' } }, e(Icon, { name: 'briefcase', size: 28, style: { marginBottom: 10 } }), e('div', null, 'No estimates here yet.'))
        : e('div', { className: 'card', style: { overflow: 'hidden' } },
            rows.map((r, i) => e('div', { key: r.id, style: { display: 'flex', alignItems: 'center', gap: 14, padding: '15px 20px', borderTop: i ? '1px solid var(--line)' : 'none' } },
              e('div', { className: 'grow', style: { minWidth: 0 } },
                e('div', { style: { fontWeight: 700, fontSize: 15 } }, (r.customer && r.customer.name) || 'Unnamed customer'),
                e('div', { className: 'muted', style: { fontSize: 12.5 } }, new Date(r.updated_at).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })),
              ),
              e('span', { className: 'badge ' + (STATUS_BADGE[r.status] || 'badge-start') }, (r.status || 'draft').toUpperCase()),
              e('div', { className: 'display num', style: { fontSize: 18, fontWeight: 700, color: 'var(--teal)', minWidth: 90, textAlign: 'right' } }, GW.fmt((r.totals && r.totals.price) || 0)),
              e(Btn, { variant: 'ghost', size: 'sm', icon: 'arrowR', onClick: () => open(r.id) }, 'Open'),
              e('button', { onClick: () => duplicate(r.id), title: 'Duplicate', style: { border: 'none', background: 'var(--field)', color: 'var(--ink-2)', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', cursor: 'pointer' } }, e(Icon, { name: 'plus', size: 16 })),
              e('button', { onClick: () => remove(r.id), title: 'Delete', style: { border: 'none', background: 'var(--danger-bg)', color: 'var(--danger)', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', cursor: 'pointer' } }, e(Icon, { name: 'trash', size: 15 })),
            )),
          ),
    );
  }
  window.MyEstimates = MyEstimates;
})();
