// illustrations12.jsx — Capítulo 12 · "La revolución de los hijos de Dios"
// Escenas 1–3 + helpers compartidos. Principio realista: volumen, sombreado,
// luz cálida que emana de Jesús (rim-light), proporciones humanas.

// ─── Hook: reinicia animaciones al activar el slide ───────────────────────
function useRun(active) {
  const [run, setRun] = React.useState(0);
  React.useEffect(() => { if (active) setRun((r) => r + 1); }, [active]);
  return run;
}

// ─── Marco oscuro de la escena ────────────────────────────────────────────
function SceneFrame({ pal, children, viewBox = '0 0 1000 900' }) {
  return (
    <div style={{
      width: '100%', height: '100%',
      borderRadius: 10, overflow: 'hidden',
      background: `radial-gradient(ellipse 130% 95% at 50% 16%, ${pal.deep}, ${pal.abyss} 70%)`,
      border: `1px solid ${pal.deep}`,
      boxShadow: `0 50px 110px ${pal.abyss}aa, inset 0 0 0 1px ${pal.deep}, inset 0 0 120px ${pal.abyss}`,
      position: 'relative',
    }}>
      <svg viewBox={viewBox} width="100%" height="100%" preserveAspectRatio="xMidYMid meet" style={{ display: 'block' }}>
        {children}
      </svg>
    </div>
  );
}

// ─── Cielo estrellado de fondo ────────────────────────────────────────────
function SkyBackdrop({ pal, w = 1000, h = 900, n = 64 }) {
  const stars = Array.from({ length: n }, (_, i) => ({
    x: (i * 97.13 + (i % 5) * 31) % w,
    y: (i * 53.77 + (i % 7) * 113) % h,
    r: 0.5 + (i % 4) * 0.35,
    d: ((i * 7) % 30) / 10,
    dur: 2.4 + (i % 5) * 0.6,
  }));
  return (
    <g>
      {stars.map((s, i) => (
        <circle key={i} cx={s.x} cy={s.y} r={s.r} fill={i % 6 === 0 ? pal.warm : pal.soft}
          style={{ animation: `c12-twinkle ${s.dur}s ease-in-out ${s.d}s infinite` }} />
      ))}
    </g>
  );
}

// ─── Malla de puntos de un globo (hemisferio frontal) ─────────────────────
function globeDots(cx, cy, R, centerLon, latStep = 11) {
  const dots = [];
  for (let lat = -78; lat <= 78; lat += latStep) {
    const ring = Math.max(0.22, Math.cos(lat * Math.PI / 180));
    const step = latStep / ring;
    for (let lon = -180; lon < 180; lon += step) {
      const a = lat * Math.PI / 180, b = (lon - centerLon) * Math.PI / 180;
      const z = Math.cos(a) * Math.cos(b);
      if (z <= 0.05) continue;
      dots.push({
        x: cx + R * Math.cos(a) * Math.sin(b),
        y: cy - R * Math.sin(a),
        op: 0.1 + 0.42 * z, r: (1.2 + 1.6 * z) * (R / 300),
      });
    }
  }
  return dots;
}

