// screen-vitrina-nodos.jsx — Vitrina de nodos del Motor de Flujos Piixi
// React 18 UMD + Babel standalone — NO import/export

// ─── Atoms (reusados de la versión anterior) ─────────────────────────────────

function Banderita({ estado, size }) {
  var sz = size || 16;
  var base = { display:'inline-flex', alignItems:'center', justifyContent:'center', width:sz, height:sz, borderRadius:'50%', flexShrink:0 };
  if (estado === 'cumplida') return <span style={{...base, background:'var(--ax-accent-soft)', border:'1.5px solid var(--ax-accent-line)', color:'var(--ax-accent)'}}><AxIcon name="check" size={sz*0.55}/></span>;
  if (estado === 'critica' || estado === 'pendiente') {
    var col = estado==='critica'?'var(--ax-danger)':'var(--ax-warm)';
    var soft = estado==='critica'?'var(--ax-danger-soft)':'var(--ax-warm-soft)';
    return <span style={{...base, background:soft, border:'1.5px solid '+(estado==='critica'?'rgba(233,76,77,0.25)':'var(--ax-warm-line)'), color:col}}><span style={{width:sz*0.33, height:sz*0.33, borderRadius:'50%', background:col}}/></span>;
  }
  return <span style={{...base, color:'var(--ax-fg-faint)', fontSize:sz*0.75}}>—</span>;
}

function ChipAuto({ label }) {
  var txt = label || 'Automático · cero red';
  return (
    <span style={{
      display:'inline-flex', alignItems:'center', gap:4,
      fontSize:11, color:'var(--ax-fg-faint)',
      background:'var(--ax-bg-3)', border:'1px solid var(--ax-border)',
      borderRadius:6, padding:'4px 8px', fontFamily:'var(--font-mono)'
    }}>
      <AxIcon name="refresh" size={11} />
      {txt}
    </span>
  );
}

function ChipMono({ text }) {
  return (
    <span style={{
      display:'inline-block',
      fontSize:11, fontFamily:'var(--font-mono)', color:'var(--ax-fg-strong)',
      background:'var(--ax-bg-3)', border:'1px solid var(--ax-border)',
      borderRadius:6, padding:'3px 8px'
    }}>
      {text}
    </span>
  );
}

function ChipSaved() {
  return (
    <span style={{
      display:'inline-flex', alignItems:'center', gap:5,
      fontSize:11, color:'var(--ax-accent)',
      background:'var(--ax-accent-soft)', border:'1px solid var(--ax-accent-line)',
      borderRadius:6, padding:'3px 8px'
    }}>
      <Banderita estado="cumplida" size={13} />
      Guardado ✓
    </span>
  );
}

function MomentoLabel({ num, label }) {
  return (
    <div style={{
      fontSize:10, letterSpacing:'0.07em', textTransform:'uppercase',
      color:'var(--ax-fg-faint)', fontWeight:600, marginBottom:8
    }}>
      {num} {label}
    </div>
  );
}

function MomentoBox({ num, label, children }) {
  return (
    <div style={{
      background:'var(--ax-bg)', border:'1px solid var(--ax-border)',
      borderRadius:8, padding:'12px 14px', minHeight:80
    }}>
      <MomentoLabel num={num} label={label} />
      <div style={{display:'flex', flexDirection:'column', gap:6}}>
        {children}
      </div>
    </div>
  );
}

function ActivityRow({ icon, label }) {
  return (
    <div style={{display:'flex', alignItems:'center', gap:8}}>
      <span style={{
        display:'inline-flex', alignItems:'center', justifyContent:'center',
        width:28, height:28, borderRadius:'50%',
        background:'var(--ax-bg-2)',
        border:'1.5px solid var(--ax-border-strong)',
        color:'var(--ax-fg-muted)', flexShrink:0
      }}>
        <AxIcon name={icon} size={13} />
      </span>
      <span style={{fontSize:12, color:'var(--ax-fg-strong)', fontWeight:500}}>
        {label}
      </span>
    </div>
  );
}

