// === PIP — MANUAL DEL ACTIVADOR ===
// App interactiva con el esquema de pasos y la estética del Portal de Activación.

const MA = {
  azul: '#3D52E8',
  turquesa: '#1ED2AF',
  ambar: '#f59e0b',
  white: '#fff',
  bg: '#f4f5fb',
  ink: '#1A1A2E',
  inkMid: '#555570',
  inkDim: '#8a8aa0',
  border: '#e5e7eb',
  danger: '#ef4444',
  violeta: '#8b5cf6',
  font: 'Asap, sans-serif',
};

const STORAGE_KEY = 'pip-manual-activador-step';
const ROLE_FILTER_KEY = 'pip-manual-role-filter';

// ─────────────────────────────────────────────────────────────
// ROLES — capa de división de tareas (Back / Ambos / Front)
// ─────────────────────────────────────────────────────────────
const ROLES = {
  back:  { key: 'back',  label: 'Back',  color: '#3D52E8', desc: 'Configuración, accesos y gestiones asincrónicas' },
  ambos: { key: 'ambos', label: 'Ambos', color: '#1ED2AF', desc: 'Compartido o según el caso' },
  front: { key: 'front', label: 'Front', color: '#f59e0b', desc: 'Sesiones y recopilación con el cliente' },
};
const ROLE_ORDER = ['back', 'ambos', 'front'];

// Rol por cada acción (según la tabla de desambiguación verificada)
const ROLE_BY_TITLE = {
  // Preparación
  'Revisá el calendar': 'ambos',
  'Dá de alta el cliente': 'back',
  'Se ha generado el resumen': 'ambos',
  // Bot / Agente IA + Equipo
  'Probá la vista previa del bot': 'back',
  'Mostralo al cliente': 'front',
  'El cliente lo prueba': 'front',
  'Feedback grabado': 'front',
  'Ajustá con la transcripción': 'back',
  'Cargá al equipo': 'front',
  'Explicá los roles': 'front',
  // Conexión a Pip (registro insertado)
  'Confirmá el portfolio': 'back',
  'Elegí el procedimiento': 'ambos',
  'Vinculá el número': 'ambos',
  // Plantillas y capacitación
  'Creá plantillas': 'front',
  'Confirmá aceptación': 'front',
  // Capacitación
  'Checklist': 'front',
  'Recorré el panel': 'front',
  'Escalar y derivar': 'front',
  'Plantillas en vivo': 'front',
  'Atá función a dolor': 'front',
  'Cerrá y anticipá': 'front',
  // Seguimiento
  '¿Está usando Pip?': 'back',
  '¿Responde desde Pip?': 'back',
  '¿Usa etiquetas?': 'back',
  '¿Usa plantillas?': 'back',
  '¿Bot / Agente IA activo?': 'back',
  '¿Tiene dudas?': 'back',
  // Adicionales (on-demand, Back)
  'Carga de contactos': 'back',
  'Bots por pauta o condicionales': 'back',
  'Integración vía webhooks o Dynamix': 'back',
};
// Rol por fase del paso Facebook
const ROLE_BY_FASE = { f1: 'front', f2: 'front', f3: 'ambos' };

function roleOf(title) { return ROLE_BY_TITLE[title] || null; }

// El filtro por rol incluye siempre las tareas de "Ambos" (compartidas).
// Front → Front + Ambos · Back → Back + Ambos · Ambos → solo compartidas.
function roleMatches(role, filter) {
  if (filter === 'all') return true;
  if (!role) return false;
  if (filter === 'ambos') return role === 'ambos';
  return role === filter || role === 'ambos';
}

// Contexto del filtro de rol
const RoleFilterCtx = React.createContext({ filter: 'all', setFilter: () => {} });

// Cuenta los roles de las acciones/fases de un paso
function tallyRoles(paso) {
  const c = { back: 0, ambos: 0, front: 0 };
  if (paso.detail === 'facebook') {
    ['f1', 'f2', 'f3'].forEach((id) => { const r = ROLE_BY_FASE[id]; if (r) c[r]++; });
  } else if (paso.acciones) {
    paso.acciones.forEach((a) => { const r = roleOf(a.title); if (r) c[r]++; });
  }
  return c;
}

// Badge de rol
function RoleBadge({ role, size }) {
  const r = ROLES[role];
  if (!r) return null;
  const sm = size === 'sm';
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: sm ? 9.5 : 10.5, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: '#fff', background: r.color, padding: sm ? '2px 7px' : '3px 9px', borderRadius: 99, lineHeight: 1.5, whiteSpace: 'nowrap' }}>
      <span style={{ width: sm ? 5 : 6, height: sm ? 5 : 6, borderRadius: '50%', background: '#ffffffcc' }}></span>
      {r.label}
    </span>
  );
}

// Barra de filtro por rol (con conteo del paso actual)
function RoleFilterBar({ paso }) {
  const { filter, setFilter } = React.useContext(RoleFilterCtx);
  const counts = tallyRoles(paso);
  const opts = [{ key: 'all', label: 'Todos' }, ...ROLE_ORDER.map((k) => ({ key: k, label: ROLES[k].label }))];
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap', padding: '11px 0' }}>
      <span style={{ fontSize: 11.5, fontWeight: 800, letterSpacing: '.05em', textTransform: 'uppercase', color: MA.inkDim }}>Ver por rol</span>
      <div style={{ display: 'flex', gap: 7 }}>
        {opts.map((o) => {
          const on = filter === o.key;
          const col = o.key === 'all' ? MA.ink : ROLES[o.key].color;
          return (
            <button key={o.key} onClick={() => setFilter(o.key)} style={{ fontFamily: MA.font, fontSize: 12.5, fontWeight: 800, padding: '7px 14px', borderRadius: 99, border: '1.5px solid ' + (on ? 'transparent' : MA.border), background: on ? col : '#fff', color: on ? '#fff' : MA.inkMid, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 7, transition: 'all .15s' }}>
              {o.key !== 'all' && <span style={{ width: 9, height: 9, borderRadius: 3, background: on ? '#fff' : ROLES[o.key].color }}></span>}
              {o.label}
            </button>
          );
        })}
      </div>
      <div style={{ marginLeft: 'auto', display: 'flex', gap: 12, fontSize: 12, fontWeight: 700, color: MA.inkMid }}>
        {ROLE_ORDER.map((k) => (
          <span key={k} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, opacity: counts[k] ? 1 : 0.4 }}>
            <span style={{ width: 9, height: 9, borderRadius: 3, background: ROLES[k].color }}></span>{ROLES[k].label} {counts[k]}
          </span>
        ))}
      </div>
    </div>
  );
}

// Requisitos para que el envío a verificar sea tarea del Front
const REQS_VALIDAR = [
  'Portfolio con historial. No puede ser un portfolio nuevo.',
  'Sin inhabilitaciones ni bloqueos en ninguna cuenta (publicitaria, WhatsApp, Instagram, fanpage). Revisar en el momento.',
  'Preguntar si el portfolio tuvo antes el bloqueo de alguna cuenta que fue eliminada. Chequear en el Inicio de ayuda para empresas.',
  'Página web con dominio propio: HTTPS, que no esté caída y con footer con la razón social e —idealmente— dirección y teléfono, tal cual ARCA.',
  'Mail con dominio propio igual al de la web. Si ya tiene la metaetiqueta cargada, no hace falta el mail de dominio propio.',
  'Número sin bloqueos previos. Si va a ser coexistencia, con al menos 3 días de historial de uso.',
];

function EnvioValidarCondicional() {
  const [open, setOpen] = React.useState(false);
  return (
    <div style={{ marginBottom: 16, border: '1px dashed #f5c98a', borderRadius: 12, background: '#fffdf7', overflow: 'hidden' }}>
      <button onClick={() => setOpen(!open)} style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 10, background: 'transparent', border: 'none', padding: '13px 16px', cursor: 'pointer', fontFamily: MA.font, textAlign: 'left' }}>
        <span style={{ fontSize: 16, flexShrink: 0 }}>⚑</span>
        <span style={{ flex: 1, minWidth: 0 }}>
          <span style={{ display: 'block', fontSize: 13, fontWeight: 800, color: '#b45309', lineHeight: 1.25 }}>Mandar a verificar: ¿lo hace el Back o el Front?</span>
          <span style={{ display: 'block', fontSize: 11.5, color: MA.inkMid, marginTop: 2 }}>Por defecto lo hace el Back. Pasa al Front solo si se cumplen los 6 requisitos.</span>
        </span>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, flexShrink: 0 }}>
          <RoleBadge role="back" size="sm" />
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#b45309" strokeWidth="3" strokeLinecap="round" style={{ transform: open ? 'rotate(90deg)' : 'none', transition: 'transform .2s' }}><path d="M9 6l6 6-6 6"></path></svg>
        </span>
      </button>
      {open && (
        <div style={{ padding: '4px 18px 18px' }}>
          <p style={{ fontSize: 12.5, fontWeight: 700, color: MA.ink, margin: '0 0 12px' }}>Por defecto <b style={{ color: MA.azul }}>lo hace el Back</b>. El Front puede mandar a verificar <b style={{ color: '#b45309' }}>si, y solo si,</b> se cumplen los seis:</p>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {REQS_VALIDAR.map((r, k) => (
              <div key={k} style={{ display: 'flex', gap: 11, alignItems: 'flex-start' }}>
                <span style={{ width: 22, height: 22, borderRadius: '50%', background: 'rgba(245,158,11,.16)', color: '#b45309', fontSize: 11, fontWeight: 800, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>{k + 1}</span>
                <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>{r}</p>
              </div>
            ))}
          </div>
          <div style={{ marginTop: 12, display: 'flex', gap: 9, alignItems: 'flex-start', background: 'rgba(30,210,175,.08)', border: '1px dashed #9fe3d2', borderRadius: 10, padding: '11px 14px' }}>
            <span style={{ fontSize: 14, flexShrink: 0 }}>💡</span>
            <p style={{ fontSize: 12, color: MA.inkMid, lineHeight: 1.45, margin: 0 }}>Si falta cualquiera, el envío a verificar lo hace el <b>Back</b>.</p>
          </div>
        </div>
      )}
    </div>
  );
}

