// ══════════════════════════════════════════════════════════════════════
// screens-end.jsx — Pantallas del final de partida
//
// Contiene:
//   · ModelBadge      — icono de modelo IA (Anthropic / OpenAI)
//   · ScreenCalculo   — animación mientras se calculan los puntos
//   · ScreenRegistro  — formulario: alias + email (ambos opcionales)
//   · ScreenLeaderboard — clasificación final mezclando:
//       · 7 modelos IA con sus puntuaciones reales de benchmark
//       · Jugadores reales del día (desde localStorage)
//       · Nombres ficticios de relleno para que la tabla no quede vacía
//
// Puntuaciones IA (escala 0–100, fuente: benchmark interno Unnic AI):
//   Claude Opus 93 · GPT-5 91 · Claude Sonnet 89 · GPT-4 81
//   GPT-3.5 56 · GPT-3 52 · GPT-2 17
// ══════════════════════════════════════════════════════════════════════

// Abstract model badges — NOT copied from real brand marks.
function ModelBadge({ brand, size = 56 }) {
  // Two generic geometric marks to visually distinguish Anthropic vs OpenAI rows
  // without reproducing their actual logos.
  if (brand === 'anthropic') {
    return (
      <div style={{ width: size, height: size, borderRadius: size/2, background: '#1a1512', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, border: `1px solid rgba(255,255,255,0.08)` }}>
        <svg width={size*0.56} height={size*0.56} viewBox="0 0 24 24" fill="none">
          <path d="M6 20L11 4h2l5 16M8.5 15h7" stroke="#d4a574" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
      </div>
    );
  }
  return (
    <div style={{ width: size, height: size, borderRadius: size/2, background: '#0f1a17', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, border: `1px solid rgba(255,255,255,0.08)` }}>
      <svg width={size*0.58} height={size*0.58} viewBox="0 0 24 24" fill="none">
        <circle cx="12" cy="12" r="9" stroke="#6fb39a" strokeWidth="2"/>
        <path d="M4 12h16M12 4v16" stroke="#6fb39a" strokeWidth="2"/>
      </svg>
    </div>
  );
}

// Other humans who've played today — interleaved with AIs in the ranking
const HUMANS = [
  { name: 'MARTA G.',  score: 90 },
  { name: 'DAVID Ñ.',  score: 84 },
  { name: 'ANA P.',    score: 72 },
  { name: 'LEO B.',    score: 68 },
  { name: 'CARLA S.',  score: 55 },
  { name: 'JAVIER R.', score: 38 },
];

// Scores de benchmark real: 7 modelos × 100 preguntas × 5 reps
// Escala 0–100 (accuracy % directa). Ej: Claude Opus 93.4% → 93
const MODELS = [
  { name: 'Claude Opus',   brand: 'anthropic', score: 93 },
  { name: 'GPT-5',         brand: 'openai',    score: 91 },
  { name: 'Claude Sonnet', brand: 'anthropic', score: 89 },
  { name: 'GPT-4',         brand: 'openai',    score: 81 },
  { name: 'GPT-3.5',       brand: 'openai',    score: 56 },
  { name: 'GPT-3',         brand: 'openai',    score: 52 },
  { name: 'GPT-2',         brand: 'openai',    score: 17 },
];

// ══════════════════════════════════════════════════════════════
// 4. LEADERBOARD
// ══════════════════════════════════════════════════════════════

const HUMAN_NAMES = [
  'ALEX M.','SARA P.','IVAN K.','NURIA F.','MARC T.','ELENA B.','PABLO R.','LUCIA G.',
  'OMAR S.','RITA V.','DIEGO C.','ALBA N.','FELIX L.','NORA H.','JOEL A.','MAYA W.',
  'TOMAS B.','CLARA F.','RUBEN S.','VERA T.','ANDRES P.','SOFIA M.','HUGO R.','IRIS C.',
  'DANI L.','LAIA B.','SERGI V.','JANA K.','MARC F.','AINA P.','GUILLEM T.','NEUS R.',
  'PAU S.','MIREIA L.','ORIOL B.','CARLA V.','ARNAU F.','MARTA C.','ROGER P.','ANNA T.',
  'JORDI M.','LAURA S.','MIKEL B.','AMAIA R.','IKER F.','LEIRE V.','UNAI C.','NAIA L.',
  'ASIER T.','ANE P.','CARLOS M.','MARINA F.','JAVIER S.','ELENA R.','PABLO T.','ANA L.',
  'LUIS B.','ROSA V.','PEDRO C.','ISABEL M.','RAMON F.','TERESA S.','JOSE R.','CARMEN T.',
  'ANTONIO P.','PILAR B.','FRANCISCO V.','DOLORES C.','MANUEL L.','RAFAEL S.','MERCEDES R.',
  'ANGEL T.','BEATRIZ F.','ENRIQUE P.','CRISTINA V.','JAIME C.','PATRICIA L.','VICTOR R.',
  'SILVIA T.','ROBERTO F.','MONICA B.','FERNANDO V.','ALICIA C.','GONZALO L.','SUSANA M.',
  'IGNACIO S.','RAQUEL R.','NICOLAS B.','CLAUDIA P.','MARIO T.','ALBA S.',
];

