<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>{{ app_name }} · Arcade</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=DM+Sans:wght@400;500&display=swap');
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
:root{
  --bg:#000510;--surface:#0a0e1a;--surface2:#111827;
  --accent:#00c8ff;--green:#00ff88;--red:#ff3355;--amber:#ffcc00;--purple:#cc44ff;
  --text:#e8edf5;--muted:#8a9bb5;--border:rgba(255,255,255,0.08);
  --pixel:'Press Start 2P',monospace;
}
html,body{width:100%;height:100%;background:var(--bg);color:var(--text);font-family:'DM Sans',sans-serif;overflow:hidden;touch-action:none;}

/* SCANLINES */
body::after{content:'';position:fixed;inset:0;background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,0.15) 2px,rgba(0,0,0,0.15) 4px);pointer-events:none;z-index:9999;}

.screen{display:none;flex-direction:column;align-items:center;justify-content:center;height:100vh;padding:1.5rem;text-align:center;}
.screen.active{display:flex;}
#lobby-screen{height:auto;min-height:100vh;overflow-y:auto;padding:2rem 1.5rem;justify-content:center;}

/* ── LANGUAGE SELECT ── */
#lang-screen .title{font-family:var(--pixel);font-size:1.2rem;color:var(--accent);margin-bottom:.3rem;text-shadow:0 0 20px var(--accent);line-height:1.8;}
#lang-screen .subtitle{font-family:var(--pixel);font-size:.45rem;color:var(--muted);margin-bottom:2.5rem;letter-spacing:.1em;}
.lang-btn{
  display:block;width:100%;max-width:280px;margin:.6rem auto;
  padding:1rem;border-radius:4px;
  font-family:var(--pixel);font-size:.65rem;letter-spacing:.1em;
  cursor:pointer;border:2px solid;transition:all .15s;
}
.lang-btn.en{border-color:var(--accent);color:var(--accent);background:rgba(0,200,255,.05);}
.lang-btn.es{border-color:var(--amber);color:var(--amber);background:rgba(255,204,0,.05);}
.lang-btn:active{transform:scale(.96);}
.lang-btn:hover{filter:brightness(1.3);}
.pixel-stars{position:fixed;inset:0;pointer-events:none;}

/* ── JOIN ── */
#join-screen .logo{font-family:var(--pixel);font-size:1rem;color:var(--accent);margin-bottom:.3rem;text-shadow:0 0 20px var(--accent);line-height:1.8;}
#join-screen .sub{font-size:.85rem;color:var(--text);margin-bottom:2rem;opacity:.75;}
.field-wrap{width:100%;max-width:380px;margin-bottom:1rem;text-align:left;}
.field-wrap label{font-family:var(--pixel);font-size:.55rem;color:var(--accent);letter-spacing:.12em;display:block;margin-bottom:.5rem;}
.field-wrap input, .field-wrap select{
  width:100%;padding:1rem 1.1rem;
  background:var(--surface2);border:1.5px solid var(--border);border-radius:6px;
  color:var(--text);font-size:1.1rem;font-family:'DM Sans',sans-serif;
  outline:none;
}
.field-wrap input:focus,.field-wrap select:focus{border-color:var(--accent);}
.field-wrap input::placeholder{color:#5a6a80;}
.field-wrap select option{background:var(--surface2);}
#join-btn{
  width:100%;max-width:380px;padding:1.1rem;margin-top:.6rem;
  background:var(--accent);border:none;border-radius:6px;
  color:#000;font-family:var(--pixel);font-size:.6rem;letter-spacing:.1em;
  cursor:pointer;
}
#join-btn:active{opacity:.85;transform:scale(.97);}