// Corroboración de la verificación (seguimiento entre sesiones) — Back
function CorroboracionVerificacion() {
  return (
    <div style={{ marginBottom: 16, background: '#fff', border: '1px solid ' + MA.border, borderLeft: '3px solid ' + ROLES.back.color, borderRadius: 12, padding: '14px 16px' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 9, marginBottom: 8 }}>
        <span style={{ fontSize: 15 }}>🔄</span>
        <span style={{ fontSize: 13, fontWeight: 800, color: MA.ink }}>Corroborar la verificación (entre sesiones)</span>
        <span style={{ marginLeft: 'auto' }}><RoleBadge role="back" size="sm" /></span>
      </div>
      <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: '0 0 10px' }}>Podés corroborar el estado de la verificación del portfolio de <b>2 maneras</b>:</p>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {[
          'El cliente comparte las credenciales de acceso y lo revisás vos.',
          'El cliente se fija por su cuenta en la sección correspondiente y te confirma.',
        ].map((t, k) => (
          <div key={k} style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
            <span style={{ width: 20, height: 20, borderRadius: '50%', background: ROLES.back.color + '18', color: ROLES.back.color, fontSize: 11, fontWeight: 800, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, marginTop: 1 }}>{k + 1}</span>
            <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>{t}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

// Bloque de tareas adicionales (a demanda, Back)
function AdicionalesBlock({ data }) {
  const { filter } = React.useContext(RoleFilterCtx);
  if (filter !== 'all' && filter !== 'back') return null;
  return (
    <div style={{ marginBottom: 30, background: '#fff', border: '1px solid ' + MA.border, borderRadius: 16, padding: '18px 20px' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 }}>
        <span style={{ fontSize: 18 }}>🧩</span>
        <div style={{ fontSize: 15, fontWeight: 800, color: MA.ink }}>{data.title}</div>
        <span style={{ marginLeft: 'auto' }}><RoleBadge role="back" size="sm" /></span>
      </div>
      <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: '0 0 12px' }}>{data.nota}</p>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
        {data.items.map((it, k) => (
          <span key={k} style={{ fontSize: 12.5, fontWeight: 600, color: MA.ink, background: '#f6f7fc', border: '1px solid ' + MA.border, borderLeft: '3px solid ' + ROLES.back.color, borderRadius: 9, padding: '8px 12px' }}>{it}</span>
        ))}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// CONTENIDO — 3 sesiones / 6 pasos (versión simplificada del contexto)
// ─────────────────────────────────────────────────────────────
const REUNIONES = [
  {
    n: 0, label: 'Previo', color: '#64748b', title: 'Preparación del activador', duration: 'Antes de la S1',
    objetivo: 'Detectar el cliente nuevo, darlo de alta en el manager y leer el resumen de ventas antes de la primera sesión.',
    disparador: 'Te enterás de que tenés un cliente nuevo cuando aparece una sesión de introducción asignada en el Google Calendar de la cuenta de soporte.',
    prereqsActivador: [
      'Acceso al manager de Pip',
    ],
    resultado: [
      'Cliente dado de alta en el manager con su slug',
      'Slug vinculado al contrato en el CRM',
      'Resumen de la transcripción de ventas leído',
    ],
    pasos: [
      {
        n: 0, name: 'Preparación', icon: '🗂️', who: 'Activador', hideRol: true,
        subtitle: 'Alta del cliente y lectura del resumen de ventas',
        rol: 'Sesión de introducción nueva en el Calendar de soporte = cliente asignado. Antes de la S1: darlo de alta en el manager y leer el resumen de ventas.',
        acciones: [
          { icon: '📅', title: 'Revisá el calendar', desc: 'Revisá a diario el Google Calendar de la cuenta de soporte: una sesión de introducción nueva significa que tenés un cliente asignado para activar.', link: { href: 'https://calendar.google.com/calendar/u/0/r/', label: 'Abrir Google Calendar' } },
          { icon: '🆕', title: 'Dá de alta el cliente', desc: 'Generalo en el manager con “CRM Alta”: elegí el contrato del CRM (así queda vinculado), escribí el slug y el rack.', action: 'alta', actionLabel: 'Cómo dar de alta el cliente' },
          { icon: '📖', title: 'Se ha generado el resumen', desc: 'Al levantar el cliente, el sistema resume automáticamente la transcripción de la sesión de ventas. Es tu brief principal, más accionable que las notas del CRM: abrilo con el botón “Info empresa (IA)” en el Portal de Activación.', action: 'portal', actionLabel: 'Conocé el Portal de Activación' },
        ],
        errores: [
          'Entrar a la S1 sin leer el resumen.',
          'Alta sin vincular slug con el contrato.',
          'No revisar el calendar a tiempo.',
        ],
      },
    ],
  },
  {
    n: 1, color: MA.azul, title: 'Datos + Facebook', duration: '45–60 min',
    objetivo: 'Registrar los datos de la empresa y dejar la cuenta conectada con Facebook. Al cerrar, tenés todo lo necesario para generar el bot / agente IA.',
    prereqsCliente: [
      'Conectarse desde computadora',
      'Acceso a Facebook de la empresa (usuario y contraseña)',
      'Número de WhatsApp a integrar disponible y celular a mano',
    ],
    prereqsActivador: [
      'Resumen IA del cliente leído (panel de manager)',
      'Notas del comercial revisadas en el CRM',
    ],
    tiempos: [
      'Verificación de Meta: hasta 14 días hábiles',
      'Detección de la metaetiqueta: hasta 72 hs',
      'Solicitud enviada → seguimiento diario',
    ],
    resultado: [
      'Datos de empresa y número de WhatsApp verificados',
      'Riesgo Meta evaluado y comunicado si aplica',
      'Portfolio Comercial resuelto según el estado del portal (verificado, en verificación o creado)',
      'Cliente entiende la ventana de 24hs y el tiempo de verificación de Meta',
      'Sesión 2 agendada',
    ],
    pasos: [
      {
        n: 1, name: 'Datos y Facebook', icon: '📘', who: 'Cliente · Activador', detail: 'facebook',
        subtitle: 'Datos de la empresa + Portfolio Comercial, App y verificación ante Meta',
        rol: 'Portfolio + App + Verificación. Todo lo que Meta verifica acá define si el número se conecta sin bloqueos.',
        reglaOro: 'No verificado + rubro sensible + Cloud API = bloqueo preventivo. Meta desactiva sin esperar infracciones. Rubro sensible → verificá primero.',
        sensibles: {
          title: 'Rubros y datos sensibles — verificá primero',
          toggle: '¿Cuándo mandar a verificar un portfolio?',
          rubrosLabel: 'Cuando se trata de un rubro sensible',
          datosLabel: 'Cuando piden datos sensibles por WhatsApp',
          rubros: ['Finanzas / préstamos / cobros', 'Salud / farmacéutica / bienestar', 'Apuestas y juegos de azar', 'Criptomonedas', 'Legal / seguros', 'Adultos', 'Bienes raíces', 'Empleo y reclutamiento', 'Educación superior y formación', 'Gobierno / política / causas sociales', 'Negocios por suscripción', 'Retail con productos por edad (ej. alcohol)'],
          datos: ['Pide cobros o pagos', 'Pide DNI o documentación', 'Pide datos bancarios / tarjeta', 'Maneja datos médicos'],
        },
        prereqs: {
          title: 'Antes de tocar Meta',
          subtitle: 'Qué debe estar listo',
          items: [
            { label: 'Cuenta', icon: '👤', detalle: ['Vinculada a Facebook o a una página web.', 'Sin cuenta vinculada → no se puede crear portfolio.'] },
            { label: 'Web', icon: '🌐', detalle: ['HTTPS activo, que no se caiga.', 'Dominio que coincida con el nombre del negocio.', 'Footer: razón social + dirección.', 'Rubro sensible → landing propia obligatoria (no sirve página de Facebook).', 'Sin web → crear landing page simple.', 'Con web → dejarla lo más simple posible: sin carrito, sin botones de redirección.', 'Nombre del dominio: sin emojis, sin MAYÚSCULAS sostenidas, sin nombres genéricos.'] },
            { label: 'Rubro sensible', icon: '⚠️', detalle: ['Rubros: finanzas, salud, apuestas, cripto, legal, adultos.', 'También activa riesgo si: pide cobros/pagos, DNI, datos bancarios, datos médicos.', 'Verificación obligatoria antes de conectar.'] },
            { label: 'Documentación', icon: '📄', detalle: ['Digital y legible (Word o texto plano).', 'Legible para formato ATS.', 'Nunca escaneada, foto ni manuscrita.'] },
            { label: 'Portfolio', icon: '🏢', detalle: ['Sin bloqueos en NINGUNA sección.', 'Secciones a revisar: Info del negocio, Apps, Cuentas, Usuarios, Seguridad.', 'Bloqueado en alguna → crear portfolio nuevo.'] },
            { label: 'Datos ARCA', icon: '📋', detalle: ['Nombre legal exacto.', 'Dirección legal exacta.', 'Teléfono asociado a la razón social (no personal).'] },
          ],
        },
        subpasos: [
          {
            id: 'f1', tag: 'Fase 1', icon: '🏢', title: 'Portfolio Comercial',
            objetivo: 'Crear o relevar el Portfolio Comercial y cargar la información legal idéntica a ARCA. Si el nombre o la dirección no coinciden, la verificación posterior se rechaza.',
            pasos: [
              { text: 'Iniciá sesión con la mejor cuenta disponible.', tip: 'Prioridad: Facebook del negocio → Facebook personal → Instagram de la empresa. Si no hay ninguna, creá primero una cuenta de Facebook (nombre real, email y teléfono del cliente).' },
              { text: 'Entrá a business.facebook.com.' },
              { text: 'Selector del negocio → “Crear un portfolio comercial”.' },
              { text: 'Nombre del portfolio = nombre real del negocio.', tip: 'Sin emojis, sin MAYÚSCULAS SOSTENIDAS, sin genéricos como “Mi Empresa”.' },
              { text: 'Configuración → Info del negocio: nombre, dirección, teléfono, web.', tip: 'Todo copiado textual de ARCA. Un acento de diferencia = rechazo.' },
              { text: 'Teléfono: el de la razón social en ARCA, no personal.' },
              { text: 'Dirección: elegir la más clara posible.', tip: 'Si usa números como “Av. 52”, sugerir dirección secundaria con nombre de calle.' },
              { text: 'Activar verificación en dos pasos. Obligatorio.' },
              { text: 'Revisar TODAS las secciones del portfolio.', tip: 'Info del negocio, Apps, Cuentas, Usuarios, Seguridad. Bloqueada → portfolio nuevo.' },
            ],
            detalles: [
              {
                title: 'Secciones del portfolio',
                icon: '📋',
                items: [
                  'Info del negocio: datos legales y web.',
                  'Apps: la app de WhatsApp.',
                  'Cuentas: cuentas publicitarias vinculadas.',
                  'Usuarios: permisos y accesos.',
                  'Seguridad: verificación en dos pasos y dominios.',
                ],
              },
            ],
            tips: [
              'Portfolio existente sin bloqueos → lo usamos. Bloqueado → crear uno nuevo.',
            ],
            errores: [
              'Nombre de fantasía, emojis o MAYÚSCULAS: Meta lo rechaza.',
              'Datos que no coinciden con ARCA: rechazo.',
              'No revisar todas las secciones del portfolio.',
              'No activar verificación en dos pasos.',
            ],
            captura: [
              { src: 'assets/fb/f1-portfolio-crear.png', cap: 'Selector de portfolios → “Crear un portfolio comercial”' },
              { src: 'assets/fb/f1-portfolio-form.png', cap: 'Formulario de creación del portfolio' },
            ],
          },
          {
            id: 'f2', tag: 'Fase 2', icon: '🧩', title: 'Creación de la App',
            objetivo: 'Crear la App que habilita el envío de la solicitud de verificación. Va ANTES de verificar: sin app, no aparece la opción de enviarla.',
            pasos: [
              { text: 'Configuración → Cuentas → Apps → “Crear app”.' },
              { text: 'Nombre: [negocio] + “WSP APP”.' },
              { text: 'Caso de uso: “Conectarte con clientes a través de WhatsApp”.' },
              { text: '“Siguiente” hasta crear. Con la app, Meta habilita la verificación.' },
            ],
            tips: [
              'Meta puede pedir verificar la cuenta con un código de seguridad: tené a mano el medio donde llega.',
              'Puede pedir registrarte como desarrollador (Meta for Developers): aceptás las condiciones, completás el registro con la misma cuenta y seguís normal.',
            ],
            errores: [
              'Saltear la app e ir directo a verificar: sin app, Meta no muestra la opción de enviar la solicitud.',
            ],
            captura: [
              { src: 'assets/fb/f2-apps.png', cap: 'Configuración → Cuentas → Apps' },
            ],
          },
          {
            id: 'f3', tag: 'Fase 3', icon: '✅', title: 'Verificación del negocio',
            objetivo: 'Enviar la solicitud de verificación del Portfolio con los datos legales idénticos a ARCA. Meta tiene hasta 14 días hábiles para aprobar o rechazar.',
            pasos: [
              { text: 'Info del negocio → Verificación → “Ver detalles”.' },
              { text: 'Info legal EXACTA de ARCA.', tip: 'Un acento, un punto o “S.A.” vs “SA” = rechazo.' },
              { text: 'Documentación digital legible (Word/ATS).', tip: 'Nunca escaneada, foto ni manuscrita.' },
              { text: 'Footer de la web: razón social + nombre de fantasía (si difiere) + teléfono.', tip: 'Requisito para verificar (no para crear el portfolio). El footer debe coincidir con los datos legales de ARCA.' },
              { text: 'Tipo de negocio → “Sociedad unipersonal” si persona física.', tip: '¿Registrado oficialmente? → “Aún no registrado”.' },
              { text: 'Elegir método de verificación.', tip: 'Correo (dominio = web), teléfono, o metaetiqueta. Ver detalle abajo.' },
              { text: 'Web ideal: landing simple, sin carrito ni redirecciones.' },
              { text: 'Enviar solicitud + seguimiento diario.' },
            ],
            subproceso: {
              title: 'Si verificás por metaetiqueta',
              items: [
                'Configuración → Seguridad e idoneidad → Dominios → agregar → crear dominio. Escribí la web sin https:// (ej.: panchitos.com.ar).',
                'Meta genera <meta name="facebook-domain-verification" content="…" />. Va dentro del <head> de la home, nunca cargada por JavaScript.',
                'Si la web es del cliente, se la pasamos a su programador; si es landing nuestra, la agregamos nosotros.',
                'Publicá la página y volvé a Meta → “Verificar dominio”. Recién con el dominio verificado completás el formulario de solicitud.',
              ],
              captura: [
                { src: 'assets/fb/f3-dominios.png', cap: 'Seguridad e idoneidad → Dominios' },
                { src: 'assets/fb/f3-metaetiqueta.png', cap: 'Código de la metaetiqueta a pegar en el <head>' },
              ],
            },
            validacion: [
              { label: 'Correo de dominio', icon: '✉️', detalle: 'Un mail cuyo dominio coincida EXACTAMENTE con la web. Ej.: si la web es panchitos.com.ar, el correo debe ser algo@panchitos.com.ar.' },
              { label: 'Número telefónico', icon: '📱', detalle: 'Sirve si los registros del negocio coinciden con ese número. El cliente debe tener el celular a mano para recibir el código.' },
              { label: 'Metaetiqueta en la web', icon: '🏷️', detalle: 'Se agrega un código al HTML del sitio (detallado abajo). Es la opción cuando no hay mail de dominio ni teléfono que coincida.' },
            ],
            verificacionFallida: {
              title: 'Qué pasa si no se verifica',
              opciones: [
                {
                  titulo: 'Rechazo total',
                  icon: '❌',
                  items: [
                    'Meta rechaza la solicitud completa.',
                    'Revisar coherencia con ARCA punto por punto.',
                    'Corregir y reenviar.',
                  ],
                },
                {
                  titulo: 'Pide más información',
                  icon: '📩',
                  items: [
                    'Leer qué motivo dio Meta.',
                    'Revisar coherencia exacta con ARCA.',
                    'Confirmar documentación legible para ATS.',
                    'Corregir y reenviar lo antes posible.',
                  ],
                },
              ],
            },
            errores: [
              'Datos que no coinciden con ARCA: rechazo.',
              'Dominio del correo ≠ dominio de la web.',
              'Documentación no legible (escaneada, foto, manuscrita).',
              'Metaetiqueta fuera del <head> o cargada por JS.',
              'Dominio con https://: va sin protocolo.',
              'Web compleja (carrito, redirecciones): usar landing simple.',
            ],
            captura: [
              { src: 'assets/fb/f3-tipo-negocio.png', cap: 'Tipo de negocio → “Sociedad unipersonal”' },
              { src: 'assets/fb/f3-registrado.png', cap: '¿Registrado oficialmente? → “Aún no registrado”' },
            ],
          },
        ],
      },
    ],
  },
  {
    n: 2, label: 'Sesión 2', color: MA.ambar, title: 'Bot / Agente IA + Equipo', duration: '45–60 min',
    objetivo: 'El cliente ve y aprueba el bot / agente IA, y carga a su equipo. El bot / agente IA ya fue generado automáticamente entre la S1 y la S2 a partir de la sesión de ventas.',
    prereqsCliente: [
      'Conectarse desde computadora',
    ],
    prereqsActivador: [
      'Bot / Agente IA generado con el método de prueba',
      'Bot / Agente IA probado a fondo y mejorado',
    ],
    resultado: [
      'Bot / Agente IA probado por el cliente y aprobado',
      'Bot / Agente IA mejorado con el feedback del cliente',
      'Equipo cargado con roles asignados',
      'Sesión 3 agendada si el portfolio está verificado / listo',
    ],
    pasos: [
      {
        n: 2, name: 'Tu Bot / Agente IA y tu equipo', icon: '🤖', who: 'Cliente · Activador', corroborarVerif: true,
        subtitle: 'Prueba del bot / agente IA autogenerado y carga del equipo con sus roles',
        rol: 'Bot / Agente IA autogenerado desde la sesión de ventas. Vos lo probás antes con el método de prueba. El cliente lo recorre en el simulador, da feedback (queda en la transcripción), y una vez aprobado lo activás en producción y cargás al equipo.',
        acciones: [
          { icon: '🧪', title: 'Probá la vista previa del bot', desc: 'Primero entrá a la cuenta del cliente, probá el bot / agente IA generado con IA y hacé todas las mejoras necesarias antes de la sesión.' },
          { icon: '💬', title: 'Mostralo al cliente', desc: 'En la sesión, mostrale al cliente el bot / agente IA funcionando desde el simulador de WhatsApp del portal.' },
          { icon: '🕹️', title: 'El cliente lo prueba', desc: 'Dejá que el cliente recorra el bot / agente IA en el simulador como un usuario real, probando el flujo completo.' },
          { icon: '🎙️', title: 'Feedback grabado', desc: 'Registrá el feedback del cliente sobre el bot / agente IA; queda en la transcripción de la sesión para ajustarlo después de forma asincrónica.' },
          { icon: '👥', title: 'Cargá al equipo', desc: 'Cargá en Pip a cada integrante del equipo del cliente con su nombre, email y rol. Si la empresa es grande y cargaste un solo usuario, confirmá con el cliente si se suman más integrantes al equipo.' },
          { icon: '🔑', title: 'Explicá los roles', desc: 'Explicale al cliente qué hace cada rol: Supervisor ve todas las conversaciones; Audiencia ve solo los chats que tiene asignados.' },
          { icon: '🛠️', title: 'Ajustá con la transcripción', desc: 'Al final de la sesión 2 se genera la transcripción, que sirve como input para mejorar el bot / agente IA. Ajustalo con esa transcripción y dejalo activo en producción sobre el número real.' },
        ],
        errores: [
          'Llegar a la sesión sin haber probado el bot / agente IA: si tiene loops, el cliente lo nota.',
          'Decir “es el bot / agente IA definitivo”: después de activarlo se puede seguir editando.',
          'Roles sin asignar o mal asignados.',
          'No explicar roles con ejemplos concretos.',
        ],
        adicionales: {
          title: 'Tareas adicionales del Back (a demanda del cliente)',
          nota: 'Pueden surgir antes de la última sesión. Sin paso a paso por ahora — se resuelven según lo que pida el cliente.',
          items: ['Carga de contactos', 'Bots por pauta o condicionales', 'Integración vía webhooks o Dynamix'],
        },
      },
    ],
  },
  {
    n: 3, color: MA.turquesa, title: 'Capacitación', duration: '60 min en vivo',
    objetivo: 'Dejar al cliente operando Pip de forma autónoma. Es la sesión más visible: no enseñamos botones, enseñamos soluciones.',
    reglaOro: 'No enseñamos botones, enseñamos soluciones. Cada función que mostrás se ata a un dolor que el cliente validó en la Sesión 1. Si no resuelve un dolor, no se muestra.',
    prereqsCliente: [
      'Conectarse desde computadora',
      'Equipo operativo presente',
      'Acceso físico al celular y chip activo para recibir códigos',
      'Tarjeta de crédito/débito a mano',
      'Si es rubro sensible: verificación de Meta aprobada',
    ],
    prereqsActivador: [
      'Bot / Agente IA activo y testeado en Pip',
      'Usuarios creados con sus credenciales',
      'Revisar resumen de IA e identificar dolores a enfocar en la capacitación',
      'Revisar las notas del chat en Pip',
    ],
    resultado: [
      'Buenas prácticas repasadas y aceptadas',
      'Cliente operando la plataforma de forma autónoma',
      'Estado del cliente actualizado a “Activo” y derivado a Customer Service',
      'Seguimientos anticipados (día 1, 3 y 5 hábiles)',
    ],
    pasos: [
      {
        n: 3, name: 'Conexión a Pip', icon: '🔗', who: 'Cliente · Activador', registroInsertado: true,
        subtitle: 'Vincular el número de WhatsApp del cliente a Pip con registro insertado',
        rol: 'Con el Portfolio ya creado y verificado, vinculamos el número de WhatsApp del cliente a Pip mediante registro insertado. Elegí el procedimiento según el caso (Coexistencia o Cloud API) y seguí el paso a paso.',
        acciones: [
          { icon: '✅', title: 'Confirmá el portfolio', desc: 'Antes de vincular, asegurate de que el Portfolio esté creado, verificado y sin bloqueos.' },
          { icon: '🔀', title: 'Elegí el procedimiento', desc: 'Definí si el número va por Coexistencia (conecta la cuenta existente + QR) o Cloud API (crea una cuenta nueva). Usá los botones “Cómo vincular” de arriba.' },
          { icon: '📱', title: 'Vinculá el número', desc: 'Seguí el registro insertado desde el manager de Pip hasta que se abra la sesión con el número ya vinculado.', action: 'registro-coex', actionLabel: 'Ver el paso a paso del registro insertado' },
        ],
        errores: [
          'Vincular antes de tener el portfolio verificado.',
          'Elegir Cloud API cuando el cliente necesita mantener grupos, llamadas o estados.',
          'Coexistencia con un número sin al menos 3 días de uso.',
        ],
      },
      {
        n: 4, name: 'Capacitación', icon: '🎓', who: 'Activador · En vivo',
        subtitle: 'Sesión en vivo de 60 min con el equipo operativo',
        rol: 'Sesión en vivo de 60 min. Compartir pantalla, recorrer Pip y atar cada función a un dolor verificado en la S1.',
        checklistPrevio: {
          title: 'Antes de arrancar — checklist previo',
          items: ['Bot / Agente IA activo', 'Usuarios creados', 'Portfolio en orden', 'Equipo operativo presente'],
        },
        sensibles: {
          title: 'Tips para mencionar durante la capacitación',
          puntos: [
            'Para iniciar una conversación siempre necesita una plantilla aprobada por Meta, y rige la ventana de 24 hs.',
            'Iniciar conversaciones se cobra (~USD 0,06 por conversación). Es política de Meta y aplica con cualquier proveedor.',
            'No puede iniciar conversaciones hasta cargar el método de pago.',
            'Las conversaciones históricas no se migran a Pip.',
            'Debe mantener la línea activa para que la compañía no revenda el número.',
            'Si el número quedó integrado en Cloud API pura, no puede escribirle a Pip desde ese número: que use otra línea.',
          ],
        },
        acciones: [
          { icon: '📝', title: 'Creá plantillas', desc: 'Creá las plantillas de mensajes según las reglas de Meta: sin variables al inicio, bien categorizadas, sin links acortados y con opciones de OPT-IN / OPT-OUT. Asigná la categoría correcta a cada una; si Meta la rechaza por estar mal categorizada, corregí la categoría antes de reenviarla.' },
          { icon: '🧭', title: 'Recorré el panel', desc: 'Compartí pantalla y recorré el panel de Pip con el equipo: navegación, conversaciones, etiquetas y reportes.' },
          { icon: '🙋', title: 'Escalar y derivar', desc: 'Mostrales cómo intervenir en una conversación y derivarla sin romper la automatización del bot / agente IA.' },
          { icon: '📄', title: 'Plantillas en vivo', desc: 'Creá 2–3 plantillas en vivo usando un caso real del rubro del cliente.' },
          { icon: '🎯', title: 'Atá función a dolor', desc: '“¿Recuerdan que me dijeron [dolor]? Así se resuelve.”' },
          { icon: '🤝', title: 'Confirmá aceptación', desc: 'Confirmá que el cliente entendió y aceptó las reglas de uso.' },
          { icon: '📆', title: 'Cerrá y anticipá', desc: 'Cerrá la capacitación anunciando que se realizará un breve seguimiento y que luego se relevará la atención a la mesa de ayuda, anunciando que la capacitación ha sido concluida.' },
        ],
        errores: [
          'Variable al inicio de plantilla: Meta la rechaza.',
          'Reenviar plantilla mal categorizada sin corregir.',
          'Links acortados: Meta los penaliza.',
          'Improvisar sin bot / agente IA, usuarios o portfolio: reagendá.',
          'Tour de funciones sin atar a dolores.',
          'Cerrar sin revalidar dolores ni anticipar seguimientos.',
        ],
        pasarActivo: {
          title: 'Pasar a cliente Activo',
          desc: 'Con la capacitación concluida, arrastrá la tarea del cliente en MeisterTask hacia la columna “Capacitado”.',
        },
      },
    ],
  },
  {
    n: 4, label: 'Post', color: '#8b5cf6', title: 'Seguimiento', duration: 'Días 1, 3 y 5 hábiles',
    objetivo: 'Que el cliente se comprometa con Pip. Acompañarlo para que descubra el valor y lo integre a su operación.',
    prereqsActivador: [
      'Cliente activado',
      'Bot / Agente IA activo y funcionando en producción',
      'Usuarios creados con sus credenciales',
    ],
    resultado: [
      'Cliente comprometido y usando Pip activamente',
      'Seguimientos día 1, 3 y 5 completados',
      'Dudas resueltas antes de que escalen',
      'Cliente autónomo, entiende el valor del sistema',
    ],
    pasos: [
      {
        n: 5, name: 'Seguimiento', icon: '📡', who: 'Activador',
        subtitle: 'Compromiso del cliente + acompañamiento días 1, 3 y 5',
        rol: 'Tu objetivo: que el cliente se COMPROMETA con Pip y lo integre a su día a día. Cuanto antes descubre el valor y aprende a usarlo, más fuerte es su adopción. El seguimiento temprano no es un control: es acompañamiento para que aproveche todo el potencial.',
        pasoNota: 'Agendá los seguimientos para los días 1, 3 y 5 hábiles (no al azar). En cada uno repetís este mismo paso a paso: revisás estos puntos con el cliente.',
        acciones: [
          { icon: '✅', title: '¿Está usando Pip?', desc: 'En cada seguimiento, verificá que el cliente esté usando Pip de verdad, no que solo figure como activo.' },
          { icon: '💬', title: '¿Responde desde Pip?', desc: 'Confirmá que el cliente responde los mensajes desde Pip y no desde el celular directamente.' },
          { icon: '🏷️', title: '¿Usa etiquetas?', desc: 'Chequeá que esté clasificando las conversaciones con etiquetas correctamente.' },
          { icon: '📄', title: '¿Usa plantillas?', desc: 'Verificá que envíe plantillas aprobadas por Meta y no mensajes sueltos.' },
          { icon: '🤖', title: '¿Bot / Agente IA activo?', desc: 'Verificá que el bot / agente IA siga funcionando en producción sin problemas.' },
          { icon: '❓', title: '¿Tiene dudas?', desc: 'Preguntale si tiene dudas y ayudalo a resolverlas en el momento. No esperes a que pregunte.' },
        ],
        sensibles: {
          title: 'Filosofía del seguimiento',
          regla: 'No es un control al cliente. Es acompañamiento para que descubra el valor y lo integre a su operación.',
          puntos: ['La adopción crece cuando el cliente entiende el valor', 'El seguimiento temprano define qué tan fuerte es la adopción', 'Si no sabe usar algo, enseñale', 'No esperar a que pregunte: ser proactivo, no reactivo', 'Cada contacto es una oportunidad de valor'],
        },
        errores: [
          'Asumir que “activo” = usando.',
          'Dejar seguimientos al azar sin agendar.',
          'No contactar si no responde desde Pip.',
          'Saltear día 5: confirma autonomía.',
          'Tratar el seguimiento como control y no como ayuda.',
        ],
      },
    ],
  },
];

// Lista plana de pasos para navegación
const FLAT = [];
REUNIONES.forEach((r) => r.pasos.forEach((p) => FLAT.push({ ...p, reunion: r })));

// ─────────────────────────────────────────────────────────────
// STEPPER
// ─────────────────────────────────────────────────────────────
function Stepper({ current, onStepClick }) {
  return (
    <div style={{ padding: '16px 16px 20px', overflowX: 'auto' }}>
      {/* Etiquetas de sesión */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minWidth: 860, marginBottom: 10 }}>
        {REUNIONES.map((r, ri) => {
          const stepW = 84, connW = 30;
          const totalW = r.pasos.length * stepW + (r.pasos.length - 1) * connW;
          return (
            <React.Fragment key={ri}>
              {ri > 0 && <div style={{ width: 44, flexShrink: 0 }}></div>}
              <div style={{ width: totalW, display: 'flex', justifyContent: 'center', flexShrink: 0 }}>
                <div style={{
                  fontSize: 10, fontWeight: 800, letterSpacing: '.1em', textTransform: 'uppercase',
                  color: r.color, border: '1.5px solid ' + r.color, padding: '3px 14px', borderRadius: 99,
                  whiteSpace: 'nowrap',
                }}>{r.label || ('Sesión ' + r.n)}</div>
              </div>
            </React.Fragment>
          );
        })}
      </div>
      {/* Pasos */}
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'center', minWidth: 860 }}>
        {FLAT.map((p, idx) => {
          const active = idx === current;
          const color = p.reunion.color;
          const isReunionStart = idx > 0 && p.reunion.pasos[0].n === p.n;
          const visited = idx <= current;
          return (
            <React.Fragment key={idx}>
              {idx > 0 && (
                <div style={{ display: 'flex', alignItems: 'center', paddingTop: 15 }}>
                  {isReunionStart ? (
                    <div style={{ width: 38, borderTop: '2.5px dashed ' + (visited ? color : '#d1d5db90'), margin: '0 4px' }}></div>
                  ) : (
                    <div style={{ width: 30, height: 2.5, background: visited ? color : '#e5e7eb', borderRadius: 2 }}></div>
                  )}
                </div>
              )}
              <div onClick={() => onStepClick(idx)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', cursor: 'pointer', minWidth: 84 }}>
                <div style={{
                  width: 36, height: 36, borderRadius: '50%',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  background: active ? color : '#fff',
                  color: active ? '#fff' : (visited ? color : '#9ca3af'),
                  border: active ? 'none' : '2px solid ' + (visited ? color + '55' : '#e5e7eb'),
                  fontSize: 14, fontWeight: 800, transition: 'all .2s',
                  boxShadow: active ? '0 0 0 4px ' + color + '22' : 'none',
                }}>{p.n}</div>
                <span style={{
                  fontSize: 10.5, fontWeight: active ? 800 : 600,
                  color: active ? color : (visited ? MA.inkMid : '#9ca3af'),
                  marginTop: 6, textAlign: 'center', lineHeight: 1.2, maxWidth: 90,
                }}>{p.name}</span>
              </div>
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// SIDEBAR DE REUNIÓN — pre-requisitos + resultado esperado
// ─────────────────────────────────────────────────────────────
function ReunionAside({ r }) {
  const checkIcon = (
    <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={r.color} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0, marginTop: 3 }}><path d="M20 6L9 17l-5-5"></path></svg>
  );
  const dot = (
    <span style={{ width: 6, height: 6, borderRadius: '50%', background: r.color, flexShrink: 0, marginTop: 6 }}></span>
  );

  function Block({ title, items, mark }) {
    return (
      <div style={{ marginBottom: 18 }}>
        <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: MA.inkDim, marginBottom: 9 }}>{title}</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 11 }}>
          {items.map((it, i) => (
            <div key={i} style={{ display: 'flex', gap: 9, alignItems: 'flex-start', fontSize: 12.5, color: MA.inkMid, lineHeight: 1.4 }}>
              {mark === 'check' ? checkIcon : dot}<span>{it}</span>
            </div>
          ))}
        </div>
      </div>
    );
  }

  return (
    <aside style={{ width: 300, flexShrink: 0 }}>
      <div style={{ position: 'sticky', top: 150 }}>
        <div style={{ background: '#fff', border: '1px solid ' + MA.border, borderTop: '4px solid ' + r.color, borderRadius: 14, padding: '20px 22px', boxShadow: '0 1px 3px #0001' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
            <span style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: r.color, background: r.color + '18', padding: '3px 10px', borderRadius: 99 }}>{r.label || ('Sesión ' + r.n)}</span>
            <span style={{ fontSize: 12, fontWeight: 600, color: MA.inkDim }}>{r.duration}</span>
          </div>
          <div style={{ fontSize: 17, fontWeight: 800, fontStyle: 'italic', color: MA.ink, marginBottom: 8, lineHeight: 1.15 }}>{r.title}</div>
          <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.55, marginBottom: 18 }}>{r.objetivo}</p>

          {r.disparador && (
            <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start', background: r.color + '12', border: '1px solid ' + r.color + '33', borderRadius: 10, padding: '12px 14px', marginBottom: 18 }}>
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke={r.color} strokeWidth="2.5" strokeLinecap="round" style={{ flexShrink: 0, marginTop: 1 }}><rect x="3" y="4" width="18" height="18" rx="2"></rect><path d="M16 2v4M8 2v4M3 10h18"></path></svg>
              <div>
                <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: r.color, marginBottom: 3 }}>Cuándo ocurre</div>
                <p style={{ fontSize: 12, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>{r.disparador}</p>
              </div>
            </div>
          )}

          {r.prereqsCliente && <Block title="Pre-requisitos del cliente" items={r.prereqsCliente} mark="dot" />}
          {r.prereqsActivador && <Block title="Pre-requisitos del activador" items={r.prereqsActivador} mark="dot" />}
          <div style={{ height: 1, background: MA.border, margin: '4px 0 18px' }}></div>
          <Block title="Resultado esperado al cierre" items={r.resultado} mark="check" />
        </div>

        {r.tiempos && (
          <div style={{ marginTop: 14, background: '#fff', border: '1px solid ' + MA.border, borderRadius: 14, padding: '16px 18px', boxShadow: '0 1px 3px #0001' }}>
            <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: MA.inkDim, marginBottom: 10, display: 'flex', alignItems: 'center', gap: 6 }}>
              <span>⏱️</span> Tiempos clave
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 9 }}>
              {r.tiempos.map((t, i) => (
                <div key={i} style={{ display: 'flex', gap: 9, alignItems: 'flex-start', fontSize: 12.5, color: MA.inkMid, lineHeight: 1.4 }}>
                  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={r.color} strokeWidth="2.5" strokeLinecap="round" style={{ flexShrink: 0, marginTop: 3 }}><circle cx="12" cy="12" r="10"></circle><path d="M12 6v6l4 2"></path></svg>
                  <span>{t}</span>
                </div>
              ))}
            </div>
          </div>
        )}

        {r.reglaOro && (
          <div style={{ marginTop: 14, background: r.color + '12', border: '1px solid ' + r.color + '40', borderRadius: 14, padding: '16px 18px' }}>
            <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: r.color, marginBottom: 7, display: 'flex', alignItems: 'center', gap: 6 }}>
              <span>🎯</span> Regla de oro
            </div>
            <p style={{ fontSize: 12.5, color: MA.ink, lineHeight: 1.55, margin: 0 }}>{r.reglaOro}</p>
          </div>
        )}
      </div>
    </aside>
  );
}

