/* MACU RACE 2026 — Step components */

const { useState, useEffect, useRef, useMemo } = React;

// ---- tiny icon helpers (inline SVG) ----
const Icon = {
  Check:    (p) => <svg width={p.s||16} height={p.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>,
  Arrow:    (p) => <svg width={p.s||16} height={p.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>,
  Back:     (p) => <svg width={p.s||16} height={p.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>,
  Alert:    (p) => <svg width={p.s||14} height={p.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>,
  Upload:   (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>,
  File:     (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>,
  Trophy:   (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"/><path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"/><path d="M18 2H6v7a6 6 0 0 0 12 0V2Z"/></svg>,
};

// Mensaje de error inline con role=alert para que sea anunciado por lectores de pantalla.
function ErrorMsg({ id, children }) {
  if (!children) return null;
  return (
    <span id={id} className="error-msg" role="alert" aria-live="polite">
      <Icon.Alert/> {children}
    </span>
  );
}

// ====== Step 1: Documento + Declaración ======
function Step1Documento({ data, set, errors, openModal }) {
  return (
    <div>
      <div className="step-head"><span className="step-head__chip">Paso 1 / 6</span></div>
      <h2 className="step-title">Identificación</h2>
      <p className="step-sub">Empecemos con tu documento. Toda la información viaja encriptada.</p>

      <div className="field--row">
        <div className="field">
          <label className="label" htmlFor="tipoDoc">Tipo de documento <span className="req">*</span></label>
          <select id="tipoDoc"
            className={"select" + (errors.tipoDoc ? ' has-error':'')}
            aria-invalid={!!errors.tipoDoc}
            aria-describedby={errors.tipoDoc ? 'err-tipoDoc' : 'tipoDoc-hint'}
            value={data.tipoDoc}
            onChange={e => set({ tipoDoc: e.target.value })}>
            <option value="">Selecciona…</option>
            <option value="CC">Cédula de ciudadanía</option>
            <option value="CE">Cédula de extranjería</option>
            <option value="TI">Tarjeta de identidad</option>
            <option value="RC">Registro civil</option>
            <option value="PA">Pasaporte</option>
            <option value="Otro">Otro</option>
          </select>
          <small id="tipoDoc-hint" className="field-hint">
            CC y CE: ≥ 18 años · TI y RC: 6 a 17 años · Pasaporte u Otro: cualquier edad.
          </small>
          <ErrorMsg id="err-tipoDoc">{errors.tipoDoc}</ErrorMsg>
        </div>

        <div className="field">
          <label className="label" htmlFor="numDoc">Número de documento <span className="req">*</span></label>
          <input id="numDoc"
            className={"input" + (errors.numDoc ? ' has-error':'')}
            inputMode="numeric"
            placeholder="Ej. 1014567890"
            aria-invalid={!!errors.numDoc}
            aria-describedby={errors.numDoc ? 'err-numDoc' : undefined}
            value={data.numDoc}
            onChange={e => set({ numDoc: e.target.value.replace(/\D/g, '').slice(0,12) })}/>
          <ErrorMsg id="err-numDoc">{errors.numDoc}</ErrorMsg>
        </div>
      </div>

      <div className="check-row-wrap">
        <button type="button"
          role="checkbox"
          aria-checked={data.acepto}
          aria-describedby={errors.acepto ? 'err-acepto' : undefined}
          className={"check-row " + (data.acepto ? 'is-checked':'')}
          onClick={() => { if (!data.acepto) openModal(); else set({ acepto: false }); }}>
          <span className="check-box" aria-hidden="true">
            {data.acepto && <Icon.Check s={14}/>}
          </span>
          <span className="check-row__text">
            He leído y acepto la <strong>declaración de responsabilidad y exoneración</strong> del Macu Race 2026. Reconozco que participo bajo mi propio riesgo.
          </span>
        </button>
        <button type="button" className="link-btn" onClick={openModal}>
          Ver declaración completa
        </button>
      </div>
      <ErrorMsg id="err-acepto">{errors.acepto}</ErrorMsg>
    </div>
  );
}

// ====== Step 2: Datos personales ======
function Step2Datos({ data, set, errors, ageWipedSelections }) {
  return (
    <div>
      <div className="step-head"><span className="step-head__chip">Paso 2 / 6</span></div>
      <h2 className="step-title">Datos del participante</h2>
      <p className="step-sub">Estos datos aparecerán en el dorsal y el certificado de llegada.</p>

      <div className="field">
        <label className="label" htmlFor="nombre">Nombre completo <span className="req">*</span></label>
        <input id="nombre"
          className={"input" + (errors.nombre ? ' has-error':'')}
          placeholder="Nombres y apellidos"
          autoComplete="name"
          aria-invalid={!!errors.nombre}
          aria-describedby={errors.nombre ? 'err-nombre' : undefined}
          value={data.nombre}
          onChange={e => set({ nombre: e.target.value })}/>
        <ErrorMsg id="err-nombre">{errors.nombre}</ErrorMsg>
      </div>

      <div className="field">
        <span className="label" id="lbl-genero">Género <span className="req">*</span></span>
        <div className="pill-group" role="radiogroup" aria-labelledby="lbl-genero" aria-describedby={errors.genero ? 'err-genero' : undefined}>
          {['Masculino','Femenino','Otro'].map(g => (
            <button key={g} type="button"
              role="radio"
              aria-checked={data.genero === g}
              className={"pill " + (data.genero === g ? 'is-active':'')}
              onClick={() => set({ genero: g })}>{g}</button>
          ))}
        </div>
        <ErrorMsg id="err-genero">{errors.genero}</ErrorMsg>
      </div>

      <div className="field">
        <label className="label" htmlFor="email">Correo electrónico <span className="req">*</span></label>
        <input id="email"
          className={"input" + (errors.email ? ' has-error':'')}
          type="email"
          inputMode="email"
          autoComplete="email"
          placeholder="tu@correo.com"
          aria-invalid={!!errors.email}
          aria-describedby={errors.email ? 'err-email' : undefined}
          value={data.email}
          onChange={e => set({ email: e.target.value })}/>
        <ErrorMsg id="err-email">{errors.email}</ErrorMsg>
      </div>

      <div className="field--row">
        <div className="field">
          <span className="label" id="lbl-tipoTel">Tipo de contacto <span className="req">*</span></span>
          <div className="pill-group" role="radiogroup" aria-labelledby="lbl-tipoTel">
            {['Celular','Fijo'].map(t => (
              <button key={t} type="button"
                role="radio"
                aria-checked={data.tipoTel === t}
                className={"pill " + (data.tipoTel === t ? 'is-active':'')}
                onClick={() => set({ tipoTel: t })}>{t}</button>
            ))}
          </div>
        </div>
        <div className="field">
          <label className="label" htmlFor="tel">Número de contacto <span className="req">*</span></label>
          <input id="tel"
            className={"input" + (errors.tel ? ' has-error':'')}
            inputMode="numeric"
            autoComplete="tel"
            placeholder="Ej. 3001234567"
            aria-invalid={!!errors.tel}
            aria-describedby={errors.tel ? 'err-tel' : undefined}
            value={data.tel}
            onChange={e => set({ tel: e.target.value.replace(/\D/g, '').slice(0,10) })}/>
          <ErrorMsg id="err-tel">{errors.tel}</ErrorMsg>
        </div>
      </div>

      <div className="field" style={{maxWidth: 200}}>
        <label className="label" htmlFor="edad">Edad <span className="req">*</span></label>
        <input id="edad"
          className={"input font-num" + (errors.edad ? ' has-error':'')}
          inputMode="numeric"
          placeholder="6 – 99"
          style={{fontSize:18, fontWeight:600}}
          aria-invalid={!!errors.edad}
          aria-describedby={errors.edad ? 'err-edad' : undefined}
          value={data.edad}
          onChange={e => set({ edad: e.target.value.replace(/\D/g, '').slice(0,2) })}/>
        <ErrorMsg id="err-edad">{errors.edad}</ErrorMsg>
      </div>

      {ageWipedSelections && (
        <div className="notice notice--warn" role="status">
          <strong>Atención:</strong> tu modalidad y talla anteriores ya no aplican para esta edad. Tendrás que elegirlas de nuevo en el paso 4.
        </div>
      )}

      {data.edad && Number(data.edad) >= 6 && Number(data.edad) <= 13 && (
        <div className="notice notice--kids">
          <strong>🧒 Macu Race Kids:</strong> participarás en la versión infantil del evento.
        </div>
      )}
    </div>
  );
}

// ====== Step 3: Salud ======
function Step3Salud({ data, set, errors }) {
  return (
    <div>
      <div className="step-head"><span className="step-head__chip">Paso 3 / 6</span></div>
      <h2 className="step-title">Salud y emergencia</h2>
      <p className="step-sub">Información que solo se usa en caso de necesitar atención el día del evento.</p>

      <div className="field--row">
        <div className="field">
          <label className="label" htmlFor="eps">EPS <span className="req">*</span></label>
          <select id="eps"
            className={"select" + (errors.eps ? ' has-error':'')}
            aria-invalid={!!errors.eps}
            aria-describedby={errors.eps ? 'err-eps' : undefined}
            value={data.eps}
            onChange={e => set({ eps: e.target.value, epsOtra: e.target.value === 'Otra' ? data.epsOtra : '' })}>
            <option value="">Selecciona…</option>
            {window.EPS_LIST.map(e => <option key={e} value={e}>{e}</option>)}
          </select>
          <ErrorMsg id="err-eps">{errors.eps}</ErrorMsg>
        </div>
        <div className="field">
          <label className="label" htmlFor="sangre">Grupo sanguíneo <span className="req">*</span></label>
          <select id="sangre"
            className={"select" + (errors.sangre ? ' has-error':'')}
            aria-invalid={!!errors.sangre}
            aria-describedby={errors.sangre ? 'err-sangre' : undefined}
            value={data.sangre}
            onChange={e => set({ sangre: e.target.value })}>
            <option value="">Selecciona…</option>
            {['O+','O-','A+','A-','B+','B-','AB+','AB-'].map(s => <option key={s} value={s}>{s}</option>)}
          </select>
          <ErrorMsg id="err-sangre">{errors.sangre}</ErrorMsg>
        </div>
      </div>

      {data.eps === 'Otra' && (
        <div className="field">
          <label className="label" htmlFor="epsOtra">Nombre de tu EPS <span className="req">*</span></label>
          <input id="epsOtra"
            className={"input" + (errors.epsOtra ? ' has-error':'')}
            placeholder="Ej. Cruz Blanca"
            aria-invalid={!!errors.epsOtra}
            aria-describedby={errors.epsOtra ? 'err-epsOtra' : undefined}
            value={data.epsOtra}
            onChange={e => set({ epsOtra: e.target.value })}/>
          <ErrorMsg id="err-epsOtra">{errors.epsOtra}</ErrorMsg>
        </div>
      )}

      <div className="field--row">
        <div className="field">
          <label className="label" htmlFor="emergName">Contacto de emergencia <span className="req">*</span></label>
          <input id="emergName"
            className={"input" + (errors.emergName ? ' has-error':'')}
            placeholder="Nombre completo"
            aria-invalid={!!errors.emergName}
            aria-describedby={errors.emergName ? 'err-emergName' : undefined}
            value={data.emergName}
            onChange={e => set({ emergName: e.target.value })}/>
          <ErrorMsg id="err-emergName">{errors.emergName}</ErrorMsg>
        </div>
        <div className="field">
          <label className="label" htmlFor="emergTel">Teléfono de emergencia <span className="req">*</span></label>
          <input id="emergTel"
            className={"input" + (errors.emergTel ? ' has-error':'')}
            inputMode="numeric"
            placeholder="Ej. 3009876543"
            aria-invalid={!!errors.emergTel}
            aria-describedby={errors.emergTel ? 'err-emergTel' : undefined}
            value={data.emergTel}
            onChange={e => set({ emergTel: e.target.value.replace(/\D/g, '').slice(0,10) })}/>
          <ErrorMsg id="err-emergTel">{errors.emergTel}</ErrorMsg>
        </div>
      </div>
    </div>
  );
}

// ====== Step 4: Categoría y distancia ======
function Step4Carrera({ data, set, errors, ageWipedSelections }) {
  const age = Number(data.edad);
  const opciones = window.getDistancesForAge(age) || [];
  const isKids = age >= 6 && age <= 13;
  const tallas = isKids ? ['6','8','10','12','14'] : ['XS','S','M','L','XL'];

  return (
    <div>
      <div className="step-head"><span className="step-head__chip">Paso 4 / 6</span></div>
      <h2 className="step-title">Tu carrera</h2>
      <p className="step-sub">Mostramos solo las distancias permitidas para <strong>{age} años</strong> según el reglamento.</p>

      {ageWipedSelections && (
        <div className="notice notice--warn" role="status">
          Cambiaste la edad: vuelve a elegir <strong>modalidad</strong> y <strong>talla</strong> para esta categoría.
        </div>
      )}

      <div className="dist-grid" role="radiogroup" aria-label="Modalidad de carrera" aria-describedby={errors.distId ? 'err-distId' : undefined}>
        {opciones.map(d => (
          <button key={d.id} type="button"
            role="radio"
            aria-checked={data.distId === d.id}
            className={"dist-card " + (data.distId === d.id ? 'is-active' : '')}
            onClick={() => set({ distId: d.id })}>
            <span className="check" aria-hidden="true"><Icon.Check s={12}/></span>
            <span className="cat">{d.cat}</span>
            <span className="name">{d.name}</span>
            <span className="desc">{d.desc}</span>
          </button>
        ))}
      </div>
      <ErrorMsg id="err-distId">{errors.distId}</ErrorMsg>

      <div className="field" style={{marginTop:24}}>
        <span className="label" id="lbl-talla">Talla de camiseta <span className="req">*</span></span>
        <div className="talla-grid" role="radiogroup" aria-labelledby="lbl-talla" aria-describedby={errors.talla ? 'err-talla' : undefined}>
          {tallas.map(t => (
            <button key={t} type="button"
              role="radio"
              aria-checked={data.talla === t}
              className={"talla-pill " + (data.talla === t ? 'is-active' : '')}
              onClick={() => set({ talla: t })}>{t}</button>
          ))}
        </div>
        <ErrorMsg id="err-talla">{errors.talla}</ErrorMsg>
      </div>
    </div>
  );
}

// ====== Step 5: Vínculo ======
function Step5Vinculo({ data, set, errors }) {
  const [fileError, setFileError] = useState(null);

  const onFile = (e) => {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    if (f.size > 5 * 1024 * 1024) {
      setFileError('El archivo supera 5 MB. Comprime o usa otro formato.');
      e.target.value = '';
      return;
    }
    const okTypes = ['image/', 'application/pdf'];
    if (!okTypes.some(t => f.type.startsWith(t))) {
      setFileError('Formato no permitido. Sube una imagen (JPG/PNG) o un PDF.');
      e.target.value = '';
      return;
    }
    setFileError(null);
    // soporte = metadata serializable (lo que se envía como JSON al API)
    // soporteFile = File real, se sube aparte vía presigned URL a S3.
    set({
      soporte: { name: f.name, size: f.size, type: f.type },
      soporteFile: f,
    });
  };

  return (
    <div>
      <div className="step-head"><span className="step-head__chip">Paso 5 / 6</span></div>
      <h2 className="step-title">Vínculo con el GBCMC</h2>
      <p className="step-sub">Si haces parte de la comunidad Marie Curie, accedes a tarifas con beneficio.</p>

      <div className="field">
        <span className="label" id="lbl-vinculo">¿Tienes vínculo con el colegio? <span className="req">*</span></span>
        <div className="toggle-row" role="radiogroup" aria-labelledby="lbl-vinculo" aria-describedby={errors.hasVinculo ? 'err-hasVinculo' : undefined}>
          <button type="button"
            role="radio"
            aria-checked={data.hasVinculo === true}
            className={data.hasVinculo === true ? 'is-active':''}
            onClick={() => set({ hasVinculo: true })}>Sí, soy parte</button>
          <button type="button"
            role="radio"
            aria-checked={data.hasVinculo === false}
            className={data.hasVinculo === false ? 'is-active':''}
            onClick={() => set({ hasVinculo: false, tipoVinculo: '', soporte: null })}>No, soy público general</button>
        </div>
        <ErrorMsg id="err-hasVinculo">{errors.hasVinculo}</ErrorMsg>
      </div>

      {data.hasVinculo === true && (
        <>
          <div className="field">
            <label className="label" htmlFor="tipoVinculo">Tipo de vinculación <span className="req">*</span></label>
            <select id="tipoVinculo"
              className={"select" + (errors.tipoVinculo ? ' has-error':'')}
              aria-invalid={!!errors.tipoVinculo}
              aria-describedby={errors.tipoVinculo ? 'err-tipoVinculo' : undefined}
              value={data.tipoVinculo}
              onChange={e => set({
                tipoVinculo: e.target.value,
                codigoEstudiante: '', curso: '', anoGraduacion: '', cargoInstitucion: ''
              })}>
              <option value="">Selecciona…</option>
              {window.TIPOS_VINCULO.map(t => <option key={t.id} value={t.id}>{t.label}</option>)}
            </select>
            <ErrorMsg id="err-tipoVinculo">{errors.tipoVinculo}</ErrorMsg>
          </div>

          {(data.tipoVinculo === 'estudiante' || data.tipoVinculo === 'padre') && (
            <div className="field--row">
              <div className="field">
                <label className="label" htmlFor="codigoEstudiante">
                  Código de estudiante{data.tipoVinculo === 'padre' ? ' (del hijo/a)' : ''} <span className="req">*</span>
                </label>
                <input id="codigoEstudiante"
                  className={"input" + (errors.codigoEstudiante ? ' has-error':'')}
                  placeholder="Ej. 2024001"
                  aria-invalid={!!errors.codigoEstudiante}
                  aria-describedby={errors.codigoEstudiante ? 'err-codigoEstudiante' : undefined}
                  value={data.codigoEstudiante}
                  onChange={e => set({ codigoEstudiante: e.target.value.replace(/[^A-Za-z0-9-]/g, '').slice(0, 20) })}/>
                <ErrorMsg id="err-codigoEstudiante">{errors.codigoEstudiante}</ErrorMsg>
              </div>
              <div className="field">
                <label className="label" htmlFor="curso">
                  Curso{data.tipoVinculo === 'padre' ? ' (del hijo/a)' : ''} <span className="req">*</span>
                </label>
                <input id="curso"
                  className={"input" + (errors.curso ? ' has-error':'')}
                  placeholder="Ej. 10A"
                  aria-invalid={!!errors.curso}
                  aria-describedby={errors.curso ? 'err-curso' : undefined}
                  value={data.curso}
                  onChange={e => set({ curso: e.target.value.slice(0, 20) })}/>
                <ErrorMsg id="err-curso">{errors.curso}</ErrorMsg>
              </div>
            </div>
          )}

          {data.tipoVinculo === 'egresado' && (
            <div className="field" style={{maxWidth: 240}}>
              <label className="label" htmlFor="anoGraduacion">Año de graduación <span className="req">*</span></label>
              <input id="anoGraduacion"
                className={"input font-num" + (errors.anoGraduacion ? ' has-error':'')}
                inputMode="numeric"
                placeholder="Ej. 2018"
                aria-invalid={!!errors.anoGraduacion}
                aria-describedby={errors.anoGraduacion ? 'err-anoGraduacion' : undefined}
                value={data.anoGraduacion}
                onChange={e => set({ anoGraduacion: e.target.value.replace(/\D/g, '').slice(0, 4) })}/>
              <ErrorMsg id="err-anoGraduacion">{errors.anoGraduacion}</ErrorMsg>
            </div>
          )}

          {(data.tipoVinculo === 'docente' || data.tipoVinculo === 'hijo_colaborador') && (
            <div className="field">
              <label className="label" htmlFor="cargoInstitucion">
                {data.tipoVinculo === 'hijo_colaborador'
                  ? 'Cargo del colaborador (tu padre/madre)'
                  : 'Cargo en la institución'} <span className="req">*</span>
              </label>
              <input id="cargoInstitucion"
                className={"input" + (errors.cargoInstitucion ? ' has-error':'')}
                placeholder={data.tipoVinculo === 'hijo_colaborador' ? 'Ej. Docente de matemáticas' : 'Ej. Docente de primaria'}
                aria-invalid={!!errors.cargoInstitucion}
                aria-describedby={errors.cargoInstitucion ? 'err-cargoInstitucion' : undefined}
                value={data.cargoInstitucion}
                onChange={e => set({ cargoInstitucion: e.target.value.slice(0, 80) })}/>
              <ErrorMsg id="err-cargoInstitucion">{errors.cargoInstitucion}</ErrorMsg>
            </div>
          )}

          <div className="field">
            <label className="label" htmlFor="soporte-file">Soporte del vínculo <span className="req">*</span></label>
            <label className={"upload " + (data.soporte ? 'has-file':'')} htmlFor="soporte-file">
              {data.soporte ? (
                <>
                  <div className="upload__icon" aria-hidden="true"><Icon.File s={22}/></div>
                  <div style={{fontWeight:700, color:'var(--azul-noche)'}}>{data.soporte.name}</div>
                  <p className="upload__hint">{(data.soporte.size / 1024).toFixed(0)} KB · Click para reemplazar</p>
                </>
              ) : (
                <>
                  <div className="upload__icon" aria-hidden="true"><Icon.Upload s={22}/></div>
                  <div style={{fontWeight:700, color:'var(--azul-noche)'}}>Sube tu carné o documento institucional</div>
                  <p className="upload__hint" id="soporte-hint">JPG, PNG o PDF · Máx 5 MB</p>
                </>
              )}
              <input id="soporte-file"
                type="file"
                accept="image/*,.pdf"
                aria-describedby="soporte-hint"
                aria-invalid={!!(errors.soporte || fileError)}
                onChange={onFile}
                style={{display:'none'}}/>
            </label>
            <ErrorMsg id="err-soporte-file">{fileError || errors.soporte}</ErrorMsg>
          </div>
        </>
      )}

      {data.hasVinculo === false && (
        <div className="notice notice--info">
          <strong>Inscripción pública</strong> — Aplica la tarifa general. ¡Te esperamos en la línea de salida! 🏁
        </div>
      )}
    </div>
  );
}

// ====== Step 6: Resumen ======
function Step6Resumen({ data, precio, distObj, onPay, onJump, isPaying, apiError }) {
  const tipoVinculoLabel = (window.TIPOS_VINCULO.find(t => t.id === data.tipoVinculo) || {}).label;
  return (
    <div>
      <div className="step-head"><span className="step-head__chip">Paso 6 / 6</span></div>
      <h2 className="step-title">Confirma y paga</h2>
      <p className="step-sub">Revisa tu inscripción antes de pagar. Puedes editar cualquier sección.</p>

      <div className="resumen-grid">
        <ResumenBlock title="Participante" editStep={2} onJump={onJump} rows={[
          ['Nombre', data.nombre],
          ['Documento', `${data.tipoDoc} ${data.numDoc}`],
          ['Edad', `${data.edad} años`],
          ['Correo', data.email],
          ['Contacto', `${data.tipoTel}: ${data.tel}`],
        ]}/>
        <ResumenBlock title="Carrera" editStep={4} onJump={onJump} rows={[
          ['Modalidad', distObj?.label || distObj?.name],
          ['Categoría', distObj?.cat],
          ['Talla', data.talla],
        ]}/>
        <ResumenBlock title="Salud" editStep={3} onJump={onJump} rows={[
          ['EPS', data.eps === 'Otra' && data.epsOtra ? `Otra: ${data.epsOtra}` : data.eps],
          ['Grupo sanguíneo', data.sangre],
          ['Emergencia', `${data.emergName} · ${data.emergTel}`],
        ]}/>
        <ResumenBlock title="Vínculo" editStep={5} onJump={onJump} rows={[
          ['¿Vinculado?', data.hasVinculo ? 'Sí' : 'No'],
          ...(data.hasVinculo ? [['Tipo', tipoVinculoLabel]] : []),
          ...(data.codigoEstudiante ? [['Cód. estudiante', data.codigoEstudiante]] : []),
          ...(data.curso ? [['Curso', data.curso]] : []),
          ...(data.anoGraduacion ? [['Año graduación', data.anoGraduacion]] : []),
          ...(data.cargoInstitucion ? [['Cargo', data.cargoInstitucion]] : []),
          ...(data.soporte ? [['Soporte', data.soporte.name]] : []),
        ]}/>
      </div>

      {apiError && (
        <div className="notice notice--warn" role="alert" style={{borderLeftColor: 'var(--rojo)', background: '#fff5f5', color: 'var(--rojo)'}}>
          <strong>No se pudo registrar:</strong> {apiError}
        </div>
      )}

      <div className="pay-bar">
        <div>
          <div className="pay-bar__lbl">Total a pagar</div>
          <div className="pay-bar__price">
            {window.fmtCOP(precio.price)}
            <small>COP</small>
          </div>
          <div className="pay-bar__sub">{precio.label}</div>
        </div>
        <button
          type="button"
          className="btn btn-primary btn-pay"
          onClick={onPay}
          disabled={isPaying}
          aria-busy={isPaying}>
          {isPaying ? <>PROCESANDO… <span className="spinner" aria-hidden="true"/></> : <>PAGAR AHORA <Icon.Arrow s={18}/></>}
        </button>
      </div>
    </div>
  );
}

function ResumenBlock({ title, rows, editStep, onJump }) {
  return (
    <div className="resumen-block">
      <div className="resumen-block__head">
        <h4>{title}</h4>
        {onJump && editStep && (
          <button type="button" className="resumen-block__edit" onClick={() => onJump(editStep)}>
            Editar
          </button>
        )}
      </div>
      {rows.filter(r => r[1]).map(([k,v]) => (
        <div key={k} className="resumen-block__row">
          <span className="resumen-block__k">{k}</span>
          <span className="resumen-block__v">{v}</span>
        </div>
      ))}
    </div>
  );
}

Object.assign(window, {
  Step1Documento, Step2Datos, Step3Salud, Step4Carrera, Step5Vinculo, Step6Resumen, Icon
});