/* ── LOBBY ── */
#lobby-screen{
  justify-content:center;
  min-height:100vh;
  height:auto;
  padding:2rem 1.5rem;
  overflow-y:auto;
}
#lobby-screen .big{font-size:3.5rem;margin-bottom:1rem;animation:float 2s ease-in-out infinite;}
#lobby-screen .pname{font-family:var(--pixel);font-size:.7rem;color:var(--accent);margin:.5rem 0;}
#lobby-screen .wait{font-family:var(--pixel);font-size:.4rem;color:var(--muted);animation:blink 1s step-end infinite;margin-top:1rem;}
.exit-btn{
  margin-top:1.5rem;
  background:transparent;border:1px solid var(--muted);
  color:var(--muted);font-family:var(--pixel);font-size:.4rem;
  letter-spacing:.08em;padding:.6rem 1.4rem;border-radius:4px;
  cursor:pointer;transition:all .2s;
}
.exit-btn:hover,.exit-btn:active{border-color:var(--red);color:var(--red);}

/* ── GAME CANVAS ── */
#game-screen{padding:0;position:relative;background:var(--bg);}
#game-canvas{display:block;width:100%;height:100vh;}
/* ── HUD + BANNER — stacked, no overlap ── */
#game-overlay{
  position:absolute;top:0;left:0;right:0;
  pointer-events:none;
  display:flex;flex-direction:column;
  padding:8px 12px 0;
  gap:6px;
}
#score-hud{
  display:flex;justify-content:space-between;align-items:center;
}
#score-hud .hud-score{font-family:var(--pixel);font-size:.5rem;color:var(--accent);}
#score-hud .hud-timer{font-family:var(--pixel);font-size:.75rem;color:var(--amber);}
#score-hud .hud-q{font-family:var(--pixel);font-size:.4rem;color:var(--muted);}
#projector-hint{
  font-family:var(--pixel);font-size:.42rem;
  color:var(--muted);line-height:1.5;text-align:center;
  letter-spacing:.08em;padding:.3rem 0;
  animation:blink 2s step-end infinite;
}

/* ── RESULT FLASH ── */
#result-flash{
  position:absolute;inset:0;display:none;
  flex-direction:column;align-items:center;justify-content:center;
  background:rgba(0,5,16,.92);z-index:50;
}
#result-flash.active{display:flex;}
#flash-icon{font-size:4rem;margin-bottom:.5rem;}
#flash-title{font-family:var(--pixel);font-size:.9rem;margin-bottom:.4rem;}
#flash-pts{font-family:var(--pixel);font-size:1.4rem;color:var(--accent);}
#flash-total{font-family:var(--pixel);font-size:.45rem;color:var(--muted);margin-top:.3rem;}

/* ── RESULTS / FUNFACT ── */
#results-screen{background:var(--bg);}
#results-screen .r-label{font-family:var(--pixel);font-size:.45rem;color:var(--green);letter-spacing:.1em;margin-bottom:1rem;}
#results-screen .r-fact{
  background:var(--surface2);border:1px solid var(--border);border-left:3px solid var(--accent);
  border-radius:0 8px 8px 0;padding:1rem 1.2rem;
  font-size:.88rem;line-height:1.65;text-align:left;max-width:360px;margin:0 auto 1rem;
}
#results-screen .r-score{font-family:var(--pixel);font-size:.65rem;color:var(--accent);margin-bottom:.5rem;}
#results-screen .r-wait{font-family:var(--pixel);font-size:.38rem;color:var(--muted);animation:blink 1s step-end infinite;}

/* ── PODIUM ── */
#podium-screen{background:var(--bg);height:auto;min-height:100vh;overflow-y:auto;padding:2rem 1.5rem;justify-content:center;}
#podium-screen h2{font-family:var(--pixel);font-size:.85rem;color:var(--amber);margin-bottom:.3rem;text-shadow:0 0 20px var(--amber);}
#podium-screen .sub{font-size:.75rem;color:var(--muted);margin-bottom:1.5rem;}
.podium-list{width:100%;max-width:360px;}
.podium-item{
  display:flex;align-items:center;gap:.8rem;
  background:var(--surface2);border:1px solid var(--border);
  border-radius:4px;padding:.7rem 1rem;margin-bottom:.5rem;
}
.podium-item.r1{border-color:var(--amber);background:rgba(255,204,0,.06);}
.podium-item.r2{border-color:rgba(200,200,200,.4);}
.podium-item.r3{border-color:rgba(180,120,60,.4);}
.p-rank{font-family:var(--pixel);font-size:.7rem;min-width:28px;}
.p-name{flex:1;font-size:.85rem;}
.p-score{font-family:var(--pixel);font-size:.6rem;color:var(--accent);}