// ─────────────────────────────────────────────────────────────
// PLACEHOLDER DE CAPTURA
// ─────────────────────────────────────────────────────────────
function CapturaSlot({ items, onZoom }) {
  const list = Array.isArray(items) ? items : [{ cap: items }];
  const hasImg = list.some((it) => it && it.src);
  if (!hasImg) {
    // Fallback: placeholders de texto
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {list.map((it, i) => (
          <div key={i} style={{ borderRadius: 10, border: '1px dashed ' + MA.border, background: 'repeating-linear-gradient(45deg, #f8f9fc, #f8f9fc 10px, #f2f4f9 10px, #f2f4f9 20px)', padding: '13px 16px', display: 'flex', alignItems: 'center', gap: 12 }}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={MA.inkDim} strokeWidth="2" strokeLinecap="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle></svg>
            <div style={{ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', fontSize: 11.5, color: MA.inkDim, lineHeight: 1.4 }}>Captura — {it.cap}</div>
          </div>
        ))}
      </div>
    );
  }
  const res = (window.__resources) || {};
  return (
    <div style={{ display: 'grid', gridTemplateColumns: list.length > 1 ? 'repeat(auto-fit, minmax(180px, 1fr))' : '1fr', gap: 12 }}>
      {list.map((it, i) => {
        const src = (it.src && res[it.src]) || it.src;
        return (
          <figure key={i} style={{ margin: 0 }}>
            <button onClick={() => onZoom && onZoom(src, it.cap)} title="Ampliar" style={{ display: 'block', width: '100%', padding: 0, border: '1px solid ' + MA.border, borderRadius: 12, overflow: 'hidden', background: '#fff', cursor: 'zoom-in', boxShadow: '0 1px 3px #0001' }}>
              <img src={src} alt={it.cap} loading="lazy" style={{ display: 'block', width: '100%', height: 'auto' }} />
            </button>
            <figcaption style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 7, fontSize: 11.5, color: MA.inkDim, lineHeight: 1.4 }}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={MA.inkDim} strokeWidth="2" strokeLinecap="round" style={{ flexShrink: 0 }}><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle></svg>
              <span>{it.cap}</span>
            </figcaption>
          </figure>
        );
      })}
    </div>
  );
}

// Lightbox para ampliar capturas
function Lightbox({ data, onClose }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);
  if (!data) return null;
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 1000, background: 'rgba(10,21,37,.82)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 32, cursor: 'zoom-out', backdropFilter: 'blur(2px)' }}>
      <div onClick={(e) => e.stopPropagation()} style={{ maxWidth: 'min(1000px, 92vw)', maxHeight: '90vh', display: 'flex', flexDirection: 'column', cursor: 'default' }}>
        <img src={data.src} alt={data.cap} style={{ maxWidth: '100%', maxHeight: '82vh', objectFit: 'contain', borderRadius: 12, boxShadow: '0 20px 60px #0008' }} />
        {data.cap && <div style={{ color: '#fff', fontSize: 13, marginTop: 14, textAlign: 'center', opacity: .9 }}>{data.cap}</div>}
      </div>
      <button onClick={onClose} aria-label="Cerrar" style={{ position: 'fixed', top: 20, right: 24, width: 40, height: 40, borderRadius: '50%', background: '#ffffff22', border: '1px solid #ffffff44', color: '#fff', cursor: 'pointer', fontSize: 20, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>✕</button>
    </div>
  );
}

const pMod = { fontSize: 13, color: MA.inkMid, lineHeight: 1.55, margin: 0 };
const numDot = { width: 20, height: 20, borderRadius: '50%', background: MA.azul, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, fontWeight: 800, flexShrink: 0, marginTop: 1 };

// ─────────────────────────────────────────────────────────────
// STEPS MODAL — ventana emergente genérica con pasos numerados
// (config: eyebrow, title, intro, steps[{t, body:(h)=>JSX}])
// ─────────────────────────────────────────────────────────────
function StepsModal({ open, onClose, onZoom, eyebrow, title, intro, steps }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    if (open) window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);
  if (!open) return null;

  const res = (window.__resources) || {};
  const img = (p) => (res[p] || p);
  const A = MA.azul;

  const Shot = ({ src, cap }) => (
    <figure style={{ margin: '12px 0 0' }}>
      <button onClick={() => onZoom && onZoom(img(src), cap)} title="Ampliar" style={{ display: 'block', width: '100%', padding: 0, border: '1px solid ' + MA.border, borderRadius: 10, overflow: 'hidden', background: '#fff', cursor: 'zoom-in' }}>
        <img src={img(src)} alt={cap} loading="lazy" style={{ display: 'block', width: '100%', height: 'auto' }} />
      </button>
      <figcaption style={{ fontSize: 11, color: MA.inkDim, marginTop: 6, lineHeight: 1.4 }}>{cap}</figcaption>
    </figure>
  );

  const LinkChip = ({ href, label, sub }) => (
    <a href={href} target="_blank" rel="noopener noreferrer" style={{ display: 'flex', alignItems: 'center', gap: 10, textDecoration: 'none', background: '#f6f7fc', border: '1px solid ' + MA.border, borderRadius: 10, padding: '10px 13px', marginTop: 10 }}>
      <span style={{ width: 30, height: 30, borderRadius: 8, background: A + '15', color: A, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
        <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.3" strokeLinecap="round" strokeLinejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
      </span>
      <span style={{ flex: 1, minWidth: 0 }}>
        <span style={{ display: 'block', fontSize: 12.5, fontWeight: 800, color: A }}>{label}</span>
        {sub && <span style={{ display: 'block', fontSize: 11, color: MA.inkDim, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{sub}</span>}
      </span>
      <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke={MA.inkDim} strokeWidth="2.3" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}><path d="M7 17L17 7M7 7h10v10"></path></svg>
    </a>
  );

  const Cuenta = ({ children }) => (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: '#eef1fe', color: A, fontWeight: 700, fontSize: 12, padding: '1px 7px', borderRadius: 6, fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace' }}>{children}</span>
  );

  const Check = ({ items }) => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 12 }}>
      {items.map((c, k) => (
        <div key={k} style={{ display: 'flex', gap: 10, alignItems: 'flex-start', background: c.ok ? '#f0fdf9' : '#fef2f2', border: '1px solid ' + (c.ok ? '#a7f3d0' : '#fecaca'), borderRadius: 9, padding: '10px 13px' }}>
          <span style={{ width: 20, height: 20, borderRadius: '50%', background: c.ok ? MA.turquesa : MA.danger, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 12, fontWeight: 800, flexShrink: 0, marginTop: 1 }}>{c.ok ? '✓' : '✕'}</span>
          <p style={{ fontSize: 12.5, color: c.ok ? '#065f46' : '#7f1d1d', lineHeight: 1.5, margin: 0 }}>{c.txt}</p>
        </div>
      ))}
    </div>
  );

  const Tip = ({ children }) => (
    <div style={{ display: 'flex', gap: 9, alignItems: 'flex-start', background: '#eff6ff', border: '1px solid #bfdbfe', borderRadius: 9, padding: '10px 13px', marginTop: 12 }}>
      <span style={{ fontSize: 13, flexShrink: 0 }}>💡</span>
      <p style={{ fontSize: 12, color: '#1e3a8a', lineHeight: 1.5, margin: 0 }}>{children}</p>
    </div>
  );

  const h = { Shot, LinkChip, Cuenta, Check, Tip, pMod, numDot, A };

  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 1000, background: 'rgba(10,21,37,.6)', backdropFilter: 'blur(3px)', display: 'flex', alignItems: 'flex-start', justifyContent: 'center', padding: '5vh 20px', overflowY: 'auto' }}>
      <div onClick={(e) => e.stopPropagation()} className="landing-modal" style={{ width: 'min(620px, 100%)', background: '#fff', borderRadius: 20, boxShadow: '0 24px 70px #0007', overflow: 'hidden', marginBottom: 40 }}>
        {/* Header */}
        <div style={{ position: 'sticky', top: 0, background: MA.azul, padding: '20px 24px', display: 'flex', alignItems: 'center', gap: 14, zIndex: 2 }}>
          <div style={{ width: 44, height: 44, borderRadius: 12, background: '#ffffff22', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><path d="M3 9h18M9 21V9"></path></svg>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: '#ffffffbb' }}>{eyebrow}</div>
            <div style={{ fontSize: 20, fontWeight: 800, fontStyle: 'italic', color: '#fff', lineHeight: 1.1 }}>{title}</div>
          </div>
          <button onClick={onClose} aria-label="Cerrar" style={{ width: 34, height: 34, borderRadius: '50%', background: '#ffffff22', border: '1px solid #ffffff33', color: '#fff', cursor: 'pointer', fontSize: 17, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>✕</button>
        </div>

        {/* Body */}
        <div style={{ padding: '24px 24px 28px' }}>
          {intro && <p style={{ fontSize: 13.5, color: MA.inkMid, lineHeight: 1.55, margin: '0 0 22px' }}>{intro}</p>}
          <div style={{ position: 'relative', paddingLeft: 6 }}>
            {steps.map((s, k) => (
              <div key={k} style={{ position: 'relative', paddingLeft: 40, paddingBottom: k < steps.length - 1 ? 24 : 0 }}>
                {k < steps.length - 1 && <span style={{ position: 'absolute', left: 15, top: 30, bottom: 0, width: 2, background: '#e9ebf3' }}></span>}
                <span style={{ position: 'absolute', left: 0, top: 0, width: 32, height: 32, borderRadius: '50%', background: A, color: '#fff', fontSize: 14, fontWeight: 800, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{k + 1}</span>
                <div style={{ fontSize: 15.5, fontWeight: 800, color: MA.ink, lineHeight: 1.2, paddingTop: 5, marginBottom: 4 }}>{s.t}</div>
                {typeof s.body === 'function' ? s.body(h) : s.body}
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Config: Cómo crear una landing en GrapesJS ──
const LANDING_STEPS = [
  { t: 'Ingresá a GrapesJS', body: (h) => (
    <div>
      <p style={pMod}>Entrá a la plataforma e iniciá sesión con Google desde la cuenta de soporte.</p>
      <h.LinkChip href="https://app.grapesjs.com/dashboard" label="app.grapesjs.com/dashboard" />
      <p style={{ ...pMod, marginTop: 10 }}>Cuenta de acceso: <h.Cuenta>support@fintechesolutions.io</h.Cuenta></p>
      <h.Shot src="assets/landing/grapes-dashboard.png" cap="Dashboard de proyectos de GrapesJS" />
    </div>
  ) },
  { t: 'Creá un nuevo proyecto', body: (h) => (
    <div>
      <p style={pMod}>Clic en <b>“Create new project”</b>. Se abre una ventana que pide un <b>nombre</b> y un <b>prompt</b>.</p>
      <p style={{ ...pMod, marginTop: 8 }}>En <b>Project Name</b> poné el nombre de la cuenta del cliente.</p>
      <h.Shot src="assets/landing/grapes-new-project.png" cap="Ventana “New Project”: nombre + prompt" />
    </div>
  ) },
  { t: 'Generá el prompt con Claude', body: (h) => (
    <div>
      <p style={pMod}>El prompt lo generamos con el proyecto de Claude <b>“Landings”</b>, que arma el prompt para GrapesJS.</p>
      <h.LinkChip href="https://claude.ai/project/019e88f9-51ca-7666-8312-471bc734994e" label="Proyecto Claude — Landings" sub="Generador de prompts para GrapesJS" />
      <p style={{ ...pMod, marginTop: 10 }}>Se accede desde la cuenta <h.Cuenta>team@fintechsolutions.io</h.Cuenta></p>
      <h.Tip>Alimentá a Claude con información básica de la empresa <b>o</b> con el resumen de la transcripción de la sesión de ventas.</h.Tip>
      <h.Shot src="assets/landing/claude-landings.png" cap="Proyecto “Landings” en Claude" />
    </div>
  ) },
  { t: 'Creá el proyecto y esperá', body: (h) => (
    <div>
      <p style={pMod}>Pegá el prompt generado en GrapesJS y dale <b>“Create Project”</b>. Tarda algunos minutos en generarse; después vas a poder visualizar la página creada.</p>
    </div>
  ) },
  { t: 'Verificá los requisitos de Meta', body: (h) => (
    <div>
      <p style={pMod}>Revisá que la página generada cumpla con lo que Meta exige:</p>
      <h.Check items={[
        { ok: true, txt: 'Razón social cargada en el footer.' },
        { ok: false, txt: 'Sin botones, carritos ni redireccionamientos que no lleven a ningún lado.' },
        { ok: true, txt: 'Único redireccionamiento permitido: un botón de WhatsApp tipo wa.me con el número del cliente.' },
      ]} />
    </div>
  ) },
  { t: 'Cargá metaetiqueta y dominio', body: (h) => (
    <div>
      <p style={pMod}>Con la landing verificada:</p>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 9, marginTop: 10 }}>
        <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
          <span style={numDot}>1</span>
          <p style={pMod}>Pegá la <b>metaetiqueta</b> (la obtenés desde el Portfolio Comercial) en el <b>header</b> del código de la landing.</p>
        </div>
        <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
          <span style={numDot}>2</span>
          <p style={pMod}>Editá el <b>dominio</b> de la landing para que quede con esta forma:</p>
        </div>
      </div>
      <div style={{ marginTop: 12, background: MA.ink, borderRadius: 10, padding: '13px 16px', fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', fontSize: 13.5, color: '#8be9d4', textAlign: 'center' }}>
        {'{nombre del cliente}'}<span style={{ color: '#fff' }}>.guia-local.com</span>
      </div>
    </div>
  ) },
  { t: 'Landing lista', body: (h) => (
    <div>
      <p style={pMod}>Con todo cargado, la página queda <b>habilitada y lista</b> para ser cargada en el Portfolio Comercial. 🎉</p>
    </div>
  ) },
];

function LandingModal({ open, onClose, onZoom }) {
  return <StepsModal open={open} onClose={onClose} onZoom={onZoom}
    eyebrow="Verificación · si el cliente no tiene web" title="Cómo crear una landing"
    intro={<span>Cuando el cliente no dispone de un sitio web, le creamos una landing con <b>GrapesJS</b>. Seguí estos pasos:</span>}
    steps={LANDING_STEPS} />;
}

// ── Config: Crear un Portfolio Comercial ──
const PORTFOLIO_MODAL_STEPS = [
  { t: 'Iniciá sesión y abrí Meta Business Suite', body: (h) => (
    <div>
      <p style={pMod}>Con la <b>mejor cuenta disponible</b> (Facebook del negocio → personal → Instagram; si no hay ninguna, creá una), entrá a <b>business.facebook.com</b>.</p>
      <h.LinkChip href="https://business.facebook.com" label="Meta Business Suite" sub="business.facebook.com" />
    </div>
  ) },
  { t: 'Abrí el selector de portfolios', body: (h) => (
    <div>
      <p style={pMod}>Arriba a la izquierda, clic en el <b>selector de portfolios</b> y luego en <b>“Crear un portfolio comercial”</b>.</p>
      <h.Shot src="assets/fb/f1-portfolio-crear.png" cap="Selector de portfolios → “Crear un portfolio comercial”" />
    </div>
  ) },
  { t: 'Completá los datos del negocio', body: (h) => (
    <div>
      <p style={pMod}>Cargá la información de contacto <b>idéntica a ARCA</b>:</p>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 9, marginTop: 10 }}>
        <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}><span style={numDot}>1</span><p style={pMod}><b>Nombre del portfolio:</b> razón social, sin nombre de fantasía, emojis ni MAYÚSCULAS.</p></div>
        <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}><span style={numDot}>2</span><p style={pMod}><b>Nombre y apellido de contacto</b> + <b>correo electrónico del negocio</b>.</p></div>
      </div>
      <h.Shot src="assets/fb/f1-portfolio-form.png" cap="Formulario de creación del portfolio" />
      <h.Tip>Un acento o una coma que no coincida con ARCA hace que Meta rechace la verificación. Copiá los datos textuales.</h.Tip>
    </div>
  ) },
  { t: 'Confirmá y activá la seguridad', body: (h) => (
    <div>
      <p style={pMod}>Clic en <b>“Crear”</b>. Con el portfolio ya creado, activá la <b>verificación en dos pasos</b> y revisá que todas las secciones queden sin bloqueos.</p>
      <h.Tip>La web/footer no es necesaria para crear el portfolio — se necesita recién para verificarlo. Si el cliente no tiene, se crea una landing en los pasos siguientes.</h.Tip>
    </div>
  ) },
];

function PortfolioModal({ open, onClose, onZoom }) {
  return <StepsModal open={open} onClose={onClose} onZoom={onZoom}
    eyebrow="Facebook · Fase 1" title="Cómo crear un Portfolio Comercial"
    intro={<span>Cuando el negocio todavía no tiene Portfolio, lo creamos junto al cliente desde <b>Meta Business Suite</b>. Seguí estos pasos:</span>}
    steps={PORTFOLIO_MODAL_STEPS} />;
}

// ── Config: Vincular el número a Pip con registro insertado ──
// Los pasos son casi iguales para Coexistencia y Cloud API; cambian el paso de
// activos (conectar vs crear la cuenta de WhatsApp) y el escaneo de QR (solo coex).
function makeRegistroSteps(variant) {
  const isCoex = variant === 'coex';
  const steps = [
    { t: 'Iniciá el registro insertado', body: (h) => (
      <div>
        <p style={pMod}>Desde el <b>manager de Pip</b>, ingresá con <b>registro insertado</b> a Meta para vincular la cuenta del cliente. Clic en <b>“Login with Facebook”</b>.</p>
        <h.Tip>Asegurate de tener la sesión de Facebook iniciada y de aceptar todos los permisos que se soliciten durante el proceso.</h.Tip>
        <h.Shot src="assets/registro/1-login-fb.png" cap="Inicio de sesión con Facebook desde Pip" />
      </div>
    ) },
    { t: 'Conectá la cuenta con Pip', body: (h) => (
      <div>
        <p style={pMod}>Se abre el asistente de Meta <b>“Conecta tu cuenta fácilmente con Pip”</b>. Leé el detalle y clic en <b>“Continuar”</b>.</p>
        <h.Shot src="assets/registro/2-continuar.png" cap="Asistente de conexión de Meta — Continuar" />
      </div>
    ) },
    { t: 'Seleccioná los activos comerciales', body: (h) => (
      <div>
        <p style={pMod}>Elegí el <b>Portfolio comercial</b> del cliente. En <b>Cuenta de WhatsApp Business</b> está la diferencia clave según el procedimiento:</p>
        {isCoex ? (
          <p style={pMod}>Como es <b>Coexistencia</b>, seleccioná <b>“Conecta una cuenta de WhatsApp Business”</b> (la línea que el cliente ya usa en su celular).</p>
        ) : (
          <p style={pMod}>Como es <b>Cloud API</b>, seleccioná <b>“Crea una cuenta de WhatsApp Business”</b> (al crearla, aceptás las Condiciones de Meta para WhatsApp Business).</p>
        )}
        <h.Shot src={isCoex ? 'assets/registro/3-activos-coex.png' : 'assets/registro/3-activos-cloud.png'} cap={isCoex ? 'Coexistencia — “Conecta una cuenta de WhatsApp Business”' : 'Cloud API — “Crea una cuenta de WhatsApp Business”'} />
      </div>
    ) },
    { t: 'Completá la información comercial', body: (h) => (
      <div>
        <p style={pMod}>Cargá los datos que va pidiendo Meta:</p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 9, marginTop: 10 }}>
          <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}><span style={numDot}>1</span><p style={pMod}><b>Categoría:</b> debe corresponder con la asociada a la empresa.</p></div>
          <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}><span style={numDot}>2</span><p style={pMod}><b>Zona horaria:</b> seleccioná la del cliente (ej. GMT-03:00 Buenos Aires).</p></div>
        </div>
        <h.Shot src="assets/registro/4-info-comercial.png" cap="Nombre, categoría, país, sitio web y zona horaria" />
      </div>
    ) },
    { t: 'Agregá el número de teléfono', body: (h) => (
      <div>
        <p style={pMod}>Elegí <b>“Agregar un número nuevo”</b>, ingresá el <b>número a vincular</b> y el nombre visible, y seleccioná cómo verificarlo (mensaje de texto o llamada).</p>
        <h.Shot src="assets/registro/5-numero.png" cap="Alta del número de teléfono de WhatsApp" />
      </div>
    ) },
  ];
  if (isCoex) {
    steps.push({ t: 'El cliente escanea el QR', body: (h) => (
      <div>
        <p style={pMod}>Exclusivo de <b>Coexistencia</b>: se hará visible un <b>código QR</b> que el <b>cliente deberá escanear</b> con su WhatsApp para confirmar la vinculación.</p>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginTop: 12, background: '#f6f7fc', border: '1px solid ' + MA.border, borderRadius: 12, padding: '14px 16px' }}>
          <div style={{ width: 54, height: 54, borderRadius: 12, background: '#fff', border: '1px solid ' + MA.border, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={MA.ink} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect><path d="M14 14h3v3h-3zM21 14v7M14 21h7"></path></svg>
          </div>
          <p style={{ ...pMod, fontSize: 12.5 }}>Desde el celular del cliente: <b>WhatsApp → Dispositivos vinculados → Vincular un dispositivo</b> y escanear el QR en pantalla.</p>
        </div>
      </div>
    ) });
  }
  steps.push({ t: 'Se abre la sesión en Pip', body: (h) => (
    <div>
      <p style={pMod}>Seguí a la <b>última etapa</b>. Se <b>abre la sesión en Pip</b> con el número ya vinculado y podés <b>arrancar con la capacitación</b>. 🎉</p>
    </div>
  ) });
  return steps;
}

