// VISUAL EDITOR v2 — 20 opportunities (VE1-VE20) + 6 hubs
// Uses window.__au (lime automation theme) + window.ArbiterTokens
const { useState: useVeState, useMemo: useVeMemo, useEffect: useVeEffect } = React;

// ── Shared primitives ─────────────────────────────────────────────────────
function VePill({ color, bg, children }) {
  const T = window.ArbiterTokens;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', padding: '2px 8px',
      borderRadius: '10px', fontSize: '10px', fontWeight: 700,
      color, background: bg, fontFamily: T.font.family,
      letterSpacing: '0.04em', textTransform: 'uppercase', whiteSpace: 'nowrap',
    }}>{children}</span>
  );
}

function VeKPI({ label, value, color, mono, hint }) {
  const au = window.__au;
  const T = window.ArbiterTokens;
  return (
    <div style={au.stat}>
      <span style={au.statLabel}>{label}</span>
      <span style={{ ...au.statValue, color: color || T.color.text.primary, fontFamily: mono ? T.font.mono : T.font.family }}>{value}</span>
      {hint && <span style={{ fontSize: '10px', color: T.color.text.tertiary, marginTop: '2px' }}>{hint}</span>}
    </div>
  );
}

function VeFlash({ message, color }) {
  if (!message) return null;
  const au = window.__au;
  const c = color || au.lime;
  return (
    <div style={{
      padding: '8px 14px', marginBottom: '12px',
      background: `${c}14`, border: `1px solid ${c}44`,
      borderRadius: '6px', fontSize: '11px', fontWeight: 600,
      color: c, fontFamily: window.ArbiterTokens.font.family,
      textTransform: 'uppercase', letterSpacing: '0.06em',
    }}>▸ {message}</div>
  );
}

function useFlash() {
  const [msg, setMsg] = useVeState(null);
  useVeEffect(() => {
    if (!msg) return;
    const t = setTimeout(() => setMsg(null), 2600);
    return () => clearTimeout(t);
  }, [msg]);
  return [msg, setMsg];
}