@keyframes float{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}
@keyframes blink{0%,100%{opacity:1}50%{opacity:0}}
@keyframes popIn{from{transform:scale(.7);opacity:0}to{transform:scale(1);opacity:1}}
.pop{animation:popIn .3s cubic-bezier(.34,1.56,.64,1) both;}
</style>
</head>
<body>

<!-- STARS BG -->
<canvas class="pixel-stars" id="stars-canvas"></canvas>

<!-- SPLASH — goes straight to join -->
<div class="screen active" id="lang-screen">
  <div class="title">🌐 {{ app_name }}</div>
  <div class="subtitle">{{ org_name }}</div>
  
  <button class="lang-btn es" onclick="goJoin()">▶ &nbsp; JUGAR / PLAY</button>
</div>

<!-- JOIN -->
<div class="screen" id="join-screen">
  <div class="logo">🚀 {{ app_name }}</div>
  <div class="sub" id="join-sub">{{ org_name }}</div>
  <div class="field-wrap">
    <label id="lbl-fname">FIRST NAME</label>
    <input id="inp-fname" type="text" maxlength="20" autocomplete="off" autocorrect="off" autocapitalize="words">
  </div>
  <div class="field-wrap">
    <label id="lbl-lname">LAST NAME</label>
    <input id="inp-lname" type="text" maxlength="20" autocomplete="off" autocorrect="off" autocapitalize="words">
  </div>
  <div class="field-wrap">
    <label id="lbl-dept">DEPARTMENT</label>
    <select id="inp-dept">
      <option value="">-- Select --</option>
      {% for dept in departments %}<option>{{ dept }}</option>
      {% endfor %}
    </select>
  </div>
  <button id="join-btn">▶ ENTER GAME</button>
</div>

<!-- LOBBY -->
<div class="screen" id="lobby-screen">
  <div class="big">🛸</div>
  <div class="pname" id="lobby-name"></div>
  <div style="font-family:var(--pixel);font-size:.4rem;color:var(--muted);margin-bottom:.5rem;" id="lobby-dept"></div>
  <div class="wait" id="lobby-wait">WAITING FOR HOST...</div>
  <button class="exit-btn" id="exit-btn" onclick="exitGame()">✕ salir</button>
</div>

<!-- GAME -->
<div class="screen" id="game-screen">
  <canvas id="game-canvas"></canvas>
  <div id="game-overlay">
    <div id="score-hud">
      <span class="hud-score" id="hud-score">000000</span>
      <span class="hud-timer" id="hud-timer">15</span>
      <span class="hud-q" id="hud-q">Q1/5</span>
    </div>
    <div id="projector-hint"></div>
  </div>
  <div id="result-flash">
    <div id="flash-icon"></div>
    <div id="flash-title"></div>
    <div id="flash-pts"></div>
    <div id="flash-total"></div>
  </div>
</div>

<!-- RESULTS -->
<div class="screen" id="results-screen">
  <div class="r-label" id="r-label">✓ CORRECT ANSWER</div>
  <div class="r-fact" id="r-fact"></div>
  <div class="r-score" id="r-score"></div>
  <div class="r-wait" id="r-wait">WAITING FOR HOST...</div>
</div>

<!-- PODIUM -->
<div class="screen" id="podium-screen">
  <h2 id="pod-title">🏆 GAME OVER</h2>
  <p class="sub" id="pod-sub">{{ org_name }}</p>
  <div class="podium-list" id="podium-list"></div>
  <button class="exit-btn" onclick="exitGame()">✕ salir</button>
</div>

<script>
// ── STARS ────────────────────────────────────────────────────────────────────
(function() {
  const c = document.getElementById('stars-canvas');
  const ctx = c.getContext('2d');
  let stars = [];
  function resize() {
    c.width = window.innerWidth; c.height = window.innerHeight;
    stars = Array.from({length:80}, () => ({
      x: Math.random()*c.width, y: Math.random()*c.height,
      s: Math.random()*1.5+.5, b: Math.random()
    }));
  }
  function draw() {
    ctx.clearRect(0,0,c.width,c.height);
    stars.forEach(s => {
      s.b += .005; if(s.b>1) s.b=0;
      ctx.fillStyle = `rgba(255,255,255,${Math.abs(Math.sin(s.b*Math.PI))*.6})`;
      ctx.fillRect(s.x, s.y, s.s, s.s);
    });
    requestAnimationFrame(draw);
  }
  window.addEventListener('resize', resize);
  resize(); draw();
})();