const REGISTRO_VARIANTS = {
  coex: {
    label: 'Coexistencia',
    title: 'Vincular el número — Coexistencia',
    intro: <span>Vinculamos el número a Pip por <b>Coexistencia</b>: el cliente <b>conecta</b> su cuenta de WhatsApp Business existente y confirma escaneando un QR. Seguí estos pasos:</span>,
  },
  cloud: {
    label: 'Cloud API',
    title: 'Vincular el número — Cloud API',
    intro: <span>Vinculamos el número a Pip por <b>Cloud API</b>: se <b>crea</b> una nueva cuenta de WhatsApp Business (sin escaneo de QR). Seguí estos pasos:</span>,
  },
};

function RegistroModal({ variant, onClose, onZoom }) {
  const v = REGISTRO_VARIANTS[variant] || REGISTRO_VARIANTS.coex;
  return <StepsModal open={!!variant} onClose={onClose} onZoom={onZoom}
    eyebrow="Paso 4 · antes de capacitar" title={v.title}
    intro={v.intro}
    steps={makeRegistroSteps(variant)} />;
}

// ── Config: Dar de alta el cliente en el manager (CRM Alta) ──
const ALTA_STEPS = [
  { t: 'Entrá a Gestión de Clientes', body: (h) => (
    <div>
      <p style={pMod}>En el manager de Pip, abrí <b>Clientes → Gestión</b> y clic en <b>“Nuevo Cliente”</b>.</p>
      <h.LinkChip href="https://manager.rack01.pip.com.ar/dashboards/providers" label="Gestión de Clientes" sub="manager.rack01.pip.com.ar" />
    </div>
  ) },
  { t: 'Elegí la pestaña “CRM Alta”', body: (h) => (
    <div>
      <p style={pMod}>En la ventana <b>“Crear Cliente”</b> dejá seleccionada la pestaña <b>“CRM Alta”</b> (no “Manual”): así el alta queda vinculada al contrato del CRM.</p>
      <h.Shot src="assets/manager/alta-crear-cliente.png" cap="Ventana “Crear Cliente” — pestaña CRM Alta" />
    </div>
  ) },
  { t: 'Seleccioná el contrato del CRM', body: (h) => (
    <div>
      <p style={pMod}>En <b>“CRM Contract”</b> elegí el contrato del cliente. Este es el paso que <b>vincula el alta con el contrato</b> en el CRM.</p>
    </div>
  ) },
  { t: 'Cargá el slug', body: (h) => (
    <div>
      <p style={pMod}>El <b>slug</b> es el <b>nombre único</b> que tendrá la cuenta del cliente dentro de Pip.</p>
      <p style={pMod}>Asignalo correctamente: usá el <b>mismo nombre que en el CRM</b> y, si tiene espacios, reemplazalos por un <b>guion bajo</b>. Ej.: <b>Distribuidora Sur</b> → <b>Distribuidora_Sur</b>.</p>
    </div>
  ) },
  { t: 'Elegí el rack y guardá', body: (h) => (
    <div>
      <p style={pMod}>Seleccioná el <b>Rack</b> correspondiente y clic en <b>“Guardar”</b>. El cliente queda dado de alta y se genera el resumen de la sesión de ventas. 🎉</p>
    </div>
  ) },
];

function AltaModal({ open, onClose, onZoom }) {
  return <StepsModal open={open} onClose={onClose} onZoom={onZoom}
    eyebrow="Paso previo · manager" title="Dar de alta el cliente"
    intro={<span>Damos de alta al cliente en el manager con <b>CRM Alta</b>, que lo vincula al contrato del CRM. Seguí estos pasos:</span>}
    steps={ALTA_STEPS} />;
}

// ── Portal de Activación (manager): vista + acciones de cada cliente ──
const PORTAL_ACCIONES = [
  {
    name: 'Quitar capacitado', color: MA.turquesa,
    when: 'Se aprieta cuando el cliente ya está capacitado, en el paso 5.',
    icon: <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 10L12 5 2 10l10 5 10-5z"></path><path d="M6 12v5c0 1 2.7 3 6 3s6-2 6-3v-5"></path></svg>,
  },
  {
    name: 'Verificar Facebook', color: '#1877F2',
    when: 'Se presiona cuando Meta verifica el portfolio (paso 2).',
    icon: <svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path></svg>,
  },
  {
    name: 'Ver portal de cliente', color: MA.azul,
    when: 'Para entrar a la plataforma de onboarding del cliente antes de cada sesión.',
    icon: <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><path d="M15 3h6v6"></path><path d="M10 14L21 3"></path></svg>,
  },
  {
    name: 'Info empresa (IA)', color: MA.ambar,
    when: 'Es el botón que se presiona para ver el resumen automático del cliente.',
    icon: <svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z"></path></svg>,
  },
];