function ResultRow({ children }) {
  return (
    <div style={{display:'flex', alignItems:'center', gap:6, flexWrap:'wrap'}}>
      {children}
    </div>
  );
}

// ─── Zone section header ──────────────────────────────────────────────────────

function ZonaHeader({ zona, titulo, subtitulo, accentColor, badgeTone, badgeLabel }) {
  return (
    <div style={{
      marginBottom:20,
      paddingBottom:14,
      borderBottom:'2px solid ' + accentColor
    }}>
      <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:6}}>
        <AxEyebrow>{zona}</AxEyebrow>
        <AxPill tone={badgeTone}>{badgeLabel}</AxPill>
      </div>
      <h2 style={{
        margin:'0 0 4px 0', fontSize:17, fontWeight:700,
        color:'var(--ax-fg-strong)', letterSpacing:'-0.01em'
      }}>{titulo}</h2>
      <p style={{
        margin:0, fontSize:12, color:'var(--ax-fg-muted)',
        lineHeight:1.5, maxWidth:680
      }}>{subtitulo}</p>
    </div>
  );
}

// ─── Nodo card — ZONA 1 (internal, solid border) ─────────────────────────────

function NodoCardInterno({ nodo }) {
  var isHuman = !!nodo.isHuman;
  var isRich = !!nodo.isRich;
  var cardStyle = {
    background: 'var(--ax-bg-2)',
    border: isHuman
      ? '1px solid var(--ax-accent-line)'
      : '1px solid var(--ax-border)',
    borderRadius: 12,
    padding: 20,
    marginBottom: 14
  };
  if (isRich) {
    cardStyle.boxShadow = '0 0 0 1px var(--ax-info-line)';
  }

  return (
    <div style={cardStyle}>
      <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:14, flexWrap:'wrap'}}>
        <span style={{fontFamily:'var(--font-mono)', fontSize:13, color:'var(--ax-fg-strong)', fontWeight:600}}>
          {nodo.id}
        </span>
        <AxPill tone={nodo.kindTone}>{nodo.kind}</AxPill>
        {isHuman && (
          <AxPill tone="accent"><AxIcon name="user" size={11} /> requiere humano</AxPill>
        )}
        {isRich && (
          <AxPill tone="info"><AxIcon name="info" size={11} /> familia · varios modos</AxPill>
        )}
        {nodo.extraPills && nodo.extraPills()}
        <span style={{
          fontSize:12, color:'var(--ax-fg-muted)',
          marginLeft:'auto', maxWidth:340, textAlign:'right', lineHeight:1.4
        }}>
          {nodo.desc}
        </span>
      </div>

      <div style={{display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:14}}>
        <MomentoBox num="①" label="Actividad">
          <ActivityRow icon={nodo.icon} label={nodo.id} />
        </MomentoBox>
        <MomentoBox num="②" label="Captura · Ejecución">
          {nodo.momento2()}
        </MomentoBox>
        <MomentoBox num="③" label="Resultado">
          {nodo.momento3()}
        </MomentoBox>
      </div>
    </div>
  );
}

// ─── Nodo card — ZONA 2 (connector, dashed border) ───────────────────────────