// ── I18N ─────────────────────────────────────────────────────────────────────
const T = {
  en: {
    fname:'FIRST NAME', lname:'LAST NAME', dept:'DEPARTMENT',
    enter:'▶ ENTER GAME', waiting:'WAITING FOR HOST...',
    correct:'✓ CORRECT!', wrong:'✗ WRONG!', pts:'+{n} PTS', zero:'+0 PTS',
    total:'TOTAL: {n} PTS', waithost:'WAITING FOR HOST...',
    correct_ans:'✓ CORRECT ANSWER', your_score:'YOUR SCORE: {n} PTS',
    gameover:'🏆 GAME OVER', dept_select:'-- Select --',
    q_prefix:'Q', of:'/'
  },
  es: {
    fname:'NOMBRE', lname:'APELLIDO', dept:'DEPARTAMENTO',
    enter:'▶ ENTRAR AL JUEGO', waiting:'ESPERANDO AL HOST...',
    correct:'✓ ¡CORRECTO!', wrong:'✗ ¡INCORRECTO!', pts:'+{n} PTS', zero:'+0 PTS',
    total:'TOTAL: {n} PTS', waithost:'ESPERANDO AL HOST...',
    correct_ans:'✓ RESPUESTA CORRECTA', your_score:'TU PUNTAJE: {n} PTS',
    gameover:'🏆 ¡JUEGO TERMINADO!', dept_select:'-- Selecciona --',
    q_prefix:'P', of:'/'
  }
};
let lang = 'es';
function t(key, vars={}) {
  let s = T[lang][key] || key;
  Object.entries(vars).forEach(([k,v]) => s = s.replace(`{${k}}`, v));
  return s;
}

function goJoin() {
  lang = 'es';
  document.getElementById('lbl-fname').textContent = 'NOMBRE / NAME';
  document.getElementById('lbl-lname').textContent = 'APELLIDO / LAST NAME';
  document.getElementById('lbl-dept').textContent = 'DEPARTAMENTO / DEPARTMENT';
  document.getElementById('join-btn').textContent = '▶ ENTRAR / JOIN';
  document.getElementById('inp-dept').options[0].text = '-- Selecciona / Select --';
  show('join-screen');
}
function setLang(l) { goJoin(); }

// ── SCREENS ──────────────────────────────────────────────────────────────────
function show(id) {
  document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
  document.getElementById(id).classList.add('active');
}

// ── WS ───────────────────────────────────────────────────────────────────────
const WS_ID = crypto.randomUUID();
let ws, myName = '', myScore = 0, myDept = '';

function connectWS() {
  const proto = location.protocol === 'https:' ? 'wss' : 'ws';
  ws = new WebSocket(`${proto}://${location.host}/ws/player/${WS_ID}`);
  ws.onmessage = e => handleMessage(JSON.parse(e.data));
  ws.onclose = () => setTimeout(connectWS, 2000);
}

function handleMessage(msg) {
  if (msg.type === 'joined') {
    myName = msg.name;
    document.getElementById('lobby-name').textContent = msg.display;
    document.getElementById('lobby-dept').textContent = msg.dept;
    document.getElementById('lobby-wait').textContent = t('waiting');
    show('lobby-screen');
  }
  else if (msg.type === 'phase') {
    if (msg.phase === 'lobby' && myName) show('lobby-screen');
    else if (msg.phase === 'join') {
      myName = ''; myScore = 0; myDept = '';
      show('join-screen');
    }
  }
  else if (msg.type === 'question') {
    startGame(msg);
  }
  else if (msg.type === 'answer_result') {
    showFlash(msg);
  }
  else if (msg.type === 'results') {
    stopGame();
    myScore = msg.leaderboard.find(p => p.name === myName)?.score ?? myScore;
    document.getElementById('r-label').textContent = t('correct_ans');
    document.getElementById('r-fact').textContent = msg.fun_fact;
    document.getElementById('r-score').textContent = t('your_score', {n: myScore.toLocaleString()});
    document.getElementById('r-wait').textContent = t('waithost');
    show('results-screen');
  }
  else if (msg.type === 'podium') {
    stopBGM();
    stopGame();
    showPodium(msg.leaderboard);
  }
}