// ─── Cristo luminoso (la figura "de la cruz") — reutilizable ──────────────
// Reverente: cruz de luz detrás, halo, rayos, túnica con volumen, brazos
// abiertos en acogida. Coords locales centradas en (0,0).
function LuminousChrist({ pal, cx, cy, scale = 1, rayDelay = 0 }) {
  const id = `${Math.round(cx)}_${Math.round(cy)}`;
  const rays = [];
  for (let i = 0; i < 16; i++) {
    const a = (i / 16) * Math.PI * 2;
    const r1 = 70, r2 = 210 + (i % 3) * 36;
    rays.push({
      x1: Math.cos(a) * r1, y1: -90 + Math.sin(a) * r1,
      x2: Math.cos(a) * r2, y2: -90 + Math.sin(a) * r2,
      d: (i % 5) * 0.4,
    });
  }
  return (
    <g transform={`translate(${cx} ${cy}) scale(${scale})`}>
      <defs>
        <radialGradient id={`lcHalo${id}`} cx="50%" cy="34%">
          <stop offset="0%" stopColor="#fff7e6" stopOpacity="0.95" />
          <stop offset="22%" stopColor="#ffeec9" stopOpacity="0.7" />
          <stop offset="55%" stopColor={pal.warm} stopOpacity="0.32" />
          <stop offset="100%" stopColor={pal.warm} stopOpacity="0" />
        </radialGradient>
        <linearGradient id={`lcRobe${id}`} x1="0" y1="0" x2="0.25" y2="1">
          <stop offset="0%" stopColor="#fffaf0" />
          <stop offset="55%" stopColor="#fdebcb" />
          <stop offset="100%" stopColor={pal.warm} />
        </linearGradient>
        <linearGradient id={`lcCross${id}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#fff7e6" stopOpacity="0.85" />
          <stop offset="100%" stopColor={pal.warm} stopOpacity="0.25" />
        </linearGradient>
      </defs>

      {/* Gran resplandor */}
      <ellipse cx="0" cy="-50" rx="300" ry="330" fill={`url(#lcHalo${id})`}
        style={{ animation: `c12-glow 5.5s ease-in-out ${rayDelay}s infinite`, transformOrigin: '0px -50px' }} />

      {/* CRUZ de luz detrás de la figura */}
      <g style={{ animation: 'c12-glow 6s ease-in-out infinite' }}>
        <rect x="-12" y="-280" width="24" height="430" rx="6" fill={`url(#lcCross${id})`} opacity="0.5" />
        <rect x="-95" y="-205" width="190" height="22" rx="6" fill={`url(#lcCross${id})`} opacity="0.5" />
        <rect x="-5" y="-280" width="10" height="430" rx="4" fill="#fffaf0" opacity="0.55" />
        <rect x="-95" y="-200" width="190" height="9" rx="4" fill="#fffaf0" opacity="0.55" />
      </g>

      {/* Rayos */}
      <g style={{ animation: `c12-glowS 6s ease-in-out infinite` }}>
        {rays.map((r, i) => (
          <line key={i} x1={r.x1} y1={r.y1} x2={r.x2} y2={r.y2}
            stroke={pal.warm} strokeWidth="1.4" strokeLinecap="round" opacity="0.5"
            style={{ animation: `c12-glowS ${3 + (i % 4) * 0.6}s ease-in-out ${r.d}s infinite` }} />
        ))}
      </g>

      {/* Halo del rostro */}
      <circle cx="0" cy="-118" r="52" fill="none" stroke="#fff7e6" strokeWidth="2.5" opacity="0.65"
        style={{ animation: 'c12-pulseSm 4.5s ease-in-out infinite', transformOrigin: '0px -118px' }} />
      <circle cx="0" cy="-118" r="40" fill={`url(#lcHalo${id})`} opacity="0.9" />

      {/* Túnica de luz con volumen */}
      <path d="M 0 -150
               C -26 -150 -40 -126 -40 -98
               C -40 -78 -34 -64 -30 -52
               L -68 150 L 68 150 L 30 -52
               C 34 -64 40 -78 40 -98
               C 40 -126 26 -150 0 -150 Z"
        fill={`url(#lcRobe${id})`} stroke="#fff7e6" strokeWidth="1.2" strokeOpacity="0.6"
        style={{ animation: 'c12-breatheSm 6s ease-in-out infinite' }} />
      {/* pliegue central — volumen */}
      <path d="M 0 -120 L -4 150 M 0 -120 L 6 150" stroke={pal.warmDeep} strokeWidth="1.5" opacity="0.3" fill="none" />
      {/* Rostro */}
      <ellipse cx="0" cy="-116" rx="22" ry="27" fill="#fff8ec" />
      {/* Brazos abiertos / acogida */}
      <path d="M -30 -62 C -64 -50 -86 -10 -90 30" stroke="#fff8ec" strokeWidth="14" fill="none" strokeLinecap="round" opacity="0.95" />
      <path d="M 30 -62 C 64 -50 86 -10 90 30" stroke="#fff8ec" strokeWidth="14" fill="none" strokeLinecap="round" opacity="0.95" />
    </g>
  );
}

// ════════════════════════════════════════════════════════════════════════
// ─── ESCENA 1 · EL MUNDO SE ENCIENDE (RED NEURONAL) ──────────────────────
// Muchas luces se encienden por toda la tierra y se conectan entre sí en una
// malla viva — como una red neuronal de hijos de Dios.
// ════════════════════════════════════════════════════════════════════════
function SceneMundo({ pal, active }) {
  const run = useRun(active);
  const cx = 500, cy = 440, R = 300;
  const dots = globeDots(cx, cy, R, 22, 11);

  // Nodos distribuidos sobre la esfera (espiral áureo) — hemisferio frontal
  const N = 64, ga = Math.PI * (3 - Math.sqrt(5)), tilt = -0.24;
  const nodes = [];
  for (let i = 0; i < N; i++) {
    const yy = 1 - (i / (N - 1)) * 2;
    const rr = Math.sqrt(Math.max(0, 1 - yy * yy));
    const th = i * ga;
    const px = Math.cos(th) * rr, py0 = yy, pz0 = Math.sin(th) * rr;
    const py = py0 * Math.cos(tilt) - pz0 * Math.sin(tilt);
    const pz = py0 * Math.sin(tilt) + pz0 * Math.cos(tilt);
    if (pz <= 0.16) continue;
    nodes.push({ x: cx + R * px * 0.9, y: cy - R * py * 0.9, z: pz, i: nodes.length });
  }

  // Arcos a vecinos cercanos (malla neuronal)
  const arc = (a, b) => {
    const mx = (a.x + b.x) / 2, my = (a.y + b.y) / 2;
    const dx = mx - cx, dy = my - cy, dl = Math.hypot(dx, dy) || 1;
    const span = Math.hypot(b.x - a.x, b.y - a.y);
    const bow = 16 + span * 0.16;
    const ctx = mx + dx / dl * bow, cty = my + dy / dl * bow;
    return {
      d: `M ${a.x.toFixed(1)} ${a.y.toFixed(1)} Q ${ctx.toFixed(1)} ${cty.toFixed(1)} ${b.x.toFixed(1)} ${b.y.toFixed(1)}`,
      len: span * 1.1 + bow, mid: (a.i + b.i),
    };
  };
  const links = [];
  const seen = new Set();
  nodes.forEach((a) => {
    const near = nodes.filter((b) => b !== a)
      .map((b) => ({ b, d: Math.hypot(b.x - a.x, b.y - a.y) }))
      .sort((p, q) => p.d - q.d).slice(0, 3);
    near.forEach(({ b, d }) => {
      if (d > 215) return;
      const key = a.i < b.i ? `${a.i}-${b.i}` : `${b.i}-${a.i}`;
      if (seen.has(key)) return;
      seen.add(key);
      links.push(arc(a, b));
    });
  });

  return (
    <SceneFrame pal={pal}>
      <defs>
        <radialGradient id="globeSphere" cx="42%" cy="34%">
          <stop offset="0%" stopColor={pal.deep} />
          <stop offset="55%" stopColor={pal.deep} stopOpacity="0.55" />
          <stop offset="100%" stopColor={pal.abyss} />
        </radialGradient>
        <radialGradient id="cityHalo" cx="50%" cy="50%">
          <stop offset="0%" stopColor="#fff3d4" stopOpacity="0.95" />
          <stop offset="45%" stopColor={pal.warm} stopOpacity="0.55" />
          <stop offset="100%" stopColor={pal.warm} stopOpacity="0" />
        </radialGradient>
        <radialGradient id="atmGlow" cx="50%" cy="50%">
          <stop offset="0%" stopColor={pal.warm} stopOpacity="0" />
          <stop offset="80%" stopColor={pal.warm} stopOpacity="0" />
          <stop offset="92%" stopColor="#9fb2e0" stopOpacity="0.3" />
          <stop offset="100%" stopColor="#9fb2e0" stopOpacity="0" />
        </radialGradient>
      </defs>

      <SkyBackdrop pal={pal} />

      <circle cx={cx} cy={cy} r={R + 26} fill="url(#atmGlow)"
        style={{ animation: 'c12-glow 6s ease-in-out infinite', transformOrigin: `${cx}px ${cy}px` }} />
      <circle cx={cx} cy={cy} r={R} fill="url(#globeSphere)" stroke={pal.medium} strokeOpacity="0.25" strokeWidth="1" />
      <path d={`M ${cx} ${cy - R} A ${R} ${R} 0 0 1 ${cx} ${cy + R}`} fill="none"
        stroke={pal.warm} strokeOpacity="0.16" strokeWidth="2" />

      <g>{dots.map((d, i) => <circle key={i} cx={d.x} cy={d.y} r={d.r} fill={pal.soft} opacity={d.op} />)}</g>

      <g key={run}>
        {/* Conexiones de la red neuronal */}
        {links.map((l, j) => (
          <g key={j}>
            <path d={l.d} fill="none" stroke={pal.warm} strokeWidth="1.1" strokeLinecap="round" opacity="0.45"
              style={{ '--len': l.len, strokeDasharray: l.len, animation: `c12-draw 1s ease ${1.8 + j * 0.05}s both` }} />
            {j % 3 === 0 &&
              <circle r="2.2" fill="#fff3d4"
                style={{ offsetPath: `path('${l.d}')`, animation: `c12-travel ${2.4 + (j % 4) * 0.5}s linear ${3 + (j % 7) * 0.3}s infinite` }} />}
          </g>
        ))}

        {/* Luces de las naciones (muchas) */}
        {nodes.map((c) => {
          const delay = 0.25 + c.i * 0.07;
          const rad = 18 + (c.i % 3) * 6;
          return (
            <g key={c.i} style={{ animation: `c12-lightOn 0.7s cubic-bezier(.2,.8,.2,1) ${delay}s both`, transformOrigin: `${c.x}px ${c.y}px` }}>
              <circle cx={c.x} cy={c.y} r={rad} fill="url(#cityHalo)"
                style={{ animation: `c12-glow ${2.2 + (c.i % 4) * 0.4}s ease-in-out ${delay + 0.7}s infinite`, transformOrigin: `${c.x}px ${c.y}px` }} />
              <circle cx={c.x} cy={c.y} r="2.6" fill="#fffaf0" />
            </g>
          );
        })}
      </g>
    </SceneFrame>
  );
}

// ════════════════════════════════════════════════════════════════════════
// ─── ESCENA 2 · DIOS DESCIENDE Y ENTRA EN LA TIERRA ──────────────────────
// El tiempo corre hacia Su venida: Jesús desciende del cielo y entra en la
// Tierra; al llegar, Su presencia inunda de luz cálida a toda la creación.
// ════════════════════════════════════════════════════════════════════════
function SceneOrbita({ pal, active }) {
  const run = useRun(active);
  const ex = 500, ey = 620, eR = 165;
  const dots = globeDots(ex, ey, eR, 18, 12);

  // Nodos sobre la Tierra (red que se enciende y conecta)
  const NN = 30, ga2 = Math.PI * (3 - Math.sqrt(5)), tilt2 = -0.2;
  const eNodes = [];
  for (let i = 0; i < NN; i++) {
    const yy = 1 - (i / (NN - 1)) * 2;
    const rr = Math.sqrt(Math.max(0, 1 - yy * yy));
    const th = i * ga2;
    const px = Math.cos(th) * rr, py0 = yy, pz0 = Math.sin(th) * rr;
    const py = py0 * Math.cos(tilt2) - pz0 * Math.sin(tilt2);
    const pz = py0 * Math.sin(tilt2) + pz0 * Math.cos(tilt2);
    if (pz <= 0.2) continue;
    eNodes.push({ x: ex + eR * px * 0.88, y: ey - eR * py * 0.88, i: eNodes.length });
  }
  const eArc = (a, b) => {
    const mx = (a.x + b.x) / 2, my = (a.y + b.y) / 2;
    const dx = mx - ex, dy = my - ey, dl = Math.hypot(dx, dy) || 1;
    const span = Math.hypot(b.x - a.x, b.y - a.y);
    const bow = 8 + span * 0.14;
    return { d: `M ${a.x.toFixed(1)} ${a.y.toFixed(1)} Q ${(mx + dx / dl * bow).toFixed(1)} ${(my + dy / dl * bow).toFixed(1)} ${b.x.toFixed(1)} ${b.y.toFixed(1)}`, len: span * 1.1 + bow };
  };
  const eLinks = [];
  const eSeen = new Set();
  eNodes.forEach((a) => {
    eNodes.filter((b) => b !== a).map((b) => ({ b, d: Math.hypot(b.x - a.x, b.y - a.y) }))
      .sort((p, q) => p.d - q.d).slice(0, 2).forEach(({ b, d }) => {
        if (d > 150) return;
        const k = a.i < b.i ? `${a.i}-${b.i}` : `${b.i}-${a.i}`;
        if (eSeen.has(k)) return; eSeen.add(k);
        eLinks.push(eArc(a, b));
      });
  });

  return (
    <SceneFrame pal={pal}>
      <defs>
        <radialGradient id="earth2Sphere" cx="42%" cy="32%">
          <stop offset="0%" stopColor={pal.deep} />
          <stop offset="58%" stopColor={pal.deep} stopOpacity="0.5" />
          <stop offset="100%" stopColor={pal.abyss} />
        </radialGradient>
        <radialGradient id="earth2Atm" cx="50%" cy="50%">
          <stop offset="0%" stopColor="#9fb2e0" stopOpacity="0" />
          <stop offset="84%" stopColor="#9fb2e0" stopOpacity="0" />
          <stop offset="94%" stopColor="#9fb2e0" stopOpacity="0.34" />
          <stop offset="100%" stopColor="#9fb2e0" stopOpacity="0" />
        </radialGradient>
        <radialGradient id="earth2Warm" cx="50%" cy="28%">
          <stop offset="0%" stopColor="#fff3d4" stopOpacity="0.9" />
          <stop offset="45%" stopColor={pal.warm} stopOpacity="0.45" />
          <stop offset="100%" stopColor={pal.warm} stopOpacity="0" />
        </radialGradient>
        <radialGradient id="cityHalo2" cx="50%" cy="50%">
          <stop offset="0%" stopColor="#fff3d4" stopOpacity="0.95" />
          <stop offset="45%" stopColor={pal.warm} stopOpacity="0.55" />
          <stop offset="100%" stopColor={pal.warm} stopOpacity="0" />
        </radialGradient>
        <linearGradient id="beamDownGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#fff3d4" stopOpacity="0.6" />
          <stop offset="100%" stopColor={pal.warm} stopOpacity="0" />
        </linearGradient>
        <clipPath id="earth2Clip"><circle cx={ex} cy={ey} r={eR} /></clipPath>
      </defs>

      <SkyBackdrop pal={pal} n={72} />

      {/* Línea de tiempo */}
      <path d="M 90 832 H 910" stroke={pal.soft} strokeWidth="1.4" strokeDasharray="2 12" opacity="0.4" />
      {[0, 0.2, 0.4, 0.6, 0.8, 1].map((p, i) => (
        <line key={i} x1={90 + p * 820} y1="826" x2={90 + p * 820} y2="838" stroke={pal.medium} strokeWidth="1.4" opacity="0.5" />
      ))}
      <text x="92" y="864" fill={pal.soft} fontSize="24" letterSpacing="2" fontFamily="'JetBrains Mono', monospace" opacity="0.5">la creación gime</text>
      <text x="908" y="864" textAnchor="end" fill={pal.warm} fontSize="24" letterSpacing="2" fontFamily="'JetBrains Mono', monospace" opacity="0.8">su regreso</text>

      {/* TIERRA */}
      <circle cx={ex} cy={ey} r={eR + 16} fill="url(#earth2Atm)" />
      <circle cx={ex} cy={ey} r={eR} fill="url(#earth2Sphere)" stroke={pal.medium} strokeOpacity="0.25" strokeWidth="1" />
      <g clipPath="url(#earth2Clip)">
        {dots.map((d, i) => <circle key={i} cx={d.x} cy={d.y} r={d.r} fill={pal.soft} opacity={d.op} />)}
      </g>
      <g key={run}>
        {/* Red de luces sobre la Tierra — se encienden y conectan, más al acercarse Él */}
        <g clipPath="url(#earth2Clip)">
          {eLinks.map((l, j) => (
            <path key={'l' + j} d={l.d} fill="none" stroke={pal.warm} strokeWidth="1.1" strokeLinecap="round" opacity="0.5"
              style={{ '--len': l.len, strokeDasharray: l.len, animation: `c12-draw 0.9s ease ${1.4 + j * 0.28}s both` }} />
          ))}
          {eNodes.map((c) => {
            const delay = 0.6 + c.i * 0.34;
            return (
              <g key={c.i} style={{ animation: `c12-lightOn 0.6s cubic-bezier(.2,.8,.2,1) ${delay}s both`, transformOrigin: `${c.x}px ${c.y}px` }}>
                <circle cx={c.x} cy={c.y} r="13" fill="url(#cityHalo2)"
                  style={{ animation: `c12-glow ${2.2 + (c.i % 3) * 0.4}s ease-in-out ${delay + 0.6}s infinite`, transformOrigin: `${c.x}px ${c.y}px` }} />
                <circle cx={c.x} cy={c.y} r="2.3" fill="#fffaf0" />
              </g>
            );
          })}
        </g>

        {/* marcador del tiempo que avanza hacia Su regreso */}
        <circle r="5" fill="#fff3d4" cy="832"
          style={{ offsetPath: 'path("M 90 832 H 905")', animation: 'c12-ring 9s cubic-bezier(.4,0,.2,1) 0.4s both' }} />

        {/* presencia cálida que inunda la Tierra al llegar Él */}
        <g clipPath="url(#earth2Clip)">
          <circle cx={ex} cy={ey - 30} r={eR + 30} fill="url(#earth2Warm)" opacity="0"
            style={{ animation: 'c12-earthWarm 2.6s ease 6.4s both' }} />
        </g>

        {/* haz de luz que desciende del cielo a la Tierra */}
        <rect x={ex - 26} y={ey - eR - 250} width="52" height="270" fill="url(#beamDownGrad)" opacity="0"
          style={{ animation: 'c12-beamDown 2.4s ease 5.2s both', transformOrigin: `${ex}px ${ey - eR}px` }} />

        {/* Jesús desciende y entra en la Tierra */}
        <g transform={`translate(${ex} ${ey - eR - 70})`}>
          <g style={{ animation: 'c12-enter 6s cubic-bezier(.4,0,.2,1) 0.6s both' }}>
            <LuminousChrist pal={pal} cx={0} cy={0} scale={0.82} />
          </g>
        </g>
      </g>
    </SceneFrame>
  );
}

// ════════════════════════════════════════════════════════════════════════
// ─── ESCENA 3 · LA MIRADA FIJA ───────────────────────────────────────────
// Una persona (figura con túnica, sombreada) camina entre el caos y fija la
// mirada en Jesús — un haz firme que el ruido no rompe.
// ════════════════════════════════════════════════════════════════════════
function SceneMirada({ pal, active }) {
  const run = useRun(active);

  const chaos = [
    { type: 'screen', x: 150, y: 210, rot: -12, anim: 'c12-buzz', dur: 1.6 },
    { type: 'screen', x: 250, y: 700, rot: 8, anim: 'c12-driftB', dur: 3.4 },
    { type: 'bell', x: 120, y: 440, anim: 'c12-buzz', dur: 1.2 },
    { type: 'play', x: 470, y: 150, anim: 'c12-driftB', dur: 3 },
    { type: 'money', x: 110, y: 610, anim: 'c12-driftA', dur: 2.8 },
    { type: 'clock', x: 540, y: 780, anim: 'c12-buzz', dur: 1.5 },
    { type: 'scribble', x: 380, y: 270, anim: 'c12-driftA', dur: 3.6 },
    { type: 'play', x: 200, y: 330, anim: 'c12-buzz', dur: 1.4 },
    { type: 'bell', x: 650, y: 230, anim: 'c12-driftC', dur: 2.6 },
  ];

  // Distracciones que cruzan rápido por delante de su vista
  const streaks = [
    { y: 332, dir: 'R', dur: 2.6, delay: 0.3, kind: 'play' },
    { y: 416, dir: 'L', dur: 3.0, delay: 1.5, kind: 'screen' },
    { y: 300, dir: 'L', dur: 2.1, delay: 2.9, kind: 'bell' },
    { y: 470, dir: 'R', dur: 2.8, delay: 2.0, kind: 'money' },
    { y: 384, dir: 'R', dur: 1.8, delay: 3.9, kind: 'play' },
    { y: 350, dir: 'L', dur: 2.4, delay: 5.0, kind: 'screen' },
  ];

  const eye = { x: 352, y: 470 }, target = { x: 748, y: 372 };
  const beamLen = Math.hypot(target.x - eye.x, target.y - eye.y);
  const beamD = `M ${eye.x} ${eye.y} L ${target.x} ${target.y}`;

  const ChaosIcon = ({ c }) => {
    const col = pal.medium;
    const common = { style: { animation: `${c.anim} ${c.dur}s ease-in-out ${(c.x % 5) * 0.3}s infinite`, transformOrigin: `${c.x}px ${c.y}px` } };
    const flick = { animation: `c12-flick ${3 + (c.x % 3)}s ease-in-out infinite` };
    if (c.type === 'screen') return (
      <g {...common}><g transform={`rotate(${c.rot} ${c.x} ${c.y})`} style={flick}>
        <rect x={c.x - 42} y={c.y - 30} width="84" height="60" rx="6" fill="none" stroke={col} strokeWidth="2" opacity="0.5" />
        <path d={`M ${c.x - 8} ${c.y - 10} L ${c.x + 12} ${c.y} L ${c.x - 8} ${c.y + 10} Z`} fill={col} opacity="0.45" />
      </g></g>
    );
    if (c.type === 'play') return (
      <g {...common}><g style={flick}>
        <circle cx={c.x} cy={c.y} r="22" fill="none" stroke={col} strokeWidth="2" opacity="0.45" />
        <path d={`M ${c.x - 7} ${c.y - 11} L ${c.x + 12} ${c.y} L ${c.x - 7} ${c.y + 11} Z`} fill={col} opacity="0.5" />
      </g></g>
    );
    if (c.type === 'bell') return (
      <g {...common}><g style={flick}>
        <path d={`M ${c.x - 16} ${c.y + 10} Q ${c.x - 16} ${c.y - 18} ${c.x} ${c.y - 20} Q ${c.x + 16} ${c.y - 18} ${c.x + 16} ${c.y + 10} Z`}
          fill="none" stroke={col} strokeWidth="2" opacity="0.5" />
        <circle cx={c.x} cy={c.y + 16} r="3" fill={col} opacity="0.5" />
        <circle cx={c.x + 17} cy={c.y - 20} r="7" fill={pal.credit || '#b5321c'} opacity="0.8" />
      </g></g>
    );
    if (c.type === 'money') return (
      <g {...common}><text x={c.x} y={c.y} fontSize="42" textAnchor="middle" fill={col} opacity="0.4" fontFamily="'Fraunces', serif" style={flick}>$</text></g>
    );
    if (c.type === 'clock') return (
      <g {...common}><g style={flick}>
        <circle cx={c.x} cy={c.y} r="20" fill="none" stroke={col} strokeWidth="2" opacity="0.5" />
        <line x1={c.x} y1={c.y} x2={c.x} y2={c.y - 13} stroke={col} strokeWidth="2" opacity="0.5" />
        <line x1={c.x} y1={c.y} x2={c.x + 9} y2={c.y + 4} stroke={col} strokeWidth="2" opacity="0.5" />
      </g></g>
    );
    return (
      <g {...common}><path d={`M ${c.x - 40} ${c.y} q 12 -22 24 0 t 24 0 t 24 0`} fill="none" stroke={col} strokeWidth="2.4" opacity="0.4" strokeLinecap="round" style={flick} /></g>
    );
  };

  // Icono que cruza la pantalla (dibujado en 0,0)
  const StreakIcon = ({ kind }) => {
    const col = pal.medium;
    if (kind === 'screen') return (
      <g><rect x={-30} y={-22} width="60" height="44" rx="5" fill="none" stroke={col} strokeWidth="2.4" />
        <path d="M -6 -8 L 10 0 L -6 8 Z" fill={col} /></g>
    );
    if (kind === 'bell') return (
      <g><path d="M -15 9 Q -15 -16 0 -18 Q 15 -16 15 9 Z" fill="none" stroke={col} strokeWidth="2.4" />
        <circle cx="0" cy="14" r="3" fill={col} /><circle cx="16" cy="-18" r="7" fill={pal.credit || '#b5321c'} /></g>
    );
    if (kind === 'money') return (<text x="0" y="14" fontSize="46" textAnchor="middle" fill={col} fontFamily="'Fraunces', serif">$</text>);
    return (
      <g><circle cx="0" cy="0" r="22" fill="none" stroke={col} strokeWidth="2.4" />
        <path d="M -7 -11 L 12 0 L -7 11 Z" fill={col} /></g>
    );
  };

  return (
    <SceneFrame pal={pal}>
      <defs>
        <linearGradient id="clarityCone" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0%" stopColor={pal.warm} stopOpacity="0" />
          <stop offset="100%" stopColor={pal.warm} stopOpacity="0.16" />
        </linearGradient>
        <linearGradient id="m3robe" x1="0" y1="0" x2="1" y2="0.6">
          <stop offset="0%" stopColor={pal.abyss} />
          <stop offset="60%" stopColor={pal.deep} />
          <stop offset="100%" stopColor="#54608a" />
        </linearGradient>
        <linearGradient id="m3skin" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0%" stopColor="#6a5a48" />
          <stop offset="100%" stopColor="#caa17a" />
        </linearGradient>
      </defs>

      <SkyBackdrop pal={pal} n={40} />

      <g key={'chaos' + run}>{chaos.map((c, i) => <ChaosIcon key={i} c={c} />)}</g>

      <LuminousChrist pal={pal} cx={812} cy={350} scale={0.92} />

      <g key={run}>
        <path d={`M ${eye.x} ${eye.y} L ${target.x - 30} ${target.y - 70} L ${target.x - 30} ${target.y + 70} Z`}
          fill="url(#clarityCone)" opacity="0" style={{ animation: 'c12-fadeIn 1.6s ease 1.4s both' }} />
        <path d={beamD} fill="none" stroke={pal.warm} strokeWidth="10" strokeLinecap="round" opacity="0.22"
          style={{ '--len': beamLen, strokeDasharray: beamLen, animation: 'c12-draw 1.3s ease 0.6s both' }} />
        <path d={beamD} fill="none" stroke="#fff3d4" strokeWidth="2.4" strokeLinecap="round"
          style={{ '--len': beamLen, strokeDasharray: beamLen, animation: 'c12-draw 1.3s ease 0.6s both' }} />
        <circle r="3.5" fill="#fffaf0" style={{ offsetPath: `path('${beamD}')`, animation: 'c12-travel 3.2s ease-in-out 2.2s infinite' }} />
      </g>

      {/* Distracciones que cruzan rápido por delante de la vista */}
      <g key={'streaks' + run}>
        {streaks.map((s, i) => (
          <g key={i} transform={`translate(430 ${s.y})`}>
            <g style={{ opacity: 0, animation: `c12-streak${s.dir} ${s.dur}s linear ${s.delay}s infinite` }}>
              <StreakIcon kind={s.kind} />
            </g>
          </g>
        ))}
      </g>

      {/* Persona realista, túnica, caminando — rim-light cálido del lado de Jesús */}
      <g style={{ animation: 'c12-walk 3.8s ease-in-out infinite', transformOrigin: '330px 600px' }}>
        <ellipse cx="332" cy="772" rx="60" ry="10" fill={pal.abyss} opacity="0.55" />
        {/* pierna trasera */}
        <path d="M 322 600 Q 300 680 300 740 L 320 742 Q 330 686 340 612 Z" fill={pal.abyss} />
        <ellipse cx="300" cy="748" rx="20" ry="7" fill={pal.abyss} />
        {/* pierna delantera (paso) */}
        <path d="M 344 600 Q 360 676 372 730 L 354 738 Q 336 690 326 612 Z" fill={pal.deep} />
        <ellipse cx="366" cy="736" rx="22" ry="7" fill={pal.deep} />
        {/* túnica / torso */}
        <path d="M 296 506 Q 286 560 292 612 Q 320 626 372 612 Q 378 560 366 506 Q 332 490 296 506 Z" fill="url(#m3robe)" />
        {/* pliegues */}
        <path d="M 318 520 Q 322 565 318 610 M 348 520 Q 352 565 350 608" stroke={pal.abyss} strokeWidth="2" opacity="0.4" fill="none" />
        {/* rim-light cálido del borde derecho (luz de Jesús) */}
        <path d="M 366 506 Q 378 560 366 612" stroke={pal.warm} strokeWidth="2.4" fill="none" opacity="0.6" strokeLinecap="round" />
        {/* brazo */}
        <path d="M 360 520 Q 384 556 374 600" stroke="url(#m3robe)" strokeWidth="17" fill="none" strokeLinecap="round" />
        <path d="M 372 524 Q 390 556 380 596" stroke={pal.warm} strokeWidth="2" fill="none" opacity="0.45" strokeLinecap="round" />
        {/* hombro/manto */}
        <path d="M 296 510 Q 332 494 366 510 Q 350 522 332 522 Q 314 522 296 510 Z" fill={pal.deep} opacity="0.8" />
        {/* cuello */}
        <rect x="324" y="476" width="16" height="20" rx="6" fill="url(#m3skin)" />
        {/* cabeza (mira hacia la luz) */}
        <g transform="rotate(6 340 456)">
          <ellipse cx="338" cy="456" rx="23" ry="27" fill="url(#m3skin)" />
          {/* cabello */}
          <path d="M 316 450 Q 330 426 360 438 Q 364 452 358 452 L 324 452 Q 314 452 316 450 Z" fill={pal.abyss} />
          {/* rim cálido en la mejilla derecha */}
          <path d="M 358 442 Q 364 456 356 472" stroke={pal.warm} strokeWidth="2" fill="none" opacity="0.6" strokeLinecap="round" />
          {/* ojo encendido mirando a Jesús */}
          <circle cx="352" cy="454" r="2.6" fill={pal.warm} style={{ animation: 'c12-glow 2.4s ease-in-out infinite' }} />
          <path d="M 348 466 Q 354 469 360 465" stroke="#7c4838" strokeWidth="1.6" fill="none" strokeLinecap="round" opacity="0.7" />
        </g>
      </g>
    </SceneFrame>
  );
}

Object.assign(window, {
  useRun, SceneFrame, SkyBackdrop, LuminousChrist, globeDots,
  SceneMundo, SceneOrbita, SceneMirada,
});