function NodoCardConector({ nodo }) {
  return (
    <div style={{
      background:'var(--ax-bg-2)',
      border:'1px dashed var(--ax-border-strong)',
      borderRadius:12, padding:20, marginBottom:14
    }}>
      {/* Header */}
      <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:14, flexWrap:'wrap'}}>
        <span style={{fontFamily:'var(--font-mono)', fontSize:13, color:'var(--ax-fg-strong)', fontWeight:600}}>
          {nodo.id}
        </span>
        <AxPill tone="info">conector</AxPill>
        <AxPill tone="ghost">fuera de strict-line</AxPill>
        {nodo.extraPills && nodo.extraPills()}
        <span style={{
          fontSize:12, color:'var(--ax-fg-muted)',
          marginLeft:'auto', maxWidth:340, textAlign:'right', lineHeight:1.4
        }}>
          {nodo.desc}
        </span>
      </div>

      {/* IO + canales */}
      <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:14}}>
        {/* Entrada */}
        <div style={{
          background:'var(--ax-bg)', border:'1px solid var(--ax-border)',
          borderRadius:8, padding:'12px 14px'
        }}>
          <MomentoLabel num="→" label="Entrada" />
          <div style={{display:'flex', flexDirection:'column', gap:5}}>
            {nodo.entrada()}
          </div>
        </div>
        {/* Salida */}
        <div style={{
          background:'var(--ax-bg)', border:'1px solid var(--ax-border)',
          borderRadius:8, padding:'12px 14px'
        }}>
          <MomentoLabel num="←" label="Salida" />
          <div style={{display:'flex', flexDirection:'column', gap:5}}>
            {nodo.salida()}
          </div>
        </div>
      </div>

      {nodo.canales && (
        <div style={{marginTop:10, display:'flex', alignItems:'center', gap:6, flexWrap:'wrap'}}>
          <span style={{fontSize:11, color:'var(--ax-fg-faint)', marginRight:4}}>Canales:</span>
          {nodo.canales()}
        </div>
      )}
    </div>
  );
}

// ─── Sequence strip ───────────────────────────────────────────────────────────