function PortalModal({ open, onClose, onZoom }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    if (open) window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);
  if (!open) return null;
  const res = (window.__resources) || {};
  const img = (p) => (res[p] || p);
  const A = MA.azul;
  const Shot = ({ src, cap }) => (
    <figure style={{ margin: '12px 0 0' }}>
      <button onClick={() => onZoom && onZoom(img(src), cap)} title="Ampliar" style={{ display: 'block', width: '100%', padding: 0, border: '1px solid ' + MA.border, borderRadius: 10, overflow: 'hidden', background: '#fff', cursor: 'zoom-in' }}>
        <img src={img(src)} alt={cap} loading="lazy" style={{ display: 'block', width: '100%', height: 'auto' }} />
      </button>
      <figcaption style={{ fontSize: 11, color: MA.inkDim, marginTop: 6, lineHeight: 1.4 }}>{cap}</figcaption>
    </figure>
  );
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 1000, background: 'rgba(10,21,37,.6)', backdropFilter: 'blur(3px)', display: 'flex', alignItems: 'flex-start', justifyContent: 'center', padding: '5vh 20px', overflowY: 'auto' }}>
      <div onClick={(e) => e.stopPropagation()} style={{ width: 'min(660px, 100%)', background: '#fff', borderRadius: 20, boxShadow: '0 24px 70px #0007', overflow: 'hidden', marginBottom: 40 }}>
        <div style={{ position: 'sticky', top: 0, background: MA.azul, padding: '20px 24px', display: 'flex', alignItems: 'center', gap: 14, zIndex: 2 }}>
          <div style={{ width: 44, height: 44, borderRadius: 12, background: '#ffffff22', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"></rect><path d="M3 10h18M9 20V10"></path></svg>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.1em', textTransform: 'uppercase', color: '#ffffffbb' }}>Manager · Onboarding</div>
            <div style={{ fontSize: 20, fontWeight: 800, fontStyle: 'italic', color: '#fff', lineHeight: 1.1 }}>Portal de Activación</div>
          </div>
          <button onClick={onClose} aria-label="Cerrar" style={{ width: 34, height: 34, borderRadius: '50%', background: '#ffffff22', border: '1px solid #ffffff33', color: '#fff', cursor: 'pointer', fontSize: 17, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>✕</button>
        </div>
        <div style={{ padding: '24px 24px 28px' }}>
          <p style={{ fontSize: 13.5, color: MA.inkMid, lineHeight: 1.55, margin: '0 0 4px' }}>Desde el manager seguís el progreso de onboarding de cada cliente: paso actual, estado del bot, progreso y días de activación.</p>
          <a href="https://manager.rack01.pip.com.ar/dashboards/onboarding/activation-portal" target="_blank" rel="noopener noreferrer" style={{ display: 'flex', alignItems: 'center', gap: 10, textDecoration: 'none', background: '#f6f7fc', border: '1px solid ' + MA.border, borderRadius: 10, padding: '10px 13px', marginTop: 12 }}>
            <span style={{ width: 30, height: 30, borderRadius: 8, background: A + '15', color: A, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.3" strokeLinecap="round" strokeLinejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
            </span>
            <span style={{ flex: 1, minWidth: 0 }}>
              <span style={{ display: 'block', fontSize: 12.5, fontWeight: 800, color: A }}>Portal de Activación</span>
              <span style={{ display: 'block', fontSize: 11, color: MA.inkDim, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>manager.rack01.pip.com.ar</span>
            </span>
            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke={MA.inkDim} strokeWidth="2.3" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}><path d="M7 17L17 7M7 7h10v10"></path></svg>
          </a>
          <Shot src="assets/manager/portal-lista.png" cap="Vista de Activación de Clientes en el manager" />

          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: MA.inkDim, margin: '24px 0 12px' }}>Acciones de cada cliente</div>
          <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: '0 0 4px' }}>Al desplegar un cliente, a la derecha aparecen 4 botones (de izquierda a derecha):</p>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 12 }}>
            {PORTAL_ACCIONES.map((ac, k) => (
              <div key={k} style={{ display: 'flex', gap: 12, alignItems: 'center', background: '#f8f9fc', border: '1px solid ' + MA.border, borderRadius: 12, padding: '11px 14px' }}>
                <span style={{ width: 38, height: 38, borderRadius: '50%', background: '#12122a', color: ac.color, border: '1.5px solid ' + ac.color, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>{ac.icon}</span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 13.5, fontWeight: 800, color: MA.ink }}>{ac.name}</div>
                  <p style={{ fontSize: 12, color: MA.inkMid, lineHeight: 1.45, margin: '2px 0 0' }}>{ac.when}</p>
                </div>
              </div>
            ))}
          </div>
          <Shot src="assets/manager/portal-cliente.png" cap="Cliente desplegado — los 4 botones arriba a la derecha" />
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// CARRUSEL DE FASES — Facebook: cada slide es una fase con su detalle
// ─────────────────────────────────────────────────────────────
function FasesCarrusel({ subpasos, color, onZoom, index, setIndex, outcome, validationInfo, onNextStep }) {
  const [iLocal, setILocal] = React.useState(0);
  const [dir, setDir] = React.useState(1);
  const [landing, setLanding] = React.useState(false);
  const total = subpasos.length;

  const showAppeal = outcome && outcome.kind && outcome.kind !== 'create';
  const appealNote = showAppeal ? (
    <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', background: '#fffbeb', border: '1px solid #fcd34d', borderLeft: '5px solid ' + MA.ambar, borderRadius: 12, padding: '14px 18px', marginBottom: 16, boxShadow: '0 2px 8px #f59e0b1f' }}>
      <span style={{ fontSize: 18, flexShrink: 0, marginTop: 1 }}>⚠️</span>
      <div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginBottom: 4 }}>
          <span style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: '#b45309' }}>Importante — si el Portfolio tiene un bloqueo</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 9.5, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: '#fff', background: MA.azul, padding: '2px 7px', borderRadius: 99, lineHeight: 1.5 }}><span style={{ width: 5, height: 5, borderRadius: '50%', background: '#ffffffcc' }}></span>Back</span>
        </div>
        <p style={{ fontSize: 13, color: '#7c2d12', lineHeight: 1.5, margin: 0 }}>Aclaración para el Back: si al ingresar ves un <b>bloqueo</b> en alguna sección (Info del negocio, Apps, Cuentas, Usuarios, Seguridad): apelalo desde el Portfolio y esperá la resolución de Meta. Si no es apelable, creá uno nuevo. Recién con el Portfolio habilitado seguí con el paso a paso.</p>
      </div>
    </div>
  ) : null;

  if (total === 0) {
    return (
      <div>
        {appealNote}
        <div style={{ background: '#fff', border: '1px solid ' + MA.border, borderTop: '4px solid ' + MA.turquesa, borderRadius: 18, padding: '26px 28px', boxShadow: '0 2px 10px #0b153710', display: 'flex', gap: 16, alignItems: 'flex-start' }}>
          <div style={{ width: 52, height: 52, borderRadius: 14, background: MA.turquesa + '18', color: MA.turquesa, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 26, flexShrink: 0, border: '2px solid ' + MA.turquesa + '30' }}>🎉</div>
          <div>
            <div style={{ fontSize: 19, fontWeight: 800, fontStyle: 'italic', color: MA.azul, lineHeight: 1.15, marginBottom: 6 }}>No hay fases que seguir</div>
            <p style={{ fontSize: 13.5, color: MA.inkMid, lineHeight: 1.55, margin: 0 }}>El portal marcó <b>Todo listo</b>: el Portfolio Comercial ya está creado y verificado. No corresponde crear, armar la App ni verificar de nuevo. Ingresá solo para confirmar y continuá con el siguiente paso para conectar WhatsApp con Pip.</p>
          </div>
        </div>
      </div>
    );
  }

  const i = Math.min(total - 1, Math.max(0, index !== undefined ? index : iLocal));
  const sp = subpasos[i];
  const isF1 = sp.id === 'f1';
  const isF3 = sp.id === 'f3';
  const f1Variant = (isF1 && outcome && outcome.kind && outcome.kind !== 'create') ? F1_VARIANTS[outcome.kind] : null;
  const isCreate = isF1 && outcome && outcome.kind === 'create';
  const dispObjetivo = f1Variant ? f1Variant.objetivo : (isCreate ? 'Crear el Portfolio Comercial desde cero y cargar la información legal idéntica a ARCA. Si el nombre o la dirección no coinciden, la verificación posterior se rechaza.' : sp.objetivo);
  const dispPasos = f1Variant ? f1Variant.pasos : sp.pasos;
  const dispTitle = isF1 ? (f1Variant ? '¿Cómo relevar el portfolio comercial?' : '¿Cómo crear el portfolio comercial?') : sp.title;
  const showLanding = isF3 && !(outcome && outcome.kind === 'coordinate');
  const go = (next) => {
    const clamped = Math.max(0, Math.min(total - 1, next));
    setDir(clamped > i ? 1 : -1);
    (setIndex || setILocal)(clamped);
  };
  const atStart = i === 0, atEnd = i === total - 1;

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', marginBottom: 12 }}>
        <div style={{ fontSize: 12, fontWeight: 700, color: color, display: 'flex', alignItems: 'center', gap: 4 }}>
          <span style={{ fontSize: 12, fontWeight: 600, color: MA.inkDim, textTransform: 'uppercase', letterSpacing: '.04em', marginRight: 4 }}>Fase</span>
          <span style={{ fontSize: 17 }}>{i + 1}</span>
          <span style={{ color: MA.inkDim, fontWeight: 600 }}>/ {total}</span>
        </div>
      </div>

      <div style={{ position: 'relative', background: '#fff', border: '1px solid ' + MA.border, borderRadius: 18, overflow: 'hidden', boxShadow: '0 2px 10px #0b153710' }}>
        {/* Barra de progreso */}
        <div style={{ height: 4, background: '#eef0f6' }}>
          <div style={{ height: '100%', width: ((i + 1) / total * 100) + '%', background: color, borderRadius: 4, transition: 'width .3s ease' }}></div>
        </div>

        {/* Slide de fase */}
        <div style={{ padding: '22px 24px 24px' }}>
          <div key={i} className="carrusel-slide" style={{ '--slide-dir': dir }}>
            {/* Encabezado de la fase */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 16 }}>
              <div style={{ width: 52, height: 52, borderRadius: 14, background: color + '15', color: color, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 26, flexShrink: 0, border: '2px solid ' + color + '30' }}>{sp.icon}</div>
              <div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                  <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: color, background: color + '18', padding: '2px 8px', borderRadius: 99 }}>{sp.tag}</span>
                  {ROLE_BY_FASE[sp.id] && <RoleBadge role={ROLE_BY_FASE[sp.id]} size="sm" />}
                </div>
                <div style={{ fontSize: 21, fontWeight: 800, fontStyle: 'italic', color: MA.azul, lineHeight: 1.1, marginTop: 5 }}>{dispTitle}</div>
              </div>
            </div>

            <p style={{ fontSize: 13.5, color: MA.inkMid, lineHeight: 1.55, margin: '0 0 16px', fontStyle: 'italic' }}>{dispObjetivo}</p>

            {isF3 && <EnvioValidarCondicional />}

            {isF1 && (outcome && outcome.kind ? (
              <div style={{ background: (OUT_ACCENT[outcome.kind] || color) + '0f', border: '1px solid ' + (OUT_ACCENT[outcome.kind] || color) + '44', borderRadius: 10, padding: '11px 14px', marginBottom: 16, display: 'flex', gap: 10, alignItems: 'flex-start' }}>
                <span style={{ fontSize: 15, flexShrink: 0 }}>🌳</span>
                <div>
                  <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: (OUT_ACCENT[outcome.kind] || color) }}>Según el estado detectado</div>
                  <p style={{ fontSize: 12.5, color: MA.ink, margin: '2px 0 0', lineHeight: 1.5, fontWeight: 700 }}>{outcome.title}</p>
                </div>
              </div>
            ) : (
              <div style={{ background: '#f6f7fc', border: '1px dashed ' + MA.border, borderRadius: 10, padding: '11px 14px', marginBottom: 16, display: 'flex', gap: 9, alignItems: 'center', fontSize: 12.5, color: MA.inkDim, lineHeight: 1.45 }}>
                <span style={{ fontSize: 14, flexShrink: 0 }}>👆</span>
                Identificá el estado en la etapa 1 y estos pasos se adaptan al caso del cliente.
              </div>
            ))}

            {isF3 && validationInfo && (validationInfo.reglaOro || validationInfo.sensibles) && (
              <div style={{ marginBottom: 16, display: 'flex', flexDirection: 'column', gap: 12 }}>
                {validationInfo.reglaOro && (
                  <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', background: '#fff7ed', border: '1px solid #fed7aa', borderRadius: 14, padding: '16px 18px' }}>
                    <span style={{ fontSize: 18, flexShrink: 0 }}>⚠️</span>
                    <div>
                      <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: '#b45309', marginBottom: 5 }}>Regla de oro — bloqueo preventivo</div>
                      <p style={{ fontSize: 13.5, color: '#7c2d12', lineHeight: 1.55, margin: 0 }}>{validationInfo.reglaOro}</p>
                    </div>
                  </div>
                )}
                {validationInfo.sensibles && <SensiblesBlock data={validationInfo.sensibles} />}
              </div>
            )}

            {isF3 && outcome && outcome.kind === 'confirm' && (
              <div style={{ display: 'flex', gap: 9, alignItems: 'flex-start', background: '#f0f4ff', border: '1px solid #c7d7f5', borderRadius: 10, padding: '11px 14px', marginBottom: 14 }}>
                <span style={{ fontSize: 13, flexShrink: 0 }}>💡</span>
                <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>En este camino no se muestra la fase de la App porque normalmente ya existe. Si al verificar <b>no aparece la opción de enviar la solicitud</b>, es porque falta la App: creala primero (Configuración → Cuentas → Apps → “Crear app”).</p>
              </div>
            )}

            <PasosConTips pasos={dispPasos} color={color} />

            {sp.validacion && (
              <div style={{ marginBottom: 16 }}>
                <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: MA.inkDim, marginBottom: 4 }}>Métodos de verificación</div>
                <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: '0 0 10px' }}>Elegí uno. Si es por metaetiqueta, desplegá el paso a paso con las capturas.</p>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                  {sp.validacion.map((v, vi) => {
                    const isMeta = /metaetiqueta/i.test(v.label);
                    return (
                      <Expandible key={vi} label={v.label} icon={v.icon} color={color}>
                        <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>{v.detalle}</p>
                        {isMeta && sp.subproceso && (
                          <div style={{ marginTop: 12, background: color + '0a', border: '1px solid ' + color + '30', borderRadius: 10, padding: '14px 16px' }}>
                            <div style={{ fontSize: 11, fontWeight: 800, color: color, marginBottom: 10, letterSpacing: '.02em' }}>{sp.subproceso.title}</div>
                            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                              {sp.subproceso.items.map((t, k) => (
                                <div key={k} style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
                                  <span style={{ color: color, fontWeight: 800, flexShrink: 0, fontSize: 12, marginTop: 1 }}>{k + 1}.</span>
                                  <p style={{ fontSize: 12.5, color: MA.ink, lineHeight: 1.5, margin: 0 }}>{t}</p>
                                </div>
                              ))}
                            </div>
                            {sp.subproceso.captura && (
                              <div style={{ marginTop: 14 }}><CapturaSlot items={sp.subproceso.captura} onZoom={onZoom} /></div>
                            )}
                            {showLanding && (
                              <button onClick={() => setLanding(true)} style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 12, marginTop: 14, background: MA.azul, color: '#fff', border: 'none', borderRadius: 12, padding: '13px 15px', fontFamily: MA.font, cursor: 'pointer', textAlign: 'left', boxShadow: '0 4px 14px ' + MA.azul + '40' }}>
                                <span style={{ width: 34, height: 34, borderRadius: 9, background: '#ffffff22', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                                  <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><path d="M3 9h18M9 21V9"></path></svg>
                                </span>
                                <span style={{ flex: 1, minWidth: 0 }}>
                                  <span style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                                    <span style={{ fontSize: 13, fontWeight: 800, fontStyle: 'italic' }}>¿El cliente no tiene web?</span>
                                    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 9, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: MA.azul, background: '#fff', padding: '2px 7px', borderRadius: 99, lineHeight: 1.5 }}><span style={{ width: 5, height: 5, borderRadius: '50%', background: MA.azul }}></span>Back</span>
                                  </span>
                                  <span style={{ display: 'block', fontSize: 12, color: '#ffffffcc', marginTop: 3 }}>La metaetiqueta va en una web. Si no tiene, la creamos en GrapesJS (lo hace el Back) — mirá el paso a paso.</span>
                                </span>
                                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}><path d="M9 18l6-6-6-6"></path></svg>
                              </button>
                            )}
                          </div>
                        )}
                      </Expandible>
                    );
                  })}
                </div>
              </div>
            )}

            {sp.subproceso && !sp.validacion && (
              <div style={{ background: color + '0a', border: '1px solid ' + color + '30', borderRadius: 10, padding: '14px 16px', marginBottom: 16 }}>
                <div style={{ fontSize: 11, fontWeight: 800, color: color, marginBottom: 10, letterSpacing: '.02em' }}>{sp.subproceso.title}</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                  {sp.subproceso.items.map((t, k) => (
                    <div key={k} style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
                      <span style={{ color: color, fontWeight: 800, flexShrink: 0, fontSize: 12, marginTop: 1 }}>{k + 1}.</span>
                      <p style={{ fontSize: 12.5, color: MA.ink, lineHeight: 1.5, margin: 0 }}>{t}</p>
                    </div>
                  ))}
                </div>
                {sp.subproceso.captura && (
                  <div style={{ marginTop: 14 }}><CapturaSlot items={sp.subproceso.captura} onZoom={onZoom} /></div>
                )}
              </div>
            )}

            {sp.captura && <CapturaSlot items={sp.captura} onZoom={onZoom} />}

            {sp.detalles && (
              <div style={{ marginTop: 16, display: 'flex', flexDirection: 'column', gap: 6 }}>
                {sp.detalles.map((det, di) => (
                  <Expandible key={di} label={det.title} icon={det.icon} color={color}>
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
                      {det.items.map((it, ii) => (
                        <div key={ii} style={{ display: 'flex', gap: 7, alignItems: 'flex-start', fontSize: 12.5, color: MA.inkMid, lineHeight: 1.45 }}>
                          <span style={{ width: 4, height: 4, borderRadius: '50%', background: color, flexShrink: 0, marginTop: 6 }}></span>
                          <span>{it}</span>
                        </div>
                      ))}
                    </div>
                  </Expandible>
                ))}
              </div>
            )}

            {sp.tips && (
              <div style={{ marginTop: 16, display: 'flex', flexDirection: 'column', gap: 8 }}>
                {sp.tips.map((t, k) => (
                  <div key={k} style={{ display: 'flex', gap: 9, alignItems: 'flex-start', background: '#eff6ff', border: '1px solid #bfdbfe', borderRadius: 9, padding: '9px 13px' }}>
                    <span style={{ fontSize: 13, flexShrink: 0 }}>💡</span>
                    <p style={{ fontSize: 12.5, color: '#1e3a8a', lineHeight: 1.5, margin: 0 }}>{t}</p>
                  </div>
                ))}
              </div>
            )}

            {sp.verificacionFallida && (
              <div style={{ marginTop: 16, background: '#fff7ed', border: '1px solid #fed7aa', borderRadius: 14, padding: '18px 22px' }}>
                <div style={{ fontSize: 14, fontWeight: 800, fontStyle: 'italic', color: '#b45309', marginBottom: 14, display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontSize: 18 }}>⚠️</span>
                  {sp.verificacionFallida.title}
                </div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                  {sp.verificacionFallida.opciones.map((op, oi) => (
                    <Expandible key={oi} label={op.titulo} icon={op.icon} color="#b45309">
                      <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
                        {op.items.map((it, ii) => (
                          <div key={ii} style={{ display: 'flex', gap: 7, alignItems: 'flex-start', fontSize: 12.5, color: '#7c2d12', lineHeight: 1.45 }}>
                            <span style={{ width: 4, height: 4, borderRadius: '50%', background: '#f59e0b', flexShrink: 0, marginTop: 6 }}></span>
                            <span>{it}</span>
                          </div>
                        ))}
                      </div>
                    </Expandible>
                  ))}
                </div>
              </div>
            )}

            {!isF3 && sp.errores && sp.errores.length > 0 && (
              <div style={{ marginTop: 18 }}>
                <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: MA.danger, marginBottom: 8, display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ fontSize: 13 }}>⛔</span> Errores a evitar en esta fase
                </div>
                <ErroresChecklist errores={sp.errores} compact />
              </div>
            )}

            {isF3 && appealNote}

            {isF3 && <CorroboracionVerificacion />}
          </div>
        </div>

        {/* Controles */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '6px 18px 20px', borderTop: '1px solid ' + MA.border, marginTop: 4 }}>
          <button onClick={() => go(i - 1)} disabled={atStart} aria-label="Fase anterior" style={{ width: 42, height: 42, borderRadius: '50%', border: '1.5px solid ' + (atStart ? '#e5e7eb' : color), background: '#fff', color: atStart ? '#cbd0dc' : color, cursor: atStart ? 'not-allowed' : 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all .15s', flexShrink: 0 }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"></path></svg>
          </button>

          <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'center' }}>
            {subpasos.map((s, d) => (
              <button key={d} onClick={() => go(d)} aria-label={'Ir a ' + s.tag} style={{ display: 'flex', alignItems: 'center', gap: 6, padding: d === i ? '5px 12px' : '5px 9px', borderRadius: 99, border: '1px solid ' + (d === i ? color : '#e1e4ed'), background: d === i ? color + '14' : '#fff', cursor: 'pointer', transition: 'all .2s' }}>
                <span style={{ fontSize: 14 }}>{s.icon}</span>
                {d === i && <span style={{ fontSize: 11, fontWeight: 800, color: color, letterSpacing: '.04em', textTransform: 'uppercase' }}>{s.tag}</span>}
              </button>
            ))}
          </div>

          {atEnd && onNextStep ? (
          <button onClick={onNextStep} aria-label="Ir al siguiente paso" title="Ir al siguiente paso" style={{ display: 'inline-flex', alignItems: 'center', gap: 8, height: 42, borderRadius: 99, border: 'none', background: color, color: '#fff', cursor: 'pointer', padding: '0 16px 0 18px', fontFamily: MA.font, fontSize: 12.5, fontWeight: 800, whiteSpace: 'nowrap', flexShrink: 0, boxShadow: '0 3px 10px ' + color + '50' }}>
            <span>Siguiente paso</span>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
          </button>
          ) : (
          <button onClick={() => go(i + 1)} disabled={atEnd} aria-label="Fase siguiente" style={{ width: 42, height: 42, borderRadius: '50%', border: 'none', background: atEnd ? '#eef0f6' : color, color: atEnd ? '#cbd0dc' : '#fff', cursor: atEnd ? 'not-allowed' : 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all .15s', flexShrink: 0, boxShadow: atEnd ? 'none' : '0 3px 10px ' + color + '50' }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M9 18l6-6-6-6"></path></svg>
          </button>
          )}
        </div>
      </div>
      <LandingModal open={landing} onClose={() => setLanding(false)} onZoom={onZoom} />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// ─────────────────────────────────────────────────────────────
// ─────────────────────────────────────────────────────────────
// PASOS CON TIPS — numbered steps, click lightbulb for inline suggestion
// ─────────────────────────────────────────────────────────────
function PasosConTips({ pasos, color }) {
  const [openTip, setOpenTip] = React.useState(null);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 9, marginBottom: 16 }}>
      {pasos.map((t, k) => {
        const isObj = typeof t === 'object' && t !== null;
        const text = isObj ? t.text : t;
        const tip = isObj ? t.tip : null;
        const tipOpen = openTip === k;
        return (
          <div key={k}>
            <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>
              <div style={{ width: 22, height: 22, borderRadius: '50%', background: color, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, fontWeight: 800, flexShrink: 0, marginTop: 1 }}>{k + 1}</div>
              <p style={{ fontSize: 13.5, color: MA.ink, lineHeight: 1.55, margin: 0, flex: 1 }}>{text}</p>
              {tip && (
                <button onClick={() => setOpenTip(tipOpen ? null : k)} title="Ver sugerencia" style={{
                  height: 26, borderRadius: 8, flexShrink: 0, marginTop: 0,
                  background: tipOpen ? '#eff6ff' : '#f0f4ff', border: tipOpen ? '1.5px solid #93b4f5' : '1.5px solid #c7d7f5',
                  cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4,
                  fontSize: 12, padding: '0 8px', transition: 'all .15s', fontFamily: MA.font, fontWeight: 600, color: '#3D52E8',
                }}>💡<span style={{ fontSize: 10, letterSpacing: '.02em' }}>Tip</span></button>
              )}
            </div>
            {tipOpen && tip && (
              <div style={{ marginLeft: 34, marginTop: 6, background: '#eff6ff', border: '1px solid #bfdbfe', borderRadius: 8, padding: '8px 12px', fontSize: 12.5, color: '#1e3a8a', lineHeight: 1.5, animation: 'carruselIn .2s ease both', '--slide-dir': 0 }}>
                {tip}
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

// EXPANDIBLE — accordion item: label + click to expand details
// ─────────────────────────────────────────────────────────────
function Expandible({ label, icon, color, children, defaultOpen }) {
  const [open, setOpen] = React.useState(!!defaultOpen);
  return (
    <div style={{ borderRadius: 10, border: '1px solid ' + (open ? color + '55' : MA.border), overflow: 'hidden', transition: 'border-color .2s' }}>
      <button onClick={() => setOpen(!open)} style={{
        width: '100%', display: 'flex', alignItems: 'center', gap: 10,
        padding: '10px 14px', background: open ? color + '08' : '#fff',
        border: 'none', cursor: 'pointer', fontFamily: MA.font, textAlign: 'left',
      }}>
        <span style={{ width: 18, height: 18, borderRadius: 5, border: '2px solid ' + color + '55', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 10 }}>
          {open ? <span style={{ width: 8, height: 8, borderRadius: 2, background: color }}></span> : null}
        </span>
        {icon && <span style={{ fontSize: 14, flexShrink: 0 }}>{icon}</span>}
        <span style={{ fontSize: 13, fontWeight: 700, color: MA.ink, flex: 1 }}>{label}</span>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={MA.inkDim} strokeWidth="2.5" strokeLinecap="round" style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .2s', flexShrink: 0 }}>
          <path d="M6 9l6 6 6-6"></path>
        </svg>
      </button>
      {open && (
        <div style={{ padding: '4px 14px 14px 42px', background: color + '04' }}>
          {children}
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// ÁRBOL DE DECISIÓN — Portfolio Comercial (previo a la Fase 1)
// Reconstruido del diagrama del flujo de portfolio.
// ─────────────────────────────────────────────────────────────
const PORTFOLIO_TREE = {
  start: 'trigger',
  q: {
    trigger: {
      eyebrow: 'Portal de activación · paso 1 de 2',
      title: '¿En qué estado está la cuenta de Facebook del negocio?',
      hint: 'Elegí lo que muestra el portal de activación para el cliente. Una segunda pregunta define la salida exacta.',
      short: 'Estado',
      options: [
        { label: '🎉 Tiene Administrador Comercial y está verificado', sub: 'Ya tiene la cuenta de empresa y está verificada.', to: 'q_cred_val' },
        { label: '🔧 Tiene Administrador Comercial, sin verificar', sub: 'Tiene la cuenta pero falta habilitarla ante Meta.', to: 'q_cred_hab' },
        { label: '🔍 Tiene Administrador Comercial, verificación "no sé"', sub: 'Tiene la cuenta pero no sabés si está verificada.', to: 'q_cred_rev' },
        { label: '🆕 No tiene / no sabe si tiene Administrador Comercial', sub: 'Puede que haya que crearla o buscarla.', to: 'q_bm' },
        { label: '📱 No tiene cuenta de Facebook del negocio', sub: 'Arrancamos desde el Facebook personal o desde cero.', to: 'q_b' },
      ],
    },
    q_cred_val: {
      eyebrow: 'Paso 2 de 2 · credenciales',
      title: '¿Tenés las credenciales de acceso?',
      hint: 'Usuario y contraseña del Facebook del negocio.',
      short: 'Credenciales',
      options: [
        { label: '✅ Sí, las tengo a mano', sub: 'Usuario y contraseña del Facebook del negocio disponibles.', to: 'out_val_ok' },
        { label: '🔑 No las tengo', sub: 'Hay que recuperar la contraseña de Facebook.', to: 'out_val_recover' },
        { label: '🔍 No sé', sub: 'Primero revisamos usuario y contraseña / el acceso.', to: 'out_val_check' },
      ],
    },
    q_cred_hab: {
      eyebrow: 'Paso 2 de 2 · credenciales',
      title: '¿Tenés las credenciales de acceso?',
      hint: 'Usuario y contraseña del Facebook del negocio.',
      short: 'Credenciales',
      options: [
        { label: '✅ Sí, las tengo a mano', sub: 'Usuario y contraseña del Facebook del negocio disponibles.', to: 'out_hab_ok' },
        { label: '🔑 No las tengo', sub: 'Hay que recuperar la contraseña de Facebook.', to: 'out_hab_recover' },
        { label: '🔍 No sé', sub: 'Primero revisamos usuario y contraseña / el acceso.', to: 'out_hab_check' },
      ],
    },
    q_cred_rev: {
      eyebrow: 'Paso 2 de 2 · credenciales',
      title: '¿Tenés las credenciales de acceso?',
      hint: 'Usuario y contraseña del Facebook del negocio.',
      short: 'Credenciales',
      options: [
        { label: '✅ Sí, las tengo a mano', sub: 'Usuario y contraseña del Facebook del negocio disponibles.', to: 'out_rev_ok' },
        { label: '🔑 No las tengo', sub: 'Hay que recuperar la contraseña de Facebook.', to: 'out_rev_recover' },
        { label: '🔍 No sé', sub: 'Primero revisamos usuario y contraseña / el acceso.', to: 'out_rev_check' },
      ],
    },
    q_bm: {
      eyebrow: 'Paso 2 de 2 · cuenta de empresa',
      title: '¿Ya existe la cuenta de empresa?',
      hint: 'El portal no confirma si el negocio tiene Administrador Comercial.',
      short: 'Cuenta',
      options: [
        { label: '🆕 No tiene', sub: 'Hay que crear la cuenta de empresa en la sesión.', to: 'out_bm_create' },
        { label: '🔍 No sabe', sub: 'Primero vemos si ya existe una cuenta de empresa.', to: 'out_bm_check' },
      ],
    },
    q_b: {
      eyebrow: 'Paso 2 de 2 · Facebook personal',
      title: '¿Qué cuenta de Facebook personal tiene el cliente?',
      hint: 'Sin cuenta del negocio, arrancamos desde el Facebook personal.',
      short: 'Facebook',
      options: [
        { label: '🆕 Tiene personal y las credenciales', sub: 'Creamos la cuenta de empresa usando su Facebook.', to: 'out_b_create' },
        { label: '🔑 Tiene personal, sin credenciales', sub: 'Recuperamos el Facebook y creamos la cuenta de empresa.', to: 'out_b_recover' },
        { label: '📱 No tiene ninguna cuenta', sub: 'Creamos el Facebook y la cuenta de empresa desde cero.', to: 'out_b_scratch' },
      ],
    },
  },
  out: {
    out_val_ok: {
      kind: 'ready', icon: '🎉', title: '¡Ya tenés todo listo!',
      desc: 'La cuenta de empresa ya está verificada y tenés las credenciales a mano. Ingresás con el cliente solo para confirmarlo y dejar todo listo para conectar WhatsApp con Pip.',
      pasos: ['Ingresá con el cliente a la cuenta de empresa.', 'Confirmá que esté verificada y sin bloqueos.', 'Dejá todo listo para conectar WhatsApp con Pip.'],
      fase1Note: 'Relevá la cuenta y verificá los datos legales contra ARCA. No se crea nada nuevo.',
    },
    out_val_recover: {
      kind: 'confirm', icon: '🔑', title: 'Recuperamos tu contraseña de Facebook y revisamos que todo esté bien',
      desc: 'La cuenta está verificada pero no tenés las credenciales. Primero recuperás el acceso y después confirmás que esté todo bien.',
      pasos: ['Recuperá el usuario y contraseña de Facebook (recuperación de contraseña).', 'Ingresá a la cuenta de empresa.', 'Confirmá que esté verificada y sin bloqueos.', 'Dejá listo para conectar WhatsApp con Pip.'],
      nota: 'Si no podés recuperar las credenciales, fijate si alguien del equipo (MKT, CM, responsable) ya tiene acceso.',
      fase1Note: 'Con el acceso resuelto, relevá la cuenta y verificá los datos contra ARCA.',
    },
    out_val_check: {
      kind: 'confirm', icon: '🔍', title: 'Revisamos que tengas tu usuario y contraseña, y chequeamos todo',
      desc: 'La cuenta está verificada pero no sabés si tenés las credenciales. Revisás el acceso y confirmás que esté todo bien.',
      pasos: ['Revisá usuario y contraseña de la cuenta de empresa; si no los tenés, recuperalos.', 'Ingresá y confirmá que esté verificada y sin bloqueos.', 'Dejá listo para conectar WhatsApp con Pip.'],
      fase1Note: 'Con el acceso resuelto, relevá la cuenta y verificá los datos contra ARCA.',
    },
    out_hab_ok: {
      kind: 'validate', icon: '🔧', title: 'Dejamos habilitada tu cuenta de empresa en Facebook',
      desc: 'La cuenta existe pero falta habilitarla (verificarla) ante Meta. Con las credenciales a mano, completás la verificación.',
      pasos: ['Ingresá a la cuenta de empresa con el cliente.', 'Completá la verificación del negocio (documentación idéntica a ARCA).', 'Una vez habilitada, conectá WhatsApp con Pip.'],
      fase1Note: 'Relevá la cuenta y dejá los datos idénticos a ARCA antes de verificar.',
    },
    out_hab_recover: {
      kind: 'validate', icon: '🔑', title: 'Recuperamos tu contraseña y habilitamos tu cuenta de empresa',
      desc: 'Falta habilitar la cuenta y no tenés las credenciales. Primero recuperás el acceso y después completás la verificación.',
      pasos: ['Recuperá usuario y contraseña de Facebook.', 'Ingresá a la cuenta de empresa.', 'Completá la verificación (documentación idéntica a ARCA).', 'Habilitada la cuenta, conectá WhatsApp con Pip.'],
      nota: 'Si no podés recuperar las credenciales, fijate si alguien del equipo ya tiene acceso.',
      fase1Note: 'Con el acceso resuelto, relevá la cuenta y dejá los datos idénticos a ARCA.',
    },
    out_hab_check: {
      kind: 'validate', icon: '🔍', title: 'Revisamos tu acceso y habilitamos tu cuenta de empresa',
      desc: 'Falta habilitar la cuenta y no sabés si tenés las credenciales. Revisás el acceso y completás la verificación.',
      pasos: ['Revisá usuario y contraseña; si no los tenés, recuperalos.', 'Ingresá a la cuenta de empresa.', 'Completá la verificación (documentación idéntica a ARCA).', 'Habilitada, conectá WhatsApp con Pip.'],
      fase1Note: 'Con el acceso resuelto, relevá la cuenta y dejá los datos idénticos a ARCA.',
    },
    out_rev_ok: {
      kind: 'confirm', icon: '🔍', title: 'Revisamos cómo está tu cuenta de empresa en Facebook',
      desc: 'La cuenta existe pero no sabés si está verificada. Con las credenciales, ingresás a revisar su estado y seguís según corresponda.',
      link: { href: 'https://business.facebook.com/settings/request', label: 'business.facebook.com/settings/request' },
      pasos: ['Ingresá a la cuenta de empresa con el cliente.', 'Revisá si está verificada y sin bloqueos.', 'Si falta verificar, completala (datos idénticos a ARCA).', 'Dejá listo para conectar WhatsApp con Pip.'],
      fase1Note: 'Relevá la cuenta y verificá los datos legales contra ARCA.',
    },
    out_rev_recover: {
      kind: 'confirm', icon: '🔑', title: 'Recuperamos tu contraseña y revisamos tu cuenta de empresa',
      desc: 'No sabés el estado de verificación ni tenés las credenciales. Recuperás el acceso y después revisás cómo está.',
      pasos: ['Recuperá usuario y contraseña de Facebook.', 'Ingresá y revisá si está verificada y sin bloqueos.', 'Si falta verificar, completala (datos idénticos a ARCA).', 'Dejá listo para conectar WhatsApp con Pip.'],
      nota: 'Si no podés recuperar las credenciales, fijate si alguien del equipo ya tiene acceso.',
      fase1Note: 'Con el acceso resuelto, relevá la cuenta y verificá los datos contra ARCA.',
    },
    out_rev_check: {
      kind: 'confirm', icon: '🔍', title: 'Revisamos tu acceso y tu cuenta de empresa',
      desc: 'No sabés el estado de verificación ni si tenés las credenciales. Revisás el acceso y el estado de la cuenta.',
      pasos: ['Revisá usuario y contraseña; si no los tenés, recuperalos.', 'Ingresá y revisá si está verificada y sin bloqueos.', 'Si falta verificar, completala (datos idénticos a ARCA).', 'Dejá listo para conectar WhatsApp con Pip.'],
      fase1Note: 'Con el acceso resuelto, relevá la cuenta y verificá los datos contra ARCA.',
    },
    out_bm_create: {
      kind: 'create', icon: '🆕', title: 'Creamos tu cuenta de empresa en Facebook',
      desc: 'El negocio no tiene Administrador Comercial. Lo crean juntos en la sesión, desde la mejor cuenta disponible: el Facebook del negocio; si no hay, un Facebook personal o el Instagram de la empresa.',
    },
    out_bm_check: {
      kind: 'confirm', icon: '🔍', title: 'Vemos si ya tenés una cuenta de empresa en Facebook',
      desc: 'No sabés si el negocio tiene Administrador Comercial. Ingresás a buscarlo: si existe, seguís desde su estado; si no, lo crean en la sesión.',
      pasos: ['Ingresá a Facebook con el cliente y buscá la cuenta de empresa.', 'Si existe, revisá su estado (verificada / sin bloqueos).', 'Si no existe, creala desde la mejor cuenta disponible.', 'Dejá listo para conectar WhatsApp con Pip.'],
      fase1Note: 'Si la cuenta existe, relevala y verificá los datos contra ARCA; si no, se crea.',
    },
    out_b_create: {
      kind: 'create', icon: '🆕', title: 'Creamos tu cuenta de empresa usando tu Facebook',
      desc: 'El negocio no tiene cuenta de empresa pero el cliente tiene su Facebook personal con credenciales. Crean la cuenta de empresa desde ahí.',
    },
    out_b_recover: {
      kind: 'create', icon: '🔑', title: 'Recuperamos tu Facebook y creamos tu cuenta de empresa',
      desc: 'El cliente tiene Facebook personal pero no las credenciales. Recuperan el acceso al Facebook y después crean la cuenta de empresa.',
      nota: 'Si no se puede recuperar el Facebook personal, se crea uno nuevo para arrancar.',
    },
    out_b_scratch: {
      kind: 'create', icon: '📱', title: 'Creamos tu Facebook y tu cuenta de empresa desde cero',
      desc: 'El negocio no tiene ninguna cuenta de Facebook. Crean primero un Facebook y después la cuenta de empresa, desde cero.',
    },
  },
};

const F1_RELEVAR_PASOS = [
  { text: 'Ingresá a business.facebook.com y abrí el Portfolio Comercial existente del cliente.' },
  { text: 'Configuración → Info del negocio: verificá nombre, dirección, teléfono y web.', tip: 'Todo debe coincidir textual con ARCA. Un acento de diferencia = rechazo.' },
  { text: 'Teléfono: confirmá que sea el de la razón social en ARCA, no personal.' },
  { text: 'Footer web: razón social + nombre de fantasía (si difiere) + teléfono.' },
  { text: 'Confirmá que la verificación en dos pasos esté activa.' },
  { text: 'Revisá TODAS las secciones del Portfolio.', tip: 'Info del negocio, Apps, Cuentas, Usuarios, Seguridad. Deben estar sin bloqueos.' },
];
const F1_VARIANTS = {
  ready: {
    objetivo: 'Relevar el Portfolio Comercial existente y verificar que la información legal coincida con ARCA. No se crea uno nuevo.',
    pasos: F1_RELEVAR_PASOS,
  },
  confirm: {
    objetivo: 'Ingresar al Portfolio Comercial, confirmar su estado y relevar que los datos legales coincidan con ARCA.',
    pasos: F1_RELEVAR_PASOS,
  },
  validate: {
    objetivo: 'Relevar el Portfolio Comercial y dejar los datos idénticos a ARCA antes de completar la verificación del negocio ante Meta.',
    pasos: F1_RELEVAR_PASOS,
  },
  recover: {
    objetivo: 'Recuperar el acceso a la cuenta y, ya dentro, relevar el Portfolio Comercial verificando los datos legales contra ARCA.',
    pasos: [
      { text: 'Recuperá el usuario y contraseña de la cuenta de Facebook (recuperación de contraseña).', tip: 'Si no podés, fijate si alguien del equipo (MKT, CM, responsable) ya tiene acceso.' },
      ...F1_RELEVAR_PASOS,
    ],
  },
};

const OUT_ACCENT = { ready: MA.turquesa, confirm: MA.ambar, validate: MA.azul, recover: MA.violeta, create: MA.azul };
const OUT_KIND_LABEL = { ready: 'Todo listo', confirm: 'Verificar / confirmar', validate: 'Verificar', recover: 'Recuperar credenciales', create: 'Crear' };

// Qué fases del paso a paso (punto 3) mostrar según el llamado a la acción del portal.
// El portal ya resolvió lo anterior, así que ocultamos las fases que no aplican.
//   f1 = Portfolio Comercial (crear/relevar) · f2 = Creación de la App · f3 = Verificación del negocio
const OUT_PHASES = {
  ready:    [],                    // Todo listo → no hay pasos que seguir
  confirm:  ['f1', 'f3'],          // Relevar el Portfolio y confirmar la verificación
  validate: ['f1', 'f2', 'f3'],    // Relevar, crear App y verificar
  recover:  ['f1', 'f2', 'f3'],    // Tras recuperar, seguir según corresponda
  create:   ['f1', 'f2', 'f3'],    // Flujo completo desde cero
};

// Checklist contextual: qué tiene que tener listo el asesor según el estado detectado en el portal.
const OUT_CHECKLIST = {
  ready: [
    'Usuario y contraseña del Facebook del negocio a mano',
    'Número de WhatsApp a integrar disponible y celular a mano',
  ],
  confirm: [
    'Usuario y contraseña del Facebook del negocio a mano',
    'Datos legales del negocio en ARCA a mano para cotejar',
    'Número de WhatsApp a integrar disponible',
  ],
  validate: [
    'Usuario y contraseña del Facebook del negocio a mano',
    'Documentación del negocio para verificar (constancia de ARCA)',
    'Web o footer con razón social y teléfono (solo para verificar; si no tiene, se crea una landing en los pasos siguientes)',
    'Número de WhatsApp a integrar disponible',
  ],
  recover: [
    'Acceso al email o teléfono de recuperación de la cuenta',
    'Alternativa: contacto de quien administra el Portfolio (MKT, CM, responsable)',
    'Número de WhatsApp a integrar disponible',
  ],
  create: [
    'Acceso a la cuenta desde la que van a crear el Portfolio: Facebook del negocio, personal o Instagram (usuario y contraseña a mano)',
    'Si el negocio no tiene ninguna cuenta: email y teléfono para crear una nueva',
    'Datos del negocio idénticos a ARCA (nombre, dirección, teléfono)',
    'Para verificar (no para crear): web o footer con razón social y teléfono. Si no tiene, se crea una landing en los pasos siguientes',
    'Número de WhatsApp a integrar disponible',
  ],
};

function DecisionOutcome({ o, color, subpasos, onGoFase, onRestart }) {
  const accent = OUT_ACCENT[o.kind] || color;
  return (
    <div style={{ background: '#fff', border: '1px solid ' + MA.border, borderTop: '4px solid ' + accent, borderRadius: 16, padding: '22px 24px', boxShadow: '0 2px 10px #0b153710' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 14 }}>
        <div style={{ width: 52, height: 52, borderRadius: 14, background: accent + '15', color: accent, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 26, flexShrink: 0, border: '2px solid ' + accent + '30' }}>{o.icon}</div>
        <div>
          <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: accent, background: accent + '18', padding: '2px 8px', borderRadius: 99 }}>Resultado · {OUT_KIND_LABEL[o.kind]}</span>
          <div style={{ fontSize: 21, fontWeight: 800, fontStyle: 'italic', color: MA.azul, lineHeight: 1.12, marginTop: 5 }}>{o.title}</div>
        </div>
      </div>

      <p style={{ fontSize: 13.5, color: MA.inkMid, lineHeight: 1.55, margin: '0 0 16px' }}>{o.desc}</p>

      {o.link && (
        <a href={o.link.href} target="_blank" rel="noopener noreferrer" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, fontWeight: 700, color: accent, textDecoration: 'none', margin: '-8px 0 14px' }}>
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.3" strokeLinecap="round" strokeLinejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
          {o.link.label}
        </a>
      )}

      {o.nota && (
        <div style={{ display: 'flex', gap: 9, alignItems: 'flex-start', background: '#f5f3ff', border: '1px solid #ddd6fe', borderRadius: 10, padding: '11px 14px', marginBottom: 16 }}>
          <span style={{ fontSize: 13, flexShrink: 0 }}>👥</span>
          <p style={{ fontSize: 12.5, color: '#5b21b6', lineHeight: 1.5, margin: 0 }}>{o.nota}</p>
        </div>
      )}

      <div style={{ borderTop: '1px dashed ' + MA.border, paddingTop: 14, display: 'flex', gap: 9, alignItems: 'center' }}>
        <span style={{ fontSize: 14, flexShrink: 0 }}>👉</span>
        <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>Tocá <b>Siguiente</b>: primero preparás lo necesario para este caso y después venís al paso a paso detallado.</p>
      </div>

      <div style={{ marginTop: 18, borderTop: '1px solid ' + MA.border, paddingTop: 14 }}>
        <button onClick={onRestart} style={{ display: 'inline-flex', alignItems: 'center', gap: 7, background: 'transparent', border: 'none', color: MA.inkDim, fontFamily: MA.font, fontSize: 12.5, fontWeight: 700, cursor: 'pointer', padding: 0 }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path></svg>
          Volver a elegir el estado
        </button>
      </div>
    </div>
  );
}

function PortfolioDecisionTree({ color, subpasos, onGoFase, onResult }) {
  const [stack, setStack] = React.useState([PORTFOLIO_TREE.start]);
  const [answers, setAnswers] = React.useState([]); // [{ short, label }]
  const currentId = stack[stack.length - 1];
  const isOut = currentId.startsWith('out_');
  const node = isOut ? PORTFOLIO_TREE.out[currentId] : PORTFOLIO_TREE.q[currentId];

  React.useEffect(() => {
    if (onResult) onResult(isOut ? { kind: node.kind, title: node.title } : null);
  }, [currentId]);

  const choose = (opt) => {
    const q = PORTFOLIO_TREE.q[currentId];
    setAnswers((a) => [...a, { short: q.short, label: opt.label }]);
    setStack((s) => [...s, opt.to]);
  };
  const back = () => {
    if (stack.length <= 1) return;
    setStack((s) => s.slice(0, -1));
    setAnswers((a) => a.slice(0, -1));
  };
  const jumpTo = (k) => {
    // volver a la pregunta que se respondió en la posición k
    setStack((s) => s.slice(0, k + 1));
    setAnswers((a) => a.slice(0, k));
  };
  const restart = () => { setStack([PORTFOLIO_TREE.start]); setAnswers([]); };

  const stepNum = answers.length + (isOut ? 0 : 1);

  return (
    <div>
      <p style={{ fontSize: 13.5, color: MA.inkMid, lineHeight: 1.55, margin: '0 0 14px' }}>
        Respondé según el <b>estado de la cuenta de Facebook del negocio</b> que muestra el <b>portal de activación</b> del cliente (el <b>Administrador Comercial</b>, antes “Portfolio / Administrador Comercial”). Son <b>2 preguntas</b>: primero el estado, después una segunda pregunta que define la salida exacta.
      </p>

      {/* Breadcrumb de respuestas */}
      {answers.length > 0 && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 14 }}>
          {answers.map((a, k) => (
            <button key={k} onClick={() => jumpTo(k)} title="Volver a esta pregunta" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, background: '#f0f4ff', border: '1px solid #c7d7f5', borderRadius: 99, padding: '4px 10px', cursor: 'pointer', fontFamily: MA.font }}>
              <span style={{ fontSize: 9.5, fontWeight: 800, letterSpacing: '.04em', textTransform: 'uppercase', color: MA.inkDim }}>{a.short}</span>
              <span style={{ fontSize: 11.5, fontWeight: 700, color: MA.azul }}>{a.label}</span>
            </button>
          ))}
        </div>
      )}

      {!isOut ? (
        <div style={{ background: '#fff', border: '1px solid ' + MA.border, borderRadius: 16, padding: '22px 24px', boxShadow: '0 2px 10px #0b153710' }}>
          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: color, marginBottom: 8 }}>{node.eyebrow || ('Pregunta ' + stepNum)}</div>
          <h3 style={{ fontSize: 'clamp(19px,2.4vw,23px)', fontWeight: 800, fontStyle: 'italic', color: MA.azul, lineHeight: 1.15, margin: '0 0 6px' }}>{node.title}</h3>
          {node.hint && <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: '0 0 4px' }}>{node.hint}</p>}
          {node.link && (
            <a href={node.link.href} target="_blank" rel="noopener noreferrer" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, fontWeight: 700, color: color, textDecoration: 'none', marginBottom: 4 }}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.3" strokeLinecap="round" strokeLinejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
              {node.link.label}
            </a>
          )}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 9, marginTop: 16 }}>
            {node.options.map((opt, k) => (
              <button key={k} onClick={() => choose(opt)} style={{ display: 'flex', alignItems: 'flex-start', gap: 12, width: '100%', textAlign: 'left', background: '#fff', border: '1.5px solid ' + MA.border, borderRadius: 12, padding: '14px 16px', cursor: 'pointer', fontFamily: MA.font, transition: 'all .15s' }}
                onMouseEnter={(e) => { e.currentTarget.style.borderColor = color; e.currentTarget.style.background = color + '08'; }}
                onMouseLeave={(e) => { e.currentTarget.style.borderColor = MA.border; e.currentTarget.style.background = '#fff'; }}>
                <span style={{ width: 26, height: 26, borderRadius: '50%', border: '2px solid ' + color + '55', flexShrink: 0, marginTop: 1 }}></span>
                <span style={{ flex: 1, minWidth: 0 }}>
                  <span style={{ display: 'block', fontSize: 14.5, fontWeight: 700, color: MA.ink }}>{opt.label}</span>
                  {opt.sub && <span style={{ display: 'block', fontSize: 12, fontWeight: 500, color: MA.inkMid, lineHeight: 1.4, marginTop: 3 }}>{opt.sub}</span>}
                </span>
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0, marginTop: 3 }}><path d="M9 18l6-6-6-6"></path></svg>
              </button>
            ))}
          </div>

          {stack.length > 1 && (
            <button onClick={back} style={{ display: 'inline-flex', alignItems: 'center', gap: 7, marginTop: 16, background: 'transparent', border: 'none', color: MA.inkDim, fontFamily: MA.font, fontSize: 12.5, fontWeight: 700, cursor: 'pointer', padding: 0 }}>
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"></path></svg>
              Volver
            </button>
          )}
        </div>
      ) : (
        <DecisionOutcome o={node} color={color} subpasos={subpasos} onGoFase={onGoFase} onRestart={restart} />
      )}
    </div>
  );
}