function ScreenLeaderboard({ playerScore = 7, playerAlias = 'TÚ', animate = true, onContinue, extraPlayers = [], totalParticipants = 0 }) {
  const ROW_H = 82;
  const ROW_GAP = 8;
  const ROW_STRIDE = ROW_H + ROW_GAP;
  const VIEWPORT_H = 1280;

  const [currentScore, setCurrentScore] = React.useState(animate ? 0 : playerScore);
  const [scrollY, setScrollY] = React.useState(0);
  const [settled, setSettled] = React.useState(!animate);
  const scrollYRef = React.useRef(scrollY);

  // Build large competitor pool — deterministic scores (escala 0-100)
  const allCompetitors = React.useMemo(() => {
    const realPlayers = extraPlayers.map(p => ({ name: p.name, kind: 'human', brand: 'human', score: p.score }));
    // Solo añadir ficticios si no hay suficientes jugadores reales (primeras partidas del día)
    const fakeNeeded = Math.max(0, 15 - realPlayers.length);
    const realNames = new Set(extraPlayers.map(p => p.name));
    const fakeHumans = fakeNeeded > 0
      ? HUMAN_NAMES
          .filter(name => !realNames.has(name))
          .slice(0, fakeNeeded)
          .map((name, i) => {
            const noise = ((i * 7 + 13) % 19 - 9) / 9 * 6;
            const score = Math.max(3, Math.min(98, 94 - i * (90 / fakeNeeded) + noise));
            return { name, kind: 'human', brand: 'human', score };
          })
      : [];
    return [
      ...MODELS.map(m => ({ ...m, kind: 'ai' })),
      ...realPlayers,
      ...fakeHumans,
    ];
  }, [extraPlayers]);

  const maxScore = 100;  // 9 pts/acierto + hasta 1 pt bonus velocidad × 10 preguntas

  // Sorted rows — recomputed as currentScore changes
  const rows = React.useMemo(() => [
    ...allCompetitors,
    { name: playerAlias, kind: 'player', brand: 'player', score: currentScore },
  ].sort((a, b) => b.score - a.score), [allCompetitors, currentScore, playerAlias]);

  const playerIdx = rows.findIndex(r => r.kind === 'player');
  const playerRank = playerIdx + 1;
  const beaten = allCompetitors.filter(c => c.score < currentScore).length;
  const totalCount = totalParticipants > 0 ? totalParticipants : rows.length;
  const maxScrollY = Math.max(0, rows.length * ROW_STRIDE - VIEWPORT_H);

  // Target scroll: center the player row in viewport
  const targetScrollY = Math.max(0, Math.min(maxScrollY,
    playerIdx * ROW_STRIDE - VIEWPORT_H / 2 + ROW_H / 2
  ));

  // Score animation + initial scroll from bottom
  React.useEffect(() => {
    if (!animate) {
      setCurrentScore(playerScore);
      setScrollY(targetScrollY);
      scrollYRef.current = targetScrollY;
      return;
    }
    // Start at bottom of list
    const startScroll = maxScrollY;
    setScrollY(startScroll);
    scrollYRef.current = startScroll;
    setCurrentScore(0);
    setSettled(false);

    let cancelled = false;
    let raf;
    const duration = 4400;
    const startDelay = 600;
    const startAt = performance.now() + startDelay;

    const tick = (now) => {
      if (cancelled) return;
      if (now < startAt) { raf = requestAnimationFrame(tick); return; }
      const t = Math.min(1, (now - startAt) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setCurrentScore(playerScore * eased);
      if (t < 1) raf = requestAnimationFrame(tick);
      else setTimeout(() => { if (!cancelled) setSettled(true); }, 800);
    };
    raf = requestAnimationFrame(tick);
    return () => { cancelled = true; cancelAnimationFrame(raf); };
  }, [animate, playerScore]);

  // Smooth scroll spring — follows player while animating
  React.useEffect(() => {
    if (settled) return;
    let raf;
    const spring = () => {
      setScrollY(cur => {
        const target = Math.max(0, Math.min(maxScrollY,
          // Recomputed each frame — playerIdx will have moved
          playerIdx * ROW_STRIDE - VIEWPORT_H / 2 + ROW_H / 2
        ));
        const diff = target - cur;
        if (Math.abs(diff) < 0.4) return target;
        return cur + diff * 0.055;
      });
      raf = requestAnimationFrame(spring);
    };
    raf = requestAnimationFrame(spring);
    return () => cancelAnimationFrame(raf);
  }, [settled, playerIdx, maxScrollY]);

  // Drag/touch scroll after settled
  const dragRef = React.useRef({ active: false, startY: 0, startScroll: 0, vel: 0, lastY: 0, lastT: 0 });
  const momentumRef = React.useRef(null);

  const stopMomentum = () => { if (momentumRef.current) cancelAnimationFrame(momentumRef.current); };

  const onPointerDown = React.useCallback((e) => {
    if (!settled) return;
    stopMomentum();
    dragRef.current = { active: true, startY: e.clientY, startScroll: scrollYRef.current, vel: 0, lastY: e.clientY, lastT: performance.now() };
    e.currentTarget.setPointerCapture(e.pointerId);
  }, [settled]);

  const onPointerMove = React.useCallback((e) => {
    if (!dragRef.current.active) return;
    const now = performance.now();
    const dy = dragRef.current.startY - e.clientY;
    const dt = now - dragRef.current.lastT;
    if (dt > 0) dragRef.current.vel = (e.clientY - dragRef.current.lastY) / dt;
    dragRef.current.lastY = e.clientY;
    dragRef.current.lastT = now;
    const next = Math.max(0, Math.min(maxScrollY, dragRef.current.startScroll + dy));
    scrollYRef.current = next;
    setScrollY(next);
  }, [maxScrollY]);

  const onPointerUp = React.useCallback(() => {
    if (!dragRef.current.active) return;
    dragRef.current.active = false;
    // Momentum
    let vel = -dragRef.current.vel * 16;
    const glide = () => {
      vel *= 0.92;
      if (Math.abs(vel) < 0.5) return;
      scrollYRef.current = Math.max(0, Math.min(maxScrollY, scrollYRef.current + vel));
      setScrollY(scrollYRef.current);
      momentumRef.current = requestAnimationFrame(glide);
    };
    momentumRef.current = requestAnimationFrame(glide);
  }, [maxScrollY]);

  // Keep scrollYRef in sync
  React.useEffect(() => { scrollYRef.current = scrollY; }, [scrollY]);

  // Scroll to player button (after settled)
  const scrollToPlayer = () => {
    const t = Math.max(0, Math.min(maxScrollY, playerIdx * ROW_STRIDE - VIEWPORT_H / 2 + ROW_H / 2));
    let cur = scrollYRef.current;
    const go = () => {
      const diff = t - cur;
      if (Math.abs(diff) < 1) { setScrollY(t); scrollYRef.current = t; return; }
      cur += diff * 0.12;
      scrollYRef.current = cur;
      setScrollY(cur);
      momentumRef.current = requestAnimationFrame(go);
    };
    stopMomentum();
    momentumRef.current = requestAnimationFrame(go);
  };

  // Show scroll hints after settled
  const showUp = settled && scrollY > ROW_STRIDE;
  const showDown = settled && scrollY < maxScrollY - ROW_STRIDE;

  return (
    <ArcadeBG>
      <style>{`
        @keyframes arrow-bounce-up { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
        @keyframes arrow-bounce-down { 0%,100% { transform: translateY(0); } 50% { transform: translateY(8px); } }
        @keyframes rank-appear { from { opacity: 0; transform: scale(0.8); } to { opacity: 1; transform: scale(1); } }
      `}</style>

      {/* top bar */}
      <div style={{ position: 'absolute', top: 60, left: 60, right: 60, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <UnnicLogo size={100}/>
        <div style={{ textAlign: 'right' }}>
          <div style={{ fontSize: 14, color: window.TEXT_DIM, letterSpacing: '0.2em' }}>{window.t('has_superado')}</div>
          <div style={{ fontFamily: '"Space Grotesk", system-ui, sans-serif', fontSize: 54, fontWeight: 700, color: window.UNNIC_YELLOW, lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>
            {beaten} <span style={{ fontSize: 24, color: window.TEXT_DIM, fontWeight: 500 }}>/ {totalCount - 1}</span>
          </div>
        </div>
      </div>

      {/* eyebrow + title */}
      <div style={{ position: 'absolute', top: 200, left: 60, right: 60 }}>
        <div style={{ fontSize: 20, letterSpacing: '0.3em', color: window.UNNIC_YELLOW, fontWeight: 600, marginBottom: 12 }}>{window.t('clasif_directo')}</div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
          <h2 style={{ fontFamily: '"Space Grotesk", system-ui, sans-serif', fontSize: 82, fontWeight: 700, margin: 0, letterSpacing: '-0.02em', lineHeight: 1 }}>
            {window.t('humanos_ia')}
          </h2>
          {settled && (
            <div style={{ textAlign: 'right', animation: 'rank-appear 400ms cubic-bezier(.2,1.4,.4,1)' }}>
              <div style={{ fontSize: 14, color: window.TEXT_DIM, letterSpacing: '0.2em' }}>{window.t('tu_posicion')}</div>
              <div style={{ fontFamily: '"Space Grotesk", system-ui, sans-serif', fontSize: 72, fontWeight: 700, color: window.UNNIC_YELLOW, lineHeight: 1 }}>
                #{playerRank}
              </div>
            </div>
          )}
        </div>
      </div>

      {/* Scrollable list viewport */}
      <div
        style={{ position: 'absolute', top: 380, left: 60, right: 60, bottom: 220, overflow: 'hidden', cursor: settled ? 'grab' : 'default' }}
        onPointerDown={onPointerDown}
        onPointerMove={onPointerMove}
        onPointerUp={onPointerUp}
        onPointerCancel={onPointerUp}
      >
        {/* Top fade — only when not at top */}
        {scrollY > 10 && <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 60, background: `linear-gradient(to bottom, ${window.BG}, transparent)`, zIndex: 10, pointerEvents: 'none' }}/>}
        {/* Bottom fade */}
        <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 60, background: `linear-gradient(to top, ${window.BG}, transparent)`, zIndex: 10, pointerEvents: 'none' }}/>

        <div style={{
          position: 'absolute', top: 0, left: 0, right: 0,
          transform: `translateY(${-scrollY}px)`,
          willChange: 'transform',
        }}>
          {rows.map((r, idx) => (
            <LeaderRow key={r.name + '_' + r.kind}
              row={r} rank={idx + 1} maxScore={maxScore}
              y={idx * ROW_STRIDE} h={ROW_H}/>
          ))}
        </div>
      </div>

      {/* Scroll arrows */}
      {showUp && (
        <div onClick={() => setScrollY(s => Math.max(0, s - VIEWPORT_H * 0.6))} style={{
          position: 'absolute', top: 390, left: '50%', transform: 'translateX(-50%)',
          zIndex: 20, cursor: 'pointer', opacity: 0.7,
          animation: 'arrow-bounce-up 1.4s ease-in-out infinite',
        }}>
          <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke={window.UNNIC_YELLOW} strokeWidth="2.5" strokeLinecap="round">
            <path d="M5 15l7-7 7 7"/>
          </svg>
        </div>
      )}
      {showDown && (
        <div onClick={() => setScrollY(s => Math.min(maxScrollY, s + VIEWPORT_H * 0.6))} style={{
          position: 'absolute', bottom: 230, left: '50%', transform: 'translateX(-50%)',
          zIndex: 20, cursor: 'pointer', opacity: 0.7,
          animation: 'arrow-bounce-down 1.4s ease-in-out infinite',
        }}>
          <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke={window.UNNIC_YELLOW} strokeWidth="2.5" strokeLinecap="round">
            <path d="M5 9l7 7 7-7"/>
          </svg>
        </div>
      )}

      {/* footer */}
      <div style={{ position: 'absolute', bottom: 60, left: 60, right: 60, display: 'flex', flexDirection: 'column', gap: 18 }}>
        <div style={{ display: 'flex', gap: 18, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center' }}>
          <Legend dot={window.UNNIC_YELLOW} label={window.t('legend_you')}/>
          <Legend dot="#ffffff" label={window.t('legend_humans')}/>
          <Legend dot="#6fb39a" label="GPT"/>
          <Legend dot="#d4a574" label="Claude"/>
          {settled && (
            <button onClick={scrollToPlayer} style={{
              background: 'transparent', border: `1px solid ${window.UNNIC_YELLOW}55`,
              color: window.UNNIC_YELLOW, padding: '8px 18px', borderRadius: 8,
              fontSize: 14, cursor: 'pointer', fontFamily: 'inherit', letterSpacing: '0.1em',
            }}>
              {window.t('ir_posicion')}
            </button>
          )}
        </div>
        <button onClick={onContinue} style={{
          padding: '28px 48px', fontSize: 32, fontWeight: 600,
          fontFamily: '"Space Grotesk", system-ui, sans-serif',
          background: window.UNNIC_YELLOW, color: window.BG, border: 'none',
          borderRadius: 16, cursor: 'pointer', letterSpacing: '-0.01em',
          boxShadow: 'inset 0 -5px 0 rgba(0,0,0,0.15)',
        }}>
          {window.t('jugar_nuevo')}
        </button>
      </div>
    </ArcadeBG>
  );
}

function Legend({ dot, label }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: window.TEXT_DIM, letterSpacing: '0.08em' }}>
      <span style={{ width: 10, height: 10, borderRadius: 5, background: dot, boxShadow: `0 0 8px ${dot}99` }}/>
      {label}
    </div>
  );
}