function SecuenciaCedula() {
  var pasos = [
    { label:'cargar PDF', zona:'interno' },
    { label:'extracción', zona:'conector' },
    { label:'guardar-dato', zona:'interno' },
    { label:'validar·fecha', zona:'interno' },
    { label:'leer QR / calcular URL', zona:'interno' },
    { label:'cruce-CNSF', zona:'conector' },
    { label:'dictamen', zona:'interno' }
  ];

  return (
    <div style={{
      background:'var(--ax-bg-2)', border:'1px solid var(--ax-border)',
      borderRadius:12, padding:24, marginTop:32
    }}>
      <div style={{marginBottom:16}}>
        <AxEyebrow>EJEMPLO REAL</AxEyebrow>
        <h3 style={{margin:'4px 0 4px', fontSize:14, fontWeight:700, color:'var(--ax-fg-strong)'}}>
          Validación de cédula como secuencia
        </h3>
        <p style={{margin:0, fontSize:12, color:'var(--ax-fg-muted)'}}>
          Un flujo real cruza las dos zonas. Cada paso indica su zona con un punto de color.
        </p>
      </div>

      {/* Leyenda */}
      <div style={{display:'flex', alignItems:'center', gap:14, marginBottom:16, flexWrap:'wrap'}}>
        <div style={{display:'flex', alignItems:'center', gap:5}}>
          <span style={{width:9, height:9, borderRadius:'50%', background:'var(--ax-accent)', display:'inline-block'}}/>
          <span style={{fontSize:11, color:'var(--ax-fg-faint)'}}>núcleo interno</span>
        </div>
        <div style={{display:'flex', alignItems:'center', gap:5}}>
          <span style={{
            width:9, height:9, borderRadius:'50%',
            background:'var(--ax-info)', display:'inline-block',
            outline:'1.5px dashed var(--ax-info)', outlineOffset:2
          }}/>
          <span style={{fontSize:11, color:'var(--ax-fg-faint)'}}>conector externo</span>
        </div>
      </div>

      {/* Tira horizontal */}
      <div style={{
        display:'flex', alignItems:'center', gap:4, flexWrap:'wrap', rowGap:8
      }}>
        {pasos.map(function(p, i) {
          var isConector = p.zona === 'conector';
          return (
            <React.Fragment key={p.label}>
              <div style={{
                display:'inline-flex', alignItems:'center', gap:6,
                background: isConector ? 'var(--ax-info-soft)' : 'var(--ax-accent-soft)',
                border: isConector
                  ? '1px dashed var(--ax-info-line)'
                  : '1px solid var(--ax-accent-line)',
                borderRadius:20, padding:'5px 10px'
              }}>
                <span style={{
                  width:7, height:7, borderRadius:'50%', flexShrink:0,
                  background: isConector ? 'var(--ax-info)' : 'var(--ax-accent)'
                }}/>
                <span style={{
                  fontSize:11, fontFamily:'var(--font-mono)',
                  color: isConector ? 'var(--ax-info)' : 'var(--ax-accent)',
                  fontWeight:600
                }}>
                  {p.label}
                </span>
              </div>
              {i < pasos.length - 1 && (
                <span style={{color:'var(--ax-fg-faint)', flexShrink:0}}>
                  <AxIcon name="arrow-right" size={12} />
                </span>
              )}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

// ─── Data ─────────────────────────────────────────────────────────────────────

var NODOS_INTERNOS = [
  {
    id: 'leer-dato',
    kind: 'action', kindTone: 'neutral',
    desc: 'Lee un campo del modelo de datos del flujo',
    icon: 'eye',
    momento2: function() { return <ChipAuto />; },
    momento3: function() { return <ChipMono text="vigencia_fin = 2026-07-15" />; }
  },
  {
    id: 'guardar-dato',
    kind: 'action', kindTone: 'neutral',
    desc: 'Captura y persiste un campo del modelo — FAMILIA: un sub-tipo por tipo de dato',
    icon: 'edit',
    isRich: true,
    momento2: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:8}}>
          <div>
            <div style={{fontSize:10, color:'var(--ax-fg-faint)', marginBottom:3, textTransform:'uppercase', letterSpacing:'0.05em'}}>texto</div>
            <AxInput placeholder="Número de cédula" style={{fontSize:11}} />
          </div>
          <div>
            <div style={{fontSize:10, color:'var(--ax-fg-faint)', marginBottom:3, textTransform:'uppercase', letterSpacing:'0.05em'}}>fecha</div>
            <input type="date" style={{
              width:'100%', boxSizing:'border-box',
              background:'var(--ax-bg-3)', border:'1px solid var(--ax-border)',
              borderRadius:6, padding:'5px 8px', fontSize:11,
              color:'var(--ax-fg-strong)', fontFamily:'inherit'
            }} />
          </div>
          <div>
            <div style={{fontSize:10, color:'var(--ax-fg-faint)', marginBottom:3, textTransform:'uppercase', letterSpacing:'0.05em'}}>url</div>
            <input type="url" placeholder="https://..." style={{
              width:'100%', boxSizing:'border-box',
              background:'var(--ax-bg-3)', border:'1px solid var(--ax-border)',
              borderRadius:6, padding:'5px 8px', fontSize:11,
              color:'var(--ax-fg-strong)', fontFamily:'inherit'
            }} />
          </div>
          <div>
            <div style={{fontSize:10, color:'var(--ax-fg-faint)', marginBottom:3, textTransform:'uppercase', letterSpacing:'0.05em'}}>número</div>
            <input type="number" placeholder="0.00" style={{
              width:'100%', boxSizing:'border-box',
              background:'var(--ax-bg-3)', border:'1px solid var(--ax-border)',
              borderRadius:6, padding:'5px 8px', fontSize:11,
              color:'var(--ax-fg-strong)', fontFamily:'inherit'
            }} />
          </div>
        </div>
      );
    },
    momento3: function() { return <ChipSaved />; }
  },
  {
    id: 'validar',
    kind: 'validation', kindTone: 'info',
    desc: 'Nodo consolidado (antes: regex/rango/fecha-vigencia) — FAMILIA con MODOS, estilo n8n',
    icon: 'check',
    isRich: true,
    extraPills: function() {
      return (
        <React.Fragment>
          <AxPill tone="info">modo: formato</AxPill>
          <AxPill tone="neutral">modo: rango</AxPill>
          <AxPill tone="neutral">modo: fecha-vigencia</AxPill>
        </React.Fragment>
      );
    },
    momento2: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:6}}>
          <span style={{fontSize:11, color:'var(--ax-fg-faint)'}}>Elige el modo de validación:</span>
          <div style={{display:'flex', gap:5, flexWrap:'wrap'}}>
            <span style={{
              fontSize:11, padding:'3px 9px', borderRadius:20, cursor:'pointer',
              background:'var(--ax-info-soft)', border:'1px solid var(--ax-info-line)',
              color:'var(--ax-info)', fontWeight:600
            }}>formato</span>
            <span style={{
              fontSize:11, padding:'3px 9px', borderRadius:20, cursor:'pointer',
              background:'var(--ax-bg-3)', border:'1px solid var(--ax-border)',
              color:'var(--ax-fg-muted)'
            }}>rango</span>
            <span style={{
              fontSize:11, padding:'3px 9px', borderRadius:20, cursor:'pointer',
              background:'var(--ax-bg-3)', border:'1px solid var(--ax-border)',
              color:'var(--ax-fg-muted)'
            }}>fecha-vigencia</span>
          </div>
          <ChipAuto label="Automático" />
        </div>
      );
    },
    momento3: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:8}}>
          <div>
            <div style={{fontSize:10, color:'var(--ax-fg-faint)', marginBottom:4, textTransform:'uppercase', letterSpacing:'0.05em'}}>formato</div>
            <ResultRow>
              <Banderita estado="cumplida" size={14} />
              <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>pasa · "A-123456"</span>
            </ResultRow>
            <ResultRow>
              <Banderita estado="critica" size={14} />
              <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>no pasa · "abc!"</span>
            </ResultRow>
          </div>
          <div>
            <div style={{fontSize:10, color:'var(--ax-fg-faint)', marginBottom:4, textTransform:'uppercase', letterSpacing:'0.05em'}}>rango</div>
            <ResultRow>
              <Banderita estado="cumplida" size={14} />
              <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>ok · valor <ChipMono text="38" /></span>
            </ResultRow>
          </div>
          <div>
            <div style={{fontSize:10, color:'var(--ax-fg-faint)', marginBottom:4, textTransform:'uppercase', letterSpacing:'0.05em'}}>fecha-vigencia</div>
            <div style={{display:'flex', flexDirection:'column', gap:4}}>
              <AxPill tone="accent" dot>Al día · 280 d</AxPill>
              <AxPill tone="warm" dot>Por refrendar · 30 d</AxPill>
              <AxPill tone="danger" dot>Vencida</AxPill>
            </div>
          </div>
        </div>
      );
    }
  },
  {
    id: 'calcular',
    kind: 'action', kindTone: 'neutral',
    desc: 'Aplica una fórmula determinista cerrada sobre los datos del modelo',
    icon: 'plus',
    momento2: function() { return <ChipAuto />; },
    momento3: function() { return <ChipMono text="resultado = 12,480.00" />; }
  },
  {
    id: 'aprobación-guiada',
    kind: 'approval', kindTone: 'accent',
    desc: 'La ÚNICA pausa para humano — detiene el flujo y espera confirmación explícita',
    icon: 'check',
    isHuman: true,
    momento2: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:6}}>
          <AxButton variant="primary" size="sm">
            Palomear · marcar hecho
          </AxButton>
          <span style={{fontSize:10, color:'var(--ax-fg-faint)'}}>
            Único nodo que detiene el flujo y espera
          </span>
        </div>
      );
    },
    momento3: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:6}}>
          <ResultRow>
            <AxPill tone="warm" dot>Pendiente · falta tu confirmación</AxPill>
          </ResultRow>
          <ResultRow>
            <Banderita estado="cumplida" size={14} />
            <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>Hecho ✓</span>
          </ResultRow>
        </div>
      );
    }
  },
  {
    id: 'registrar-evidencia',
    kind: 'action', kindTone: 'neutral',
    desc: 'Escribe evidencia en el modelo y voltea la banderita del paso',
    icon: 'shield',
    momento2: function() { return <ChipAuto />; },
    momento3: function() {
      return (
        <ResultRow>
          <Banderita estado="pendiente" size={14} />
          <AxIcon name="arrow-right" size={11} />
          <Banderita estado="cumplida" size={14} />
          <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>evidencia registrada</span>
        </ResultRow>
      );
    }
  },
  {
    id: 'notificar',
    kind: 'notification', kindTone: 'warm',
    desc: 'Deja la intención en la bandeja de salida — NO envía (eso lo hace un conector)',
    icon: 'bell',
    momento2: function() { return <ChipAuto />; },
    momento3: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:6}}>
          <AxPill tone="warm" dot><AxIcon name="bell" size={11} /> En bandeja de salida · renovacion_proxima</AxPill>
          <span style={{fontSize:10, color:'var(--ax-fg-faint)', fontStyle:'italic'}}>
            deja la intención; el envío lo hace un conector →
          </span>
        </div>
      );
    }
  }
];