// Modo de vinculación del número — se decide al vincular a Pip, pero se anticipa acá.
const MODOS_VINCULACION = {
  intro: 'Además del estado del portfolio, anticipá cómo se va a vincular el número a Pip: define qué número usar y qué pierde o mantiene el cliente.',
  opciones: [
    {
      key: 'coex', label: 'Coexistencia', icon: '🔗',
      tagline: 'Conecta la cuenta de WhatsApp que el cliente ya usa.',
      cuando: 'El cliente usa grupos, llamadas, catálogo o estados y quiere mantenerlos.',
      warnings: [
        'Mantiene grupos, llamadas, catálogo y estados.',
        'Debe responder al menos 1 conversación cada 15 días desde WhatsApp.',
        'El número tiene que ser un WhatsApp Business con más de 3 días de uso.',
        'La vinculación termina con el cliente escaneando un QR.',
      ],
    },
    {
      key: 'cloud', label: 'Cloud API pura', icon: '☁️',
      tagline: 'Crea una cuenta de WhatsApp Business nueva.',
      cuando: 'El cliente prioriza estabilidad, escala y publicidad.',
      warnings: [
        'Pierde grupos, llamadas y estados; WhatsApp deja de usarse en el celular.',
        'El número queda sin WhatsApp asociado (la cuenta se elimina).',
        'No puede escribirle a Pip desde ese número: que use otra línea.',
        'Sin historial, Meta puede pedir verificación adicional.',
        'No verificado + rubro sensible + Cloud API = bloqueo preventivo de Meta.',
      ],
    },
  ],
};