function LeaderRow({ row, rank, maxScore, y, h }) {
  const pct = Math.max(0, Math.min(1, row.score / maxScore));
  const isPlayer = row.kind === 'player';
  const isHuman  = row.kind === 'human';
  const color = isPlayer ? window.UNNIC_YELLOW
              : isHuman  ? '#ffffff'
              : row.brand === 'anthropic' ? '#d4a574' : '#6fb39a';

  return (
    <div style={{
      position: 'absolute', left: 0, right: 0, top: y, height: h,
      display: 'flex', alignItems: 'center', gap: 14,
      padding: '0 20px',
      background: isPlayer ? `${window.UNNIC_YELLOW}18` : 'rgba(255,255,255,0.02)',
      border: `1.5px solid ${isPlayer ? window.UNNIC_YELLOW : 'rgba(255,255,255,0.05)'}`,
      borderRadius: 12,
      boxShadow: isPlayer ? `0 0 32px ${window.UNNIC_YELLOW}44` : 'none',
      zIndex: isPlayer ? 2 : 1,
    }}>
      <div style={{
        width: 48, textAlign: 'center',
        fontFamily: '"Space Grotesk", system-ui, sans-serif',
        fontSize: 26, fontWeight: 700,
        color: isPlayer ? window.UNNIC_YELLOW : window.TEXT_DIM,
        fontVariantNumeric: 'tabular-nums',
      }}>
        {String(rank).padStart(2,'0')}
      </div>
      <RowBadge row={row}/>
      <div style={{
        width: 240, flexShrink: 0,
        fontSize: 22, fontWeight: isPlayer ? 700 : 600,
        color: window.TEXT,
        fontFamily: '"Space Grotesk", system-ui, sans-serif',
        letterSpacing: '-0.01em',
        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
      }}>
        {isPlayer ? '★ ' + row.name : row.name}
      </div>
      <div style={{ flex: 1, height: 24, background: 'rgba(255,255,255,0.04)', borderRadius: 4, overflow: 'hidden', position: 'relative' }}>
        <div style={{
          height: '100%', width: `${pct * 100}%`,
          background: isPlayer
            ? `linear-gradient(90deg, ${window.UNNIC_YELLOW} 0%, #fff8a0 100%)`
            : `linear-gradient(90deg, ${color}66 0%, ${color} 100%)`,
          boxShadow: isPlayer ? `0 0 16px ${window.UNNIC_YELLOW}99` : 'none',
          transition: isPlayer ? 'none' : 'width 300ms',
          position: 'relative',
        }}>
          {isPlayer && (
            <div style={{
              position: 'absolute', top: -4, bottom: -4, right: 0, width: 4,
              background: '#fff', boxShadow: '0 0 14px #fff',
            }}/>
          )}
        </div>
      </div>
      <div style={{
        width: 96, textAlign: 'right',
        fontFamily: '"Space Grotesk", system-ui, sans-serif',
        fontSize: 30, fontWeight: 700,
        color: isPlayer ? window.UNNIC_YELLOW : window.TEXT,
        fontVariantNumeric: 'tabular-nums',
      }}>
        {Math.round(row.score)}<span style={{ fontSize: 16, color: window.TEXT_DIM, fontWeight: 500 }}>%</span>
      </div>
    </div>
  );
}