var NODOS_CONECTORES = [
  {
    id: 'comunicaciones',
    desc: 'Entrega lo que notificar dejó en la bandeja de salida hacia los canales reales',
    icon: 'mail',
    extraPills: function() {
      return <AxPill tone="info"><AxIcon name="cloud" size={11} /> red en vivo</AxPill>;
    },
    entrada: function() {
      return (
        <ResultRow>
          <AxIcon name="inbox" size={13} />
          <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>intención de notificación</span>
        </ResultRow>
      );
    },
    salida: function() {
      return <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>mensaje real al cliente</span>;
    },
    canales: function() {
      return (
        <React.Fragment>
          <AxPill tone="info">Telegram</AxPill>
          <AxPill tone="info">WhatsApp</AxPill>
          <AxPill tone="info">Correo</AxPill>
          <span style={{fontSize:11, color:'var(--ax-fg-faint)'}}>u otras APIs</span>
        </React.Fragment>
      );
    }
  },
  {
    id: 'cruce-cnsf',
    desc: 'Verificación anti-apócrifo EN VIVO contra el portal oficial de la CNSF',
    icon: 'shield',
    extraPills: function() {
      return (
        <React.Fragment>
          <AxPill tone="danger"><AxIcon name="eye" size={11} /> red en vivo</AxPill>
          <AxPill tone="warm">DOM scraping</AxPill>
        </React.Fragment>
      );
    },
    entrada: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:5}}>
          <ResultRow>
            <AxIcon name="pdf" size={13} />
            <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>datos extraídos del PDF</span>
          </ResultRow>
          <ResultRow>
            <AxIcon name="search" size={13} />
            <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>URL del QR ancla</span>
          </ResultRow>
        </div>
      );
    },
    salida: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:4}}>
          <AxPill tone="accent" dot>vigente · válida según la Comisión</AxPill>
          <AxPill tone="danger" dot>no encontrada / no coincide</AxPill>
        </div>
      );
    }
  },
  {
    id: 'extracción',
    desc: 'Extrae campos estructurados de un PDF cargado mediante motor de extracción',
    icon: 'pdf',
    extraPills: function() {
      return <AxPill tone="info"><AxIcon name="upload" size={11} /> procesamiento externo</AxPill>;
    },
    entrada: function() {
      return (
        <ResultRow>
          <AxIcon name="pdf" size={13} />
          <span style={{fontSize:11, color:'var(--ax-fg-muted)'}}>PDF cargado</span>
        </ResultRow>
      );
    },
    salida: function() {
      return (
        <div style={{display:'flex', flexDirection:'column', gap:5}}>
          <ChipMono text="cedula_num = A-123456" />
          <ChipMono text="vigencia_fin = 2026-07-15" />
          <span style={{fontSize:10, color:'var(--ax-fg-faint)'}}>campos estructurados</span>
        </div>
      );
    }
  }
];