// ── JOIN ─────────────────────────────────────────────────────────────────────
document.getElementById('join-btn').addEventListener('click', () => {
  const fn = document.getElementById('inp-fname').value.trim();
  const ln = document.getElementById('inp-lname').value.trim();
  const dept = document.getElementById('inp-dept').value;
  if (!fn || !ln || !dept) {
    // Shake empty fields
    [fn ? null : 'inp-fname', ln ? null : 'inp-lname', dept ? null : 'inp-dept']
      .filter(Boolean).forEach(id => {
        const el = document.getElementById(id);
        el.style.borderColor = 'var(--red)';
        setTimeout(() => el.style.borderColor = '', 1000);
      });
    return;
  }
  myDept = dept;
  const displayName = `${fn} ${ln}`;
  startBGM();
  ws.send(JSON.stringify({type: 'join', name: `${fn} ${ln}`, dept, display: displayName}));
});

// ── GAME ENGINE ──────────────────────────────────────────────────────────────
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
let gameLoop = null;
let gameState = {
  ship: {x: 0, targetX: 0, y: 0, w: 36, h: 28},
  bullets: [],
  invaders: [],        // {x, y, w, h, text, idx, hit, hitTimer, correct}
  particles: [],
  answered: false,
  correctIdx: -1,
  timeLeft: 15,
  timerStart: 0,
};

function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();

const COL_COLORS = ['#5b9cf6','#cc44ff','#00ff88','#ffcc00']; // A=blue B=purple C=green D=yellow

function startGame(msg) {
  resizeCanvas();
  const W = canvas.width, H = canvas.height;
  const colW = W / 4;

  // Fixed invader size — no text inside, just letter
  const invW = Math.min(colW - 16, 90);
  const invH = invW; // square-ish UFO shape

  gameState = {
    ship: {x: W/2, targetX: W/2, y: H - 120, w: 36, h: 28},
    bullets: [],
    invaders: msg.options.map((text, idx) => ({
      x: colW * idx + colW/2,
      y: 0,
      targetY: 0,
      w: invW,
      h: invH,
      idx,
      hit: false,
      hitTimer: 0,
    })),
    particles: [],
    answered: false,
    correctIdx: msg.correct_idx_hint ?? -1,
    timeLeft: msg.time_limit,
    timerStart: performance.now(),
    correctAnswer: msg.correct_idx_hint,
    W, H, colW,
    totalTime: msg.time_limit,
    qNum: msg.number,
    qTotal: msg.total,
  };

  document.getElementById('projector-hint').textContent = lang === 'es' ? '👆 MIRA EL PROYECTOR' : '👆 LOOK AT THE SCREEN';
  document.getElementById('hud-q').textContent = `${t('q_prefix')}${msg.number}${t('of')}${msg.total}`;
  document.getElementById('result-flash').classList.remove('active');

  // Measure overlay height so invaders don't spawn behind it
  const overlay = document.getElementById('game-overlay');
  const overlayH = overlay ? overlay.getBoundingClientRect().height : 100;
  const spawnY = overlayH + invH / 2 + 20;

  // Invaders start above screen and descend into position
  gameState.invaders.forEach((inv, i) => {
    inv.y = -invH - i * 30;
    inv.targetY = spawnY;
  });

  show('game-screen');
  if (gameLoop) cancelAnimationFrame(gameLoop);
  gameLoop = requestAnimationFrame(gameFrame);

  // Touch controls — tap column
  canvas.ontouchstart = (e) => {
    e.preventDefault();
    if (gameState.answered) return;
    const touch = e.touches[0];
    const col = Math.floor(touch.clientX / gameState.colW);
    moveAndShoot(col);
  };
  canvas.onmousedown = (e) => {
    if (gameState.answered) return;
    const col = Math.floor(e.clientX / gameState.colW);
    moveAndShoot(col);
  };
}