// ═══════════════════════════════════════════════════════════════════════════
// VE1. Live Validation Gutter
// ═══════════════════════════════════════════════════════════════════════════
function VE1ValidationGutter() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const ve = window.ve;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['validation.autofix']);
  const [flash, setFlash] = useFlash();

  const handleFix = (id) => {
    const i = S.applyAutofix(id, 'R. Patel');
    if (i) setFlash(`Autofix applied: ${i.title}`);
  };

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.emerald} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.crimson}`, background: au.crimsonBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.crimson, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE1 · Live validation gutter</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>
            {state.validationIssues.length} open issues · {state.validationIssues.filter(i => i.severity === 'error').length} blocking publish
          </div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '12px', marginBottom: '14px' }}>
        <VeKPI label="Open issues" value={state.validationIssues.length} />
        <VeKPI label="Errors"   value={state.validationIssues.filter(i => i.severity === 'error').length}   color={au.crimson} />
        <VeKPI label="Warnings" value={state.validationIssues.filter(i => i.severity === 'warning').length} color={au.amber} />
        <VeKPI label="Autofixable" value={state.validationIssues.filter(i => i.autofix).length} color={au.emerald} />
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Canvas gutter · issues by step</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr>
            <th style={au.th}>ID</th><th style={au.th}>Step</th><th style={au.th}>Severity</th>
            <th style={au.th}>Rule</th><th style={au.th}>Issue</th><th style={au.th}>Action</th>
          </tr></thead>
          <tbody>
            {state.validationIssues.map(i => {
              const c = ve.severityColor(i.severity);
              return (
                <tr key={i.id}>
                  <td style={{ ...au.td, fontFamily: T.font.mono, color: au.crimson, fontWeight: 700 }}>{i.id}</td>
                  <td style={{ ...au.td, fontFamily: T.font.mono, color: T.color.text.primary }}>{i.step}</td>
                  <td style={au.td}><VePill color={c.color} bg={c.bg}>{i.severity}</VePill></td>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px', color: T.color.text.tertiary }}>{i.rule}</td>
                  <td style={au.td}>{i.title}</td>
                  <td style={au.td}>
                    {i.autofix
                      ? <button style={{ ...au.btnPrimary, background: au.emerald }} onClick={() => handleFix(i.id)}>Apply autofix</button>
                      : <span style={{ fontSize: '11px', color: T.color.text.tertiary }}>Manual</span>}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE2. Version Diff & Time Travel
// ═══════════════════════════════════════════════════════════════════════════
function VE2VersionHistory() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['version.revert']);
  const [a, setA] = useVeState('v13');
  const [b, setB] = useVeState('v14');
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.cobalt} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.cobalt}`, background: au.cobaltBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.cobalt, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE2 · Version diff and time travel</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Compare any two versions · scrub through history · revert with audit trail.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '14px' }}>
        <div style={au.card}>
          <div style={au.cardH}><span>Compare A vs B</span></div>
          <div style={{ padding: '14px 16px' }}>
            <div style={{ display: 'flex', gap: '10px', alignItems: 'center', marginBottom: '12px' }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: '10px', fontWeight: 700, color: T.color.text.tertiary, textTransform: 'uppercase', marginBottom: '4px' }}>Version A</div>
                <select value={a} onChange={e => setA(e.target.value)} style={{ width: '100%', padding: '6px 10px', fontSize: '12px', border: `1px solid ${T.color.border.light}`, borderRadius: '5px' }}>
                  {state.versions.map(v => <option key={v.id} value={v.id}>{v.label}</option>)}
                </select>
              </div>
              <div style={{ fontSize: '14px', color: T.color.text.tertiary, fontWeight: 700 }}>↔</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: '10px', fontWeight: 700, color: T.color.text.tertiary, textTransform: 'uppercase', marginBottom: '4px' }}>Version B</div>
                <select value={b} onChange={e => setB(e.target.value)} style={{ width: '100%', padding: '6px 10px', fontSize: '12px', border: `1px solid ${T.color.border.light}`, borderRadius: '5px' }}>
                  {state.versions.map(v => <option key={v.id} value={v.id}>{v.label}</option>)}
                </select>
              </div>
            </div>
            <div style={{ padding: '10px 12px', background: T.color.bg.secondary, borderRadius: '5px', border: `1px solid ${T.color.border.light}`, fontFamily: T.font.mono, fontSize: '11px', lineHeight: 1.8 }}>
              <div style={{ color: au.emerald }}>+ step-6b · Auto-approve trivial branch</div>
              <div style={{ color: au.emerald }}>+ edge step-5 → step-6b</div>
              <div style={{ color: au.amber  }}>~ step-4 retries: 3 → 5</div>
              <div style={{ color: au.crimson}}>− debug-log · (removed)</div>
            </div>
          </div>
        </div>
        <div style={au.card}>
          <div style={au.cardH}><span>History timeline</span></div>
          <div style={{ padding: '8px 0' }}>
            {state.versions.map(v => (
              <div key={v.id} style={{ padding: '10px 16px', borderBottom: `1px solid ${T.color.border.light}`, display: 'flex', alignItems: 'center', gap: '12px' }}>
                <div style={{ fontFamily: T.font.mono, fontWeight: 700, color: au.cobalt, minWidth: '60px' }}>{v.id}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: '12px', fontWeight: 600, color: T.color.text.primary }}>{v.note}</div>
                  <div style={{ fontSize: '10px', color: T.color.text.tertiary, marginTop: '2px' }}>{v.author} · {v.ts} · {v.changes} changes</div>
                </div>
                <button style={au.btnSecondary} onClick={() => { S.revertToVersion(v.id, 'R. Patel'); setFlash(`Reverted to ${v.label}`); }}>Revert</button>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE3. Subflow Composition
// ═══════════════════════════════════════════════════════════════════════════
function VE3Subflows() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['subflow.collapse']);
  const [flash, setFlash] = useFlash();
  const [sel, setSel] = useVeState(3);

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.teal} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.teal}`, background: au.tealBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.teal, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE3 · Subflow composition</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Collapse groups of nodes into reusable subflows · version and publish independently.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '12px', marginBottom: '14px' }}>
        <VeKPI label="Subflows" value={state.subflows.length} />
        <VeKPI label="Total nodes" value={state.subflows.reduce((s, x) => s + x.nodes, 0)} />
        <VeKPI label="Runs 30d"   value={state.subflows.reduce((s, x) => s + x.runs30d, 0).toLocaleString()} color={au.teal} />
        <div style={{ ...au.stat, justifyContent: 'center' }}>
          <button style={{ ...au.btnPrimary, background: au.teal }}
            onClick={() => { const n = 'Auto-Group ' + (state.subflows.length + 1); S.collapseSubflow(n, sel, 'R. Patel'); setFlash(`Collapsed ${sel} nodes → ${n}`); }}>
            Collapse {sel} selected
          </button>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Registered subflows</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={au.th}>ID</th><th style={au.th}>Name</th><th style={{ ...au.th, textAlign: 'right' }}>Nodes</th><th style={{ ...au.th, textAlign: 'right' }}>Runs 30d</th><th style={au.th}>Owned by</th></tr></thead>
          <tbody>
            {state.subflows.map(s => (
              <tr key={s.id}>
                <td style={{ ...au.td, fontFamily: T.font.mono, color: au.teal, fontWeight: 700 }}>{s.id}</td>
                <td style={{ ...au.td, fontWeight: 600 }}>{s.name}</td>
                <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{s.nodes}</td>
                <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{s.runs30d.toLocaleString()}</td>
                <td style={{ ...au.td, fontSize: '11px', color: T.color.text.secondary }}>{s.ownedBy}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE4. Loop / Retry / Parallel Primitives
// ═══════════════════════════════════════════════════════════════════════════
function VE4Primitives() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['primitive.insert']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.violet} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.violet}`, background: au.violetBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.violet, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE4 · Loop / retry / parallel primitives</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Drag control-flow wrappers directly onto any node · no YAML, all visual.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '14px' }}>
        {state.primitives.map(p => (
          <div key={p.id} style={{ ...au.card, marginBottom: 0, borderLeft: `3px solid ${au.violet}` }}>
            <div style={au.cardH}>
              <span><b style={{ fontFamily: T.font.mono, color: au.violet }}>{p.id}</b> · {p.name}</span>
              <VePill color={au.violet} bg={au.violetBg}>{p.kind}</VePill>
            </div>
            <div style={{ padding: '12px 16px' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '10px' }}>
                <div>
                  <div style={{ fontSize: '10px', color: T.color.text.tertiary, textTransform: 'uppercase', fontWeight: 700 }}>Config</div>
                  <div style={{ fontFamily: T.font.mono, fontSize: '12px', fontWeight: 600, color: T.color.text.primary }}>{p.config}</div>
                </div>
                <div>
                  <div style={{ fontSize: '10px', color: T.color.text.tertiary, textTransform: 'uppercase', fontWeight: 700 }}>Used in</div>
                  <div style={{ fontFamily: T.font.mono, fontSize: '14px', fontWeight: 700, color: au.violet }}>{p.usedIn} flows</div>
                </div>
              </div>
              <button style={{ ...au.btnPrimary, background: au.violet, width: '100%' }}
                onClick={() => { S.insertPrimitive(p.id, 'step-4', 'R. Patel'); setFlash(`${p.name} wrapped step-4`); }}>
                Wrap selected step
              </button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE5. Swimlane Layout by Actor
// ═══════════════════════════════════════════════════════════════════════════
function VE5Swimlanes() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['layout.swimlane']);
  const [flash, setFlash] = useFlash();
  const total = state.swimlanes.reduce((s, l) => s + l.stepCount, 0) || 1;

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.fuchsia} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.fuchsia}`, background: au.fuchsiaBg }}>
        <div style={{ padding: '12px 16px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <div style={{ fontSize: '12px', fontWeight: 700, color: au.fuchsia, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE5 · Swimlane layout by actor</div>
            <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Re-layout canvas into horizontal swimlanes — one per actor / system. Makes hand-offs obvious.</div>
          </div>
          <button style={{ ...au.btnPrimary, background: au.fuchsia }}
            onClick={() => { S.relayoutBySwimlane('R. Patel'); setFlash('Canvas re-flowed into 5 swimlanes'); }}>
            Re-layout canvas
          </button>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Actor distribution</span></div>
        <div style={{ padding: '12px 0' }}>
          {state.swimlanes.map(l => {
            const pct = Math.round(100 * l.stepCount / total);
            return (
              <div key={l.id} style={{ padding: '8px 16px', display: 'flex', alignItems: 'center', gap: '12px' }}>
                <div style={{ minWidth: '180px', fontSize: '11px', fontWeight: 700, color: l.color, textTransform: 'uppercase', letterSpacing: '0.06em' }}>{l.label}</div>
                <div style={{ flex: 1, height: '16px', borderRadius: '4px', background: T.color.bg.secondary, overflow: 'hidden' }}>
                  <div style={{ width: `${pct}%`, height: '100%', background: l.color, opacity: 0.85 }} />
                </div>
                <div style={{ fontFamily: T.font.mono, fontWeight: 700, color: T.color.text.primary, minWidth: '60px', textAlign: 'right' }}>{l.stepCount} steps</div>
                <div style={{ fontFamily: T.font.mono, color: T.color.text.tertiary, minWidth: '40px', textAlign: 'right' }}>{pct}%</div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE6. Variable Graph Overlay
// ═══════════════════════════════════════════════════════════════════════════
function VE6VariableGraph() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['variable.prune']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.amber} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.amber}`, background: au.amberBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.amber, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE6 · Variable graph overlay</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Every variable · where it is produced and consumed · unused variables flagged.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '12px', marginBottom: '14px' }}>
        <VeKPI label="Variables" value={state.variables.length} />
        <VeKPI label="Unused"    value={state.variables.filter(v => v.unused).length} color={au.amber} />
        <VeKPI label="Cross-step" value={state.variables.filter(v => v.consumers.length > 1).length} />
        <VeKPI label="Input-only" value={state.variables.filter(v => v.source === 'input' || v.source === 'context').length} />
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Data flow graph</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr>
            <th style={au.th}>Variable</th><th style={au.th}>Type</th><th style={au.th}>Source</th>
            <th style={au.th}>Producers</th><th style={au.th}>Consumers</th><th style={au.th}>Action</th>
          </tr></thead>
          <tbody>
            {state.variables.map(v => (
              <tr key={v.id} style={v.unused ? { background: au.amberBg } : {}}>
                <td style={{ ...au.td, fontFamily: T.font.mono, color: au.amber, fontWeight: 700 }}>{v.id}</td>
                <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px', color: T.color.text.secondary }}>{v.type}</td>
                <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px', color: T.color.text.tertiary }}>{v.source}</td>
                <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px' }}>{v.producers.join(', ') || '—'}</td>
                <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px' }}>{v.consumers.join(', ') || '—'}</td>
                <td style={au.td}>
                  {v.unused
                    ? <button style={au.btnSecondary} onClick={() => { S.pruneVariable(v.id, 'R. Patel'); setFlash(`Pruned ${v.id}`); }}>Prune</button>
                    : <VePill color={au.emerald} bg={au.emeraldBg}>bound</VePill>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE7. Type-Safe Schema Binding
// ═══════════════════════════════════════════════════════════════════════════
function VE7SchemaBinding() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['schema.bind']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.cobalt} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.cobalt}`, background: au.cobaltBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.cobalt, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE7 · Type-safe schema binding</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Bind event schemas to steps · version-pinning · unbound schemas block publish.</div>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Schema registry</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr>
            <th style={au.th}>ID</th><th style={au.th}>Event</th><th style={au.th}>Ver</th>
            <th style={{ ...au.th, textAlign: 'right' }}>Fields</th>
            <th style={{ ...au.th, textAlign: 'right' }}>Required</th>
            <th style={{ ...au.th, textAlign: 'right' }}>Deprecated</th>
            <th style={au.th}>Binding</th>
          </tr></thead>
          <tbody>
            {state.schemas.map(s => (
              <tr key={s.id}>
                <td style={{ ...au.td, fontFamily: T.font.mono, color: au.cobalt, fontWeight: 700 }}>{s.id}</td>
                <td style={{ ...au.td, fontFamily: T.font.mono, fontWeight: 600 }}>{s.event}</td>
                <td style={{ ...au.td, fontFamily: T.font.mono, color: au.fuchsia, fontWeight: 700 }}>{s.version}</td>
                <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{s.fieldCount}</td>
                <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{s.required}</td>
                <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono, color: s.deprecated > 0 ? au.amber : T.color.text.tertiary }}>{s.deprecated}</td>
                <td style={au.td}>
                  {s.bound
                    ? <VePill color={au.emerald} bg={au.emeraldBg}>Bound</VePill>
                    : <button style={{ ...au.btnPrimary, background: au.cobalt }} onClick={() => { S.bindSchema(s.id, 'R. Patel'); setFlash(`Bound ${s.event}`); }}>Bind now</button>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE8. Test Harness & Sandbox Replay
// ═══════════════════════════════════════════════════════════════════════════
function VE8TestHarness() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['fixture.run']);
  const [flash, setFlash] = useFlash();
  const passed = state.testFixtures.filter(f => f.passed).length;

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.emerald} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.emerald}`, background: au.emeraldBg }}>
        <div style={{ padding: '12px 16px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <div style={{ fontSize: '12px', fontWeight: 700, color: au.emerald, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE8 · Test harness and sandbox replay</div>
            <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Run fixture suites in isolated sandbox · real integrations stubbed · full trace retained.</div>
          </div>
          <button style={{ ...au.btnPrimary, background: au.emerald }}
            onClick={() => { state.testFixtures.forEach(f => S.runFixture(f.id, 'R. Patel')); setFlash('All fixtures re-run'); }}>
            Run all fixtures
          </button>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '12px', marginBottom: '14px' }}>
        <VeKPI label="Fixtures" value={state.testFixtures.length} />
        <VeKPI label="Passing" value={passed} color={au.emerald} />
        <VeKPI label="Failing" value={state.testFixtures.length - passed} color={au.crimson} />
        <VeKPI label="Avg duration" value={`${(state.testFixtures.reduce((s, f) => s + f.durMs, 0) / Math.max(1, state.testFixtures.length) / 1000).toFixed(1)}s`} mono />
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Fixture results</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr>
            <th style={au.th}>ID</th><th style={au.th}>Name</th><th style={au.th}>Last run</th>
            <th style={{ ...au.th, textAlign: 'right' }}>Duration</th>
            <th style={{ ...au.th, textAlign: 'right' }}>Asserts</th>
            <th style={au.th}>Status</th><th style={au.th}>Action</th>
          </tr></thead>
          <tbody>
            {state.testFixtures.map(f => (
              <tr key={f.id}>
                <td style={{ ...au.td, fontFamily: T.font.mono, color: au.emerald, fontWeight: 700 }}>{f.id}</td>
                <td style={{ ...au.td, fontWeight: 600 }}>{f.name}</td>
                <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px', color: T.color.text.tertiary }}>{f.lastRun}</td>
                <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{(f.durMs/1000).toFixed(1)}s</td>
                <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{f.failed > 0 ? <span style={{ color: au.crimson }}>{f.asserts - f.failed}/{f.asserts}</span> : f.asserts}</td>
                <td style={au.td}>{f.passed
                  ? <VePill color={au.emerald} bg={au.emeraldBg}>Passed</VePill>
                  : <VePill color={au.crimson} bg={au.crimsonBg}>Failed</VePill>}</td>
                <td style={au.td}><button style={au.btnSecondary} onClick={() => { S.runFixture(f.id, 'R. Patel'); setFlash(`Re-ran ${f.name}`); }}>Replay</button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE9. Author-by-Chat Copilot
// ═══════════════════════════════════════════════════════════════════════════
function VE9Copilot() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const ve = window.ve;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['copilot.submit','copilot.apply']);
  const [flash, setFlash] = useFlash();
  const [prompt, setPrompt] = useVeState('');

  const submit = () => {
    if (!prompt.trim()) return;
    S.submitCopilot(prompt, 'R. Patel');
    setFlash('Copilot diff generated · awaiting review');
    setPrompt('');
  };

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.fuchsia} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.fuchsia}`, background: au.fuchsiaBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.fuchsia, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE9 · Author-by-chat copilot</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Describe changes in natural language · copilot produces a visual diff for approval.</div>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Ask copilot</span></div>
        <div style={{ padding: '14px 16px', display: 'flex', gap: '8px' }}>
          <input value={prompt} onChange={e => setPrompt(e.target.value)} placeholder="e.g., Add a fallback step if partner is OOO > 24h"
            style={{ flex: 1, padding: '8px 12px', fontSize: '12px', border: `1px solid ${T.color.border.light}`, borderRadius: '5px', fontFamily: T.font.family }}
            onKeyDown={e => { if (e.key === 'Enter') submit(); }} />
          <button style={{ ...au.btnPrimary, background: au.fuchsia }} onClick={submit}>Generate diff</button>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>History</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr>
            <th style={au.th}>ID</th><th style={au.th}>When</th><th style={au.th}>Author</th>
            <th style={au.th}>Prompt</th><th style={{ ...au.th, textAlign: 'right' }}>Nodes</th>
            <th style={au.th}>Status</th><th style={au.th}>Action</th>
          </tr></thead>
          <tbody>
            {state.copilotHistory.map(c => {
              const st = ve.statusColor(c.status);
              return (
                <tr key={c.id}>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontWeight: 700, color: au.fuchsia }}>{c.id}</td>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px', color: T.color.text.tertiary }}>{c.ts}</td>
                  <td style={{ ...au.td, fontSize: '11px', color: T.color.text.secondary }}>{c.user}</td>
                  <td style={{ ...au.td, fontSize: '11px', maxWidth: '320px', overflow: 'hidden', textOverflow: 'ellipsis' }}>{c.prompt}</td>
                  <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{c.nodesChanged}</td>
                  <td style={au.td}><VePill color={st.color} bg={st.bg}>{c.status}</VePill></td>
                  <td style={au.td}>
                    {c.status === 'pending'
                      ? <button style={{ ...au.btnPrimary, background: au.fuchsia }} onClick={() => { S.applyCopilot(c.id, 'R. Patel'); setFlash('Applied'); }}>Review & apply</button>
                      : <span style={{ fontSize: '11px', color: T.color.text.tertiary }}>—</span>}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE10. Workflow Optimizer (AI)
// ═══════════════════════════════════════════════════════════════════════════
function VE10Optimizer() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['optimizer.apply']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.lime} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.lime}`, background: au.limeBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.lime, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE10 · Workflow optimizer</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>AI analyzes run telemetry · suggests parallelization, retry caps, pre-routing. Apply selectively.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '12px', marginBottom: '14px' }}>
        <VeKPI label="Suggestions" value={state.optimizerSuggestions.length} />
        <VeKPI label="Est. savings" value={`${state.optimizerSuggestions.reduce((s, o) => s + o.savingsMin, 0)}m`} color={au.emerald} mono />
        <VeKPI label="Avg confidence" value={`${Math.round(100 * state.optimizerSuggestions.reduce((s, o) => s + o.confidence, 0) / Math.max(1, state.optimizerSuggestions.length))}%`} color={au.lime} mono />
      </div>
      <div>
        {state.optimizerSuggestions.map(o => {
          const riskC = o.risk === 'low' ? au.emerald : o.risk === 'medium' ? au.amber : au.crimson;
          return (
            <div key={o.id} style={{ ...au.card, borderLeft: `3px solid ${au.lime}` }}>
              <div style={{ padding: '12px 16px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '12px' }}>
                <div style={{ flex: 1 }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '4px' }}>
                    <span style={{ fontFamily: T.font.mono, fontWeight: 700, color: au.lime, fontSize: '11px' }}>{o.id}</span>
                    <VePill color={riskC} bg={`${riskC}14`}>{o.risk} risk</VePill>
                    <VePill color={au.cobalt} bg={au.cobaltBg}>{Math.round(o.confidence*100)}% conf</VePill>
                  </div>
                  <div style={{ fontSize: '13px', fontWeight: 600, color: T.color.text.primary }}>{o.rationale}</div>
                  {o.savingsMin > 0 && <div style={{ fontSize: '11px', color: au.emerald, marginTop: '4px', fontWeight: 600 }}>Saves ≈ {o.savingsMin} min per run (p95)</div>}
                </div>
                <button style={{ ...au.btnPrimary, background: au.lime }}
                  onClick={() => { S.applyOptimizer(o.id, 'R. Patel'); setFlash(`Applied ${o.id}`); }}>
                  Apply
                </button>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE11. Compliance Overlay (Rulebook-aware)
// ═══════════════════════════════════════════════════════════════════════════
function VE11ComplianceOverlay() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const ve = window.ve;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['compliance.bind']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.teal} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.teal}`, background: au.tealBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.teal, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE11 · Compliance overlay (Rulebook-aware)</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Each Rulebook rule renders as an overlay badge on the canvas · unbound rules block publish.</div>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Rule bindings</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={au.th}>ID</th><th style={au.th}>Rule</th><th style={au.th}>Bound to</th><th style={au.th}>Status</th><th style={au.th}>Action</th></tr></thead>
          <tbody>
            {state.complianceRules.map(r => {
              const st = ve.statusColor(r.status);
              return (
                <tr key={r.id}>
                  <td style={{ ...au.td, fontFamily: T.font.mono, color: au.teal, fontWeight: 700 }}>{r.id}</td>
                  <td style={au.td}>{r.rule}</td>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px' }}>{r.bindings.join(', ') || <span style={{ color: T.color.text.tertiary }}>— unbound —</span>}</td>
                  <td style={au.td}><VePill color={st.color} bg={st.bg}>{r.status}</VePill></td>
                  <td style={au.td}>
                    {r.status === 'unbound' || r.status === 'warn'
                      ? <button style={{ ...au.btnPrimary, background: au.teal }} onClick={() => { S.bindComplianceRule(r.id, 'step-4', 'R. Patel'); setFlash(`Bound ${r.id} to step-4`); }}>Bind</button>
                      : <span style={{ fontSize: '11px', color: T.color.text.tertiary }}>—</span>}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE12. Multi-author Collaboration
// ═══════════════════════════════════════════════════════════════════════════
function VE12Collaboration() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['comment.resolve','comment.add']);
  const [flash, setFlash] = useFlash();
  const [newMsg, setNewMsg] = useVeState('');

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.cobalt} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.cobalt}`, background: au.cobaltBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.cobalt, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE12 · Multi-author collaboration</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Live cursors · anchored comments · @-mentions · presence indicators on the canvas.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', gap: '14px' }}>
        <div style={au.card}>
          <div style={au.cardH}><span>Presence</span></div>
          <div>
            {state.collaborators.map(c => (
              <div key={c.id} style={{ padding: '10px 16px', borderBottom: `1px solid ${T.color.border.light}`, display: 'flex', alignItems: 'center', gap: '10px' }}>
                <div style={{ width: '10px', height: '10px', borderRadius: '50%', background: c.online ? c.color : T.color.text.tertiary }} />
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: '12px', fontWeight: 600, color: T.color.text.primary }}>{c.name}</div>
                  <div style={{ fontSize: '10px', color: T.color.text.tertiary }}>{c.role} {c.cursor && `· on step-${c.cursor.col + 1}`}</div>
                </div>
                <VePill color={c.online ? au.emerald : T.color.text.tertiary} bg={c.online ? au.emeraldBg : T.color.bg.secondary}>{c.online ? 'online' : 'away'}</VePill>
              </div>
            ))}
          </div>
        </div>
        <div style={au.card}>
          <div style={au.cardH}><span>Comments ({state.comments.filter(c => !c.resolved).length} open)</span></div>
          <div>
            {state.comments.map(c => (
              <div key={c.id} style={{ padding: '10px 16px', borderBottom: `1px solid ${T.color.border.light}`, background: c.resolved ? T.color.bg.secondary : 'transparent' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '4px' }}>
                  <div style={{ fontSize: '11px', fontWeight: 600, color: T.color.text.primary }}>
                    <span style={{ color: au.cobalt, fontFamily: T.font.mono }}>{c.step}</span> · {c.author}
                  </div>
                  <div style={{ fontSize: '10px', color: T.color.text.tertiary, fontFamily: T.font.mono }}>{c.ts}</div>
                </div>
                <div style={{ fontSize: '12px', color: c.resolved ? T.color.text.tertiary : T.color.text.primary, textDecoration: c.resolved ? 'line-through' : 'none' }}>{c.text}</div>
                {!c.resolved && <button style={{ ...au.btnSecondary, marginTop: '6px' }} onClick={() => { S.resolveComment(c.id, 'R. Patel'); setFlash('Comment resolved'); }}>Resolve</button>}
              </div>
            ))}
            <div style={{ padding: '10px 16px', display: 'flex', gap: '8px' }}>
              <input value={newMsg} onChange={e => setNewMsg(e.target.value)} placeholder="Comment on selected step..."
                style={{ flex: 1, padding: '6px 10px', fontSize: '12px', border: `1px solid ${T.color.border.light}`, borderRadius: '5px' }} />
              <button style={{ ...au.btnPrimary, background: au.cobalt }} onClick={() => { if (newMsg.trim()) { S.addComment('step-4', newMsg, 'R. Patel'); setNewMsg(''); setFlash('Comment added'); } }}>Add</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE13. Approval & Publish Pipeline
// ═══════════════════════════════════════════════════════════════════════════
function VE13ApprovalPipeline() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const ve = window.ve;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['pipeline.approve']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.emerald} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.emerald}`, background: au.emeraldBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.emerald, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE13 · Approval and publish pipeline</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Multi-stage gate · peer review · compliance · ops sign-off · canary release. Each stage bridges to Calendar.</div>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Pipeline stages</span></div>
        <div style={{ padding: '8px 0' }}>
          {state.approvalChain.map((s, i) => {
            const st = ve.statusColor(s.status);
            return (
              <div key={s.id} style={{ padding: '12px 16px', borderBottom: `1px solid ${T.color.border.light}`, display: 'flex', alignItems: 'center', gap: '12px' }}>
                <div style={{ width: '28px', height: '28px', borderRadius: '50%', background: st.bg, color: st.color, display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: '12px', fontFamily: T.font.mono }}>{i + 1}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: '13px', fontWeight: 600, color: T.color.text.primary }}>{s.stage}</div>
                  <div style={{ fontSize: '10px', color: T.color.text.tertiary, marginTop: '2px' }}>{s.role} · {s.approver}{s.ts && ` · ${s.ts}`}</div>
                </div>
                <VePill color={st.color} bg={st.bg}>{s.status}</VePill>
                {s.status === 'pending' &&
                  <button style={{ ...au.btnPrimary, background: au.emerald }} onClick={() => { S.approveStage(s.id, 'R. Patel'); setFlash(`${s.stage} approved`); }}>Approve</button>}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE14. Canary / Staged Rollout
// ═══════════════════════════════════════════════════════════════════════════
function VE14Canary() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['canary.advance','canary.rollback']);
  const [flash, setFlash] = useFlash();
  const c = state.canary;
  const allGood = (c.healthGates || []).every(g => g.passing);

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.amber} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.amber}`, background: au.amberBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.amber, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE14 · Canary / staged rollout</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Progressive rollout (5 → 10 → 25 → 50 → 100%) · auto-halt on gate failure · one-click rollback.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '12px', marginBottom: '14px' }}>
        <VeKPI label="Current stage" value={c.stage} mono color={au.amber} />
        <VeKPI label="Canary allocation" value={`${c.pctVariant}%`} mono color={au.amber} />
        <VeKPI label="Success (canary)" value={`${c.successVariant}%`} color={au.emerald} mono hint={`Base: ${c.successBase}%`} />
        <VeKPI label="p95 (canary)" value={`${c.p95Variant}ms`} color={au.cobalt} mono hint={`Base: ${c.p95Base}ms`} />
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: '14px' }}>
        <div style={au.card}>
          <div style={au.cardH}><span>Health gates</span></div>
          <div>
            {(c.healthGates || []).map(g => (
              <div key={g.id} style={{ padding: '10px 16px', borderBottom: `1px solid ${T.color.border.light}`, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <div style={{ fontSize: '12px', color: T.color.text.primary }}>{g.label}</div>
                <VePill color={g.passing ? au.emerald : au.crimson} bg={g.passing ? au.emeraldBg : au.crimsonBg}>{g.passing ? 'passing' : 'failing'}</VePill>
              </div>
            ))}
          </div>
        </div>
        <div style={au.card}>
          <div style={au.cardH}><span>Next action</span></div>
          <div style={{ padding: '14px 16px' }}>
            <div style={{ fontSize: '11px', color: T.color.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 700 }}>Auto-advance</div>
            <div style={{ fontSize: '18px', fontWeight: 700, color: au.amber, fontFamily: T.font.mono, marginTop: '4px' }}>→ {c.nextAutoStep}</div>
            <div style={{ fontSize: '11px', color: T.color.text.tertiary, marginTop: '2px' }}>in {c.nextAutoIn}</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', marginTop: '14px' }}>
              <button style={{ ...au.btnPrimary, background: allGood ? au.emerald : T.color.text.tertiary, width: '100%', cursor: allGood ? 'pointer' : 'not-allowed' }}
                disabled={!allGood} onClick={() => { S.advanceCanary('R. Patel'); setFlash(`Advanced canary`); }}>
                Advance now
              </button>
              <button style={{ ...au.btnSecondary, color: au.crimson, borderColor: `${au.crimson}44`, width: '100%' }}
                onClick={() => { S.rollbackCanary('R. Patel'); setFlash('Rolled back to baseline'); }}>
                Rollback
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE15. A/B Variants on Canvas
// ═══════════════════════════════════════════════════════════════════════════
function VE15Variants() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['variant.promote']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.violet} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.violet}`, background: au.violetBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.violet, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE15 · A/B variants on canvas</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Fork a flow into a variant · overlay both on canvas · compare telemetry side-by-side · promote winner.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '14px' }}>
        {state.variants.map(v => (
          <div key={v.id} style={{ ...au.card, borderLeft: `3px solid ${au.violet}`, marginBottom: 0 }}>
            <div style={au.cardH}>
              <span><b style={{ fontFamily: T.font.mono, color: au.violet }}>{v.id}</b> · {v.name}</span>
              <VePill color={au.amber} bg={au.amberBg}>{v.status}</VePill>
            </div>
            <div style={{ padding: '14px 16px' }}>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', marginBottom: '12px' }}>
                <div style={{ padding: '10px', background: T.color.bg.secondary, borderRadius: '5px', border: `1px solid ${T.color.border.light}` }}>
                  <div style={{ fontSize: '9px', fontWeight: 700, color: T.color.text.tertiary, textTransform: 'uppercase', marginBottom: '4px' }}>Baseline</div>
                  <div style={{ fontFamily: T.font.mono, fontSize: '18px', fontWeight: 700, color: T.color.text.primary }}>{v.baseVal}</div>
                </div>
                <div style={{ padding: '10px', background: `${au.violet}0f`, borderRadius: '5px', border: `1px solid ${au.violet}33` }}>
                  <div style={{ fontSize: '9px', fontWeight: 700, color: au.violet, textTransform: 'uppercase', marginBottom: '4px' }}>Variant ({v.allocation}%)</div>
                  <div style={{ fontFamily: T.font.mono, fontSize: '18px', fontWeight: 700, color: au.violet }}>{v.variantVal}</div>
                </div>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 12px', background: T.color.bg.secondary, borderRadius: '5px', border: `1px solid ${T.color.border.light}`, marginBottom: '10px' }}>
                <span style={{ fontSize: '10px', fontWeight: 700, color: T.color.text.tertiary, textTransform: 'uppercase' }}>Δ {v.metric}</span>
                <span style={{ fontFamily: T.font.mono, fontSize: '16px', fontWeight: 700, color: au.emerald }}>{v.delta}</span>
              </div>
              <button style={{ ...au.btnPrimary, background: au.violet, width: '100%' }}
                onClick={() => { S.promoteVariant(v.id, 'R. Patel'); setFlash(`Promoted ${v.name}`); }}>
                Promote variant
              </button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE16. Live Heatmap
// ═══════════════════════════════════════════════════════════════════════════
function VE16Heatmap() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const ve = window.ve;
  const state = window.useVisualEditorStore('*');
  const maxP95 = Math.max(...state.heatmap.map(h => h.p95Ms));
  const maxErr = Math.max(...state.heatmap.map(h => h.errRate), 0.001);

  return (
    <div>
      <div style={{ ...au.card, borderLeft: `3px solid ${au.crimson}`, background: au.crimsonBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.crimson, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE16 · Live heatmap</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Every node glows red for error rate, amber for p95 tail · real-time · last 30 days.</div>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Per-step telemetry</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr>
            <th style={au.th}>Step</th>
            <th style={{ ...au.th, textAlign: 'right' }}>Runs 30d</th>
            <th style={au.th}>p50</th>
            <th style={au.th}>p95</th>
            <th style={au.th}>Err rate</th>
            <th style={au.th}>Last run</th>
          </tr></thead>
          <tbody>
            {state.heatmap.map(h => {
              const heatP95 = h.p95Ms / maxP95;
              const heatErr = h.errRate / maxErr;
              return (
                <tr key={h.step}>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontWeight: 700, color: T.color.text.primary }}>{h.step}</td>
                  <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{h.runs30d.toLocaleString()}</td>
                  <td style={{ ...au.td, fontFamily: T.font.mono }}>{ve.ms(h.p50Ms)}</td>
                  <td style={{ ...au.td }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                      <div style={{ width: '60px', height: '6px', borderRadius: '3px', background: T.color.bg.secondary, overflow: 'hidden' }}>
                        <div style={{ width: `${heatP95*100}%`, height: '100%', background: au.amber }} />
                      </div>
                      <span style={{ fontFamily: T.font.mono, fontSize: '11px' }}>{ve.ms(h.p95Ms)}</span>
                    </div>
                  </td>
                  <td style={au.td}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                      <div style={{ width: '60px', height: '6px', borderRadius: '3px', background: T.color.bg.secondary, overflow: 'hidden' }}>
                        <div style={{ width: `${heatErr*100}%`, height: '100%', background: au.crimson }} />
                      </div>
                      <span style={{ fontFamily: T.font.mono, fontSize: '11px', color: h.errRate > 0.02 ? au.crimson : T.color.text.secondary }}>
                        {(h.errRate*100).toFixed(2)}%
                      </span>
                    </div>
                  </td>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px', color: T.color.text.tertiary }}>{h.lastRun}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE17. Incident Replay
// ═══════════════════════════════════════════════════════════════════════════
function VE17IncidentReplay() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const ve = window.ve;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['incident.replay']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.orange} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.orange}`, background: au.orangeBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.orange, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE17 · Incident replay</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Select an incident and step through every node in time-order · inputs / outputs / latencies annotated.</div>
        </div>
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Recent incidents</span></div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr>
            <th style={au.th}>ID</th><th style={au.th}>When</th><th style={au.th}>Step</th>
            <th style={au.th}>Kind</th><th style={au.th}>Run</th>
            <th style={au.th}>Severity</th>
            <th style={{ ...au.th, textAlign: 'right' }}>MTTR</th>
            <th style={au.th}>Action</th>
          </tr></thead>
          <tbody>
            {state.incidents.map(i => {
              const c = ve.severityColor(i.severity);
              return (
                <tr key={i.id}>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontWeight: 700, color: au.orange }}>{i.id}</td>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontSize: '11px', color: T.color.text.tertiary }}>{i.ts}</td>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontWeight: 600 }}>{i.step}</td>
                  <td style={au.td}>{i.kind}</td>
                  <td style={{ ...au.td, fontFamily: T.font.mono, color: au.cobalt, fontWeight: 700 }}>{i.runId}</td>
                  <td style={au.td}><VePill color={c.color} bg={c.bg}>{i.severity}</VePill></td>
                  <td style={{ ...au.td, textAlign: 'right', fontFamily: T.font.mono }}>{i.mttrMin}m</td>
                  <td style={au.td}><button style={{ ...au.btnPrimary, background: au.orange }} onClick={() => { S.replayIncident(i.id, 'R. Patel'); setFlash(`Replaying ${i.id}`); }}>Replay</button></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE18. Cost Ledger per Flow
