I want to you take this game: <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover" />
<title>Touchscreen Snake Game with 3 Apples</title>
<style>
  /* Reset */
  * {
    box-sizing: border-box;
  }
  html, body {
    margin: 0; padding: 0;
    height: 100%;
    background: #111;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    overscroll-behavior: none;
    user-select: none;
  }
  body {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
    height: 100vh;
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
    background: linear-gradient(45deg, #0f2027, #203a43, #2c5364);
  }
  #game {
    position: relative;
    width: 90vmin;
    height: 90vmin;
    max-width: 720px;
    max-height: 720px;
    border: 5px solid #00ff99;
    border-radius: 24px;
    background: #111;
    box-shadow: 0 0 30px #00ff99cc inset;
    touch-action: none; /* prevent default gestures */
  }
  canvas {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 24px;
    background: #111;
  }
  #scoreboard {
    position: absolute;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    color: #00ff99;
    font-weight: 700;
    font-size: 2rem;
    text-shadow: 0 0 20px #00ff99;
    user-select: none;
    pointer-events: none;
    z-index: 10;
    font-variant-numeric: tabular-nums;
  }

  @media (max-width: 480px) {
    #game {
      width: 95vmin;
      height: 95vmin;
      max-width: 100vw;
      max-height: 100vw;
      border-width: 4px;
      border-radius: 20px;
      box-shadow: 0 0 20px #00ff99aa inset;
    }
    #scoreboard {
      font-size: 1.6rem;
      top: 8px;
    }
  }
</style>
</head>
<body>

<div id="game">
  <canvas id="canvas" width="720" height="720" aria-label="Snake game canvas" role="img"></canvas>
  <div id="scoreboard" aria-live="polite" aria-atomic="true">Score: 0</div>
</div>