function moveAndShoot(col) {
  const gs = gameState;
  if (gs.answered) return;
  const targetX = gs.colW * col + gs.colW / 2;
  gs.ship.targetX = targetX;
  // Fire bullet from current position toward that column
  gs.bullets.push({
    x: gs.ship.x, y: gs.ship.y - 20,
    targetCol: col,
    vx: (targetX - gs.ship.x) * 0.04,
    vy: -18, w: 4, h: 16,
    col
  });
  playBeep(880, 0.08, 0.05);
}

function stopGame() {
  if (gameLoop) { cancelAnimationFrame(gameLoop); gameLoop = null; }
  canvas.ontouchstart = null;
  canvas.onmousedown = null;
}

function gameFrame(ts) {
  const gs = gameState;
  const W = gs.W, H = gs.H;
  ctx.clearRect(0, 0, W, H);

  // ── BACKGROUND ──
  ctx.fillStyle = '#000510';
  ctx.fillRect(0, 0, W, H);

  // Column dividers
  for (let i = 1; i < 4; i++) {
    ctx.strokeStyle = 'rgba(255,255,255,0.04)';
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.moveTo(gs.colW * i, 0);
    ctx.lineTo(gs.colW * i, H);
    ctx.stroke();
  }

  // Timer update
  const elapsed = (performance.now() - gs.timerStart) / 1000;
  const timeLeft = Math.max(0, gs.totalTime - elapsed);
  document.getElementById('hud-timer').textContent = Math.ceil(timeLeft);
  document.getElementById('hud-timer').style.color = timeLeft < 5 ? 'var(--red)' : 'var(--amber)';

  // ── INVADERS ──
  gs.invaders.forEach((inv, i) => {
    if (inv.hit) {
      inv.hitTimer--;
      return;
    }
    // Slowly descend after appearing
    if (!gs.answered) {
      inv.y += (inv.targetY - inv.y) * 0.08;
      inv.targetY += 0.25;
    }

    const color = COL_COLORS[i];
    const letters = ['A','B','C','D'];
    const urgent = timeLeft <= 3 && !gs.answered && i === gs.correctIdx;

    // Shake offset when urgent
    const shakeX = urgent ? Math.sin(ts * 0.045 + i * 1.3) * 4 : 0;
    const shakeY = urgent ? Math.cos(ts * 0.05 + i * 0.9) * 3 : 0;
    const cx = inv.x + shakeX, cy = inv.y + shakeY;
    const r = inv.w / 2;

    // Urgent pulse: glow intensity oscillates fast
    const pulse = urgent ? 0.5 + 0.5 * Math.sin(ts * 0.025) : 0;

    // UFO dome (top half ellipse)
    ctx.fillStyle = `rgba(${hexToRgb(color)},${0.18 + pulse * 0.22})`;
    ctx.strokeStyle = color;
    ctx.lineWidth = urgent ? 2 + pulse * 2 : 2;
    ctx.shadowColor = color;
    ctx.shadowBlur = urgent ? 10 + pulse * 24 : 0;
    ctx.beginPath();
    ctx.ellipse(cx, cy, r, r * 0.55, 0, Math.PI, 0);
    ctx.fill(); ctx.stroke();

    // UFO saucer body (full ellipse)
    ctx.fillStyle = `rgba(${hexToRgb(color)},${0.25 + pulse * 0.2})`;
    ctx.strokeStyle = color;
    ctx.lineWidth = urgent ? 2 + pulse * 2 : 2;
    ctx.shadowColor = color;
    ctx.shadowBlur = urgent ? 14 + pulse * 20 : 0;
    ctx.beginPath();
    ctx.ellipse(cx, cy, r, r * 0.32, 0, 0, Math.PI * 2);
    ctx.fill(); ctx.stroke();
    ctx.shadowBlur = 0;

    // Glow under saucer
    ctx.shadowColor = color;
    ctx.shadowBlur = urgent ? 18 + pulse * 28 : 14;
    ctx.beginPath();
    ctx.ellipse(cx, cy + r * 0.1, r * 0.6, r * 0.12, 0, 0, Math.PI * 2);
    ctx.fillStyle = `rgba(${hexToRgb(color)},${0.35 + pulse * 0.35})`;
    ctx.fill();
    ctx.shadowBlur = 0;

    // Big centered letter
    const letterSize = Math.max(18, r * 0.85);
    ctx.fillStyle = color;
    ctx.font = `bold ${letterSize}px 'Press Start 2P', monospace`;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.shadowColor = color;
    ctx.shadowBlur = urgent ? 16 + pulse * 20 : 10;
    ctx.fillText(letters[i], cx, cy - r * 0.28);
    ctx.shadowBlur = 0;
  });

  // ── SHIP ──
  gs.ship.x += (gs.ship.targetX - gs.ship.x) * 0.18;
  const sx = gs.ship.x, sy = gs.ship.y;
  // Ship body
  ctx.fillStyle = '#00c8ff';
  ctx.beginPath();
  ctx.moveTo(sx, sy - 16);
  ctx.lineTo(sx - 14, sy + 12);
  ctx.lineTo(sx + 14, sy + 12);
  ctx.closePath();
  ctx.fill();
  // Engine glow
  ctx.fillStyle = `rgba(0,200,255,${0.3 + Math.sin(ts*0.01)*0.2})`;
  ctx.beginPath();
  ctx.arc(sx, sy + 14, 8, 0, Math.PI*2);
  ctx.fill();
  // Cockpit
  ctx.fillStyle = '#fff';
  ctx.beginPath();
  ctx.arc(sx, sy - 2, 4, 0, Math.PI*2);
  ctx.fill();

  // ── BULLETS ──
  gs.bullets = gs.bullets.filter(b => b.y > -20);
  gs.bullets.forEach(b => {
    b.x += b.vx;
    b.y += b.vy;
    ctx.fillStyle = '#ffcc00';
    ctx.shadowColor = '#ffcc00';
    ctx.shadowBlur = 8;
    ctx.fillRect(b.x - 2, b.y, 4, 16);
    ctx.shadowBlur = 0;

    // Collision check — circular hitbox matching UFO saucer radius
    if (!gs.answered) {
      gs.invaders.forEach((inv, i) => {
        if (inv.hit) return;
        const r = inv.w / 2;
        const dx = b.x - inv.x;
        const dy = b.y - inv.y;
        if (Math.sqrt(dx*dx + dy*dy) < r) {
          b.y = -999; // destroy bullet
          if (!gs.answered) {
            gs.answered = true;
            ws.send(JSON.stringify({type: 'answer', choice: i}));
            spawnParticles(inv.x, inv.y, COL_COLORS[i], 20);
            inv.hit = true;
            playBeep(i === gs.correctAnswer ? 1046 : 220, 0.3, 0.3);
          }
        }
      });
    }
  });

  // ── PARTICLES ──
  gs.particles = gs.particles.filter(p => p.life > 0);
  gs.particles.forEach(p => {
    p.x += p.vx; p.y += p.vy; p.vy += 0.3; p.life--;
    const a = p.life / p.maxLife;
    ctx.fillStyle = p.color + Math.floor(a*255).toString(16).padStart(2,'0');
    ctx.fillRect(p.x, p.y, p.s, p.s);
  });

  // ── GROUND LINE ──
  ctx.strokeStyle = 'rgba(0,200,255,0.2)';
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(0, H - 90);
  ctx.lineTo(W, H - 90);
  ctx.stroke();

  gameLoop = requestAnimationFrame(gameFrame);
}