function ModoVinculacionSelector({ color }) {
  const [modo, setModo] = React.useState('coex');
  const sel = MODOS_VINCULACION.opciones.find((o) => o.key === modo);
  return (
    <div style={{ marginTop: 18, background: '#fff', border: '1px solid ' + MA.border, borderRadius: 14, padding: '16px 18px' }}>
      <div style={{ fontSize: 13.5, fontWeight: 800, color: MA.ink, marginBottom: 3 }}>🔀 ¿Coexistencia o Cloud API pura?</div>
      <p style={{ fontSize: 12, color: MA.inkMid, lineHeight: 1.5, margin: '0 0 12px' }}>{MODOS_VINCULACION.intro}</p>
      <div style={{ display: 'flex', gap: 8, marginBottom: 14 }}>
        {MODOS_VINCULACION.opciones.map((o) => {
          const on = o.key === modo;
          return (
            <button key={o.key} onClick={() => setModo(o.key)} style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 2, alignItems: 'flex-start', textAlign: 'left', background: on ? color : '#fff', color: on ? '#fff' : MA.ink, border: '1.5px solid ' + (on ? color : MA.border), borderRadius: 11, padding: '11px 14px', fontFamily: MA.font, cursor: 'pointer', transition: 'all .15s' }}>
              <span style={{ fontSize: 13, fontWeight: 800 }}>{o.icon} {o.label}</span>
              <span style={{ fontSize: 11, fontWeight: 500, color: on ? '#ffffffcc' : MA.inkMid, lineHeight: 1.35 }}>{o.tagline}</span>
            </button>
          );
        })}
      </div>
      <div style={{ background: color + '0e', border: '1px solid ' + color + '33', borderRadius: 11, padding: '13px 15px' }}>
        <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.05em', textTransform: 'uppercase', color: color, marginBottom: 3 }}>Cuándo va {sel.label}</div>
        <p style={{ fontSize: 12.5, color: MA.ink, lineHeight: 1.5, margin: '0 0 11px', fontWeight: 600 }}>{sel.cuando}</p>
        <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.05em', textTransform: 'uppercase', color: '#b45309', marginBottom: 7 }}>⚠️ Tené en cuenta</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
          {sel.warnings.map((w, j) => (
            <div key={j} style={{ display: 'flex', gap: 9, alignItems: 'flex-start', fontSize: 12.5, color: MA.ink, lineHeight: 1.5 }}>
              <span style={{ width: 5, height: 5, borderRadius: '50%', background: '#f59e0b', flexShrink: 0, marginTop: 6 }}></span>
              <span>{w}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// PASO FACEBOOK — sub-pasos en acordeón (Portfolio → App → Verificación)
// ─────────────────────────────────────────────────────────────
function FacebookDetail({ paso, r, onNextStep }) {
  const [zoom, setZoom] = React.useState(null);
  const doZoom = (src, cap) => setZoom({ src, cap });
  const [faseIdx, setFaseIdx] = React.useState(0);
  const carRef = React.useRef(null);
  const [treeResult, setTreeResult] = React.useState(null);
  const phaseFilter = treeResult && treeResult.kind ? OUT_PHASES[treeResult.kind] : null;
  const visibleSubpasos = phaseFilter ? paso.subpasos.filter((sp) => phaseFilter.includes(sp.id)) : paso.subpasos;
  React.useEffect(() => { setFaseIdx(0); }, [treeResult]);
  const [stage, setStage] = React.useState(0);
  const [checkedItems, setCheckedItems] = React.useState({});
  const topRef = React.useRef(null);
  const mounted = React.useRef(false);
  React.useEffect(() => { setCheckedItems({}); }, [treeResult]);
  const currentChecklist = treeResult && treeResult.kind ? (OUT_CHECKLIST[treeResult.kind] || []) : [];
  const allChecked = currentChecklist.length > 0 && currentChecklist.every((_, i) => checkedItems[i]);
  const STAGES = [{ title: 'Identificá el estado' }, { title: 'Preparate' }, { title: 'Paso a paso' }];
  const canNext = stage === 0 ? !!treeResult : stage === 1 ? true : false;
  const goStage = (s) => setStage(Math.max(0, Math.min(2, s)));
  React.useEffect(() => {
    if (!mounted.current) { mounted.current = true; return; }
    if (topRef.current) {
      const top = topRef.current.getBoundingClientRect().top + window.scrollY - 90;
      window.scrollTo({ top, behavior: 'smooth' });
    }
  }, [stage]);
  const goToFase = (idx) => { setStage(2); setFaseIdx(idx); };
  return (
    <div ref={topRef}>
      <div style={{ display: 'flex', gap: 8, marginBottom: 26, flexWrap: 'wrap' }}>
        {STAGES.map((st, idx) => {
          const done = idx < stage, current = idx === stage, clickable = idx <= stage;
          return (
            <button key={idx} onClick={() => { if (clickable) goStage(idx); }} disabled={!clickable} style={{ display: 'flex', alignItems: 'center', gap: 9, background: current ? r.color : (done ? r.color + '14' : '#f1f3f8'), border: '1px solid ' + (current ? r.color : (done ? r.color + '44' : MA.border)), borderRadius: 99, padding: '8px 14px', cursor: clickable ? 'pointer' : 'default', fontFamily: MA.font, opacity: clickable ? 1 : 0.5 }}>
              <span style={{ width: 22, height: 22, borderRadius: '50%', background: current ? '#fff' : (done ? r.color : '#d7dbe8'), color: current ? r.color : '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, fontWeight: 800, flexShrink: 0 }}>{done ? '✓' : (idx + 1)}</span>
              <span style={{ fontSize: 12.5, fontWeight: 800, color: current ? '#fff' : MA.inkMid }}>{st.title}</span>
            </button>
          );
        })}
      </div>

      {stage === 0 && (
      <Bloque num="1" of="3" title="Identificá el estado" hint="Completá el flujo del portal de activación y detectá el estado del cliente" icon="🧭" color={r.color}>
        {paso.prereqs && (
          <div style={{ marginTop: 4 }}>
            <PortfolioDecisionTree color={r.color} subpasos={visibleSubpasos} onGoFase={goToFase} onResult={setTreeResult} />
          </div>
        )}
        <ModoVinculacionSelector color={r.color} />
      </Bloque>
      )}

      {stage === 1 && (
      <Bloque num="2" of="3" title="Preparate" hint="Tené esto listo antes de arrancar el paso a paso" icon="✅" color={r.color}>
        {treeResult && (
          <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start', background: (OUT_ACCENT[treeResult.kind] || r.color) + '12', border: '1px solid ' + (OUT_ACCENT[treeResult.kind] || r.color) + '44', borderRadius: 12, padding: '12px 15px', marginBottom: 16 }}>
            <span style={{ fontSize: 15, flexShrink: 0 }}>🌳</span>
            <div>
              <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: (OUT_ACCENT[treeResult.kind] || r.color) }}>Estado detectado</div>
              <p style={{ fontSize: 12.5, color: MA.ink, margin: '2px 0 0', lineHeight: 1.5, fontWeight: 700 }}>{treeResult.title}</p>
            </div>
          </div>
        )}
        <div style={{ background: '#fff', border: '1px solid ' + MA.border, borderRadius: 14, padding: '16px 20px' }}>
          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: MA.inkDim, marginBottom: 14 }}>Checklist para este caso</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {currentChecklist.map((it, i) => {
              const on = !!checkedItems[i];
              return (
                <div key={i} style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
                  <button onClick={() => setCheckedItems((c) => ({ ...c, [i]: !c[i] }))} style={{ width: 20, height: 20, borderRadius: 6, border: '2px solid ' + (on ? r.color : r.color + '66'), background: on ? r.color : '#fff', flexShrink: 0, marginTop: 1, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 0 }}>
                    {on && <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5"></path></svg>}
                  </button>
                  <span style={{ fontSize: 13.5, color: MA.ink, lineHeight: 1.5, textDecoration: on ? 'line-through' : 'none', opacity: on ? 0.55 : 1 }}>{it}</span>
                </div>
              );
            })}
          </div>
        </div>
      </Bloque>
      )}

      {stage === 2 && (
      <>
      <div ref={carRef}>
      <Bloque num="3" of="3" title="Paso a paso" hint="Recorré las fases en orden" icon="👣" color={r.color}>
        <FasesCarrusel subpasos={visibleSubpasos} color={r.color} onZoom={doZoom} index={faseIdx} setIndex={setFaseIdx} outcome={treeResult} validationInfo={{ reglaOro: paso.reglaOro, sensibles: paso.sensibles }} onNextStep={onNextStep} />
      </Bloque>
      </div>
      </>
      )}

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, marginTop: 4 }}>
        <button onClick={() => goStage(stage - 1)} disabled={stage === 0} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, background: '#fff', border: '1px solid ' + MA.border, borderRadius: 10, padding: '11px 18px', fontFamily: MA.font, fontSize: 13, fontWeight: 800, color: MA.inkMid, cursor: stage === 0 ? 'default' : 'pointer', opacity: stage === 0 ? 0 : 1 }}>
          <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"></path></svg>
          Anterior
        </button>
        {stage < 2 && (
          <button onClick={() => { if (canNext) goStage(stage + 1); }} disabled={!canNext} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, background: canNext ? MA.azul : '#c7cbd8', color: '#fff', border: 'none', borderRadius: 10, padding: '12px 22px', fontFamily: MA.font, fontSize: 13.5, fontWeight: 800, fontStyle: 'italic', cursor: canNext ? 'pointer' : 'default', boxShadow: canNext ? '0 4px 14px ' + MA.azul + '45' : 'none' }}>
            {stage === 0 ? (treeResult ? 'Siguiente' : 'Identificá el estado para seguir') : 'Siguiente'}
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
          </button>
        )}
      </div>

      <Lightbox data={zoom} onClose={() => setZoom(null)} />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// BLOQUE — encabezado numerado que separa las 3 secciones del paso
// ─────────────────────────────────────────────────────────────
function Bloque({ num, of, title, hint, icon, color, children }) {
  return (
    <section style={{ marginBottom: 30 }}>
      <header style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 14 }}>
        <div style={{ position: 'relative', flexShrink: 0 }}>
          <div style={{ width: 44, height: 44, borderRadius: 13, background: color, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 21, fontWeight: 800, fontStyle: 'italic', boxShadow: '0 4px 12px ' + color + '55' }}>{num}</div>
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
            <span style={{ fontSize: 18 }}>{icon}</span>
            <span style={{ fontSize: 17, fontWeight: 800, letterSpacing: '.02em', color: MA.ink, lineHeight: 1 }}>{title}</span>
            {of && <span style={{ fontSize: 10.5, fontWeight: 700, color: MA.inkDim, background: '#eef0f6', padding: '2px 7px', borderRadius: 99, letterSpacing: '.04em' }}>{num} de {of}</span>}
          </div>
          <div style={{ fontSize: 13, color: MA.inkDim, marginTop: 4 }}>{hint}</div>
        </div>
      </header>
      <div style={{ paddingLeft: 58 }}>{children}</div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// SENSIBLES — rubros y datos sensibles (colapsable si trae `toggle`)
// ─────────────────────────────────────────────────────────────
function SensiblesBlock({ data, onGoStep }) {
  const [open, setOpen] = React.useState(false);
  const Items = ({ items }) => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {items.map((it, i) => (
        <div key={i} style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: '#7c2d12' }}>
          <span style={{ width: 5, height: 5, borderRadius: '50%', background: '#f59e0b', flexShrink: 0 }}></span>{it}
        </div>
      ))}
    </div>
  );
  return (
    <div style={{ background: '#fff7ed', border: '1px solid #fed7aa', borderRadius: 14, padding: '18px 22px' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
        <span style={{ fontSize: 18 }}>⚠️</span>
        <div style={{ fontSize: 12, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: '#b45309' }}>{data.title}</div>
      </div>
      {data.regla && <p style={{ fontSize: 14, color: '#7c2d12', lineHeight: 1.55, margin: '0 0 14px', fontWeight: 700 }}>{data.regla}</p>}

      {data.toggle ? (
        <div>
          <button onClick={() => setOpen(!open)} style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, background: '#fff', border: '1.5px solid #fdba74', borderRadius: 10, padding: '11px 14px', cursor: 'pointer', fontFamily: MA.font }}>
            <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ fontSize: 15 }}>🛡️</span>
              <span style={{ fontSize: 13.5, fontWeight: 800, color: '#b45309' }}>{data.toggle}</span>
            </span>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#b45309" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round" style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .2s', flexShrink: 0 }}><path d="M6 9l6 6 6-6"></path></svg>
          </button>
          {open && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 12 }}>
              <div style={{ background: '#fff', border: '1px solid #fed7aa', borderRadius: 10, padding: '13px 15px' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 9 }}>
                  <span style={{ fontSize: 14 }}>🏷️</span>
                  <div style={{ fontSize: 11.5, fontWeight: 800, color: '#b45309' }}>{data.rubrosLabel || 'Cuando el rubro es sensible'}</div>
                </div>
                <Items items={data.rubros} />
              </div>
              <div style={{ background: '#fff', border: '1px solid #fed7aa', borderRadius: 10, padding: '13px 15px' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 9 }}>
                  <span style={{ fontSize: 14 }}>💬</span>
                  <div style={{ fontSize: 11.5, fontWeight: 800, color: '#b45309' }}>{data.datosLabel || 'Cuando piden datos sensibles por WhatsApp'}</div>
                </div>
                <Items items={data.datos} />
              </div>
              {onGoStep && (
                <button onClick={() => onGoStep(FLAT.findIndex(p => p.detail === 'facebook'))} style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, width: '100%', background: '#b45309', color: '#fff', border: 'none', borderRadius: 10, padding: '12px 16px', fontFamily: MA.font, fontSize: 13, fontWeight: 800, cursor: 'pointer', marginTop: 2, boxShadow: '0 3px 10px #b4530944' }}>
                  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><path d="M3 9h18M9 21V9"></path></svg>
                  Mandar a verificar el portfolio · Paso 2 (Facebook)
                  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
                </button>
              )}
            </div>
          )}
        </div>
      ) : data.puntos ? (
        <Items items={data.puntos} />
      ) : (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
          <div>
            <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: '#b45309', marginBottom: 8 }}>Rubros</div>
            <Items items={data.rubros} />
          </div>
          <div>
            <div style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: '#b45309', marginBottom: 8 }}>Datos sensibles</div>
            <Items items={data.datos} />
          </div>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// CONTENIDO DE UN PASO
// ─────────────────────────────────────────────────────────────
function ErroresChecklist({ errores, compact }) {
  const [done, setDone] = React.useState({});
  return (
    <div style={{ background: '#fef2f2', border: '1px solid #fecaca', borderRadius: compact ? 12 : 14, padding: '6px 6px' }}>
      {errores.map((e, i) => {
        const on = !!done[i];
        return (
          <button key={i} onClick={() => setDone((d) => ({ ...d, [i]: !d[i] }))} title={on ? 'Marcar como pendiente' : 'Marcar como repasado'} style={{ width: '100%', textAlign: 'left', background: 'transparent', border: 'none', cursor: 'pointer', fontFamily: MA.font, display: 'flex', gap: 12, alignItems: 'flex-start', padding: compact ? '11px 16px' : '12px 16px', borderBottom: i < errores.length - 1 ? '1px solid #fecaca80' : 'none' }}>
            <span style={{ width: 22, height: 22, borderRadius: '50%', background: on ? MA.turquesa : '#fee2e2', color: on ? '#fff' : MA.danger, fontWeight: 800, flexShrink: 0, fontSize: 13, display: 'flex', alignItems: 'center', justifyContent: 'center', marginTop: 1, transition: 'all .15s' }}>{on ? '✓' : '✕'}</span>
            <p style={{ fontSize: compact ? 13.5 : 14, color: '#7f1d1d', lineHeight: 1.5, margin: 0, textDecoration: on ? 'line-through' : 'none', opacity: on ? 0.5 : 1, transition: 'opacity .15s' }}>{e}</p>
          </button>
        );
      })}
    </div>
  );
}