function RowBadge({ row }) {
  if (row.kind === 'player') {
    return (
      <div style={{
        width: 40, height: 40, borderRadius: 20, flexShrink: 0,
        background: window.UNNIC_YELLOW, color: window.BG,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        border: '2px solid rgba(255,255,255,0.3)',
      }}>
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
          <circle cx="12" cy="8" r="4"/><path d="M4 21v-2a6 6 0 0 1 6-6h4a6 6 0 0 1 6 6v2"/>
        </svg>
      </div>
    );
  }
  if (row.kind === 'human') {
    return (
      <div style={{
        width: 40, height: 40, borderRadius: 20, flexShrink: 0,
        background: 'rgba(255,255,255,0.08)', color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        border: '1px solid rgba(255,255,255,0.15)',
        fontFamily: '"Space Grotesk", system-ui, sans-serif',
        fontSize: 13, fontWeight: 700, letterSpacing: '0.04em',
      }}>
        {row.name.split(' ').map(s => s[0]).slice(0,2).join('')}
      </div>
    );
  }
  return <ModelBadge brand={row.brand} size={40}/>;
}

function Confetti() {
  const pieces = React.useMemo(() => Array.from({ length: 60 }, (_, i) => ({
    id: i,
    x: Math.random() * 100,
    delay: Math.random() * 800,
    duration: 2500 + Math.random() * 2000,
    size: 6 + Math.random() * 10,
    color: [window.UNNIC_YELLOW, '#fff8a0', '#ffffff', window.UNNIC_YELLOW][i % 4],
    rot: Math.random() * 360,
  })), []);
  return (
    <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', overflow: 'hidden' }}>
      <style>{`
        @keyframes confetti-fall {
          0% { transform: translateY(-40px) rotate(0deg); opacity: 0; }
          10% { opacity: 1; }
          100% { transform: translateY(1200px) rotate(720deg); opacity: 0.8; }
        }
      `}</style>
      {pieces.map(p => (
        <div key={p.id} style={{
          position: 'absolute', top: 0, left: `${p.x}%`,
          width: p.size, height: p.size * 0.4,
          background: p.color,
          animation: `confetti-fall ${p.duration}ms ${p.delay}ms linear forwards`,
          transform: `rotate(${p.rot}deg)`,
        }}/>
      ))}
    </div>
  );
}