function spawnParticles(x, y, color, count) {
  for (let i = 0; i < count; i++) {
    gameState.particles.push({
      x, y,
      vx: (Math.random()-0.5)*8,
      vy: (Math.random()-0.5)*8,
      s: Math.random()*4+2,
      life: 30+Math.random()*20,
      maxLife: 50,
      color
    });
  }
}

function showFlash(msg) {
  stopGame();
  const flash = document.getElementById('result-flash');
  document.getElementById('flash-icon').textContent = msg.correct ? '🎯' : '💥';
  document.getElementById('flash-title').textContent = msg.correct ? t('correct') : t('wrong');
  document.getElementById('flash-pts').textContent = msg.correct ? t('pts',{n:msg.points}) : t('zero');
  document.getElementById('flash-total').textContent = t('total',{n:msg.total.toLocaleString()});
  flash.classList.add('active');
  flash.classList.add('pop');
  show('game-screen');
}

function showPodium(leaderboard) {
  const medals = ['🥇','🥈','🥉'];
  const rc = ['r1','r2','r3'];
  document.getElementById('pod-title').textContent = t('gameover');
  const list = document.getElementById('podium-list');
  list.innerHTML = '';
  leaderboard.slice(0,10).forEach((p,i) => {
    const div = document.createElement('div');
    div.className = `podium-item ${rc[i]||''}`;
    const isMe = p.name === myName;
    div.innerHTML = `
      <span class="p-rank">${i<3?medals[i]:i+1}</span>
      <span class="p-name">${p.name}${isMe?' 👈':''}</span>
      <span class="p-score">${p.score.toLocaleString()}</span>`;
    list.appendChild(div);
  });
  show('podium-screen');
}