<script>
(() => {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  const scoreboard = document.getElementById('scoreboard');

  // Increase grid size for larger screen and smoother visuals
  const gridSize = 30; // size of one square (increased from 20)
  const tileCount = canvas.width / gridSize; // 24x24 grid (720/30=24)

  // Initial snake state
  let snake = [
    { x: 12, y: 12 },
    { x: 11, y: 12 },
    { x: 10, y: 12 }
  ];
  let velocity = { x: 1, y: 0 };
  let nextVelocity = { x: 1, y: 0 };
  let apples = [];
  const maxApples = 3;
  let score = 0;
  let gameOver = false;

  // Create gradients every frame for dynamic glow effect
  function createSnakeGradient() {
    const grad = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
    grad.addColorStop(0, "#00ff99");
    grad.addColorStop(1, "#00ffaa");
    return grad;
  }
  function createAppleGradient() {
    const grad = ctx.createRadialGradient(0, 0, 7, 0, 0, 18);
    grad.addColorStop(0, "#ff4444");
    grad.addColorStop(1, "#990000");
    return grad;
  }

  // Draw rounded rect helper
  function roundedRect(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();
    ctx.fill();
  }

  // Spawn apples on empty tiles
  function spawnApples() {
    while (apples.length < maxApples) {
      let pos = {
        x: Math.floor(Math.random() * tileCount),
        y: Math.floor(Math.random() * tileCount)
      };
      if (isCellEmpty(pos.x, pos.y)) {
        apples.push(pos);
      }
    }
  }

  // Check if a tile is free (no snake, no apple)
  function isCellEmpty(x, y) {
    for (let s of snake) {
      if (s.x === x && s.y === y) return false;
    }
    for (let a of apples) {
      if (a.x === x && a.y === y) return false;
    }
    return true;
  }

  // Draw everything
  function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Background subtle grid lines
    ctx.strokeStyle = "#222";
    ctx.lineWidth = 1;
    for (let i = 0; i <= tileCount; i++) {
      ctx.beginPath();
      ctx.moveTo(i * gridSize, 0);
      ctx.lineTo(i * gridSize, canvas.height);
      ctx.stroke();
      ctx.beginPath();
      ctx.moveTo(0, i * gridSize);
      ctx.lineTo(canvas.width, i * gridSize);
      ctx.stroke();
    }

    // Draw apples with glow
    apples.forEach(({x, y}) => {
      const cx = x * gridSize + gridSize/2;
      const cy = y * gridSize + gridSize/2;

      ctx.save();
      ctx.translate(cx, cy);
      ctx.shadowColor = '#ff4444';
      ctx.shadowBlur = 24;
      ctx.fillStyle = createAppleGradient();
      ctx.beginPath();
      ctx.ellipse(0, 0, gridSize * 0.45, gridSize * 0.6, Math.PI / 6, 0, 2 * Math.PI);
      ctx.fill();

      // Apple leaf
      ctx.fillStyle = '#228822';
      ctx.beginPath();
      ctx.ellipse(0, -gridSize * 0.35, gridSize * 0.18, gridSize * 0.35, Math.PI / 4, 0, 2 * Math.PI);
      ctx.fill();

      ctx.restore();
    });

    // Draw snake with brighter glow
    ctx.fillStyle = createSnakeGradient();
    for (let i = 0; i < snake.length; i++) {
      const s = snake[i];
      const px = s.x * gridSize;
      const py = s.y * gridSize;

      ctx.save();
      ctx.shadowColor = '#00ffcc';
      ctx.shadowBlur = i === 0 ? 32 : 22; // brighter glow for head
      roundedRect(px + 3, py + 3, gridSize - 6, gridSize - 6, 10);
      ctx.restore();
    }
  }

  // Move snake and handle game logic
  function update() {
    if (gameOver) return;

    // Update velocity from buffered direction
    if ((nextVelocity.x !== -velocity.x || nextVelocity.y !== -velocity.y) &&
        (nextVelocity.x !== velocity.x || nextVelocity.y !== velocity.y)) {
      velocity = nextVelocity;
    }

    // New head position
    const head = { x: snake[0].x + velocity.x, y: snake[0].y + velocity.y };

    // Wrap around screen edges
    if (head.x < 0) head.x = tileCount - 1;
    else if (head.x >= tileCount) head.x = 0;
    if (head.y < 0) head.y = tileCount - 1;
    else if (head.y >= tileCount) head.y = 0;

    // Check collision with self
    for (let part of snake) {
      if (part.x === head.x && part.y === head.y) {
        gameOver = true;
        setTimeout(() => alert(`Game Over! Your score was ${score}. Refresh to play again.`), 100);
        return;
      }
    }

    snake.unshift(head);

    // Check apple eat
    let ateApple = false;
    for (let i = 0; i < apples.length; i++) {
      if (apples[i].x === head.x && apples[i].y === head.y) {
        apples.splice(i, 1);
        score++;
        ateApple = true;
        break;
      }
    }

    if (!ateApple) {
      snake.pop();
    } else {
      spawnApples();
    }

    scoreboard.textContent = `Score: ${score}`;
  }

  // Touch controls: improved swipe detection
  let touchStartX = null;
  let touchStartY = null;
  let touchStartTime = 0;
  const minSwipeDistance = 30;
  const maxSwipeTime = 500; // max time in ms for swipe to count

  canvas.addEventListener('touchstart', e => {
    if (e.touches.length === 1) {
      const t = e.touches[0];
      touchStartX = t.clientX;
      touchStartY = t.clientY;
      touchStartTime = e.timeStamp;
    }
  }, { passive: true });

  canvas.addEventListener('touchmove', e => {
    if (touchStartX === null || touchStartY === null) return;
    const t = e.touches[0];
    const dx = t.clientX - touchStartX;
    const dy = t.clientY - touchStartY;
    const dt = e.timeStamp - touchStartTime;

    if (dt > maxSwipeTime) {
      // Too slow, ignore swipe
      touchStartX = null;
      touchStartY = null;
      return;
    }

    if (Math.abs(dx) >= minSwipeDistance || Math.abs(dy) >= minSwipeDistance) {
      if (Math.abs(dx) > Math.abs(dy)) {
        // Horizontal swipe
        if (dx > 0) tryChangeDirection('right');
        else tryChangeDirection('left');
      } else {
        // Vertical swipe
        if (dy > 0) tryChangeDirection('down');
        else tryChangeDirection('up');
      }
      touchStartX = null;
      touchStartY = null;
    }
  }, { passive: true });

  canvas.addEventListener('touchend', e => {
    // Reset on touch end to avoid stuck state
    touchStartX = null;
    touchStartY = null;
  }, { passive: true });

  // Change direction helper
  function tryChangeDirection(dir) {
    switch(dir) {
      case 'up':
        if (velocity.y === 0) nextVelocity = { x: 0, y: -1 };
        break;
      case 'down':
        if (velocity.y === 0) nextVelocity = { x: 0, y: 1 };
        break;
      case 'left':
        if (velocity.x === 0) nextVelocity = { x: -1, y: 0 };
        break;
      case 'right':
        if (velocity.x === 0) nextVelocity = { x: 1, y: 0 };
        break;
    }
  }

  // Game loop
  const fps = 10;
  let lastRender = 0;
  function gameLoop(time = 0) {
    if (time - lastRender > 1000 / fps) {
      lastRender = time;
      update();
      draw();
    }
    requestAnimationFrame(gameLoop);
  }

  // Initialize
  spawnApples();
  draw();
  requestAnimationFrame(gameLoop);
})();
</script>

</body>
</html>