// ══════════════════════════════════════════════════════════════
// 5. REGISTRO
// ══════════════════════════════════════════════════════════════
function ScreenRegistro({ onSubmit, onSkip, initialAlias = '', initialEmail = '' }) {
  const [alias, setAlias] = React.useState(initialAlias);
  const [email, setEmail] = React.useState(initialEmail);
  const [kb, setKb] = React.useState({ visible: false, field: null });

  const handleKey = (k) => {
    if (!kb.field) return;
    const setter = kb.field === 'email' ? setEmail : setAlias;
    const val = kb.field === 'email' ? email : alias;
    if (k === '⌫') setter(val.slice(0, -1));
    else if (k === '␣') setter(val + ' ');
    else setter(val + k);
  };

  const canSubmit = alias.trim().length >= 2 && email.includes('@') && email.includes('.');

  return (
    <ArcadeBG>
      <CornerMarks/>
      <div style={{ position: 'absolute', top: 60, left: 60, right: 60, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <UnnicLogo size={100}/>
        <button onClick={onSkip} style={{
          background: 'transparent', border: `1px solid ${window.BORDER}`, color: window.TEXT_DIM,
          padding: '14px 28px', borderRadius: 10, fontSize: 18, cursor: 'pointer', fontFamily: 'inherit',
        }}>
          {window.t('saltar')}
        </button>
      </div>

      {!kb.visible && (
        <div style={{
          position: 'absolute', left: 60, right: 60,
          top: '50%', transform: 'translateY(-50%)',
          display: 'flex', flexDirection: 'column', alignItems: 'stretch', textAlign: 'center',
        }}>
          <div style={{ fontSize: 22, letterSpacing: '0.3em', color: window.UNNIC_YELLOW, fontWeight: 600, marginBottom: 24 }}>
            {window.t('como_quedado')}
          </div>
          <h2 style={{
            fontFamily: '"Space Grotesk", system-ui, sans-serif',
            fontSize: 84, fontWeight: 700, margin: 0, letterSpacing: '-0.03em', lineHeight: 1.05,
          }}>
            {window.t('reg_q1')}<br/>{window.t('reg_q2')} <span style={{ color: window.UNNIC_YELLOW }}>{window.t('reg_qword')}</span>?
          </h2>
          <div style={{ fontSize: 26, color: window.TEXT_DIM, marginTop: 28, marginBottom: 56 }}>
            {window.t('ademas')}
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 22, textAlign: 'left' }}>
            <Field label={window.t('alias_label')} placeholder={window.t('alias_ph')} value={alias}
              focused={false}
              onFocus={() => setKb({ visible: true, field: 'alias' })} maxLen={14}/>
            <Field label="EMAIL" placeholder="tu@empresa.com" value={email}
              focused={false}
              onFocus={() => setKb({ visible: true, field: 'email' })} maxLen={40}/>

            <button disabled={!canSubmit} onClick={() => canSubmit && onSubmit && onSubmit({ alias, email })}
              style={{
                marginTop: 12, padding: '28px', fontSize: 32, fontWeight: 600,
                fontFamily: '"Space Grotesk", system-ui, sans-serif',
                background: canSubmit ? window.UNNIC_YELLOW : 'rgba(255,255,255,0.08)',
                color: canSubmit ? window.BG : window.TEXT_DIM,
                border: 'none', borderRadius: 16,
                cursor: canSubmit ? 'pointer' : 'not-allowed',
                letterSpacing: '-0.01em',
                boxShadow: canSubmit ? 'inset 0 -4px 0 rgba(0,0,0,0.15)' : 'none',
                transition: 'all 200ms',
              }}>
              {window.t('ver_clasif')}
            </button>

            <div style={{ fontSize: 14, color: window.TEXT_DIM, textAlign: 'center', lineHeight: 1.5, marginTop: 4 }}>
              {window.t('privacy')}
            </div>
          </div>
        </div>
      )}

      {/* Live input preview — centered, large, always visible above the keyboard */}
      {kb.visible && (
        <LiveInputPreview
          field={kb.field}
          value={kb.field === 'email' ? email : alias}
          otherLabel={kb.field === 'email' ? 'ALIAS' : 'EMAIL'}
          otherValue={kb.field === 'email' ? alias : email}
          onSwitch={() => setKb({ visible: true, field: kb.field === 'email' ? 'alias' : 'email' })}
        />
      )}

      {/* On-screen keyboard */}
      {kb.visible && (
        <OnScreenKeyboard onKey={handleKey} onDone={() => setKb({ visible: false, field: null })}
          field={kb.field}/>
      )}
    </ArcadeBG>
  );
}