// ── AUDIO ────────────────────────────────────────────────────────────────────
let audioCtx;
function playBeep(freq, vol, dur) {
  try {
    if (!audioCtx) audioCtx = new (window.AudioContext||window.webkitAudioContext)();
    const o = audioCtx.createOscillator();
    const g = audioCtx.createGain();
    o.connect(g); g.connect(audioCtx.destination);
    o.type = 'square';
    o.frequency.value = freq;
    g.gain.setValueAtTime(vol, audioCtx.currentTime);
    g.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + dur);
    o.start(); o.stop(audioCtx.currentTime + dur);
  } catch(e) {}
}

// ── UTILS ────────────────────────────────────────────────────────────────────
function wrapText(ctx, text, x, centerY, maxW, lineH) {
  const words = text.split(' ');
  let line = '';
  const lines = [];
  words.forEach(w => {
    const test = line ? line + ' ' + w : w;
    if (ctx.measureText(test).width > maxW && line) {
      lines.push(line); line = w;
    } else line = test;
  });
  lines.push(line);
  const totalH = lines.length * lineH;
  const startY = centerY - totalH / 2 + lineH / 2;
  lines.forEach((l, i) => ctx.fillText(l, x, startY + i * lineH));
}

function roundRect(ctx, x, y, w, h, r) {
  ctx.beginPath();
  ctx.moveTo(x+r, y);
  ctx.lineTo(x+w-r, y);
  ctx.quadraticCurveTo(x+w, y, x+w, y+r);
  ctx.lineTo(x+w, y+h-r);
  ctx.quadraticCurveTo(x+w, y+h, x+w-r, y+h);
  ctx.lineTo(x+r, y+h);
  ctx.quadraticCurveTo(x, y+h, x, y+h-r);
  ctx.lineTo(x, y+r);
  ctx.quadraticCurveTo(x, y, x+r, y);
  ctx.closePath();
}

function hexToRgb(hex) {
  const r = parseInt(hex.slice(1,3),16);
  const g = parseInt(hex.slice(3,5),16);
  const b = parseInt(hex.slice(5,7),16);
  return `${r},${g},${b}`;
}

// ── BACKGROUND MUSIC ─────────────────────────────────────────────────────────
const bgm = document.getElementById('bgm');
let bgmStarted = false;
function startBGM() {
  if (bgmStarted) return;
  bgmStarted = true;
  bgm.volume = 0.35;
  bgm.play().catch(() => {});
}
function stopBGM() {
  bgm.pause();
  bgm.currentTime = 0;
  bgmStarted = false;
}

connectWS();

function exitGame() {
  if (ws) { ws.onclose = null; ws.close(); }
  myName = ''; myScore = 0; myDept = '';
  show('lang-screen');
  connectWS();
}
</script>
<audio id="bgm" src="/static/music.mp3" loop preload="auto"></audio>
</body>
</html>