// SIGNDESK — Template Builder / Field Placement Canvas
// Pattern adapted from StudioBuilder.jsx. Layout:
//   LEFT   — Field palette (draggable chips) + Recipients
//   CENTER — Pages (drop targets); fields render as absolutely positioned overlays
//   RIGHT  — Selected-field inspector
//
// DnD contract:
//   dataTransfer.setData('application/esign-field', <typeId>)  — from palette
//   dataTransfer.setData('application/esign-field-move', <fieldId>) — moving an existing field
//
// Activation:
//   window.EsOpenBuilder(template)  — opens builder in an overlay.
//   Templates cards in EsTemplates become clickable to invoke this.

(function () {
  const { useState, useRef, useEffect, useCallback } = React;
  const T = window.ArbiterTokens;
  const Icons = window.Icons || {};
  const A = window.Arbiter || {};

  // ── Field type catalog ────────────────────────────────────────────────────
  const FIELD_TYPES = [
    { id: 'signature', label: 'Signature',   w: 200, h: 44, iconPath: 'M3 11 Q6 6 9 11 Q12 16 15 11', hint: 'drawn / typed' },
    { id: 'initials',  label: 'Initials',    w: 56,  h: 44, iconPath: 'M4 4 L4 14 M14 4 L14 14 M4 9 L14 9', hint: 'short signoff' },
    { id: 'date',      label: 'Date signed', w: 120, h: 32, iconPath: 'M3 5 H15 V14 H3 Z M3 8 H15 M7 3 V6 M11 3 V6', hint: 'auto-filled at sign' },
    { id: 'name',      label: 'Full name',   w: 180, h: 32, iconPath: 'M9 8 A2.5 2.5 0 1 0 9 3 A2.5 2.5 0 0 0 9 8 M4 15 Q4 10 9 10 Q14 10 14 15', hint: 'text · required' },
    { id: 'email',     label: 'Email',       w: 200, h: 32, iconPath: 'M2 5 H16 V13 H2 Z M2 6 L9 10 L16 6', hint: 'auto-validated' },
    { id: 'title',     label: 'Title',       w: 160, h: 32, iconPath: 'M3 3 H15 V6 H3 Z M5 9 H13 M5 12 H13', hint: 'text' },
    { id: 'company',   label: 'Company',     w: 180, h: 32, iconPath: 'M3 15 V6 L9 3 L15 6 V15 M6 9 H8 M6 12 H8 M10 9 H12 M10 12 H12', hint: 'text' },
    { id: 'text',      label: 'Text field',  w: 180, h: 32, iconPath: 'M3 6 H15 M3 9 H13 M3 12 H10', hint: 'free-form' },
    { id: 'checkbox',  label: 'Checkbox',    w: 20,  h: 20, iconPath: 'M4 4 H14 V14 H4 Z M6 9 L8 11 L12 7', hint: 'toggle' },
    { id: 'radio',     label: 'Radio',       w: 20,  h: 20, iconPath: 'M9 14 A5 5 0 1 1 9 4 A5 5 0 0 1 9 14 M9 11 A2 2 0 1 1 9 7 A2 2 0 0 1 9 11', hint: 'mutually exclusive' },
    { id: 'dropdown',  label: 'Dropdown',    w: 160, h: 32, iconPath: 'M3 6 H15 V12 H3 Z M6 9 L9 11 L12 9', hint: 'pick one' },
    { id: 'attach',    label: 'Attachment',  w: 140, h: 40, iconPath: 'M5 15 Q2 12 5 9 L11 3 Q14 0 14 5 L8 11', hint: 'file upload' },
    { id: 'notary',    label: 'Notary stamp',w: 140, h: 80, iconPath: 'M9 14 A5 5 0 1 1 9 4 A5 5 0 0 1 9 14 M5 9 H13 M9 5 V13', hint: 'required for notary' },
  ];
  const FIELD_BY_ID = Object.fromEntries(FIELD_TYPES.map(f => [f.id, f]));

  // Default recipients when template carries none
  const DEFAULT_RECIPIENTS = [
    { id: 'R1', name: 'Primary Signer',  email: 'signer@example.com',   role: 'Signer',   color: '#2563EB' },
    { id: 'R2', name: 'Counter-signer',  email: 'cosigner@example.com', role: 'Signer',   color: '#7C3AED' },
    { id: 'R3', name: 'Approver',        email: 'approver@example.com', role: 'Approver', color: '#059669' },
  ];
  const RECIPIENT_COLORS = ['#2563EB', '#7C3AED', '#059669', '#D97706', '#DC2626', '#0891B2'];

  // ── FieldGlyph — SVG path renderer for palette + field-body ──────────────
  const FieldGlyph = ({ path, size = 14, color = 'currentColor' }) => (
    <svg width={size} height={size} viewBox="0 0 18 18" fill="none"
      stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"
      aria-hidden="true" focusable="false" style={{ flexShrink: 0 }}>
      <path d={path} />
    </svg>
  );

  // ── Main builder ──────────────────────────────────────────────────────────
  function EsBuilder({ template, onClose }) {
    const es = window.__es;
    const pages = Math.max(1, template?.pages || 3);
    const [fields, setFields] = useState(() => {
      // Seed with one signature + date per required field type, per primary recipient.
      const req = template?.requiredFields || ['signature', 'date'];
      return req.slice(0, 3).map((type, i) => {
        const base = FIELD_BY_ID[type] || FIELD_BY_ID.signature;
        return {
          id: `F-${Math.random().toString(36).slice(2, 7)}`,
          type, page: 0,
          x: 120, y: 360 + i * 60, w: base.w, h: base.h,
          recipientId: 'R1', required: true, label: base.label,
        };
      });
    });
    const [recipients, setRecipients] = useState(() => {
      // derive from template if possible, else defaults
      const n = Math.min(3, Math.max(1, (template?.requiredFields?.length || 1) > 2 ? 2 : 1));
      return DEFAULT_RECIPIENTS.slice(0, n).map((r, i) => ({ ...r, color: RECIPIENT_COLORS[i] }));
    });
    const [activeRecipient, setActiveRecipient] = useState('R1');
    const [selectedId, setSelectedId] = useState(null);
    const [history, setHistory] = useState([]);
    const [sent, setSent] = useState(false);
    const pageRefs = useRef({});
    A.useTrack && A.useTrack('esign.builder.open', { template: template?.id }, []);

    const snap = useCallback(() => setHistory(h => [...h.slice(-29), fields]), [fields]);
    const undo = useCallback(() => {
      setHistory(h => {
        if (!h.length) return h;
        const prev = h[h.length - 1];
        setFields(prev);
        return h.slice(0, -1);
      });
    }, []);
    useEffect(() => {
      const onKey = (e) => {
        if (e.key === 'Escape') { onClose?.(); return; }
        if (e.key === 'z' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); undo(); }
        if ((e.key === 'Delete' || e.key === 'Backspace') && selectedId) {
          snap(); setFields(fs => fs.filter(f => f.id !== selectedId)); setSelectedId(null);
        }
      };
      window.addEventListener('keydown', onKey);
      return () => window.removeEventListener('keydown', onKey);
    }, [onClose, undo, snap, selectedId]);

    // ── Drag from palette ──
    const onPaletteDragStart = (e, type) => {
      e.dataTransfer.setData('application/esign-field', type.id);
      e.dataTransfer.effectAllowed = 'copy';
    };

    // ── Drag existing field ──
    const onFieldDragStart = (e, f) => {
      e.stopPropagation();
      e.dataTransfer.setData('application/esign-field-move', f.id);
      e.dataTransfer.effectAllowed = 'move';
      const rect = e.currentTarget.getBoundingClientRect();
      e.dataTransfer.setData('offsetX', String(e.clientX - rect.left));
      e.dataTransfer.setData('offsetY', String(e.clientY - rect.top));
    };

    // ── Drop on a page ──
    const onPageDrop = (e, pageIdx) => {
      e.preventDefault();
      const pageEl = pageRefs.current[pageIdx];
      if (!pageEl) return;
      const rect = pageEl.getBoundingClientRect();
      const newType = e.dataTransfer.getData('application/esign-field');
      const moveId  = e.dataTransfer.getData('application/esign-field-move');
      snap();
      if (newType) {
        const spec = FIELD_BY_ID[newType];
        const x = Math.round(e.clientX - rect.left - spec.w / 2);
        const y = Math.round(e.clientY - rect.top - spec.h / 2);
        const f = {
          id: `F-${Math.random().toString(36).slice(2, 7)}`,
          type: newType, page: pageIdx,
          x: Math.max(8, Math.min(rect.width - spec.w - 8, x)),
          y: Math.max(8, Math.min(rect.height - spec.h - 8, y)),
          w: spec.w, h: spec.h,
          recipientId: activeRecipient, required: true, label: spec.label,
        };
        setFields(fs => [...fs, f]);
        setSelectedId(f.id);
        A.track?.('esign.field.add', { type: newType, page: pageIdx });
      } else if (moveId) {
        const ox = parseFloat(e.dataTransfer.getData('offsetX') || '0');
        const oy = parseFloat(e.dataTransfer.getData('offsetY') || '0');
        setFields(fs => fs.map(f => {
          if (f.id !== moveId) return f;
          const x = Math.round(e.clientX - rect.left - ox);
          const y = Math.round(e.clientY - rect.top - oy);
          return {
            ...f, page: pageIdx,
            x: Math.max(8, Math.min(rect.width - f.w - 8, x)),
            y: Math.max(8, Math.min(rect.height - f.h - 8, y)),
          };
        }));
      }
    };
    const allowDrop = (e) => { e.preventDefault(); e.dataTransfer.dropEffect = e.dataTransfer.types.includes('application/esign-field-move') ? 'move' : 'copy'; };

    const updateField = (id, patch) => { snap(); setFields(fs => fs.map(f => f.id === id ? { ...f, ...patch } : f)); };
    const removeField = (id) => { snap(); setFields(fs => fs.filter(f => f.id !== id)); setSelectedId(null); };
    const addRecipient = () => {
      const n = recipients.length;
      if (n >= RECIPIENT_COLORS.length) return;
      setRecipients(rs => [...rs, {
        id: `R${n+1}`, name: `Recipient ${n+1}`, email: `r${n+1}@example.com`,
        role: 'Signer', color: RECIPIENT_COLORS[n],
      }]);
    };

    const selected = fields.find(f => f.id === selectedId);
    const fieldsByPage = (p) => fields.filter(f => f.page === p);
    const completionByRecipient = recipients.map(r => ({
      ...r, count: fields.filter(f => f.recipientId === r.id).length,
    }));

    const doSend = () => {
      if (!fields.length) {
        A.toast?.({ kind: 'warning', title: 'Empty envelope', message: 'Drop at least one field before sending.' });
        return;
      }
      setSent(true);
      A.track?.('esign.envelope.queued', { fields: fields.length, recipients: recipients.length });
      A.toast?.({ kind: 'active', title: 'Envelope queued', message: `${fields.length} field${fields.length === 1 ? '' : 's'} placed across ${recipients.length} recipient${recipients.length === 1 ? '' : 's'}.` });
      setTimeout(() => setSent(false), 1800);
    };

    // ── Render ──
    return (
      <div style={{
        position: 'fixed', inset: 0, zIndex: 1100,
        background: 'rgba(10,22,40,0.48)',
        display: 'flex', flexDirection: 'column',
      }} role="dialog" aria-label="Envelope builder" aria-modal="true">
        {/* Header */}
        <div style={{
          background: 'color-mix(in srgb, var(--color-bg-card) 88%, transparent)',
          backdropFilter: 'saturate(180%) blur(10px)',
          WebkitBackdropFilter: 'saturate(180%) blur(10px)',
          borderBottom: `1px solid ${T.color.border.medium}`,
          padding: '12px 22px', display: 'flex', alignItems: 'center', gap: 14,
          flexShrink: 0,
        }}>
          <button onClick={onClose} aria-label="Close builder"
            className="arb-row"
            style={{ padding: '6px 12px', border: `1px solid ${T.color.border.medium}`, background: 'transparent',
              borderRadius: 6, cursor: 'pointer', color: T.color.text.secondary, fontSize: 12, fontFamily: T.font.family }}>
            ← Close
          </button>
          <div style={{ borderLeft: `1px solid ${T.color.border.light}`, height: 28, margin: '0 2px' }} />
          <div>
            <div style={{ fontSize: 14, fontWeight: 600, color: T.color.text.primary, letterSpacing: '-0.01em', lineHeight: 1.2 }}>
              {template?.name || 'New Envelope'}
            </div>
            <div className="arb-num" style={{ fontSize: 11, color: T.color.text.tertiary, marginTop: 2, letterSpacing: 0 }}>
              {template?.category ? template.category + ' · ' : ''}
              <span style={{ color: T.color.text.secondary }}>{pages}</span> page{pages === 1 ? '' : 's'} ·{' '}
              <span style={{ color: T.color.text.secondary }}>{fields.length}</span> field{fields.length === 1 ? '' : 's'} ·{' '}
              <span style={{ color: T.color.text.secondary }}>{recipients.length}</span> recipient{recipients.length === 1 ? '' : 's'}
            </div>
          </div>
          <div style={{ flex: 1 }} />
          <kbd className="arb-kbd" title="Undo">⌘Z</kbd>
          <button onClick={undo} disabled={!history.length}
            style={{ padding: '6px 12px', border: `1px solid ${T.color.border.medium}`, background: 'transparent',
              borderRadius: 6, cursor: history.length ? 'pointer' : 'default', opacity: history.length ? 1 : 0.4,
              color: T.color.text.secondary, fontSize: 12, fontFamily: T.font.family }}>
            Undo{history.length ? ` · ${history.length}` : ''}
          </button>
          <button onClick={() => { snap(); setFields([]); setSelectedId(null); }}
            style={{ padding: '6px 12px', border: `1px solid ${T.color.border.medium}`, background: 'transparent',
              borderRadius: 6, cursor: 'pointer', color: T.color.text.secondary, fontSize: 12, fontFamily: T.font.family }}>
            Clear
          </button>
          <button onClick={doSend}
            style={{
              padding: '7px 16px', border: 'none',
              background: sent
                ? 'linear-gradient(180deg, #059669 0%, #047857 100%)'
                : `linear-gradient(180deg, ${(es?.indigo || '#4338CA')} 0%, color-mix(in srgb, ${(es?.indigo || '#4338CA')} 85%, black) 100%)`,
              boxShadow: '0 1px 2px rgba(10,22,40,0.16), inset 0 1px 0 rgba(255,255,255,0.12)',
              borderRadius: 7, cursor: 'pointer', color: '#fff', fontSize: 12.5, fontWeight: 600,
              letterSpacing: '-0.005em',
              transition: 'transform 140ms var(--easing-standard,ease), background 240ms',
              fontFamily: T.font.family,
            }}
            onMouseDown={e => e.currentTarget.style.transform = 'scale(0.98)'}
            onMouseUp={e => e.currentTarget.style.transform = 'scale(1)'}
            onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}>
            {sent ? '✓ Sent' : 'Send envelope →'}
          </button>
        </div>

        {/* Body */}
        <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '240px 1fr 240px', minHeight: 0 }}>
          {/* LEFT — palette */}
          <div style={{ background: T.color.bg.secondary, borderRight: `1px solid ${T.color.border.light}`,
            overflowY: 'auto', padding: 12 }}>
            <Section title="Recipients" right={recipients.length < RECIPIENT_COLORS.length &&
              <button onClick={addRecipient} style={miniBtn}>+ add</button>
            }>
              {completionByRecipient.map(r => {
                const isActive = activeRecipient === r.id;
                return (
                  <button key={r.id} onClick={() => setActiveRecipient(r.id)}
                    style={{
                      display: 'flex', alignItems: 'center', gap: 8, width: '100%', padding: '6px 8px',
                      marginBottom: 4, borderRadius: 6, border: `1px solid ${isActive ? r.color : T.color.border.light}`,
                      background: isActive ? r.color + '14' : T.color.bg.card, cursor: 'pointer',
                      textAlign: 'left', fontFamily: T.font.family,
                    }}>
                    <span style={{ width: 10, height: 10, borderRadius: 5, background: r.color, flexShrink: 0 }} />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 11, fontWeight: 600, color: T.color.text.primary, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.name}</div>
                      <div style={{ fontSize: 9, color: T.color.text.tertiary }}>{r.role} · {r.count} field{r.count === 1 ? '' : 's'}</div>
                    </div>
                    {isActive && <span style={{ fontSize: 9, color: r.color, fontWeight: 700 }}>active</span>}
                  </button>
                );
              })}
            </Section>

            <Section title="Fields" hint="Drag onto a page">
              {FIELD_TYPES.map(f => (
                <div key={f.id}
                  draggable
                  onDragStart={e => onPaletteDragStart(e, f)}
                  style={{
                    display: 'flex', alignItems: 'center', gap: 8,
                    padding: '6px 8px', marginBottom: 3, borderRadius: 6,
                    border: `1px solid ${T.color.border.light}`,
                    background: T.color.bg.card, cursor: 'grab', userSelect: 'none',
                    transition: 'border-color 100ms, background 100ms',
                  }}
                  onMouseEnter={e => {
                    e.currentTarget.style.borderColor = '#4338CA55';
                    e.currentTarget.style.background = '#4338CA08';
                  }}
                  onMouseLeave={e => {
                    e.currentTarget.style.borderColor = T.color.border.light;
                    e.currentTarget.style.background = T.color.bg.card;
                  }}>
                  <FieldGlyph path={f.iconPath} color="#4338CA" />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 11, fontWeight: 500, color: T.color.text.primary }}>{f.label}</div>
                    <div style={{ fontSize: 9, color: T.color.text.tertiary }}>{f.hint}</div>
                  </div>
                  <span style={{ fontSize: 11, color: T.color.text.tertiary, letterSpacing: 2 }}>⋮⋮</span>
                </div>
              ))}
            </Section>
          </div>

          {/* CENTER — pages */}
          <div style={{ overflow: 'auto', padding: 24, background: T.color.bg.tertiary }}>
            {Array.from({ length: pages }, (_, pageIdx) => (
              <div key={pageIdx}
                ref={el => (pageRefs.current[pageIdx] = el)}
                onDragOver={allowDrop}
                onDrop={e => onPageDrop(e, pageIdx)}
                onClick={e => { if (e.target === e.currentTarget) setSelectedId(null); }}
                style={{
                  position: 'relative',
                  width: 612, minHeight: 792,   // 8.5" x 11" at 72dpi
                  margin: '0 auto 22px',
                  background: '#FEFEFB',
                  boxShadow: '0 1px 2px rgba(10,22,40,0.06), 0 12px 32px rgba(10,22,40,0.08), 0 0 0 1px rgba(10,22,40,0.04)',
                  borderRadius: 3,
                }}>
                {/* Page label */}
                <div className="arb-num" style={{
                  position: 'absolute', top: -20, left: 2, fontSize: 10,
                  color: T.color.text.tertiary, letterSpacing: '0.08em', textTransform: 'uppercase',
                }}>
                  Page <span style={{ color: T.color.text.secondary }}>{String(pageIdx + 1).padStart(2, '0')}</span>
                  <span style={{ opacity: 0.5 }}> / {String(pages).padStart(2, '0')}</span>
                </div>
                {/* Faux body text to suggest a document */}
                <div style={{ padding: '48px 56px', color: '#D4D4D4', userSelect: 'none', pointerEvents: 'none' }}>
                  <div style={{ fontSize: 14, fontWeight: 700, marginBottom: 8 }}>{template?.name || 'Document'}</div>
                  <div style={{ fontSize: 10, marginBottom: 16 }}>{(template?.category || 'Document') + ' — Page ' + (pageIdx + 1)}</div>
                  {Array.from({ length: 18 }, (_, i) => (
                    <div key={i} style={{
                      height: 6, marginBottom: 8, borderRadius: 3,
                      background: '#EEEEEE', width: `${60 + ((i * 37 + pageIdx * 13) % 35)}%`,
                    }} />
                  ))}
                </div>

                {/* Fields for this page */}
                {fieldsByPage(pageIdx).map(f => {
                  const rec = recipients.find(r => r.id === f.recipientId) || recipients[0];
                  const spec = FIELD_BY_ID[f.type];
                  const isSel = f.id === selectedId;
                  return (
                    <div key={f.id}
                      draggable
                      onDragStart={e => onFieldDragStart(e, f)}
                      onClick={e => { e.stopPropagation(); setSelectedId(f.id); }}
                      style={{
                        position: 'absolute',
                        left: f.x, top: f.y, width: f.w, height: f.h,
                        border: `1.5px ${isSel ? 'solid' : 'dashed'} ${rec.color}`,
                        background: `${rec.color}${isSel ? '26' : '12'}`,
                        borderRadius: 4, cursor: 'move',
                        display: 'flex', alignItems: 'center', gap: 6,
                        padding: '0 7px', overflow: 'hidden',
                        fontSize: 10.5, fontFamily: T.font.family,
                        color: rec.color, fontWeight: 600, letterSpacing: '-0.005em',
                        boxShadow: isSel
                          ? `0 0 0 3px ${rec.color}24, 0 2px 6px ${rec.color}22`
                          : `0 1px 2px rgba(10,22,40,0.04)`,
                        transition: 'box-shadow 160ms, background 140ms',
                      }}>
                      <FieldGlyph path={spec.iconPath} size={12} color={rec.color} />
                      <span style={{ flex: 1, minWidth: 0, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                        {f.label}{f.required ? ' *' : ''}
                      </span>
                      {isSel && (
                        <button onClick={e => { e.stopPropagation(); removeField(f.id); }}
                          aria-label="Remove field"
                          style={{ background: 'transparent', border: 'none', color: rec.color, cursor: 'pointer', fontSize: 14, lineHeight: 1, padding: 0 }}>×</button>
                      )}
                    </div>
                  );
                })}

                {/* Empty-page hint */}
                {fieldsByPage(pageIdx).length === 0 && (
                  <div style={{
                    position: 'absolute', inset: 0, display: 'flex', alignItems: 'center',
                    justifyContent: 'center', pointerEvents: 'none',
                    color: T.color.text.tertiary, fontSize: 11, fontStyle: 'italic', opacity: 0.5,
                  }}>
                    Drop fields onto this page
                  </div>
                )}
              </div>
            ))}
          </div>

          {/* RIGHT — inspector */}
          <div style={{ background: T.color.bg.secondary, borderLeft: `1px solid ${T.color.border.light}`,
            overflowY: 'auto', padding: 12 }}>
            {selected ? (
              <Section title={`Field · ${FIELD_BY_ID[selected.type].label}`}>
                <Row label="Type"><span style={{ fontSize: 11, color: T.color.text.secondary }}>{selected.type}</span></Row>
                <Row label="Label">
                  <input value={selected.label}
                    onChange={e => updateField(selected.id, { label: e.target.value })}
                    style={inspInput} />
                </Row>
                <Row label="Required">
                  <input type="checkbox" checked={!!selected.required}
                    onChange={e => updateField(selected.id, { required: e.target.checked })} />
                </Row>
                <Row label="Assigned">
                  <select value={selected.recipientId}
                    onChange={e => updateField(selected.id, { recipientId: e.target.value })}
                    style={inspInput}>
                    {recipients.map(r => <option key={r.id} value={r.id}>{r.name}</option>)}
                  </select>
                </Row>
                <Row label="Position">
                  <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 4 }}>
                    <input type="number" value={selected.x}
                      onChange={e => updateField(selected.id, { x: parseInt(e.target.value || '0', 10) })}
                      style={inspInput} aria-label="x" />
                    <input type="number" value={selected.y}
                      onChange={e => updateField(selected.id, { y: parseInt(e.target.value || '0', 10) })}
                      style={inspInput} aria-label="y" />
                  </div>
                </Row>
                <Row label="Size">
                  <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 4 }}>
                    <input type="number" value={selected.w}
                      onChange={e => updateField(selected.id, { w: parseInt(e.target.value || '0', 10) })}
                      style={inspInput} aria-label="width" />
                    <input type="number" value={selected.h}
                      onChange={e => updateField(selected.id, { h: parseInt(e.target.value || '0', 10) })}
                      style={inspInput} aria-label="height" />
                  </div>
                </Row>
                <Row label="Page">
                  <select value={selected.page}
                    onChange={e => updateField(selected.id, { page: parseInt(e.target.value, 10) })}
                    style={inspInput}>
                    {Array.from({ length: pages }, (_, i) => <option key={i} value={i}>Page {i + 1}</option>)}
                  </select>
                </Row>
                <button onClick={() => removeField(selected.id)}
                  style={{ marginTop: 8, width: '100%', padding: '6px 10px',
                    border: `1px solid #DC262655`, background: '#DC262611', color: '#DC2626',
                    borderRadius: 6, cursor: 'pointer', fontSize: 11, fontWeight: 600 }}>
                  Remove field
                </button>
              </Section>
            ) : (
              <Section title="Inspector">
                <div style={{ fontSize: 11, color: T.color.text.tertiary, lineHeight: 1.5 }}>
                  Select a field to edit its label, recipient assignment, position and required state.
                </div>
              </Section>
            )}

            <Section title="Summary">
              <Row label="Template"><span style={{ fontSize: 11, color: T.color.text.secondary }}>{template?.name || '—'}</span></Row>
              <Row label="Pages"><span style={{ fontSize: 11, fontFamily: T.font.mono, color: T.color.text.primary }}>{pages}</span></Row>
              <Row label="Fields"><span style={{ fontSize: 11, fontFamily: T.font.mono, color: T.color.text.primary }}>{fields.length}</span></Row>
              <Row label="Recipients"><span style={{ fontSize: 11, fontFamily: T.font.mono, color: T.color.text.primary }}>{recipients.length}</span></Row>
              <Row label="Coverage">
                <div style={{ display: 'flex', height: 6, borderRadius: 3, overflow: 'hidden', border: `1px solid ${T.color.border.light}` }}>
                  {recipients.map(r => {
                    const c = fields.filter(f => f.recipientId === r.id).length;
                    const w = fields.length ? (c / fields.length) * 100 : 0;
                    return <div key={r.id} title={`${r.name}: ${c}`} style={{ width: w + '%', background: r.color }} />;
                  })}
                </div>
              </Row>
            </Section>
          </div>
        </div>
      </div>
    );
  }

  // ── Tiny inspector primitives ─────────────────────────────────────────────
  const Section = ({ title, right, hint, children }) => (
    <div style={{ marginBottom: 18 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
        <div style={{ fontSize: 9, fontWeight: 700, color: T.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.08em' }}>{title}</div>
        <div style={{ flex: 1 }} />
        {right}
      </div>
      {hint && <div style={{ fontSize: 10, color: T.color.text.tertiary, marginBottom: 6 }}>{hint}</div>}
      {children}
    </div>
  );
  const Row = ({ label, children }) => (
    <div style={{ display: 'grid', gridTemplateColumns: '80px 1fr', gap: 8, alignItems: 'center', marginBottom: 6 }}>
      <label style={{ fontSize: 10, color: T.color.text.tertiary }}>{label}</label>
      {children}
    </div>
  );
  const inspInput = {
    width: '100%', padding: '5px 8px', fontSize: 11.5, fontFamily: T.font.family,
    border: `1px solid ${T.color.border.medium}`, borderRadius: 5,
    background: T.color.bg.card, color: T.color.text.primary,
    outline: 'none', transition: 'border-color 140ms, box-shadow 140ms',
    fontFeatureSettings: '"tnum" 1',
  };
  const miniBtn = {
    padding: '2px 6px', fontSize: 10, border: `1px solid ${T.color.border.medium}`,
    background: 'transparent', color: T.color.text.secondary, borderRadius: 4, cursor: 'pointer',
  };

  // ── Public launcher ───────────────────────────────────────────────────────
  let openFn = null;

  function EsBuilderHost() {
    const [template, setTemplate] = useState(null);
    openFn = setTemplate;
    useEffect(() => { window.EsOpenBuilder = (t) => setTemplate(t); }, []);
    if (!template) return null;
    return <EsBuilder template={template} onClose={() => setTemplate(null)} />;
  }

  // ── Export ────────────────────────────────────────────────────────────────
  window.EsBuilder = EsBuilder;
  window.EsBuilderHost = EsBuilderHost;
  window.EsOpenBuilder = (t) => { if (openFn) openFn(t); else console.warn('EsBuilder host not mounted'); };

  // Command-palette hook
  if (window.Arbiter?.CommandRegistry) {
    window.Arbiter.CommandRegistry.register('esign.builder.new', {
      label: 'SignDesk: New envelope from template…',
      group: 'SignDesk', keywords: 'esign envelope template builder signature',
      run: () => {
        window.dispatchEvent(new CustomEvent('arbiter:navigate', { detail: { view: 'esign' } }));
        window.Arbiter?.toast?.({ title: 'Open SignDesk',
          message: 'Click any template card on the Templates tab to start the builder.' });
      },
    });
  }
})();