function Field({ label, value, placeholder, onFocus, focused, maxLen }) {
  return (
    <div onClick={onFocus} style={{
      padding: '24px 32px',
      background: focused ? window.SURFACE_2 : window.SURFACE,
      border: `2px solid ${focused ? window.UNNIC_YELLOW : window.BORDER}`,
      borderRadius: 16,
      cursor: 'pointer',
      boxShadow: focused ? `0 0 28px ${window.UNNIC_YELLOW}22` : 'none',
      transition: 'all 200ms',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ fontSize: 14, letterSpacing: '0.25em', color: focused ? window.UNNIC_YELLOW : window.TEXT_DIM, fontWeight: 600 }}>
          {label}
        </div>
        <div style={{ fontSize: 12, color: window.TEXT_DIM, fontVariantNumeric: 'tabular-nums' }}>
          {value.length}/{maxLen}
        </div>
      </div>
      <div style={{
        marginTop: 10, minHeight: 52,
        fontFamily: '"Space Grotesk", system-ui, sans-serif',
        fontSize: 44, fontWeight: 600, letterSpacing: '-0.01em',
        color: value ? window.TEXT : 'rgba(255,255,255,0.22)',
      }}>
        {value || placeholder}
        {focused && <span style={{
          display: 'inline-block', width: 3, height: 44, verticalAlign: 'middle',
          marginLeft: 4, background: window.UNNIC_YELLOW,
          animation: 'blink 1s steps(2) infinite',
        }}/>}
        <style>{`@keyframes blink { 50% { opacity: 0; } }`}</style>
      </div>
    </div>
  );
}

