/* WPSiteBeam — SA Leads dashboard
   v1.1.0 — May 14 2026 (schema-aligned to existing leads table)

   Columns surfaced match the Supabase leads schema:
     id (bigint), first_name, last_name, agency_name, business_email, phone,
     target_url, source, ip_address, user_agent, captured_at,
     ghl_contact_id, pandadoc_doc_id, status, converted_account_id, notes,
     utm_source, utm_medium, utm_campaign, updated_at

   Gated to super_admin / internal_partner / admin via Shell.jsx + App.jsx
   allowed-pages.
*/
(function () {
  'use strict';

  const { useState, useEffect, useCallback } = React;
  const RAILWAY = (window.WPSB && window.WPSB.RAILWAY) || 'https://wpsitebeam-railway-api-production.up.railway.app';

  /* Status pill colors — match audit-report severity palette */
  const STATUS_STYLES = {
    'new':       { bg: 'var(--purple-dim)',  fg: 'var(--purple)',  border: 'rgba(168,85,247,.4)' },
    'contacted': { bg: 'var(--warn-dim)',    fg: 'var(--warn)',    border: 'rgba(245,158,11,.4)' },
    'qualified': { bg: 'rgba(59,130,246,.12)', fg: '#60a5fa',      border: 'rgba(59,130,246,.4)' },
    'converted': { bg: 'var(--green-dim)',   fg: '#6ee7b7',        border: 'rgba(34,197,94,.4)' },
    'rejected':  { bg: 'rgba(100,116,139,.12)', fg: 'var(--dim)',  border: 'var(--border)' },
  };
  const STATUS_ORDER = ['new', 'contacted', 'qualified', 'converted', 'rejected'];

  function fmtDate(iso) {
    if (!iso) return '\u2014';
    try {
      const d = new Date(iso);
      const now = new Date();
      const diff = (now - d) / 1000;
      if (diff < 60) return 'just now';
      if (diff < 3600) return Math.floor(diff / 60) + ' min ago';
      if (diff < 86400) return Math.floor(diff / 3600) + ' hr ago';
      if (diff < 604800) return Math.floor(diff / 86400) + ' days ago';
      return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
    } catch (e) { return iso; }
  }

  function shortUrl(url) {
    if (!url) return '';
    try {
      const u = new URL(url);
      return u.hostname.replace(/^www\./, '') + (u.pathname && u.pathname !== '/' ? u.pathname : '');
    } catch (e) { return String(url).slice(0, 60); }
  }

  function fullName(lead) {
    const parts = [lead.first_name, lead.last_name].filter(Boolean).map(s => String(s).trim()).filter(Boolean);
    return parts.join(' ') || '';
  }

  function initials(lead) {
    const fn = (lead.first_name || '').trim();
    const ln = (lead.last_name || '').trim();
    if (fn || ln) return ((fn[0] || '') + (ln[0] || '')).toUpperCase() || '?';
    const e = (lead.business_email || '?')[0];
    return (e || '?').toUpperCase();
  }

  function StatusPill({ status, onChange, disabled }) {
    const style = STATUS_STYLES[status] || STATUS_STYLES['new'];
    if (!onChange) {
      return (
        <span style={{
          display: 'inline-block', padding: '2px 10px', borderRadius: 12, fontSize: '.72rem',
          fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.04em',
          background: style.bg, color: style.fg, border: '1px solid ' + style.border,
        }}>{status}</span>
      );
    }
    return (
      <select
        value={status || 'new'}
        disabled={disabled}
        onChange={e => onChange(e.target.value)}
        style={{
          padding: '4px 8px', borderRadius: 6, fontSize: '.72rem', fontWeight: 600,
          textTransform: 'uppercase', letterSpacing: '.04em',
          background: style.bg, color: style.fg, border: '1px solid ' + style.border,
          cursor: disabled ? 'not-allowed' : 'pointer',
          opacity: disabled ? 0.6 : 1,
        }}>
        {STATUS_ORDER.map(s => <option key={s} value={s}>{s}</option>)}
      </select>
    );
  }

  function SectionLabel({ children, style }) {
    return (
      <div style={{
        fontSize: '.72rem', textTransform: 'uppercase', letterSpacing: '.06em',
        color: 'var(--dim)', marginBottom: 8, marginTop: 4, fontWeight: 600,
        ...style,
      }}>{children}</div>
    );
  }

  function KV({ label, value, mono }) {
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '90px 1fr', gap: 12, marginBottom: 8, alignItems: 'baseline' }}>
        <span style={{ fontSize: '.72rem', color: 'var(--dim)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{label}</span>
        <span style={{ fontSize: '.82rem', color: 'var(--text)', fontFamily: mono ? 'var(--mono, monospace)' : 'inherit', wordBreak: 'break-all' }}>{value}</span>
      </div>
    );
  }

  function NotesEditor({ lead, onSave }) {
    const [editing, setEditing] = useState(false);
    const [text, setText] = useState(lead.notes || '');
    const [saving, setSaving] = useState(false);

    useEffect(() => { setText(lead.notes || ''); }, [lead.notes]);

    if (!editing) {
      return (
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
          <span style={{ flex: 1, fontSize: '.82rem', color: lead.notes ? 'var(--text)' : 'var(--dimmer)', fontStyle: lead.notes ? 'normal' : 'italic', whiteSpace: 'pre-wrap' }}>
            {lead.notes || 'No notes'}
          </span>
          <button
            onClick={() => setEditing(true)}
            style={{
              padding: '2px 8px', fontSize: '.7rem', background: 'transparent',
              color: 'var(--accent)', border: '1px solid var(--border)', borderRadius: 4, cursor: 'pointer',
            }}>edit</button>
        </div>
      );
    }
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <textarea
          value={text}
          onChange={e => setText(e.target.value)}
          rows={3}
          style={{
            width: '100%', padding: 6, fontSize: '.82rem', resize: 'vertical',
            background: 'var(--panel)', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: 4,
          }}
          placeholder="Internal notes about this lead (visible only to staff)" />
        <div style={{ display: 'flex', gap: 6 }}>
          <button
            disabled={saving}
            onClick={async () => {
              setSaving(true);
              try { await onSave({ notes: text }); setEditing(false); } catch (e) {}
              setSaving(false);
            }}
            style={{
              padding: '4px 12px', fontSize: '.75rem', background: 'var(--accent)',
              color: '#0a0e1a', border: 'none', borderRadius: 4, cursor: 'pointer', fontWeight: 600,
            }}>{saving ? 'Saving\u2026' : 'Save'}</button>
          <button
            onClick={() => { setText(lead.notes || ''); setEditing(false); }}
            style={{
              padding: '4px 12px', fontSize: '.75rem', background: 'transparent',
              color: 'var(--dim)', border: '1px solid var(--border)', borderRadius: 4, cursor: 'pointer',
            }}>Cancel</button>
        </div>
      </div>
    );
  }

  function CrmIdEditor({ value, fieldName, placeholder, onSave }) {
    const [editing, setEditing] = useState(false);
    const [text, setText] = useState(value || '');
    const [saving, setSaving] = useState(false);

    useEffect(() => { setText(value || ''); }, [value]);

    if (!editing) {
      return (
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ flex: 1, fontSize: '.82rem', color: value ? 'var(--text)' : 'var(--dimmer)', fontStyle: value ? 'normal' : 'italic', fontFamily: value ? 'var(--mono, monospace)' : 'inherit', wordBreak: 'break-all' }}>
            {value || '(not set)'}
          </span>
          <button
            onClick={() => setEditing(true)}
            style={{
              padding: '2px 8px', fontSize: '.7rem', background: 'transparent',
              color: 'var(--accent)', border: '1px solid var(--border)', borderRadius: 4, cursor: 'pointer',
            }}>edit</button>
        </div>
      );
    }
    return (
      <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
        <input
          type="text"
          value={text}
          onChange={e => setText(e.target.value)}
          placeholder={placeholder || 'ID or leave blank to clear'}
          style={{
            flex: 1, padding: '4px 8px', fontSize: '.82rem', fontFamily: 'var(--mono, monospace)',
            background: 'var(--panel)', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: 4,
          }} />
        <button
          disabled={saving}
          onClick={async () => {
            setSaving(true);
            try { await onSave({ [fieldName]: text.trim() || null }); setEditing(false); } catch (e) {}
            setSaving(false);
          }}
          style={{
            padding: '4px 10px', fontSize: '.72rem', background: 'var(--accent)',
            color: '#0a0e1a', border: 'none', borderRadius: 4, cursor: 'pointer', fontWeight: 600,
          }}>{saving ? '\u2026' : 'Save'}</button>
        <button
          onClick={() => { setText(value || ''); setEditing(false); }}
          style={{
            padding: '4px 10px', fontSize: '.72rem', background: 'transparent',
            color: 'var(--dim)', border: '1px solid var(--border)', borderRadius: 4, cursor: 'pointer',
          }}>Cancel</button>
      </div>
    );
  }

  function LeadRow({ lead, onUpdate, expanded, onToggle }) {
    const [updating, setUpdating] = useState(false);

    const patch = useCallback(async (updates) => {
      setUpdating(true);
      try {
        const token = (window.WPSB && window.WPSB.getToken && window.WPSB.getToken()) || localStorage.getItem('wpsb-auth-token');
        const r = await fetch(RAILWAY + '/admin/leads/' + lead.id, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
          body: JSON.stringify(updates),
        });
        if (!r.ok) {
          const errBody = await r.json().catch(() => ({}));
          throw new Error(errBody.error || ('Update failed: HTTP ' + r.status));
        }
        const j = await r.json();
        if (j.row) onUpdate(j.row);
      } catch (e) {
        alert('Could not update lead: ' + e.message);
        throw e;
      } finally { setUpdating(false); }
    }, [lead.id, onUpdate]);

    const name = fullName(lead);
    const hasUtm = lead.utm_source || lead.utm_medium || lead.utm_campaign;
    const ghlAssigned = !!lead.ghl_contact_id;
    const pandaDocLinked = !!lead.pandadoc_doc_id;
    const converted = !!lead.converted_account_id;

    return (
      <>
        <tr style={{ borderBottom: '1px solid var(--border)', cursor: 'pointer' }} onClick={onToggle}>
          <td style={{ padding: '12px 8px' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <div style={{
                width: 32, height: 32, borderRadius: '50%', background: 'var(--accent-dim, var(--purple-dim))',
                color: 'var(--accent)', display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: '.72rem', fontWeight: 700, letterSpacing: '.02em',
              }}>{initials(lead)}</div>
              <div style={{ display: 'flex', flexDirection: 'column' }}>
                <span style={{ color: 'var(--text)', fontWeight: 500 }}>
                  {name || <em style={{ color: 'var(--dimmer)' }}>(no name)</em>}
                </span>
                <a href={'mailto:' + lead.business_email} onClick={e => e.stopPropagation()}
                   style={{ fontSize: '.78rem', color: 'var(--accent)', textDecoration: 'none' }}>
                  {lead.business_email}
                </a>
              </div>
            </div>
          </td>
          <td style={{ padding: '12px 8px', color: 'var(--text)', fontSize: '.85rem' }}>
            {lead.agency_name || <span style={{ color: 'var(--dimmer)' }}>—</span>}
          </td>
          <td style={{ padding: '12px 8px', fontSize: '.85rem' }}>
            <a href={lead.target_url} target="_blank" rel="noopener noreferrer" onClick={e => e.stopPropagation()}
               style={{ color: 'var(--accent)', textDecoration: 'none' }}>
              {shortUrl(lead.target_url)} ↗
            </a>
          </td>
          <td style={{ padding: '12px 8px' }} onClick={e => e.stopPropagation()}>
            <StatusPill status={lead.status} disabled={updating} onChange={s => patch({ status: s })} />
          </td>
          <td style={{ padding: '12px 8px', color: 'var(--dim)', fontSize: '.78rem' }}>
            {fmtDate(lead.captured_at)}
          </td>
          <td style={{ padding: '12px 8px', fontSize: '.78rem' }}>
            <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
              {ghlAssigned    && <span title={'GHL contact: ' + lead.ghl_contact_id}      style={{ padding: '1px 6px', borderRadius: 10, background: 'rgba(34,197,94,.12)', color: '#6ee7b7', fontSize: '.65rem', fontWeight: 600 }}>GHL</span>}
              {pandaDocLinked && <span title={'PandaDoc: ' + lead.pandadoc_doc_id}        style={{ padding: '1px 6px', borderRadius: 10, background: 'rgba(59,130,246,.12)', color: '#60a5fa', fontSize: '.65rem', fontWeight: 600 }}>PD</span>}
              {converted      && <span title={'Converted to ' + lead.converted_account_id} style={{ padding: '1px 6px', borderRadius: 10, background: 'var(--green-dim)', color: '#6ee7b7', fontSize: '.65rem', fontWeight: 600 }}>✓</span>}
              {!ghlAssigned && !pandaDocLinked && !converted && <span style={{ color: 'var(--dimmer)' }}>—</span>}
            </div>
          </td>
          <td style={{ padding: '12px 8px', fontSize: '.78rem' }}>
            {hasUtm
              ? <span title={'utm_source=' + (lead.utm_source||'') + ' utm_medium=' + (lead.utm_medium||'') + ' utm_campaign=' + (lead.utm_campaign||'')}
                      style={{ color: 'var(--dim)', fontFamily: 'var(--mono, monospace)' }}>
                  {lead.utm_source || lead.source}
                </span>
              : <span style={{ color: 'var(--dim)' }}>{lead.source || '\u2014'}</span>}
          </td>
        </tr>
        {expanded && (
          <tr style={{ background: 'var(--bg-elevated, rgba(255,255,255,0.02))' }}>
            <td colSpan={7} style={{ padding: '14px 24px', borderBottom: '1px solid var(--border)' }}>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
                {/* Left column — contact + tracking */}
                <div>
                  <SectionLabel>Contact</SectionLabel>
                  <KV label="Phone" value={lead.phone
                    ? <a href={'tel:' + lead.phone} style={{ color: 'var(--accent)', textDecoration: 'none' }}>{lead.phone}</a>
                    : <span style={{ color: 'var(--dimmer)' }}>(not provided)</span>} />
                  <KV label="Captured" value={lead.captured_at ? new Date(lead.captured_at).toLocaleString() : '\u2014'} />
                  <KV label="Last updated" value={lead.updated_at ? new Date(lead.updated_at).toLocaleString() : '\u2014'} />

                  <SectionLabel>Attribution</SectionLabel>
                  <KV label="Source" value={lead.source || 'unknown'} mono />
                  <KV label="utm_source"   value={lead.utm_source   || <span style={{ color: 'var(--dimmer)' }}>(none)</span>} mono />
                  <KV label="utm_medium"   value={lead.utm_medium   || <span style={{ color: 'var(--dimmer)' }}>(none)</span>} mono />
                  <KV label="utm_campaign" value={lead.utm_campaign || <span style={{ color: 'var(--dimmer)' }}>(none)</span>} mono />

                  <SectionLabel>Technical</SectionLabel>
                  <KV label="IP address" value={lead.ip_address || <span style={{ color: 'var(--dimmer)' }}>(not recorded)</span>} mono />
                  <KV label="User agent" value={lead.user_agent
                    ? <span style={{ fontSize: '.72rem', color: 'var(--dim)' }}>{String(lead.user_agent).slice(0, 120)}{lead.user_agent.length > 120 ? '\u2026' : ''}</span>
                    : <span style={{ color: 'var(--dimmer)' }}>(not recorded)</span>} />
                  <KV label="Lead ID" value={lead.id} mono />
                </div>

                {/* Right column — notes + CRM links */}
                <div>
                  <SectionLabel>Notes</SectionLabel>
                  <NotesEditor lead={lead} onSave={patch} />

                  <SectionLabel style={{ marginTop: 18 }}>CRM links</SectionLabel>
                  <div style={{ display: 'grid', gridTemplateColumns: '110px 1fr', gap: '10px 12px', alignItems: 'center' }}>
                    <span style={{ fontSize: '.72rem', color: 'var(--dim)', textTransform: 'uppercase', letterSpacing: '.06em' }}>GHL contact</span>
                    <CrmIdEditor value={lead.ghl_contact_id} fieldName="ghl_contact_id"
                                 placeholder="GHL contact ID" onSave={patch} />
                    <span style={{ fontSize: '.72rem', color: 'var(--dim)', textTransform: 'uppercase', letterSpacing: '.06em' }}>PandaDoc</span>
                    <CrmIdEditor value={lead.pandadoc_doc_id} fieldName="pandadoc_doc_id"
                                 placeholder="PandaDoc document ID" onSave={patch} />
                    <span style={{ fontSize: '.72rem', color: 'var(--dim)', textTransform: 'uppercase', letterSpacing: '.06em' }}>Converted to</span>
                    <CrmIdEditor value={lead.converted_account_id} fieldName="converted_account_id"
                                 placeholder="Account UUID (when lead converts)" onSave={patch} />
                  </div>
                </div>
              </div>
            </td>
          </tr>
        )}
      </>
    );
  }

  function Leads() {
    const [rows, setRows] = useState([]);
    const [total, setTotal] = useState(0);
    const [page, setPage] = useState(1);
    const [pageSize] = useState(50);
    const [statusFilter, setStatusFilter] = useState('');
    const [searchQ, setSearchQ] = useState('');
    const [sort, setSort] = useState('captured_at_desc');
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const [expandedId, setExpandedId] = useState(null);

    const load = useCallback(async () => {
      setLoading(true);
      setError(null);
      try {
        const token = (window.WPSB && window.WPSB.getToken && window.WPSB.getToken()) || localStorage.getItem('wpsb-auth-token');
        const params = new URLSearchParams({
          page: page,
          page_size: pageSize,
          sort: sort,
        });
        if (statusFilter) params.set('status', statusFilter);
        if (searchQ.trim()) params.set('q', searchQ.trim());
        const r = await fetch(RAILWAY + '/admin/leads?' + params.toString(), {
          headers: { 'Authorization': 'Bearer ' + token },
        });
        if (!r.ok) {
          if (r.status === 401) throw new Error('Not authenticated — token missing or expired');
          if (r.status === 403) throw new Error('Not authorized — super_admin/admin role required');
          throw new Error('Failed to load leads (HTTP ' + r.status + ')');
        }
        const j = await r.json();
        setRows(j.rows || []);
        setTotal(j.total || 0);
      } catch (e) {
        setError(e.message);
        setRows([]);
        setTotal(0);
      } finally { setLoading(false); }
    }, [page, pageSize, statusFilter, searchQ, sort]);

    useEffect(() => { load(); }, [load]);

    const updateRow = useCallback((updatedRow) => {
      setRows(prev => prev.map(r => r.id === updatedRow.id ? updatedRow : r));
    }, []);

    const totalPages = Math.max(1, Math.ceil(total / pageSize));

    /* Width fix 2026-05-18 — removed `padding:24, maxWidth:1400, margin:'0 auto'`
       to match Brand Profile / Account / Billing standard width.
       The .main grid container handles overall width + padding. */
    return (
      <div>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 20 }}>
          <div>
            <h1 style={{ margin: 0, fontSize: '1.6rem', color: 'var(--text)' }}>Leads</h1>
            <div style={{ marginTop: 4, fontSize: '.85rem', color: 'var(--dim)' }}>
              Incoming captures from the Lead Magnet Scanner ({total.toLocaleString()} total)
            </div>
          </div>
          <button onClick={load} disabled={loading}
            style={{
              padding: '8px 14px', fontSize: '.85rem', background: 'transparent',
              color: 'var(--accent)', border: '1px solid var(--accent)', borderRadius: 6,
              cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.5 : 1,
            }}>{loading ? 'Loading\u2026' : '\u21bb Refresh'}</button>
        </div>

        <div style={{
          display: 'flex', gap: 12, marginBottom: 16, alignItems: 'center', flexWrap: 'wrap',
          padding: 12, background: 'var(--panel)', border: '1px solid var(--border)', borderRadius: 8,
        }}>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            <button
              onClick={() => { setStatusFilter(''); setPage(1); }}
              style={{
                padding: '6px 12px', fontSize: '.78rem', borderRadius: 16,
                background: statusFilter === '' ? 'var(--accent)' : 'transparent',
                color: statusFilter === '' ? '#0a0e1a' : 'var(--dim)',
                border: '1px solid ' + (statusFilter === '' ? 'var(--accent)' : 'var(--border)'),
                cursor: 'pointer', fontWeight: statusFilter === '' ? 600 : 400,
              }}>All</button>
            {STATUS_ORDER.map(s => {
              const isActive = statusFilter === s;
              const sty = STATUS_STYLES[s];
              return (
                <button key={s} onClick={() => { setStatusFilter(s); setPage(1); }}
                  style={{
                    padding: '6px 12px', fontSize: '.78rem', borderRadius: 16,
                    background: isActive ? sty.fg : 'transparent',
                    color: isActive ? '#0a0e1a' : sty.fg,
                    border: '1px solid ' + (isActive ? sty.fg : sty.border),
                    cursor: 'pointer', fontWeight: isActive ? 600 : 400,
                    textTransform: 'uppercase', letterSpacing: '.04em',
                  }}>{s}</button>
              );
            })}
          </div>
          <input
            type="search"
            placeholder="Search business email…"
            value={searchQ}
            onChange={e => setSearchQ(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter') { setPage(1); load(); } }}
            style={{
              padding: '6px 10px', fontSize: '.85rem', minWidth: 220,
              background: 'var(--bg)', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: 6,
            }} />
          <select
            value={sort}
            onChange={e => { setSort(e.target.value); setPage(1); }}
            style={{
              padding: '6px 10px', fontSize: '.85rem',
              background: 'var(--bg)', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: 6,
            }}>
            <option value="captured_at_desc">Newest first</option>
            <option value="captured_at_asc">Oldest first</option>
            <option value="email_asc">Email A→Z</option>
            <option value="email_desc">Email Z→A</option>
          </select>
        </div>

        {error && (
          <div style={{
            padding: 16, marginBottom: 16, background: 'var(--red-dim)', color: 'var(--red)',
            border: '1px solid rgba(239,68,68,.4)', borderRadius: 8, fontSize: '.85rem',
          }}>
            <strong>Error:</strong> {error}
          </div>
        )}

        {!loading && !error && rows.length === 0 && (
          <div style={{
            padding: 48, textAlign: 'center', color: 'var(--dim)',
            background: 'var(--panel)', border: '1px solid var(--border)', borderRadius: 8,
          }}>
            <div style={{ fontSize: '2rem', marginBottom: 12 }}>📬</div>
            <strong style={{ color: 'var(--text)' }}>No leads yet</strong>
            <div style={{ marginTop: 8, fontSize: '.85rem' }}>
              When visitors submit the Lead Magnet Scanner form, captures will appear here.
            </div>
          </div>
        )}

        {rows.length > 0 && (
          <div style={{ background: 'var(--panel)', border: '1px solid var(--border)', borderRadius: 8, overflow: 'hidden' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '.85rem' }}>
              <thead>
                <tr style={{ background: 'var(--bg-elevated, rgba(255,255,255,0.02))', borderBottom: '1px solid var(--border)' }}>
                  <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600, color: 'var(--dim)', fontSize: '.75rem', textTransform: 'uppercase', letterSpacing: '.04em' }}>Lead</th>
                  <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600, color: 'var(--dim)', fontSize: '.75rem', textTransform: 'uppercase', letterSpacing: '.04em' }}>Agency</th>
                  <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600, color: 'var(--dim)', fontSize: '.75rem', textTransform: 'uppercase', letterSpacing: '.04em' }}>Target site</th>
                  <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600, color: 'var(--dim)', fontSize: '.75rem', textTransform: 'uppercase', letterSpacing: '.04em' }}>Status</th>
                  <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600, color: 'var(--dim)', fontSize: '.75rem', textTransform: 'uppercase', letterSpacing: '.04em' }}>Captured</th>
                  <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600, color: 'var(--dim)', fontSize: '.75rem', textTransform: 'uppercase', letterSpacing: '.04em' }}>CRM</th>
                  <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600, color: 'var(--dim)', fontSize: '.75rem', textTransform: 'uppercase', letterSpacing: '.04em' }}>Source</th>
                </tr>
              </thead>
              <tbody>
                {rows.map(lead => (
                  <LeadRow
                    key={lead.id}
                    lead={lead}
                    onUpdate={updateRow}
                    expanded={expandedId === lead.id}
                    onToggle={() => setExpandedId(prev => prev === lead.id ? null : lead.id)} />
                ))}
              </tbody>
            </table>
          </div>
        )}

        {totalPages > 1 && (
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 16, fontSize: '.85rem', color: 'var(--dim)' }}>
            <span>Page {page} of {totalPages} — showing {rows.length} of {total.toLocaleString()}</span>
            <div style={{ display: 'flex', gap: 6 }}>
              <button onClick={() => setPage(1)} disabled={page === 1}
                style={{ padding: '6px 10px', background: 'transparent', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: 4, cursor: page === 1 ? 'not-allowed' : 'pointer', opacity: page === 1 ? 0.4 : 1 }}>« First</button>
              <button onClick={() => setPage(p => Math.max(1, p - 1))} disabled={page === 1}
                style={{ padding: '6px 10px', background: 'transparent', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: 4, cursor: page === 1 ? 'not-allowed' : 'pointer', opacity: page === 1 ? 0.4 : 1 }}>‹ Prev</button>
              <button onClick={() => setPage(p => Math.min(totalPages, p + 1))} disabled={page === totalPages}
                style={{ padding: '6px 10px', background: 'transparent', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: 4, cursor: page === totalPages ? 'not-allowed' : 'pointer', opacity: page === totalPages ? 0.4 : 1 }}>Next ›</button>
              <button onClick={() => setPage(totalPages)} disabled={page === totalPages}
                style={{ padding: '6px 10px', background: 'transparent', color: 'var(--text)', border: '1px solid var(--border)', borderRadius: 4, cursor: page === totalPages ? 'not-allowed' : 'pointer', opacity: page === totalPages ? 0.4 : 1 }}>Last »</button>
            </div>
          </div>
        )}
      </div>
    );
  }

  window.Leads = Leads;
  console.log('[WPSB] Leads v1.1.0 loaded (SA Leads dashboard \u2014 schema-aligned)');
})();