function PasoContent({ paso, onNavigate, stepIndex, stepTotal }) {
  const r = paso.reunion;
  const [registro, setRegistro] = React.useState(null);
  const [alta, setAlta] = React.useState(false);
  const [portal, setPortal] = React.useState(false);
  const [zoom, setZoom] = React.useState(null);
  const handleAction = (id) => { if (id === 'alta') setAlta(true); else if (id === 'portal') setPortal(true); else if (id === 'registro-cloud') setRegistro('cloud'); else if (id === 'registro-coex') setRegistro('coex'); };
  return (
    <div style={{ flex: 1, minWidth: 0, maxWidth: 680 }}>
      {/* Header del paso */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 22 }}>
        <div style={{ width: 54, height: 54, borderRadius: 14, background: r.color + '18', color: r.color, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 26, flexShrink: 0 }}>{paso.icon}</div>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4 }}>
            <span style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.06em', color: r.color }}>{paso.n === 0 ? 'PASO PREVIO' : 'PASO ' + paso.n}</span>
            <span style={{ fontSize: 11, fontWeight: 600, color: r.color, background: r.color + '15', padding: '3px 9px', borderRadius: 99 }}>{paso.who}</span>
          </div>
          <h2 style={{ fontSize: 'clamp(24px,3vw,32px)', fontWeight: 800, fontStyle: 'italic', color: MA.azul, lineHeight: 1.05, letterSpacing: '-.02em', margin: 0 }}>{paso.name}</h2>
          <p style={{ fontSize: 14, color: MA.inkMid, margin: '5px 0 0' }}>{paso.subtitle}</p>
        </div>
      </div>

      {/* Contenido: detalle Facebook (sub-pasos) o formato estándar */}
      {paso.detail === 'facebook' ? (
        <FacebookDetail paso={paso} r={r} onNextStep={(stepIndex != null && stepIndex < stepTotal - 1) ? () => onNavigate(stepIndex + 1) : null} />
      ) : (
      <React.Fragment>

      {/* ① QUÉ HACÉS */}
      {!paso.hideRol && (
      <Bloque num="1" of="3" title="Qué hacés" hint="Tu rol en este paso — leé primero el panorama" icon="🎯" color={r.color}>
        <div style={{ background: r.color + '0a', border: '1px solid ' + r.color + '2e', borderRadius: 14, padding: '20px 24px', marginBottom: (paso.sensibles || paso.checklistPrevio) ? 16 : 0 }}>
          <p style={{ fontSize: 15.5, color: MA.ink, lineHeight: 1.62, margin: 0 }}>{paso.rol}</p>
        </div>

        {paso.checklistPrevio && (
          <div style={{ marginBottom: paso.sensibles ? 16 : 0, background: '#fff', border: '1px solid ' + r.color + '33', borderLeft: '4px solid ' + r.color, borderRadius: 12, padding: '15px 18px' }}>
            <div style={{ fontSize: 13.5, fontWeight: 800, color: MA.ink, marginBottom: 10 }}>✅ {paso.checklistPrevio.title}</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
              {paso.checklistPrevio.items.map((it, j) => (
                <span key={j} style={{ display: 'inline-flex', alignItems: 'center', gap: 7, fontSize: 12.5, fontWeight: 600, color: MA.ink, background: r.color + '10', border: '1px solid ' + r.color + '33', borderRadius: 99, padding: '6px 13px' }}>
                  <span style={{ width: 6, height: 6, borderRadius: '50%', background: r.color, flexShrink: 0 }}></span>{it}
                </span>
              ))}
            </div>
          </div>
        )}

        {paso.sensibles && <SensiblesBlock data={paso.sensibles} onGoStep={onNavigate} />}
        {paso.registroInsertado && (
          <div style={{ marginTop: 14, background: '#fff', border: '1px solid ' + r.color + '33', borderRadius: 14, padding: '16px 18px' }}>
            <div style={{ marginBottom: 12 }}>
              <div style={{ fontSize: 14, fontWeight: 800, color: MA.ink, marginBottom: 3 }}>Vinculá el número a Pip primero</div>
              <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>Antes de capacitar, conectá el WhatsApp del cliente con <b>registro insertado</b>. Hay <b>dos procedimientos</b> según el caso — elegí el que corresponda:</p>
            </div>
            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
              {[{ v: 'coex', t: 'Cómo vincular — Coexistencia', s: 'Conecta la cuenta existente + QR' }, { v: 'cloud', t: 'Cómo vincular — Cloud API', s: 'Crea una cuenta nueva' }].map((b) => (
                <button key={b.v} onClick={() => setRegistro(b.v)} style={{ flex: '1 1 220px', display: 'flex', alignItems: 'center', gap: 11, background: b.v === 'coex' ? MA.azul : '#fff', color: b.v === 'coex' ? '#fff' : MA.azul, border: '1.5px solid ' + MA.azul, borderRadius: 11, padding: '12px 15px', fontFamily: MA.font, cursor: 'pointer', textAlign: 'left', boxShadow: b.v === 'coex' ? '0 3px 10px ' + MA.azul + '45' : 'none', transition: 'all .15s' }}>
                  <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}><path d="M17 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z"></path><path d="M11 18h2"></path></svg>
                  <span style={{ minWidth: 0 }}>
                    <span style={{ display: 'block', fontSize: 12.5, fontWeight: 800, lineHeight: 1.2 }}>{b.t}</span>
                    <span style={{ display: 'block', fontSize: 11, fontWeight: 500, color: b.v === 'coex' ? '#ffffffcc' : MA.inkMid, marginTop: 2 }}>{b.s}</span>
                  </span>
                </button>
              ))}
            </div>
          </div>
        )}
      </Bloque>
      )}

      {/* ② PASO A PASO */}
      <Bloque num={paso.hideRol ? "1" : "2"} of={paso.hideRol ? "2" : "3"} title="Paso a paso" hint="Las acciones en orden — recorré una por una" icon="👣" color={r.color}>
        {paso.pasoNota && (
          <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start', background: r.color + '10', border: '1px solid ' + r.color + '33', borderRadius: 12, padding: '12px 15px', marginBottom: 14 }}>
            <span style={{ fontSize: 15, flexShrink: 0 }}>📆</span>
            <p style={{ fontSize: 12.5, color: MA.ink, lineHeight: 1.5, margin: 0 }}>{paso.pasoNota}</p>
          </div>
        )}
        <AccionesCarrusel key={'car-' + paso.n} acciones={paso.acciones} color={r.color} showLabel={false} onAction={handleAction} onNext={(stepIndex != null && stepIndex < stepTotal - 1) ? () => onNavigate(stepIndex + 1) : null} nextLabel={(stepIndex != null && stepIndex < stepTotal - 1 && FLAT[stepIndex + 1]) ? FLAT[stepIndex + 1].name : null} />
      </Bloque>

      {paso.adicionales && <AdicionalesBlock data={paso.adicionales} />}

      {paso.corroborarVerif && <div style={{ marginBottom: 30 }}><CorroboracionVerificacion /></div>}

      {/* ③ ERRORES A EVITAR */}
      <Bloque num={paso.hideRol ? "2" : "3"} of={paso.hideRol ? "2" : "3"} title="Errores a evitar" hint="Tildá cada uno al repasarlo antes de cerrar" icon="⛔" color={MA.danger}>
        <ErroresChecklist errores={paso.errores} />
      </Bloque>

      {paso.pasarActivo && (
        <div style={{ marginTop: 4, background: r.color + '0c', border: '1px solid ' + r.color + '3a', borderLeft: '5px solid ' + r.color, borderRadius: 14, padding: '18px 20px' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 }}>
            <span style={{ fontSize: 20 }}>🏁</span>
            <div style={{ fontSize: 16, fontWeight: 800, fontStyle: 'italic', color: r.color }}>{paso.pasarActivo.title}</div>
          </div>
          <p style={{ fontSize: 13.5, color: MA.ink, lineHeight: 1.55, margin: 0 }}>{paso.pasarActivo.desc}</p>
        </div>
      )}

      {paso.registroInsertado && <RegistroModal variant={registro} onClose={() => setRegistro(null)} onZoom={(src, cap) => setZoom({ src, cap })} />}
      <AltaModal open={alta} onClose={() => setAlta(false)} onZoom={(src, cap) => setZoom({ src, cap })} />
      <PortalModal open={portal} onClose={() => setPortal(false)} onZoom={(src, cap) => setZoom({ src, cap })} />
      <Lightbox data={zoom} onClose={() => setZoom(null)} />
      </React.Fragment>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// CARRUSEL DE ACCIONES — guiado, secuencial, con iconografía grande
// ─────────────────────────────────────────────────────────────
function AccionesCarrusel({ acciones: allAcciones, color, showLabel = true, onAction, onNext, nextLabel }) {
  const { filter } = React.useContext(RoleFilterCtx);
  const acciones = filter === 'all' ? allAcciones : allAcciones.filter((x) => roleMatches(roleOf(x.title), filter));
  const [iRaw, setI] = React.useState(0);
  const [dir, setDir] = React.useState(1);
  const [grid, setGrid] = React.useState(false);
  React.useEffect(() => { setI(0); }, [filter]);
  const total = acciones.length;
  const i = Math.max(0, Math.min(iRaw, total - 1));
  const a = acciones[i];
  const go = (next) => {
    setDir(next > i ? 1 : -1);
    setI(Math.max(0, Math.min(total - 1, next)));
  };
  const atStart = i === 0, atEnd = i === total - 1;

  if (total === 0) {
    return (
      <div style={{ background: '#fff', border: '1px dashed ' + MA.border, borderRadius: 16, padding: '30px 26px', textAlign: 'center' }}>
        <div style={{ marginBottom: 10 }}><RoleBadge role={filter} /></div>
        <p style={{ fontSize: 14, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>En este paso no hay tareas de <b>{(ROLES[filter] || {}).label || ''}</b>. Cambiá el filtro de rol para ver el resto.</p>
      </div>
    );
  }

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: showLabel ? 'space-between' : 'flex-end', marginBottom: 14 }}>
        {showLabel && <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase', color: MA.inkDim }}>Paso a paso</div>}
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          {!grid && (
            <div style={{ fontSize: 12, fontWeight: 700, color: color, display: 'flex', alignItems: 'center', gap: 4 }}>
              <span style={{ fontSize: 12, fontWeight: 600, color: MA.inkDim, textTransform: 'uppercase', letterSpacing: '.04em', marginRight: 4 }}>Acción</span>
              <span style={{ fontSize: 17 }}>{i + 1}</span>
              <span style={{ color: MA.inkDim, fontWeight: 600 }}>/ {total}</span>
            </div>
          )}
          <button onClick={() => setGrid(!grid)} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, background: grid ? color : '#fff', color: grid ? '#fff' : MA.inkMid, border: '1px solid ' + (grid ? color : MA.border), borderRadius: 99, padding: '5px 12px', fontFamily: MA.font, fontSize: 11.5, fontWeight: 800, cursor: 'pointer' }}>
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect></svg>
            {grid ? 'Ver de a uno' : 'Ver todo'}
          </button>
        </div>
      </div>

      {grid ? (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(230px, 1fr))', gap: 10 }}>
          {acciones.map((a2, k) => (
            <div key={k} style={{ background: '#fff', border: '1px solid ' + MA.border, borderRadius: 14, padding: '15px 16px', display: 'flex', flexDirection: 'column', gap: 8, boxShadow: '0 1px 4px #0b15370d' }}>
              {roleOf(a2.title) && <div style={{ display: 'flex', justifyContent: 'flex-end' }}><RoleBadge role={roleOf(a2.title)} size="sm" /></div>}
              <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <span style={{ width: 38, height: 38, borderRadius: '50%', background: color + '15', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 19, border: '2px solid ' + color + '30', flexShrink: 0 }}>{a2.icon}</span>
                <div>
                  <div style={{ fontSize: 9.5, fontWeight: 800, color: color, letterSpacing: '.04em' }}>{String(k + 1).padStart(2, '0')}</div>
                  <div style={{ fontSize: 13.5, fontWeight: 800, color: MA.ink, lineHeight: 1.2 }}>{a2.title}</div>
                </div>
              </div>
              <p style={{ fontSize: 12.5, color: MA.inkMid, lineHeight: 1.5, margin: 0 }}>{a2.desc}</p>
              {a2.link && (
                <a href={a2.link.href} target="_blank" rel="noopener noreferrer" style={{ fontSize: 12, fontWeight: 800, color: color, textDecoration: 'none' }}>{a2.link.label} ↗</a>
              )}
              {a2.action && onAction && (
                <button onClick={() => onAction(a2.action)} style={{ alignSelf: 'flex-start', background: MA.azul, color: '#fff', border: 'none', borderRadius: 8, padding: '7px 12px', fontFamily: MA.font, fontSize: 11.5, fontWeight: 800, cursor: 'pointer' }}>{a2.actionLabel || 'Ver detalle'}</button>
              )}
            </div>
          ))}
        </div>
      ) : (
      <div style={{ position: 'relative', background: '#fff', border: '1px solid ' + MA.border, borderRadius: 18, overflow: 'hidden', boxShadow: '0 2px 10px #0b153710' }}>
        {/* Barra de progreso */}
        <div style={{ height: 4, background: '#eef0f6' }}>
          <div style={{ height: '100%', width: ((i + 1) / total * 100) + '%', background: color, borderRadius: 4, transition: 'width .3s ease' }}></div>
        </div>

        {/* Slide */}
        <div style={{ padding: '34px 30px 26px', minHeight: 232, display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', justifyContent: 'center' }}>
          <div key={i} className="carrusel-slide" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', '--slide-dir': dir }}>
            <div style={{ width: 92, height: 92, borderRadius: '50%', background: color + '15', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 46, marginBottom: 20, border: '2px solid ' + color + '30' }}>{a.icon}</div>
            <div style={{ fontSize: 13, fontWeight: 800, color: color, letterSpacing: '.02em', marginBottom: 8 }}>{String(i + 1).padStart(2, '0')}</div>
            {roleOf(a.title) && <div style={{ marginBottom: 10 }}><RoleBadge role={roleOf(a.title)} /></div>}
            <h3 style={{ fontSize: 'clamp(20px,2.6vw,26px)', fontWeight: 800, fontStyle: 'italic', color: MA.azul, lineHeight: 1.1, letterSpacing: '-.01em', margin: '0 0 12px' }}>{a.title}</h3>
            <p style={{ fontSize: 15, color: MA.inkMid, lineHeight: 1.55, margin: 0, maxWidth: 440 }}>{a.desc}</p>
            {a.link && (
              <a href={a.link.href} target="_blank" rel="noopener noreferrer" style={{ display: 'inline-flex', alignItems: 'center', gap: 8, marginTop: 18, background: '#fff', border: '1.5px solid ' + color, color: color, borderRadius: 10, padding: '10px 18px', fontFamily: MA.font, fontSize: 13, fontWeight: 800, textDecoration: 'none' }}>
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"></rect><path d="M16 2v4M8 2v4M3 10h18"></path></svg>
                {a.link.label}
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M7 17L17 7M7 7h10v10"></path></svg>
              </a>
            )}
            {a.action && onAction && (
              <button onClick={() => onAction(a.action)} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, marginTop: 18, background: MA.azul, color: '#fff', border: 'none', borderRadius: 10, padding: '11px 20px', fontFamily: MA.font, fontSize: 13, fontWeight: 800, cursor: 'pointer', boxShadow: '0 3px 10px ' + MA.azul + '45' }}>
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><path d="M3 9h18M9 21V9"></path></svg>
                {a.actionLabel || 'Ver detalle'}
              </button>
            )}

          </div>
        </div>

        {/* Controles */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 18px 20px' }}>
          <button onClick={() => go(i - 1)} disabled={atStart} aria-label="Anterior" style={{ width: 42, height: 42, borderRadius: '50%', border: '1.5px solid ' + (atStart ? '#e5e7eb' : color), background: '#fff', color: atStart ? '#cbd0dc' : color, cursor: atStart ? 'not-allowed' : 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all .15s', flexShrink: 0 }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"></path></svg>
          </button>

          <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'center' }}>
            {acciones.map((_, d) => (
              <button key={d} onClick={() => go(d)} aria-label={'Ir a paso ' + (d + 1)} style={{ width: d === i ? 24 : 9, height: 9, borderRadius: 99, border: 'none', background: d === i ? color : '#d6dae5', cursor: 'pointer', padding: 0, transition: 'all .25s' }}></button>
            ))}
          </div>

          {atEnd && onNext ? (
            <button onClick={onNext} aria-label={'Siguiente paso' + (nextLabel ? ': ' + nextLabel : '')} title={nextLabel || 'Siguiente paso'} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, height: 42, borderRadius: 99, border: 'none', background: color, color: '#fff', cursor: 'pointer', padding: '0 16px 0 18px', fontFamily: MA.font, fontSize: 12.5, fontWeight: 800, transition: 'all .15s', flexShrink: 0, boxShadow: '0 3px 10px ' + color + '50', whiteSpace: 'nowrap' }}>
            <span>Siguiente paso</span>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
          </button>
          ) : (
          <button onClick={() => go(i + 1)} disabled={atEnd} aria-label="Siguiente" style={{ width: 42, height: 42, borderRadius: '50%', border: 'none', background: atEnd ? '#eef0f6' : color, color: atEnd ? '#cbd0dc' : '#fff', cursor: atEnd ? 'not-allowed' : 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all .15s', flexShrink: 0, boxShadow: atEnd ? 'none' : '0 3px 10px ' + color + '50' }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M9 18l6-6-6-6"></path></svg>
          </button>
          )}
        </div>
      </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// PORTADA
// ─────────────────────────────────────────────────────────────
function Portada({ onStart }) {
  const logo = (window.__resources && window.__resources.pipLogo) || 'assets/pip-logo.png';
  const robot = (window.__resources && window.__resources.pipRobot) || 'assets/pip-robot-nobg.png';
  return (
    <div className="portada">
      <div className="portada-inner">
        <div className="portada-content">
          <img src={logo} alt="Pip" className="portada-logo" />
          <div className="eyebrow">Guía operativa interna</div>
          <h1>Manual del <span>Activador</span></h1>
          <p className="portada-sub">
            Todo lo que necesitás para acompañar a un cliente en las <strong>3 sesiones</strong> de activación + <strong>seguimiento</strong> post-activación.
            Mismo esquema de pasos que el Portal: un <strong>paso previo</strong> de preparación + <strong>5 pasos</strong>, en orden, sin improvisar.
          </p>
          <button className="portada-cta" onClick={onStart}>
            Empezar
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
          </button>
        </div>
        <div className="portada-robot-wrap">
          <img src={robot} alt="Pip Bot" className="portada-robot" />
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// APP
// ─────────────────────────────────────────────────────────────
function ManualApp() {
  const logo = (window.__resources && window.__resources.pipLogo) || 'assets/pip-logo.png';
  const [recurso, setRecurso] = React.useState(null);
  const [recMenu, setRecMenu] = React.useState(false);
  const [mainView, setMainView] = React.useState('manual'); // 'manual' | 'portal-client' | 'portal-activator'
  const [navZoom, setNavZoom] = React.useState(null);
  const [started, setStarted] = React.useState(() => {
    try { return localStorage.getItem(STORAGE_KEY) !== null; } catch { return false; }
  });
  const [step, setStep] = React.useState(() => {
    try { const s = parseInt(localStorage.getItem(STORAGE_KEY), 10); return isNaN(s) ? 0 : Math.max(0, Math.min(FLAT.length - 1, s)); } catch { return 0; }
  });
  const [roleFilter, setRoleFilter] = React.useState(() => {
    try { return localStorage.getItem(ROLE_FILTER_KEY) || 'all'; } catch { return 'all'; }
  });
  React.useEffect(() => { try { localStorage.setItem(ROLE_FILTER_KEY, roleFilter); } catch {} }, [roleFilter]);

  React.useEffect(() => {
    if (started) { try { localStorage.setItem(STORAGE_KEY, String(step)); } catch {} }
  }, [step, started]);

  React.useEffect(() => {
    if (!started) return;
    const onScroll = () => {
      const el = document.querySelector('.stepper-wrap');
      if (!el) return;
      const y = window.scrollY;
      const collapsed = el.classList.contains('is-collapsed');
      if (!collapsed && y > 200) el.classList.add('is-collapsed');
      else if (collapsed && y < 90) el.classList.remove('is-collapsed');
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, [started]);

  function goTo(i) {
    setStep(Math.max(0, Math.min(FLAT.length - 1, i)));
    window.scrollTo({ top: 0 });
  }

  const paso = FLAT[step];

  return (
    <RoleFilterCtx.Provider value={{ filter: roleFilter, setFilter: setRoleFilter }}>
    <div>
      <nav className="pip-nav">
        <div className="pip-nav-left">
          <img src={logo} alt="Pip" className="pip-nav-logo" />
        </div>
        <div className="pip-view-switch">
          {[
            { id: 'manual', label: 'Manual del activador' },
            { id: 'portal-client', label: 'Portal (Cliente)' },
            { id: 'portal-activator', label: 'Portal (Activador)' },
          ].map((v) => (
            <button key={v.id} className={'pip-view-btn' + (mainView === v.id ? ' active' : '')} onClick={() => setMainView(v.id)}>{v.label}</button>
          ))}
        </div>
        <div className="pip-nav-right">
          <div style={{ position: 'relative' }}>
            <button className="pip-nav-link" onClick={() => setRecMenu(!recMenu)}>
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>
              <span>Recursos</span>
              <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" style={{ transform: recMenu ? 'rotate(180deg)' : 'none', transition: 'transform .15s' }}><path d="M6 9l6 6 6-6"></path></svg>
            </button>
            {recMenu && (
              <div style={{ position: 'absolute', top: 'calc(100% + 10px)', right: 0, background: '#fff', border: '1px solid ' + MA.border, borderRadius: 12, boxShadow: '0 12px 32px #0b153726', padding: 6, minWidth: 250, zIndex: 600 }}>
                {[
                  { id: 'alta', icon: '🆕', label: 'Dar de alta un cliente' },
                  { id: 'portal', icon: '🖥️', label: 'El Portal de Activación' },
                  { id: 'portfolio', icon: '🏢', label: 'Crear un Portfolio Comercial' },
                  { id: 'landing', icon: '🛠️', label: 'Crear una landing (GrapesJS)' },
                  { id: 'registro-coex', icon: '📲', label: 'Vincular el número — Coexistencia' },
                  { id: 'registro-cloud', icon: '📲', label: 'Vincular el número — Cloud API' },
                ].map((it) => (
                  <button key={it.id} onClick={() => { setRecurso(it.id); setRecMenu(false); }} style={{ display: 'flex', alignItems: 'center', gap: 10, width: '100%', textAlign: 'left', background: 'transparent', border: 'none', borderRadius: 8, padding: '9px 10px', fontFamily: MA.font, fontSize: 13, fontWeight: 700, color: MA.ink, cursor: 'pointer' }}
                    onMouseEnter={(e) => { e.currentTarget.style.background = '#f0f4ff'; }}
                    onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
                    <span style={{ fontSize: 15 }}>{it.icon}</span>
                    {it.label}
                  </button>
                ))}
              </div>
            )}
          </div>
          {started && (
            <button className="pip-nav-link" onClick={() => { setStarted(false); setStep(0); try { localStorage.removeItem(STORAGE_KEY); } catch {} window.scrollTo({ top: 0 }); }}>
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path></svg>
              <span>Inicio</span>
            </button>
          )}
        </div>
      </nav>

      {mainView !== 'manual' ? (
        <iframe
          key={mainView}
          src={(window.__resources && window.__resources.portalBundle)
            ? window.__resources.portalBundle + '#view=' + (mainView === 'portal-activator' ? 'activator' : 'client')
            : 'Portal de Activación.html?view=' + (mainView === 'portal-activator' ? 'activator' : 'client')}
          title="Portal de Activación"
          style={{ display: 'block', width: '100%', height: 'calc(100vh - 58px)', border: 'none' }}
        ></iframe>
      ) : !started ? (
        <Portada onStart={() => { setStarted(true); setStep(0); }} />
      ) : (
        <div>
          <div className="sticky-head">
            <div className="stepper-wrap">
              <Stepper key={'stepper-' + step} current={step} onStepClick={goTo} />
            </div>

            <div className="role-filter-bar">
              <div style={{ maxWidth: 1080, margin: '0 auto' }}>
                <RoleFilterBar paso={paso} />
              </div>
            </div>
          </div>

          <div className="main-area">
            <div style={{ maxWidth: 1080, margin: '0 auto', display: 'flex', gap: 44, alignItems: 'flex-start', flexWrap: 'wrap' }}>
              <PasoContent paso={paso} onNavigate={goTo} stepIndex={step} stepTotal={FLAT.length} />
              <ReunionAside r={paso.reunion} />
            </div>
          </div>
        </div>
      )}

      <AltaModal open={recurso === 'alta'} onClose={() => setRecurso(null)} onZoom={(src, cap) => setNavZoom({ src, cap })} />
      <PortalModal open={recurso === 'portal'} onClose={() => setRecurso(null)} onZoom={(src, cap) => setNavZoom({ src, cap })} />
      <LandingModal open={recurso === 'landing'} onClose={() => setRecurso(null)} onZoom={(src, cap) => setNavZoom({ src, cap })} />
      <PortfolioModal open={recurso === 'portfolio'} onClose={() => setRecurso(null)} onZoom={(src, cap) => setNavZoom({ src, cap })} />
      <RegistroModal variant={recurso === 'registro-coex' ? 'coex' : recurso === 'registro-cloud' ? 'cloud' : null} onClose={() => setRecurso(null)} onZoom={(src, cap) => setNavZoom({ src, cap })} />
      <Lightbox data={navZoom} onClose={() => setNavZoom(null)} />
    </div>
    </RoleFilterCtx.Provider>
  );
}

window.ManualApp = ManualApp;