function LiveInputPreview({ field, value, otherLabel, otherValue, onSwitch }) {
  const isEmail = field === 'email';
  const label = isEmail ? 'EMAIL' : window.t('alias_label');
  const placeholder = isEmail ? window.t('email_ph') : window.t('alias_ph_live');
  const hint = isEmail ? window.t('email_hint') : window.t('alias_hint');

  return (
    <div style={{
      position: 'absolute',
      left: 60, right: 60,
      top: 200,
      display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 28,
      animation: 'lip-in 300ms cubic-bezier(.2,.8,.2,1)',
    }}>
      <style>{`@keyframes lip-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }`}</style>

      {/* field label */}
      <div style={{
        fontSize: 16, letterSpacing: '0.3em', color: window.UNNIC_YELLOW, fontWeight: 600,
      }}>
        ── {label} ──
      </div>

      {/* giant input */}
      <div style={{
        width: '100%',
        padding: '34px 48px',
        background: window.SURFACE,
        border: `2px solid ${window.UNNIC_YELLOW}`,
        borderRadius: 20,
        boxShadow: `0 0 48px ${window.UNNIC_YELLOW}22, inset 0 0 0 1px rgba(255,255,255,0.04)`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        minHeight: 120,
        fontFamily: '"Space Grotesk", system-ui, sans-serif',
        fontSize: 56, fontWeight: 600, letterSpacing: '-0.01em',
        color: value ? window.TEXT : 'rgba(255,255,255,0.22)',
        whiteSpace: 'nowrap', overflow: 'hidden',
      }}>
        <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '100%' }}>
          {value || placeholder}
        </span>
        <span style={{
          display: 'inline-block', width: 4, height: 56, verticalAlign: 'middle',
          marginLeft: 6, background: window.UNNIC_YELLOW, flexShrink: 0,
          animation: 'blink 1s steps(2) infinite',
        }}/>
      </div>

      {/* helper + switch to other field */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }}>
        <div style={{ fontSize: 17, color: window.TEXT_DIM }}>
          {hint}
        </div>
        <button onClick={onSwitch} style={{
          background: 'transparent', border: `1px solid ${window.BORDER}`,
          color: window.TEXT, padding: '14px 24px', borderRadius: 10,
          fontSize: 16, cursor: 'pointer', fontFamily: 'inherit',
          display: 'flex', alignItems: 'center', gap: 16,
        }}>
          <span style={{ color: window.TEXT_DIM, letterSpacing: '0.15em', fontSize: 13 }}>{otherLabel}</span>
          <span style={{
            fontFamily: '"Space Grotesk", system-ui, sans-serif', fontWeight: 600,
            color: otherValue ? window.TEXT : window.TEXT_DIM,
            maxWidth: 280, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>
            {otherValue || window.t('vacio')}
          </span>
          <span style={{ color: window.UNNIC_YELLOW, fontSize: 18 }}>{window.t('editar')}</span>
        </button>
      </div>
    </div>
  );
}

function OnScreenKeyboard({ onKey, onDone, field }) {
  const rows = field === 'email'
    ? [
        '1234567890'.split(''),
        'qwertyuiop'.split(''),
        'asdfghjkl'.split('').concat(['@']),
        'zxcvbnm.-_'.split(''),
      ]
    : [
        'qwertyuiop'.split(''),
        'asdfghjkl'.split(''),
        'zxcvbnm'.split(''),
      ];
  return (
    <div style={{
      position: 'absolute', top: 960, left: 0, right: 0,
      background: window.SURFACE, borderTop: `2px solid ${window.BORDER}`,
      padding: '22px 40px 32px',
      animation: 'kb-slide 300ms cubic-bezier(.2,.8,.2,1)',
    }}>
      <style>{`@keyframes kb-slide { from { transform: translateY(100%); } to { transform: translateY(0); } }`}</style>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 14 }}>
        <div style={{ fontSize: 16, color: window.TEXT_DIM, letterSpacing: '0.2em' }}>
          {window.t('teclado_field', { f: field === 'email' ? 'EMAIL' : window.t('alias_label') })}
        </div>
        <button onClick={onDone} style={{
          padding: '10px 22px', background: window.PRIMARY, color: '#fff',
          border: 'none', borderRadius: 8, fontSize: 16, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
        }}>{window.t('listo')}</button>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' }}>
        {rows.map((row, i) => (
          <div key={i} style={{ display: 'flex', gap: 6 }}>
            {row.map((k) => <Key key={k} k={k} onKey={onKey}/>)}
          </div>
        ))}
        <div style={{ display: 'flex', gap: 6, marginTop: 4 }}>
          <Key k="␣" label={window.t('espacio')} wide={6} onKey={onKey}/>
          <Key k="⌫" label={window.t('borrar')} wide={3} danger onKey={onKey}/>
        </div>
      </div>
    </div>
  );
}

function Key({ k, label, wide = 1, danger, onKey }) {
  return (
    <button onClick={() => onKey(k)} style={{
      minWidth: wide * 88, height: 86,
      background: danger ? 'rgba(255,80,80,0.12)' : window.SURFACE_2,
      border: `1px solid ${danger ? 'rgba(255,80,80,0.3)' : window.BORDER}`,
      borderRadius: 12,
      color: window.TEXT,
      fontSize: 30, fontWeight: 600,
      fontFamily: '"Space Grotesk", system-ui, sans-serif',
      cursor: 'pointer', padding: '0 10px',
    }}>
      {label || k.toUpperCase()}
    </button>
  );
}

