code html

Pasted Oct 18, 2026, 6:26 PM1 file559 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/t12341
untitled
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>تحدي السرعة ⚡</title>
<style>
/* ===========================
   1) المتغيرات والأساسيات
   =========================== */
:root{
  --bg1:#0f172a; --bg2:#1e1b4b;
  --card:rgba(255,255,255,.07);
  --border:rgba(255,255,255,.14);
  --text:#f8fafc; --muted:#cbd5e1;
  --accent1:#f59e0b; --accent2:#f97316;
  --green1:#22c55e; --green2:#16a34a;
  --red1:#ef4444; --red2:#b91c1c;
  --blue1:#3b82f6; --blue2:#8b5cf6;
  --radius:18px;
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
body{
  font-family:"Segoe UI",Tahoma,"Noto Naskh Arabic","Arial",sans-serif;
  background:radial-gradient(circle at 20% 10%,#312e81 0%,transparent 45%),
             radial-gradient(circle at 80% 90%,#7c2d12 0%,transparent 40%),
             linear-gradient(135deg,var(--bg1),var(--bg2));
  color:var(--text);
  min-height:100vh;
  display:flex;align-items:center;justify-content:center;
  padding:16px;
  overflow-x:hidden;
}

/* ===========================
   2) الشاشات والبطاقات
   =========================== */
.screen{display:none;width:100%;max-width:560px;animation:fadeIn .4s ease}
.screen.active{display:block}
@keyframes fadeIn{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

.card{
  background:var(--card);
  border:1px solid var(--border);
  border-radius:var(--radius);
  padding:28px 22px;
  backdrop-filter:blur(10px);
  box-shadow:0 20px 50px rgba(0,0,0,.35);
  text-align:center;
}
h1{
  font-size:clamp(2rem,7vw,3rem);
  background:linear-gradient(90deg,var(--accent1),var(--accent2));
  -webkit-background-clip:text;background-clip:text;color:transparent;
  margin-bottom:8px;
}
.tagline{color:var(--muted);font-size:1.05rem;margin-bottom:24px}
.bolt{font-size:4rem;display:block;margin-bottom:6px;animation:pulse 1.6s infinite}
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.12)}}

input[type=text]{
  width:100%;padding:14px 16px;border-radius:12px;
  border:1px solid var(--border);background:rgba(0,0,0,.25);
  color:var(--text);font-size:1.05rem;text-align:center;outline:none;
  margin-bottom:16px;transition:border .2s;
}
input[type=text]:focus{border-color:var(--accent1)}

/* ===========================
   3) الأزرار
   =========================== */
.btn{
  display:inline-block;border:none;cursor:pointer;
  padding:14px 28px;border-radius:14px;font-size:1.1rem;font-weight:700;
  color:#fff;transition:transform .15s,box-shadow .15s,opacity .2s;
  font-family:inherit;margin:6px 4px;
}
.btn:active{transform:scale(.96)}
.btn-primary{background:linear-gradient(135deg,var(--accent1),var(--accent2));box-shadow:0 8px 20px rgba(249,115,22,.4)}
.btn-primary:hover{transform:translateY(-2px);box-shadow:0 12px 26px rgba(249,115,22,.5)}
.btn-secondary{background:linear-gradient(135deg,var(--blue1),var(--blue2));box-shadow:0 8px 20px rgba(99,102,241,.35)}
.btn-ghost{background:transparent;border:1px solid var(--border);color:var(--muted)}
.btn-ghost:hover{background:rgba(255,255,255,.08)}
.btn-row{display:flex;flex-wrap:wrap;justify-content:center;gap:6px;margin-top:14px}

/* ===========================
   4) شاشة اللعب
   =========================== */
.hud{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;font-weight:700}
.hud .round{font-size:1.1rem}
.hud .name{color:var(--muted);font-weight:500;font-size:.95rem;max-width:50%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.progress{height:10px;background:rgba(255,255,255,.1);border-radius:99px;overflow:hidden;margin-bottom:16px}
.progress > div{height:100%;width:0;background:linear-gradient(90deg,var(--accent1),var(--accent2));border-radius:99px;transition:width .4s ease}

.zone{
  min-height:min(55vh,420px);
  border-radius:var(--radius);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  cursor:pointer;user-select:none;touch-action:manipulation;
  padding:20px;transition:background .15s;
  box-shadow:inset 0 0 0 2px rgba(255,255,255,.08);
}
.zone.idle{background:linear-gradient(135deg,#334155,#1e293b)}
.zone.waiting{background:linear-gradient(135deg,var(--red1),var(--red2));animation:breathe 1.4s infinite}
.zone.ready{background:linear-gradient(135deg,var(--green1),var(--green2));animation:flash .3s}
.zone.early{background:linear-gradient(135deg,#f59e0b,#b45309)}
.zone.done{background:linear-gradient(135deg,#0ea5e9,#6366f1)}
@keyframes breathe{0%,100%{box-shadow:inset 0 0 0 2px rgba(255,255,255,.08)}50%{box-shadow:inset 0 0 0 2px rgba(255,255,255,.4)}}
@keyframes flash{from{filter:brightness(1.8)}to{filter:brightness(1)}}

.zone .icon{font-size:3.5rem;margin-bottom:10px}
.zone .msg{font-size:clamp(1.3rem,5vw,2rem);font-weight:800;text-shadow:0 2px 10px rgba(0,0,0,.4)}
.zone .sub{margin-top:8px;color:rgba(255,255,255,.85);font-size:1rem}
.zone .time{font-size:clamp(2.2rem,9vw,3.6rem);font-weight:900;letter-spacing:1px;margin-top:4px}

.rounds-list{display:flex;justify-content:center;gap:8px;margin-top:14px;flex-wrap:wrap}
.chip{
  min-width:62px;padding:8px 10px;border-radius:10px;font-size:.9rem;font-weight:700;
  background:rgba(255,255,255,.08);border:1px solid var(--border);color:var(--muted);
}
.chip.ok{background:rgba(34,197,94,.2);border-color:var(--green1);color:#bbf7d0}
.chip.bad{background:rgba(239,68,68,.2);border-color:var(--red1);color:#fecaca}
.chip.cur{border-color:var(--accent1);color:#fde68a}

/* ===========================
   5) شاشة النتائج
   =========================== */
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:18px 0}
.stat{background:rgba(0,0,0,.25);border-radius:14px;padding:14px 8px;border:1px solid var(--border)}
.stat .v{font-size:1.6rem;font-weight:900;color:var(--accent1)}
.stat .l{font-size:.85rem;color:var(--muted);margin-top:4px}
.rating{
  font-size:1.25rem;font-weight:800;margin:10px 0 16px;
  padding:12px;border-radius:12px;
  background:linear-gradient(135deg,rgba(245,158,11,.25),rgba(139,92,246,.25));
}
.chart{display:flex;align-items:flex-end;justify-content:center;gap:10px;height:150px;padding:10px 6px 0;border-bottom:1px solid var(--border);margin-bottom:6px}
.bar-wrap{flex:1;max-width:70px;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%}
.bar{width:100%;border-radius:8px 8px 0 0;background:linear-gradient(180deg,var(--accent1),var(--accent2));transition:height .6s ease;position:relative;min-height:4px}
.bar.bad{background:linear-gradient(180deg,var(--red1),var(--red2))}
.bar span{position:absolute;top:-22px;left:0;right:0;font-size:.78rem;font-weight:700;color:var(--text)}
.chart-labels{display:flex;justify-content:center;gap:10px}
.chart-labels div{flex:1;max-width:70px;font-size:.8rem;color:var(--muted)}

/* ===========================
   6) سجل الأبطال
   =========================== */
table{width:100%;border-collapse:collapse;margin-top:14px;font-size:.95rem}
th,td{padding:10px 6px;border-bottom:1px solid var(--border)}
th{color:var(--accent1);font-size:.85rem}
tr:first-child td{color:#fde68a}
.note{font-size:.85rem;color:var(--muted);margin-top:14px;line-height:1.6;background:rgba(0,0,0,.2);padding:10px;border-radius:10px}
.empty{color:var(--muted);padding:20px}

/* ===========================
   7) مؤثر الاحتفال (Canvas)
   =========================== */
#confetti{position:fixed;inset:0;pointer-events:none;z-index:50}

@media (max-width:420px){
  .card{padding:22px 14px}
  .btn{padding:12px 18px;font-size:1rem}
  .stats{grid-template-columns:repeat(3,1fr);gap:6px}
  .stat .v{font-size:1.25rem}
}
</style>
</head>
<body>

<canvas id="confetti"></canvas>

<!-- ============ الشاشة الرئيسية ============ -->
<section id="screen-home" class="screen active">
  <div class="card">
    <span class="bolt">⚡</span>
    <h1>تحدي السرعة</h1>
    <p class="tagline">هل تستطيع التغلب على سرعة البرق؟</p>
    <input type="text" id="player-name" maxlength="16" placeholder="اسمك المستعار (اختياري)" autocomplete="off">
    <button class="btn btn-primary" id="btn-start">ابدأ التحدي 🚀</button>
    <div class="btn-row">
      <button class="btn btn-ghost" id="btn-show-board">🏆 سجل الأبطال</button>
    </div>
  </div>
</section>

<!-- ============ شاشة اللعب ============ -->
<section id="screen-game" class="screen">
  <div class="card">
    <div class="hud">
      <div class="round">الجولة <span id="round-num">1</span> / 5</div>
      <div class="name" id="hud-name"></div>
    </div>
    <div class="progress"><div id="progress-bar"></div></div>

    <div id="zone" class="zone idle">
      <div class="icon" id="zone-icon">👆</div>
      <div class="msg" id="zone-msg">انقر للبدء</div>
      <div class="time" id="zone-time" style="display:none"></div>
      <div class="sub" id="zone-sub">عندما تصبح الشاشة خضراء، انقر بأسرع ما يمكن</div>
    </div>

    <div class="rounds-list" id="rounds-list"></div>

    <div class="btn-row">
      <button class="btn btn-secondary" id="btn-next" style="display:none">الجولة التالية ←</button>
      <button class="btn btn-ghost" id="btn-quit">إنهاء</button>
    </div>
  </div>
</section>

<!-- ============ شاشة النتائج ============ -->
<section id="screen-results" class="screen">
  <div class="card">
    <h1 style="font-size:2rem">النتائج 🏁</h1>
    <div class="rating" id="rating"></div>
    <div class="stats">
      <div class="stat"><div class="v" id="stat-avg">—</div><div class="l">متوسط الاستجابة</div></div>
      <div class="stat"><div class="v" id="stat-best">—</div><div class="l">أفضل زمن</div></div>
      <div class="stat"><div class="v" id="stat-fails">0</div><div class="l">محاولات خاطئة</div></div>
    </div>
    <div class="chart" id="chart"></div>
    <div class="chart-labels" id="chart-labels"></div>
    <p class="note" id="save-note"></p>
    <div class="btn-row">
      <button class="btn btn-primary" id="btn-replay">العب مرة أخرى 🔁</button>
      <button class="btn btn-ghost" id="btn-home">العودة للرئيسية</button>
    </div>
  </div>
</section>

<!-- ============ شاشة سجل الأبطال ============ -->
<section id="screen-board" class="screen">
  <div class="card">
    <h1 style="font-size:2rem">🏆 سجل الأبطال</h1>
    <div id="board-body"></div>
    <p class="note">ℹ️ هذا السجل محلي ويُحفظ على هذا الجهاز فقط، ولا تتم مشاركة النتائج بين أجهزة الطلاب.</p>
    <div class="btn-row">
      <button class="btn btn-ghost" id="btn-board-home">العودة للرئيسية</button>
      <button class="btn btn-ghost" id="btn-board-clear">مسح السجل</button>
    </div>
  </div>
</section>

<script>
/* =========================================================
   تحدي السرعة ⚡ — المنطق البرمجي
   ========================================================= */
(function () {
  'use strict';

  /* ---------- الإعدادات ---------- */
  const TOTAL_ROUNDS = 5;
  const MIN_DELAY = 2000;   // أقل مدة انتظار (ms)
  const MAX_DELAY = 5000;   // أعلى مدة انتظار (ms)
  const STORAGE_KEY = 'speedChallengeLeaderboard';
  const MAX_BOARD = 10;

  /* ---------- حالة اللعبة ---------- */
  const state = {
    playerName: '',
    round: 0,               // رقم الجولة الحالية (1..5)
    results: [],            // لكل جولة: رقم (ms) أو null إذا كانت خاطئة
    falseStarts: 0,
    phase: 'idle',          // idle | waiting | ready | done
    timer: null,            // مؤقت تحوّل الشاشة إلى الأخضر
    greenAt: 0,             // لحظة ظهور اللون الأخضر (performance.now)
    locked: false           // قفل لمنع النقرات المتكررة أثناء الانتقال
  };

  /* ---------- عناصر الواجهة ---------- */
  const $ = (id) => document.getElementById(id);
  const screens = {
    home: $('screen-home'), game: $('screen-game'),
    results: $('screen-results'), board: $('screen-board')
  };
  const zone = $('zone'), zoneIcon = $('zone-icon'), zoneMsg = $('zone-msg'),
        zoneSub = $('zone-sub'), zoneTime = $('zone-time'),
        btnNext = $('btn-next'), roundNum = $('round-num'),
        progressBar = $('progress-bar'), roundsList = $('rounds-list');

  /* ---------- أدوات مساعدة ---------- */
  function showScreen(name) {
    Object.values(screens).forEach(s => s.classList.remove('active'));
    screens[name].classList.add('active');
    window.scrollTo(0, 0);
  }
  function clearTimer() {
    if (state.timer) { clearTimeout(state.timer); state.timer = null; }
  }
  function setZone(cls, icon, msg, sub, time) {
    zone.className = 'zone ' + cls;
    zoneIcon.textContent = icon;
    zoneMsg.textContent = msg;
    zoneSub.textContent = sub || '';
    if (time !== undefined) { zoneTime.style.display = 'block'; zoneTime.textContent = time; }
    else { zoneTime.style.display = 'none'; }
  }
  function validResults() { return state.results.filter(r => typeof r === 'number'); }
  function fmtDate(d) {
    const p = (n) => String(n).padStart(2, '0');
    return `${d.getFullYear()}/${p(d.getMonth() + 1)}/${p(d.getDate())}`;
  }

  /* ---------- بدء لعبة جديدة ---------- */
  function startGame() {
    clearTimer();
    state.playerName = $('player-name').value.trim() || 'لاعب مجهول';
    state.round = 0;
    state.results = [];
    state.falseStarts = 0;
    state.phase = 'idle';
    state.locked = false;
    $('hud-name').textContent = '👤 ' + state.playerName;
    showScreen('game');
    nextRound();
  }

  /* ---------- الانتقال إلى الجولة التالية ---------- */
  function nextRound() {
    clearTimer();
    if (state.round >= TOTAL_ROUNDS) { showResults(); return; }
    state.round++;
    state.phase = 'idle';
    state.locked = false;
    btnNext.style.display = 'none';
    roundNum.textContent = state.round;
    progressBar.style.width = ((state.round - 1) / TOTAL_ROUNDS * 100) + '%';
    setZone('idle', '👆', 'انقر للبدء', 'استعد للجولة ' + state.round);
    renderRoundChips();
  }

  /* ---------- بدء الانتظار (الشاشة الحمراء) ---------- */
  function beginWaiting() {
    clearTimer();
    state.phase = 'waiting';
    setZone('waiting', '🔴', 'انتظر الإشارة الخضراء', 'لا تنقر قبل أن تتحول الشاشة إلى الأخضر!');
    const delay = MIN_DELAY + Math.random() * (MAX_DELAY - MIN_DELAY);
    state.timer = setTimeout(() => {
      if (state.phase !== 'waiting') return; // تم إلغاء الجولة
      state.phase = 'ready';
      state.greenAt = performance.now();
      setZone('ready', '🟢', 'انقر الآن!', '');
    }, delay);
  }

  /* ---------- معالجة النقر على المنطقة ---------- */
  function handleZoneClick() {
    if (state.locked) return;

    if (state.phase === 'idle') {
      beginWaiting();
      return;
    }

    if (state.phase === 'waiting') {
      // نقرة مبكرة
      clearTimer();
      state.phase = 'done';
      state.locked = true;
      state.falseStarts++;
      state.results.push(null);
      setZone('early', '😅', 'تسرعت! حاول التركيز', 'لم تُحتسب هذه الجولة');
      finishRound();
      return;
    }

    if (state.phase === 'ready') {
      const reaction = Math.round(performance.now() - state.greenAt);
      state.phase = 'done';
      state.locked = true;
      state.results.push(reaction);
      setZone('done', '⚡', 'زمن استجابتك', reactionComment(reaction), reaction + ' ms');
      finishRound();
      return;
    }
    // phase === 'done' : تجاهل أي نقرات إضافية
  }

  function reactionComment(ms) {
    if (ms < 200) return 'مذهل! أسرع من البرق 🌩️';
    if (ms < 260) return 'ممتاز! ردة فعل سريعة جدًا';
    if (ms < 330) return 'جيد جدًا، استمر!';
    if (ms < 450) return 'جيد، يمكنك أن تكون أسرع';
    return 'ركّز أكثر في الجولة القادمة';
  }

  /* ---------- إنهاء الجولة وعرض زر المتابعة ---------- */
  function finishRound() {
    progressBar.style.width = (state.round / TOTAL_ROUNDS * 100) + '%';
    renderRoundChips();
    btnNext.textContent = state.round >= TOTAL_ROUNDS ? 'عرض النتائج 🏁' : 'الجولة التالية ←';
    // تأخير بسيط يمنع النقر العرضي على الزر فور انتهاء الجولة
    setTimeout(() => { btnNext.style.display = 'inline-block'; }, 350);
  }

  /* ---------- رسم شرائح الجولات ---------- */
  function renderRoundChips() {
    roundsList.innerHTML = '';
    for (let i = 0; i < TOTAL_ROUNDS; i++) {
      const chip = document.createElement('div');
      chip.className = 'chip';
      if (i < state.results.length) {
        const r = state.results[i];
        if (r === null) { chip.classList.add('bad'); chip.textContent = `ج${i + 1}: ✖`; }
        else { chip.classList.add('ok'); chip.textContent = `ج${i + 1}: ${r}`; }
      } else {
        if (i === state.round - 1) chip.classList.add('cur');
        chip.textContent = `ج${i + 1}: —`;
      }
      roundsList.appendChild(chip);
    }
  }

  /* ---------- شاشة النتائج ---------- */
  function showResults() {
    clearTimer();
    state.phase = 'idle';
    const valid = validResults();
    const hasValid = valid.length > 0;
    const avg = hasValid ? Math.round(valid.reduce((a, b) => a + b, 0) / valid.length) : null;
    const best = hasValid ? Math.min(...valid) : null;

    $('stat-avg').textContent = hasValid ? avg + ' ms' : '—';
    $('stat-best').textContent = hasValid ? best + ' ms' : '—';
    $('stat-fails').textContent = state.falseStarts;
    $('rating').textContent = getRating(avg, state.falseStarts);

    renderChart();

    // الحفظ في سجل الأبطال
    if (hasValid) {
      const rank = saveScore(state.playerName, avg);
      $('save-note').textContent = rank
        ? `🎉 تم حفظ نتيجتك في سجل الأبطال (المركز ${rank}). السجل محلي على هذا الجهاز فقط.`
        : 'تم تسجيل نتيجتك، لكنها لم تدخل ضمن أفضل 10 نتائج على هذا الجهاز.';
    } else {
      $('save-note').textContent = 'لم تُسجَّل النتيجة لأنها لا تتضمن أي جولة صحيحة. حاول مرة أخرى!';
    }

    showScreen('results');
    if (hasValid && avg < 250) launchConfetti();
  }

  function getRating(avg, fails) {
    if (avg === null) return '😴 لم تُحتسب أي جولة... هل كنت نائمًا؟';
    if (avg < 200) return '⚡ أنت البرق بنفسه! سرعة أسطورية';
    if (avg < 250) return '🚀 صاروخ! ردود فعل استثنائية';
    if (avg < 300) return '🐆 فهد سريع! نتيجة ممتازة';
    if (avg < 380) return '🐇 أرنب نشيط! نتيجة جيدة';
    if (avg < 500) return '🐢 سلحفاة مجتهدة! تحتاج قليلًا من التدريب';
    return '🦥 كسلان لطيف... حاول التركيز أكثر!';
  }

  function renderChart() {
    const chart = $('chart'), labels = $('chart-labels');
    chart.innerHTML = ''; labels.innerHTML = '';
    const valid = validResults();
    const max = valid.length ? Math.max(...valid, 100) : 100;
    state.results.forEach((r, i) => {
      const wrap = document.createElement('div'); wrap.className = 'bar-wrap';
      const bar = document.createElement('div'); bar.className = 'bar';
      const label = document.createElement('span');
      if (r === null) { bar.classList.add('bad'); bar.style.height = '8%'; label.textContent = '✖'; }
      else { bar.style.height = Math.max(8, Math.round(r / max * 100)) + '%'; label.textContent = r; }
      bar.appendChild(label); wrap.appendChild(bar); chart.appendChild(wrap);
      const l = document.createElement('div'); l.textContent = 'ج' + (i + 1); labels.appendChild(l);
    });
  }

  /* ---------- سجل الأبطال (localStorage) ---------- */
  function loadBoard() {
    try {
      const data = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
      return Array.isArray(data) ? data : [];
    } catch (e) { return []; }
  }
  function saveScore(name, avg) {
    const board = loadBoard();
    const entry = { name, avg, date: fmtDate(new Date()) };
    board.push(entry);
    board.sort((a, b) => a.avg - b.avg);
    const trimmed = board.slice(0, MAX_BOARD);
    try { localStorage.setItem(STORAGE_KEY, JSON.stringify(trimmed)); } catch (e) { /* التخزين غير متاح */ }
    const rank = trimmed.indexOf(entry);
    return rank === -1 ? null : rank + 1;
  }
  function renderBoard() {
    const board = loadBoard();
    const body = $('board-body');
    if (!board.length) { body.innerHTML = '<p class="empty">لا توجد نتائج بعد. كن أول الأبطال! 🏅</p>'; return; }
    const medals = ['🥇', '🥈', '🥉'];
    let html = '<table><thead><tr><th>#</th><th>اللاعب</th><th>المتوسط</th><th>التاريخ</th></tr></thead><tbody>';
    board.forEach((e, i) => {
      const nameSafe = String(e.name).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
      html += `<tr><td>${medals[i] || i + 1}</td><td>${nameSafe}</td><td>${e.avg} ms</td><td>${e.date}</td></tr>`;
    });
    body.innerHTML = html + '</tbody></table>';
  }

  /* ---------- مؤثر الاحتفال ---------- */
  function launchConfetti() {
    const canvas = $('confetti');
    const ctx = canvas.getContext('2d');
    canvas.width = window.innerWidth; canvas.height = window.innerHeight;
    const colors = ['#f59e0b', '#f97316', '#22c55e', '#3b82f6', '#8b5cf6', '#ec4899', '#facc15'];
    const pieces = Array.from({ length: 140 }, () => ({
      x: Math.random() * canvas.width, y: -20 - Math.random() * canvas.height * .5,
      w: 6 + Math.random() * 8, h: 8 + Math.random() * 10,
      vy: 2 + Math.random() * 4, vx: -1.5 + Math.random() * 3,
      rot: Math.random() * Math.PI, vr: -.15 + Math.random() * .3,
      color: colors[Math.floor(Math.random() * colors.length)]
    }));
    const start = performance.now();
    function frame(now) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      let alive = false;
      pieces.forEach(p => {
        p.x += p.vx; p.y += p.vy; p.rot += p.vr;
        if (p.y < canvas.height + 20) alive = true;
        ctx.save(); ctx.translate(p.x, p.y); ctx.rotate(p.rot);
        ctx.fillStyle = p.color; ctx.fillRect(-p.w / 2, -p.h / 2, p.w, p.h); ctx.restore();
      });
      if (alive && now - start < 4500) requestAnimationFrame(frame);
      else ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
    requestAnimationFrame(frame);
  }

  /* ---------- ربط الأحداث ---------- */
  $('btn-start').addEventListener('click', startGame);
  $('player-name').addEventListener('keydown', e => { if (e.key === 'Enter') startGame(); });

  // استخدام pointerdown لأسرع استجابة ممكنة على اللمس والفأرة
  zone.addEventListener('pointerdown', (e) => { e.preventDefault(); handleZoneClick(); });
  // دعم لوحة المفاتيح (مسافة) أثناء اللعب
  document.addEventListener('keydown', (e) => {
    if (e.code === 'Space' && screens.game.classList.contains('active')) { e.preventDefault(); handleZoneClick(); }
  });

  btnNext.addEventListener('click', nextRound);
  $('btn-quit').addEventListener('click', () => { clearTimer(); state.phase = 'idle'; showScreen('home'); });
  $('btn-replay').addEventListener('click', startGame);
  $('btn-home').addEventListener('click', () => showScreen('home'));
  $('btn-show-board').addEventListener('click', () => { renderBoard(); showScreen('board'); });
  $('btn-board-home').addEventListener('click', () => showScreen('home'));
  $('btn-board-clear').addEventListener('click', () => {
    if (confirm('هل تريد مسح سجل الأبطال على هذا الجهاز؟')) {
      try { localStorage.removeItem(STORAGE_KEY); } catch (e) {}
      renderBoard();
    }
  });
  window.addEventListener('resize', () => {
    const c = $('confetti'); c.width = window.innerWidth; c.height = window.innerHeight;
  });
})();
</script>
</body>
</html>

23,230 chars · codepastes.com