// ═══════════════════════════════════════════════════════════════════════════
function VE18CostLedger() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const ve = window.ve;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['cost.report']);
  const [flash, setFlash] = useFlash();
  const c = state.costLedger;
  const max = Math.max(...(c.byStep || []).map(s => s.usd), 1);

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.emerald} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.emerald}`, background: au.emeraldBg }}>
        <div style={{ padding: '12px 16px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <div style={{ fontSize: '12px', fontWeight: 700, color: au.emerald, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE18 · Cost ledger per flow</div>
            <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>{c.period} · {ve.money(c.totalUsd)} of {ve.money(c.budgetUsd)} budget · {c.burnPct}% burn · trajectory: {c.trajectory}</div>
          </div>
          <button style={{ ...au.btnPrimary, background: au.emerald }}
            onClick={() => { S.reportCostPeriod('R. Patel'); setFlash('Cost pushed to Billing platform'); }}>
            Push to Billing
          </button>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '12px', marginBottom: '14px' }}>
        <VeKPI label="MTD spend" value={ve.money(c.totalUsd)} color={au.emerald} mono />
        <VeKPI label="Budget"    value={ve.money(c.budgetUsd)} mono />
        <VeKPI label="Burn"      value={`${c.burnPct}%`} color={c.burnPct > 90 ? au.crimson : au.amber} mono />
        <VeKPI label="Trajectory" value={c.trajectory} color={c.trajectory === 'under' ? au.emerald : au.crimson} />
      </div>
      <div style={au.card}>
        <div style={au.cardH}><span>Cost by step / resource</span></div>
        <div>
          {(c.byStep || []).map(s => (
            <div key={s.step} style={{ padding: '10px 16px', borderBottom: `1px solid ${T.color.border.light}`, display: 'flex', alignItems: 'center', gap: '14px' }}>
              <div style={{ fontFamily: T.font.mono, fontWeight: 700, color: T.color.text.primary, minWidth: '80px' }}>{s.step}</div>
              <div style={{ fontSize: '11px', color: T.color.text.secondary, minWidth: '140px' }}>{s.kind}</div>
              <div style={{ flex: 1, height: '12px', borderRadius: '3px', background: T.color.bg.secondary, overflow: 'hidden' }}>
                <div style={{ width: `${Math.round(100*s.usd/max)}%`, height: '100%', background: au.emerald, opacity: 0.85 }} />
              </div>
              <div style={{ fontFamily: T.font.mono, fontWeight: 700, color: au.emerald, minWidth: '90px', textAlign: 'right' }}>{ve.money(s.usd)}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE19. Integration Marketplace Drop-ins
// ═══════════════════════════════════════════════════════════════════════════
function VE19MarketplaceDropIns() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const S = window.VisualEditorStore;
  const state = window.useVisualEditorStore(['dropin.install']);
  const [flash, setFlash] = useFlash();

  return (
    <div>
      {flash && <VeFlash message={flash} color={au.teal} />}
      <div style={{ ...au.card, borderLeft: `3px solid ${au.teal}`, background: au.tealBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.teal, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE19 · Integration marketplace drop-ins</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Pre-configured integration nodes · vendor-verified · tenant-scoped · installs appear in palette instantly.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '12px' }}>
        {state.marketplaceDropIns.map(d => (
          <div key={d.id} style={{ ...au.card, marginBottom: 0 }}>
            <div style={{ padding: '12px 14px', borderBottom: `1px solid ${T.color.border.light}` }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '6px' }}>
                <span style={{ fontFamily: T.font.mono, fontWeight: 700, color: au.teal, fontSize: '10px' }}>{d.id}</span>
                {d.verified
                  ? <VePill color={au.emerald} bg={au.emeraldBg}>verified</VePill>
                  : <VePill color={au.amber} bg={au.amberBg}>unverified</VePill>}
              </div>
              <div style={{ fontSize: '13px', fontWeight: 700, color: T.color.text.primary, marginBottom: '3px' }}>{d.name}</div>
              <div style={{ fontSize: '10px', color: T.color.text.tertiary }}>{d.vendor} · {d.kind} · {d.category}</div>
            </div>
            <div style={{ padding: '10px 14px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <div style={{ fontSize: '11px', color: T.color.text.secondary }}><b>{d.installs}</b> installs</div>
              <button style={{ ...au.btnPrimary, background: au.teal }} onClick={() => { S.installDropIn(d.id, 'R. Patel'); setFlash(`Installed ${d.name}`); }}>Install</button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// VE20. Keyboard-First + A11y
// ═══════════════════════════════════════════════════════════════════════════
function VE20KeyboardA11y() {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const ve = window.ve;
  const state = window.useVisualEditorStore('*');
  const scoreColor = state.a11y.score >= 95 ? au.emerald : state.a11y.score >= 85 ? au.amber : au.crimson;

  return (
    <div>
      <div style={{ ...au.card, borderLeft: `3px solid ${au.violet}`, background: au.violetBg }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: au.violet, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ VE20 · Keyboard-first and accessibility</div>
          <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>Every canvas action has a shortcut · focus-visible throughout · screen-reader live regions on state change.</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '12px', marginBottom: '14px' }}>
        <VeKPI label="A11y score"         value={`${state.a11y.score}`} color={scoreColor} mono />
        <VeKPI label="Keyboard coverage"  value={ve.pctRaw(state.a11y.keyboardCoverage)} color={au.violet} mono />
        <VeKPI label="Open issues"        value={state.a11y.issues.filter(i => i.status === 'open').length} color={au.amber} />
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '14px' }}>
        <div style={au.card}>
          <div style={au.cardH}><span>Keyboard shortcuts</span></div>
          <table style={{ width: '100%', borderCollapse: 'collapse' }}>
            <thead><tr><th style={au.th}>Combo</th><th style={au.th}>Action</th><th style={au.th}>Category</th></tr></thead>
            <tbody>
              {state.keyboardShortcuts.map((k, i) => (
                <tr key={i}>
                  <td style={{ ...au.td, fontFamily: T.font.mono, fontWeight: 700, color: au.violet }}>
                    <kbd style={{ padding: '2px 6px', background: T.color.bg.secondary, border: `1px solid ${T.color.border.light}`, borderRadius: '4px', fontSize: '11px' }}>{k.combo}</kbd>
                  </td>
                  <td style={{ ...au.td, fontWeight: 600 }}>{k.action}</td>
                  <td style={{ ...au.td, fontSize: '11px', color: T.color.text.tertiary }}>{k.category}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div style={au.card}>
          <div style={au.cardH}><span>A11y issues</span></div>
          <table style={{ width: '100%', borderCollapse: 'collapse' }}>
            <thead><tr><th style={au.th}>ID</th><th style={au.th}>Rule</th><th style={au.th}>Severity</th><th style={au.th}>Status</th></tr></thead>
            <tbody>
              {state.a11y.issues.map(i => {
                const c = ve.severityColor(i.severity);
                const s = ve.statusColor(i.status);
                return (
                  <tr key={i.id}>
                    <td style={{ ...au.td, fontFamily: T.font.mono, fontWeight: 700, color: au.violet }}>{i.id}</td>
                    <td style={au.td}>{i.rule}</td>
                    <td style={au.td}><VePill color={c.color} bg={c.bg}>{i.severity}</VePill></td>
                    <td style={au.td}><VePill color={s.color} bg={s.bg}>{i.status}</VePill></td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════
// HUBS — Pill sub-nav groupings
// ═══════════════════════════════════════════════════════════════════════════
function VeHubShell({ title, accent, bg, description, subs, active, onChange, children }) {
  const au = window.__au;
  const T = window.ArbiterTokens;
  const accentColor = accent || au.lime;
  const bgColor = bg || au.limeBg;
  return (
    <div>
      <div style={{ ...au.card, borderLeft: `3px solid ${accentColor}`, background: bgColor }}>
        <div style={{ padding: '12px 16px' }}>
          <div style={{ fontSize: '12px', fontWeight: 700, color: accentColor, textTransform: 'uppercase', letterSpacing: '0.08em' }}>◆ {title}</div>
          {description && <div style={{ fontSize: '11px', color: T.color.text.secondary, marginTop: '4px' }}>{description}</div>}
        </div>
      </div>
      <div style={{ display: 'flex', gap: '8px', padding: '10px', background: T.color.bg.secondary, border: `1px solid ${T.color.border.light}`, borderRadius: '6px', marginBottom: '14px', flexWrap: 'wrap' }}>
        {subs.map(s => {
          const isActive = active === s.id;
          return (
            <button key={s.id} onClick={() => onChange(s.id)} style={{
              padding: '6px 12px', fontSize: '11px', fontWeight: isActive ? 700 : 500,
              color: isActive ? '#fff' : T.color.text.secondary,
              background: isActive ? accentColor : 'transparent',
              border: `1px solid ${isActive ? accentColor : T.color.border.light}`,
              borderRadius: '6px', cursor: 'pointer',
              letterSpacing: '0.02em', whiteSpace: 'nowrap',
              fontFamily: T.font.family,
            }}>{s.label}</button>
          );
        })}
      </div>
      {children}
    </div>
  );
}

function VeCanvasIntelligenceHub() {
  const au = window.__au;
  const [sub, setSub] = useVeState('ve1');
  const subs = [
    { id: 've1', label: 'Validation gutter' },
    { id: 've2', label: 'Version history' },
    { id: 've3', label: 'Subflows' },
    { id: 've4', label: 'Primitives' },
    { id: 've5', label: 'Swimlanes' },
  ];
  const render = () => {
    switch (sub) {
      case 've1': return <VE1ValidationGutter />;
      case 've2': return <VE2VersionHistory />;
      case 've3': return <VE3Subflows />;
      case 've4': return <VE4Primitives />;
      case 've5': return <VE5Swimlanes />;
      default: return <VE1ValidationGutter />;
    }
  };
  return (
    <VeHubShell title="Canvas intelligence" accent={au.fuchsia} bg={au.fuchsiaBg}
      description="Five opportunities that turn the canvas from a drawing surface into an intelligent authoring environment."
      subs={subs} active={sub} onChange={setSub}>
      {render()}
    </VeHubShell>
  );
}

function VeDataTestingHub() {
  const au = window.__au;
  const [sub, setSub] = useVeState('ve6');
  const subs = [
    { id: 've6', label: 'Variables' },
    { id: 've7', label: 'Schemas' },
    { id: 've8', label: 'Test harness' },
  ];
  const render = () => {
    switch (sub) {
      case 've6': return <VE6VariableGraph />;
      case 've7': return <VE7SchemaBinding />;
      case 've8': return <VE8TestHarness />;
      default: return <VE6VariableGraph />;
    }
  };
  return (
    <VeHubShell title="Data and testing" accent={au.amber} bg={au.amberBg}
      description="Data contracts and test coverage — make flows type-safe and regression-safe before publish."
      subs={subs} active={sub} onChange={setSub}>
      {render()}
    </VeHubShell>
  );
}

function VeAIComplianceHub() {
  const au = window.__au;
  const [sub, setSub] = useVeState('ve9');
  const subs = [
    { id: 've9',  label: 'Copilot' },
    { id: 've10', label: 'Optimizer' },
    { id: 've11', label: 'Compliance overlay' },
  ];
  const render = () => {
    switch (sub) {
      case 've9':  return <VE9Copilot />;
      case 've10': return <VE10Optimizer />;
      case 've11': return <VE11ComplianceOverlay />;
      default: return <VE9Copilot />;
    }
  };
  return (
    <VeHubShell title="AI and compliance" accent={au.lime} bg={au.limeBg}
      description="AI-authored changes, automated optimization, and Rulebook-aware compliance overlays."
      subs={subs} active={sub} onChange={setSub}>
      {render()}
    </VeHubShell>
  );
}

function VeGovernanceReleaseHub() {
  const au = window.__au;
  const [sub, setSub] = useVeState('ve12');
  const subs = [
    { id: 've12', label: 'Collaboration' },
    { id: 've13', label: 'Publish pipeline' },
    { id: 've14', label: 'Canary' },
    { id: 've15', label: 'A/B variants' },
  ];
  const render = () => {
    switch (sub) {
      case 've12': return <VE12Collaboration />;
      case 've13': return <VE13ApprovalPipeline />;
      case 've14': return <VE14Canary />;
      case 've15': return <VE15Variants />;
      default: return <VE12Collaboration />;
    }
  };
  return (
    <VeHubShell title="Governance and release" accent={au.emerald} bg={au.emeraldBg}
      description="Live collaboration, staged approvals, canary rollouts, and variant experiments."
      subs={subs} active={sub} onChange={setSub}>
      {render()}
    </VeHubShell>
  );
}

function VeObservabilityEconomicsHub() {
  const au = window.__au;
  const [sub, setSub] = useVeState('ve16');
  const subs = [
    { id: 've16', label: 'Heatmap' },
    { id: 've17', label: 'Incident replay' },
    { id: 've18', label: 'Cost ledger' },
  ];
  const render = () => {
    switch (sub) {
      case 've16': return <VE16Heatmap />;
      case 've17': return <VE17IncidentReplay />;
      case 've18': return <VE18CostLedger />;
      default: return <VE16Heatmap />;
    }
  };
  return (
    <VeHubShell title="Observability and economics" accent={au.crimson} bg={au.crimsonBg}
      description="Live telemetry on the canvas, incident replay, and real cost attribution per step."
      subs={subs} active={sub} onChange={setSub}>
      {render()}
    </VeHubShell>
  );
}

function VeExtensibilityHub() {
  const au = window.__au;
  const [sub, setSub] = useVeState('ve19');
  const subs = [
    { id: 've19', label: 'Marketplace drop-ins' },
    { id: 've20', label: 'Keyboard & A11y' },
  ];
  const render = () => {
    switch (sub) {
      case 've19': return <VE19MarketplaceDropIns />;
      case 've20': return <VE20KeyboardA11y />;
      default: return <VE19MarketplaceDropIns />;
    }
  };
  return (
    <VeHubShell title="Extensibility and UX" accent={au.teal} bg={au.tealBg}
      description="Third-party drop-ins and keyboard-first / accessibility coverage."
      subs={subs} active={sub} onChange={setSub}>
      {render()}
    </VeHubShell>
  );
}

// Global exports
window.VE1ValidationGutter      = VE1ValidationGutter;
window.VE2VersionHistory        = VE2VersionHistory;
window.VE3Subflows              = VE3Subflows;
window.VE4Primitives            = VE4Primitives;
window.VE5Swimlanes             = VE5Swimlanes;
window.VE6VariableGraph         = VE6VariableGraph;
window.VE7SchemaBinding         = VE7SchemaBinding;
window.VE8TestHarness           = VE8TestHarness;
window.VE9Copilot               = VE9Copilot;
window.VE10Optimizer            = VE10Optimizer;
window.VE11ComplianceOverlay    = VE11ComplianceOverlay;
window.VE12Collaboration        = VE12Collaboration;
window.VE13ApprovalPipeline     = VE13ApprovalPipeline;
window.VE14Canary               = VE14Canary;
window.VE15Variants             = VE15Variants;
window.VE16Heatmap              = VE16Heatmap;
window.VE17IncidentReplay       = VE17IncidentReplay;
window.VE18CostLedger           = VE18CostLedger;
window.VE19MarketplaceDropIns   = VE19MarketplaceDropIns;
window.VE20KeyboardA11y         = VE20KeyboardA11y;

window.VeCanvasIntelligenceHub    = VeCanvasIntelligenceHub;
window.VeDataTestingHub           = VeDataTestingHub;
window.VeAIComplianceHub          = VeAIComplianceHub;
window.VeGovernanceReleaseHub     = VeGovernanceReleaseHub;
window.VeObservabilityEconomicsHub= VeObservabilityEconomicsHub;
window.VeExtensibilityHub         = VeExtensibilityHub;