// ══════════════════════════════════════════════════════════════
// 6. CONFIRMACIÓN
// ══════════════════════════════════════════════════════════════
function ScreenConfirmacion({ alias = 'MARTA G.', rank = 3, total = 8, score = 7.8, onPlayAgain }) {
  return (
    <ArcadeBG>
      <Confetti/>
      <CornerMarks/>
      <div style={{ position: 'absolute', top: 60, left: 60, right: 60, display: 'flex', justifyContent: 'center' }}>
        <UnnicLogo size={64}/>
      </div>

      <div style={{
        position: 'absolute', top: 180, left: 60, right: 60,
        display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center',
      }}>
        <div style={{
          width: 160, height: 160, borderRadius: 80,
          background: window.UNNIC_YELLOW, color: window.BG,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: `0 0 80px ${window.UNNIC_YELLOW}66`,
          animation: 'pop 600ms cubic-bezier(.2,1.6,.5,1)',
        }}>
          <svg width="90" height="90" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
            <path d="M5 13l4 4L19 7"/>
          </svg>
        </div>
        <style>{`@keyframes pop { 0% { transform: scale(0); } 80% { transform: scale(1.08); } 100% { transform: scale(1); } }`}</style>

        <h1 style={{
          marginTop: 44,
          fontFamily: '"Space Grotesk", system-ui, sans-serif',
          fontSize: 86, fontWeight: 700, letterSpacing: '-0.03em', lineHeight: 1,
          margin: '44px 0 0',
        }}>
          {window.t('conf_line1')}<br/><span style={{ color: window.UNNIC_YELLOW }}>{window.t('conf_word')}</span>!
        </h1>

        <div style={{
          marginTop: 48,
          display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18, width: '100%',
        }}>
          <Stat label={window.t('stat_alias')} value={alias} accent={window.PRIMARY}/>
          <Stat label={window.t('stat_score')} value={`${Math.round(score * 10)}%`} accent={window.PRIMARY}/>
          <div style={{ gridColumn: '1 / -1' }}>
            <Stat label={window.t('stat_pos')} value={`#${rank}`} sub={window.t('de_total', { n: total })} accent={window.UNNIC_YELLOW} big/>
          </div>
        </div>

        <div style={{ marginTop: 36, fontSize: 22, color: window.TEXT_DIM, maxWidth: 860, lineHeight: 1.4 }}>
          {window.t('si_ganas')}
        </div>
      </div>

      {/* Bottom: top5 + replay */}
      <div style={{
        position: 'absolute', bottom: 60, left: 60, right: 60,
        display: 'flex', flexDirection: 'column', gap: 24,
      }}>
        <div style={{
          background: window.SURFACE, border: `1px solid ${window.BORDER}`,
          borderRadius: 14, padding: '20px 24px',
        }}>
          <div style={{ fontSize: 12, color: window.TEXT_DIM, letterSpacing: '0.25em', marginBottom: 12, textAlign: 'center' }}>
            {window.t('top5')}
          </div>
          {[
            { a: 'MARTA G.', s: 9.0 },
            { a: 'DAVID Ñ.', s: 8.4 },
            { a: alias, s: score, me: true },
            { a: 'ANA P.', s: 7.2 },
            { a: 'LEO B.', s: 6.8 },
          ].map((r, i) => (
            <div key={i} style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              padding: '10px 0', borderBottom: i < 4 ? `1px solid ${window.BORDER}` : 'none',
              color: r.me ? window.UNNIC_YELLOW : window.TEXT,
              fontWeight: r.me ? 700 : 500,
            }}>
              <span style={{ fontVariantNumeric: 'tabular-nums', width: 36, color: window.TEXT_DIM }}>#{i+1}</span>
              <span style={{ flex: 1, fontSize: 20 }}>{r.a}{r.me ? ' ' + window.t('es_tu') : ''}</span>
              <span style={{ fontFamily: '"Space Grotesk"', fontWeight: 700, fontSize: 22, fontVariantNumeric: 'tabular-nums' }}>{Math.round(r.s * 10)}%</span>
            </div>
          ))}
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
          <button onClick={onPlayAgain} style={{
            padding: '28px 72px',
            fontFamily: '"Space Grotesk", system-ui, sans-serif',
            fontSize: 36, fontWeight: 600,
            background: 'transparent', color: window.TEXT,
            border: `2px solid ${window.UNNIC_YELLOW}`,
            borderRadius: 16, cursor: 'pointer', letterSpacing: '-0.01em',
          }}>
            {window.t('jugar_nuevo')}
          </button>
          <div style={{ fontSize: 14, color: window.TEXT_DIM, letterSpacing: '0.22em' }}>
            {window.t('pasa_turno')}
          </div>
        </div>
      </div>
    </ArcadeBG>
  );
}

function Stat({ label, value, sub, accent, big }) {
  return (
    <div style={{
      padding: big ? '28px 36px' : '22px 26px',
      background: window.SURFACE,
      border: `2px solid ${big ? accent : window.BORDER}`,
      borderRadius: 16,
      boxShadow: big ? `0 0 32px ${accent}33` : 'none',
      textAlign: big ? 'center' : 'left',
    }}>
      <div style={{ fontSize: 13, color: window.TEXT_DIM, letterSpacing: '0.25em', fontWeight: 600 }}>{label}</div>
      <div style={{
        marginTop: 8,
        fontFamily: '"Space Grotesk", system-ui, sans-serif',
        fontSize: big ? 110 : 44, fontWeight: 700,
        color: big ? accent : window.TEXT,
        letterSpacing: '-0.03em', lineHeight: 1,
        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
      }}>
        {value}
        {sub && <span style={{ fontSize: big ? 32 : 22, color: window.TEXT_DIM, fontWeight: 500, marginLeft: 10 }}>{sub}</span>}
      </div>
    </div>
  );
}

window.ScreenLeaderboard = ScreenLeaderboard;
window.ScreenRegistro = ScreenRegistro;
window.ScreenConfirmacion = ScreenConfirmacion;
window.MODELS = MODELS;