// ─── Main screen ──────────────────────────────────────────────────────────────

function VitrinaNodosScreen() {
  return (
    <div style={{ flex:1, display:'flex', flexDirection:'column', overflow:'hidden' }}>
      <AxPageHeader
        eyebrow="MOTOR DE FLUJOS · CATÁLOGO"
        title="Vitrina de nodos"
        subtitle="Dos zonas: el núcleo interno determinista y los conectores externos. Las familias muestran sus variantes."
      />
      <div style={{ flex:1, overflow:'auto', padding:'24px 32px 48px' }}>

        {/* Intro */}
        <p style={{
          fontSize:13, color:'var(--ax-fg-muted)', marginBottom:28,
          maxWidth:720, lineHeight:1.6
        }}>
          Los nodos se dividen en dos zonas con separación física: el <strong style={{color:'var(--ax-fg-strong)'}}>núcleo interno</strong> (determinista, cero red, predecible) y los <strong style={{color:'var(--ax-fg-strong)'}}>conectores externos</strong> (tocan red o servicios externos, viven fuera del strict-line). Las familias guardar-dato y validar muestran todas sus variantes.
        </p>

        {/* ── ZONA 1 ─────────────────────────────────────────────────────── */}
        <ZonaHeader
          zona="ZONA 1 · 7 NODOS"
          titulo="Núcleo interno · determinista"
          subtitulo="Pasos puros, cero red, cero LLM — el motor los corre y son predecibles"
          accentColor="var(--ax-accent-line)"
          badgeTone="accent"
          badgeLabel="cero red · strict-line"
        />

        {NODOS_INTERNOS.map(function(nodo) {
          return <NodoCardInterno key={nodo.id} nodo={nodo} />;
        })}

        {/* Divisor entre zonas */}
        <div style={{
          display:'flex', alignItems:'center', gap:14,
          margin:'32px 0 28px'
        }}>
          <div style={{flex:1, height:1, background:'var(--ax-border-strong)'}}/>
          <span style={{
            fontSize:11, color:'var(--ax-fg-faint)', fontFamily:'var(--font-mono)',
            letterSpacing:'0.06em', whiteSpace:'nowrap', textTransform:'uppercase'
          }}>
            ── límite interno / externo ──
          </span>
          <div style={{flex:1, height:1, background:'var(--ax-border-strong)'}}/>
        </div>

        {/* ── ZONA 2 ─────────────────────────────────────────────────────── */}
        <ZonaHeader
          zona="ZONA 2 · 3 CONECTORES"
          titulo="Conectores · externos"
          subtitulo="Tocan red o servicios de afuera — VIVEN FUERA del núcleo determinista. El motor los invoca, no los ejecuta inline"
          accentColor="var(--ax-info-line)"
          badgeTone="info"
          badgeLabel="red · servicios externos"
        />

        {/* Nota informativa zona 2 */}
        <div style={{
          display:'flex', alignItems:'flex-start', gap:10,
          background:'var(--ax-info-soft)', border:'1px dashed var(--ax-info-line)',
          borderRadius:8, padding:'10px 14px', marginBottom:16
        }}>
          <AxIcon name="info" size={14} />
          <span style={{fontSize:12, color:'var(--ax-fg-muted)', lineHeight:1.5}}>
            Las tarjetas de esta zona usan borde punteado y esquema entrada→salida (sin momentos) porque su gracia es precisamente que SÍ salen del motor. Cada conector recibe lo que el núcleo preparó y devuelve un resultado externo.
          </span>
        </div>

        {NODOS_CONECTORES.map(function(nodo) {
          return <NodoCardConector key={nodo.id} nodo={nodo} />;
        })}

        {/* ── Secuencia de cédula ─────────────────────────────────────────── */}
        <SecuenciaCedula />

      </div>
    </div>
  );
}

window.VitrinaNodosScreen = VitrinaNodosScreen;
