/* 2048.js — Complete Version with WASD + Interactive Effects + Sound Controls */

/* ------------------------
   State & Variables
   ------------------------ */
let board = [];
let currentScore = 0;
let bestScore = parseInt(localStorage.getItem('bestScore2048')) || 0;
let lastMoveDir = null;
let isMoving = false;
let mergesInCurrentMove = 0;

/* ------------------------
   Audio Setup
   ------------------------ */
const audio = {
  bg: new Audio("Bgmusic.mp3"),
  pop: new Audio("Pop.mp3"),
  merge: new Audio("Merge.mp3")
};

// Sound State (baca dari localStorage atau default ON)
let soundState = {
  bg: localStorage.getItem('sound_bg') !== 'false',
  pop: localStorage.getItem('sound_pop') !== 'false',
  merge: localStorage.getItem('sound_merge') !== 'false'
};

// Update audio volumes based on state
function updateAudioVolumes() {
  audio.bg.volume = soundState.bg ? 0.25 : 0;
  audio.pop.volume = soundState.pop ? 0.9 : 0;
  audio.merge.volume = soundState.merge ? 1.0 : 0;
}

audio.bg.loop = true;

function tryPlayBg() {
  if (!soundState.bg) return; // Jangan play kalau muted
  
  audio.bg.play().catch(() => {
    const unlock = () => {
      if (soundState.bg) audio.bg.play().catch(()=>{});
      window.removeEventListener("keydown", unlock);
      window.removeEventListener("click", unlock);
    };
    window.addEventListener("keydown", unlock, { once: true });
    window.addEventListener("click", unlock, { once: true });
  });
}

/* ------------------------
   DOM Ready
   ------------------------ */
document.addEventListener("DOMContentLoaded", () => {
  updateBestScoreDisplay();
  setupBoard();
  addNewTile();
  addNewTile();
  updateAudioVolumes(); // Apply saved sound settings
  tryPlayBg();
  document.addEventListener("keydown", handleKey);
  setupEventListeners();
});

/* ------------------------
   Event Listeners Setup
   ------------------------ */
function setupEventListeners() {
  // Tutorial Modal
  const btnTutorial = document.getElementById('btn-tutorial');
  const tutorialOverlay = document.getElementById('tutorial-overlay');
  const closeTutorial = document.getElementById('close-tutorial');

  if (btnTutorial) {
    btnTutorial.addEventListener('click', function() {
      tutorialOverlay.style.display = 'flex';
    });
  }

  if (closeTutorial) {
    closeTutorial.addEventListener('click', function() {
      tutorialOverlay.style.display = 'none';
    });
  }

  if (tutorialOverlay) {
    tutorialOverlay.addEventListener('click', function(e) {
      if (e.target === tutorialOverlay) {
        tutorialOverlay.style.display = 'none';
      }
    });
  }

  // Restart button (top right)
  const btnRestart = document.getElementById('btn-restart');
  if (btnRestart) {
    btnRestart.addEventListener('click', restartGame);
  }

  // Game over modal buttons
  const btnPlayAgain = document.getElementById('btn-play-again');
  const btnHome = document.getElementById('btn-home');
  const gameOverClose = document.getElementById('game-over-close');
  
  if (btnPlayAgain) {
    btnPlayAgain.addEventListener('click', playAgain);
  }
  
  if (btnHome) {
    btnHome.addEventListener('click', goHome);
  }

  if (gameOverClose) {
    gameOverClose.addEventListener('click', hideGameOver);
  }

  const gameOverOverlay = document.getElementById('game-over-overlay');
  if (gameOverOverlay) {
    gameOverOverlay.addEventListener('click', function(e) {
      if (e.target === this) {
        hideGameOver();
      }
    });
  }

  // Sound Control Buttons
  const btnSoundBg = document.getElementById('btn-sound-bg');
  const btnSoundPop = document.getElementById('btn-sound-pop');
  const btnSoundMerge = document.getElementById('btn-sound-merge');

  if (btnSoundBg) {
    btnSoundBg.addEventListener('click', () => toggleSound('bg'));
    updateSoundButtonState(btnSoundBg, soundState.bg);
  }

  if (btnSoundPop) {
    btnSoundPop.addEventListener('click', () => toggleSound('pop'));
    updateSoundButtonState(btnSoundPop, soundState.pop);
  }

  if (btnSoundMerge) {
    btnSoundMerge.addEventListener('click', () => toggleSound('merge'));
    updateSoundButtonState(btnSoundMerge, soundState.merge);
  }
}

/* ------------------------
   Setup & Rendering
   ------------------------ */
function setupBoard() {
  board = [];
  currentScore = 0;
  updateScoreDisplay();

  const container = document.getElementById("board");
  if (!container) {
    console.error("Board element not found (#board).");
    return;
  }

  container.innerHTML = "";
  for (let r = 0; r < 4; r++) {
    board[r] = [];
    for (let c = 0; c < 4; c++) {
      board[r][c] = 0;
      const tile = document.createElement("div");
      tile.id = `${r}-${c}`;
      tile.className = "tile";
      container.appendChild(tile);
    }
  }
}

function updateTile(row, col, num) {
  const tile = document.getElementById(`${row}-${col}`);
  if (!tile) return;

  tile.className = "tile";

  if (num > 0) {
    tile.textContent = num;
    tile.classList.add("tile-" + num);
  } else {
    tile.textContent = "";
  }
}

function refreshBoard() {
  for (let r = 0; r < 4; r++) {
    for (let c = 0; c < 4; c++) {
      updateTile(r, c, board[r][c]);
    }
  }
  updateScoreDisplay();
}

/* ------------------------
   Score Management
   ------------------------ */
function updateScoreDisplay() {
  const scoreEl = document.getElementById("score");
  if (scoreEl) {
    scoreEl.textContent = currentScore;
  }
  
  if (currentScore > bestScore) {
    bestScore = currentScore;
    localStorage.setItem('bestScore2048', bestScore);
    updateBestScoreDisplay();
  }
}

function updateBestScoreDisplay() {
  const bestScoreEl = document.getElementById('best-score');
  if (bestScoreEl) {
    bestScoreEl.textContent = bestScore;
  }
}

function resetScore() {
  currentScore = 0;
  updateScoreDisplay();
}

/* ------------------------
   Add New Tile
   ------------------------ */
function addNewTile() {
  const empty = [];
  for (let r = 0; r < 4; r++) {
    for (let c = 0; c < 4; c++) {
      if (board[r][c] === 0) empty.push({ r, c });
    }
  }

  if (empty.length === 0) return false;

  const spot = empty[Math.floor(Math.random() * empty.length)];
  board[spot.r][spot.c] = 2;

  const tile = document.getElementById(`${spot.r}-${spot.c}`);
  if (tile) {
    tile.classList.add("new");
    playSound(audio.pop);
    setTimeout(() => tile.classList.remove("new"), 300);
  }
  updateTile(spot.r, spot.c, 2);
  return true;
}

/* Safe playSound with mute check */
function playSound(soundObj) {
  try {
    // Check if sound is enabled
    if (soundObj === audio.pop && !soundState.pop) return;
    if (soundObj === audio.merge && !soundState.merge) return;
    if (soundObj === audio.bg && !soundState.bg) return;
    
    soundObj.currentTime = 0;
    soundObj.play().catch(() => {});
  } catch (e) {}
}

/* ------------------------
   Movement Logic
   ------------------------ */
function filterZero(row) {
  return row.filter(n => n !== 0);
}

function slide(row) {
  row = filterZero(row);
  let mergedThisMove = false;
  let mergedPositions = [];
  let mergeCount = 0;

  for (let i = 0; i < row.length - 1; i++) {
    if (row[i] === row[i + 1]) {
      row[i] = row[i] * 2;
      
      playSound(audio.merge);
      
      if (navigator.vibrate) {
        navigator.vibrate([80, 20, 80]);
      }

      currentScore += row[i];
      row[i + 1] = 0;
      mergedThisMove = true;
      mergedPositions.push(i);
      mergeCount++;
    }
  }

  row = filterZero(row);
  while (row.length < 4) row.push(0);
  return { row, merged: mergedThisMove, mergedPositions, mergeCount };
}

function arraysEqual(a, b) {
  return a.length === b.length && a.every((v, i) => v === b[i]);
}

/* Move functions */
function moveLeft() {
  let moved = false;
  let mergedCells = [];
  mergesInCurrentMove = 0;
  
  for (let r = 0; r < 4; r++) {
    const { row: newRow, mergedPositions, mergeCount } = slide(board[r]);
    if (!arraysEqual(newRow, board[r])) moved = true;
    board[r] = newRow;
    
    mergesInCurrentMove += mergeCount;
    
    if (mergedPositions && mergedPositions.length > 0) {
      mergedPositions.forEach(c => {
        mergedCells.push({ r, c });
      });
    }
  }
  
  if (moved) {
    refreshBoard();
    triggerComboEffect(mergedCells, mergesInCurrentMove);
  }
  return moved;
}

function moveRight() {
  let moved = false;
  let mergedCells = [];
  mergesInCurrentMove = 0;
  
  for (let r = 0; r < 4; r++) {
    let reversed = [...board[r]].reverse();
    const { row: slid, mergedPositions, mergeCount } = slide(reversed);
    let newRow = slid.reverse();
    if (!arraysEqual(newRow, board[r])) moved = true;
    board[r] = newRow;
    
    mergesInCurrentMove += mergeCount;
    
    if (mergedPositions && mergedPositions.length > 0) {
      mergedPositions.forEach(pos => {
        const c = 3 - pos;
        mergedCells.push({ r, c });
      });
    }
  }
  
  if (moved) {
    refreshBoard();
    triggerComboEffect(mergedCells, mergesInCurrentMove);
  }
  return moved;
}

function moveUp() {
  let moved = false;
  let mergedCells = [];
  mergesInCurrentMove = 0;
  
  for (let c = 0; c < 4; c++) {
    const col = [board[0][c], board[1][c], board[2][c], board[3][c]];
    const { row: newCol, mergedPositions, mergeCount } = slide(col);
    for (let r = 0; r < 4; r++) {
      if (board[r][c] !== newCol[r]) moved = true;
      board[r][c] = newCol[r];
    }
    
    mergesInCurrentMove += mergeCount;
    
    if (mergedPositions && mergedPositions.length > 0) {
      mergedPositions.forEach(r => {
        mergedCells.push({ r, c });
      });
    }
  }
  
  if (moved) {
    refreshBoard();
    triggerComboEffect(mergedCells, mergesInCurrentMove);
  }
  return moved;
}

function moveDown() {
  let moved = false;
  let mergedCells = [];
  mergesInCurrentMove = 0;
  
  for (let c = 0; c < 4; c++) {
    const col = [board[3][c], board[2][c], board[1][c], board[0][c]];
    const { row: slid, mergedPositions, mergeCount } = slide(col);
    const newCol = slid.reverse();
    for (let r = 0; r < 4; r++) {
      if (board[r][c] !== newCol[r]) moved = true;
      board[r][c] = newCol[r];
    }
    
    mergesInCurrentMove += mergeCount;
    
    if (mergedPositions && mergedPositions.length > 0) {
      mergedPositions.forEach(pos => {
        const r = 3 - pos;
        mergedCells.push({ r, c });
      });
    }
  }
  
  if (moved) {
    refreshBoard();
    triggerComboEffect(mergedCells, mergesInCurrentMove);
  }
  return moved;
}

/* ------------------------
   Input Handling
   ------------------------ */
function handleKey(e) {
  if (isMoving) return;
  
  let moved = false;
  
  if (e.key === "ArrowLeft") { 
    e.preventDefault();
    moved = moveLeft(); 
  }
  else if (e.key === "ArrowRight") { 
    e.preventDefault();
    moved = moveRight(); 
  }
  else if (e.key === "ArrowUp") { 
    e.preventDefault();
    moved = moveUp(); 
  }
  else if (e.key === "ArrowDown") { 
    e.preventDefault();
    moved = moveDown(); 
  }
  else if (e.key === "a" || e.key === "A") {
    e.preventDefault();
    moved = moveLeft();
  }
  else if (e.key === "d" || e.key === "D") {
    e.preventDefault();
    moved = moveRight();
  }
  else if (e.key === "w" || e.key === "W") {
    e.preventDefault();
    moved = moveUp();
  }
  else if (e.key === "s" || e.key === "S") {
    e.preventDefault();
    moved = moveDown();
  }

  if (moved) {
    isMoving = true;
    setTimeout(() => {
      const added = addNewTile();
      if (!added || !canMove()) {
        setTimeout(() => showGameOver(), 300);
      }
      isMoving = false;
    }, 100);
  } else {
    const b = document.getElementById("board");
    if (b) {
      b.classList.add("shake");
      setTimeout(()=>b.classList.remove("shake"), 400);
    }
  }
}

function canMove() {
  for (let r = 0; r < 4; r++) {
    for (let c = 0; c < 4; c++) {
      if (board[r][c] === 0) return true;
    }
  }
  
  for (let r = 0; r < 4; r++) {
    for (let c = 0; c < 4; c++) {
      const current = board[r][c];
      if (c < 3 && board[r][c + 1] === current) return true;
      if (r < 3 && board[r + 1][c] === current) return true;
    }
  }
  
  return false;
}

/* ------------------------
   Touch Swipe
   ------------------------ */
let touchStartX = 0;
let touchStartY = 0;

document.addEventListener("touchstart", function (e) {
  const t = e.touches[0];
  touchStartX = t.clientX;
  touchStartY = t.clientY;
}, { passive: true });

document.addEventListener("touchend", function (e) {
  if (isMoving) return;
  
  const t = e.changedTouches[0];
  const dx = t.clientX - touchStartX;
  const dy = t.clientY - touchStartY;
  
  let moved = false;
  
  if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 30) {
    if (dx > 0) { 
      moved = moveRight();
    } else { 
      moved = moveLeft();
    }
  } else if (Math.abs(dy) > 30) {
    if (dy > 0) { 
      moved = moveDown();
    } else { 
      moved = moveUp();
    }
  }
  
  if (moved) {
    isMoving = true;
    setTimeout(() => {
      const added = addNewTile();
      if (!added || !canMove()) {
        setTimeout(() => showGameOver(), 300);
      }
      isMoving = false;
    }, 100);
  }
}, { passive: true });

/* ------------------------
   Game Controls
   ------------------------ */
function restartGame() {
  hideGameOver();
  resetScore();
  setupBoard();
  addNewTile();
  addNewTile();
  refreshBoard();
  isMoving = false;
}

function playAgain() {
  restartGame();
}

function goHome() {
  try { 
    audio.bg.pause(); 
    audio.bg.currentTime = 0; 
  } catch (e) {}
  window.location.href = "Homepage.html";
}

/* ------------------------
   Game Over Modal
   ------------------------ */
function showGameOver() {
  const finalScore = currentScore;
  const isNewHighScore = finalScore >= bestScore && finalScore > 0;
  
  const finalScoreEl = document.getElementById('final-score');
  if (finalScoreEl) {
    finalScoreEl.textContent = finalScore;
  }
  
  const newHighScoreBadge = document.getElementById('new-high-score-badge');
  const bestScoreDisplay = document.getElementById('best-score-display');
  
  if (isNewHighScore) {
    if (newHighScoreBadge) newHighScoreBadge.style.display = 'inline-block';
    if (bestScoreDisplay) bestScoreDisplay.style.display = 'none';
  } else {
    if (newHighScoreBadge) newHighScoreBadge.style.display = 'none';
    if (bestScoreDisplay) bestScoreDisplay.style.display = 'block';
    const modalBestScore = document.getElementById('modal-best-score');
    if (modalBestScore) modalBestScore.textContent = bestScore;
  }
  
  const gameOverOverlay = document.getElementById('game-over-overlay');
  if (gameOverOverlay) {
    gameOverOverlay.style.display = 'flex';
  }
}

function hideGameOver() {
  const gameOverOverlay = document.getElementById('game-over-overlay');
  if (gameOverOverlay) {
    gameOverOverlay.style.display = 'none';
  }
}

/* =============================================
   SOUND CONTROLS
   ============================================= */
/* =============================================
   ADVANCED VOLUME CONTROL SYSTEM
   ============================================= */

// Volume State (0-100 for each sound)
let volumeState = {
  music: parseInt(localStorage.getItem('vol_music')) || 25,
  pop: parseInt(localStorage.getItem('vol_pop')) || 90,
  merge: parseInt(localStorage.getItem('vol_merge')) || 100
};

// Apply volumes on load
function initVolumeControl() {
  // Set audio volumes
  audio.bg.volume = volumeState.music / 100;
  audio.pop.volume = volumeState.pop / 100;
  audio.merge.volume = volumeState.merge / 100;
  
  // Update sliders
  const musicSlider = document.getElementById('vol-music');
  const popSlider = document.getElementById('vol-pop');
  const mergeSlider = document.getElementById('vol-merge');
  
  if (musicSlider) {
    musicSlider.value = volumeState.music;
    updateSliderFill(musicSlider, volumeState.music);
    document.getElementById('vol-music-display').textContent = volumeState.music + '%';
  }
  
  if (popSlider) {
    popSlider.value = volumeState.pop;
    updateSliderFill(popSlider, volumeState.pop);
    document.getElementById('vol-pop-display').textContent = volumeState.pop + '%';
  }
  
  if (mergeSlider) {
    mergeSlider.value = volumeState.merge;
    updateSliderFill(mergeSlider, volumeState.merge);
    document.getElementById('vol-merge-display').textContent = volumeState.merge + '%';
  }
  
  updateMainSoundIcon();
  
  // Event listeners for sliders
  if (musicSlider) {
    musicSlider.addEventListener('input', (e) => {
      const val = parseInt(e.target.value);
      volumeState.music = val;
      audio.bg.volume = val / 100;
      localStorage.setItem('vol_music', val);
      document.getElementById('vol-music-display').textContent = val + '%';
      updateSliderFill(e.target, val);
      updateMainSoundIcon();
      
      // Auto-play BG music if volume > 0
      if (val > 0 && audio.bg.paused) {
        tryPlayBg();
      } else if (val === 0) {
        audio.bg.pause();
      }
    });
  }
  
  if (popSlider) {
    popSlider.addEventListener('input', (e) => {
      const val = parseInt(e.target.value);
      volumeState.pop = val;
      audio.pop.volume = val / 100;
      localStorage.setItem('vol_pop', val);
      document.getElementById('vol-pop-display').textContent = val + '%';
      updateSliderFill(e.target, val);
      updateMainSoundIcon();
    });
  }
  
  if (mergeSlider) {
    mergeSlider.addEventListener('input', (e) => {
      const val = parseInt(e.target.value);
      volumeState.merge = val;
      audio.merge.volume = val / 100;
      localStorage.setItem('vol_merge', val);
      document.getElementById('vol-merge-display').textContent = val + '%';
      updateSliderFill(e.target, val);
      updateMainSoundIcon();
    });
  }
  
  // Toggle panel visibility
  const btnSoundMain = document.getElementById('btn-sound-main');
  const volumePanel = document.getElementById('volume-panel');
  
  if (btnSoundMain && volumePanel) {
    btnSoundMain.addEventListener('click', (e) => {
      e.stopPropagation();
      const isVisible = volumePanel.style.display === 'block';
      volumePanel.style.display = isVisible ? 'none' : 'block';
    });
    
    // Close panel when clicking outside
    document.addEventListener('click', (e) => {
      if (!volumePanel.contains(e.target) && !btnSoundMain.contains(e.target)) {
        volumePanel.style.display = 'none';
      }
    });
    
    // Prevent panel click from closing
    volumePanel.addEventListener('click', (e) => {
      e.stopPropagation();
    });
  }
}

// Update slider fill effect
function updateSliderFill(slider, value) {
  slider.style.setProperty('--value', value + '%');
}

// Update main sound icon based on volumes
function updateMainSoundIcon() {
  const btnMain = document.getElementById('btn-sound-main');
  if (!btnMain) return;
  
  const iconFull = btnMain.querySelector('.sound-full');
  const iconMedium = btnMain.querySelector('.sound-medium');
  const iconLow = btnMain.querySelector('.sound-low');
  const iconMuted = btnMain.querySelector('.sound-muted');
  
  // Calculate total volume average
  const totalVolume = volumeState.music + volumeState.pop + volumeState.merge;
  const avgVolume = totalVolume / 3;
  
  // Hide all icons first
  iconFull.style.display = 'none';
  iconMedium.style.display = 'none';
  iconLow.style.display = 'none';
  iconMuted.style.display = 'none';
  
  // Show appropriate icon based on average
  if (totalVolume === 0) {
    iconMuted.style.display = 'block';
    btnMain.classList.add('all-muted');
  } else {
    btnMain.classList.remove('all-muted');
    
    if (avgVolume >= 60) {
      iconFull.style.display = 'block';
    } else if (avgVolume >= 30) {
      iconMedium.style.display = 'block';
    } else {
      iconLow.style.display = 'block';
    }
  }
}

// Initialize on DOM load (add this to your existing DOMContentLoaded)
document.addEventListener("DOMContentLoaded", () => {
  // ... existing code ...
  initVolumeControl(); // ADD THIS LINE
});

/* =============================================
   COMBO EFFECTS
   ============================================= */
function triggerComboEffect(mergedCells, comboCount) {
  if (mergedCells.length === 0) return;
  
  mergedCells.forEach(cell => {
    const tile = document.getElementById(`${cell.r}-${cell.c}`);
    if (!tile) return;
    
    tile.classList.add('merge');
    setTimeout(() => tile.classList.remove('merge'), 300);
    
    createParticleBurst(tile);
    
    tile.style.boxShadow = '0 0 40px currentColor';
    setTimeout(() => {
      tile.style.boxShadow = '';
    }, 300);
    
    const rect = tile.getBoundingClientRect();
    const centerX = rect.left + rect.width / 2;
    const centerY = rect.top + rect.height / 2;
    const tileValue = parseInt(tile.textContent);
    createScorePopup(centerX, centerY, tileValue);
  });
  
  if (comboCount >= 2) {
    showComboPopup(comboCount);
  }
}

function showComboPopup(comboCount) {
  const board = document.getElementById('board');
  if (!board) return;
  
  const rect = board.getBoundingClientRect();
  const centerX = rect.left + rect.width / 2;
  const centerY = rect.top + rect.height / 2;
  
  const popup = document.createElement('div');
  popup.className = 'combo-popup';
  popup.style.left = centerX + 'px';
  popup.style.top = centerY + 'px';
  popup.style.position = 'fixed';
  popup.style.fontWeight = '900';
  popup.style.pointerEvents = 'none';
  popup.style.zIndex = '9999';
  popup.style.transform = 'translate(-50%, -50%)';
  popup.style.textTransform = 'uppercase';
  popup.style.letterSpacing = '3px';
  
  if (comboCount === 2) {
    popup.textContent = 'COMBO x2!';
    popup.style.fontSize = '36px';
    popup.style.color = '#00ff99';
    popup.style.textShadow = '0 0 30px rgba(0, 255, 153, 1), 0 0 50px rgba(0, 255, 153, 0.5)';
  } else if (comboCount === 3) {
    popup.textContent = 'AMAZING x3!';
    popup.style.fontSize = '42px';
    popup.style.color = '#ff00ff';
    popup.style.textShadow = '0 0 35px rgba(255, 0, 255, 1), 0 0 60px rgba(255, 0, 255, 0.6)';
  } else if (comboCount >= 4) {
    popup.textContent = 'PERFECT x' + comboCount + '!';
    popup.style.fontSize = '48px';
    popup.style.color = '#ffd700';
    popup.style.textShadow = '0 0 40px rgba(255, 215, 0, 1), 0 0 70px rgba(255, 215, 0, 0.7)';
  }
  
  document.body.appendChild(popup);
  
  popup.animate([
    { 
      transform: 'translate(-50%, -50%) scale(0.3) rotate(-10deg)',
      opacity: 0
    },
    { 
      transform: 'translate(-50%, -50%) scale(1.3) rotate(5deg)',
      opacity: 1,
      offset: 0.3
    },
    {
      transform: 'translate(-50%, -50%) scale(1.1) rotate(-2deg)',
      opacity: 1,
      offset: 0.6
    },
    { 
      transform: 'translate(-50%, -50%) scale(0.8) rotate(0deg)',
      opacity: 0
    }
  ], {
    duration: 1200,
    easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)'
  }).onfinish = () => popup.remove();
}

function createParticleBurst(tileElement) {
  const rect = tileElement.getBoundingClientRect();
  const centerX = rect.left + rect.width / 2;
  const centerY = rect.top + rect.height / 2;
  
  const tileValue = parseInt(tileElement.textContent);
  const tileColor = getTileColor(tileValue);
  
  const particleCount = 8 + Math.floor(Math.random() * 5);
  
  for (let i = 0; i < particleCount; i++) {
    const particle = document.createElement('div');
    particle.className = 'merge-particle';
    particle.style.left = centerX + 'px';
    particle.style.top = centerY + 'px';
    particle.style.background = tileColor;
    
    document.body.appendChild(particle);
    
    const angle = (Math.PI * 2 * i) / particleCount + (Math.random() - 0.5) * 0.5;
    const velocity = 60 + Math.random() * 40;
    const tx = Math.cos(angle) * velocity;
    const ty = Math.sin(angle) * velocity;
    
    particle.animate([
      { 
        transform: 'translate(0, 0) scale(1)',
        opacity: 1
      },
      { 
        transform: `translate(${tx}px, ${ty}px) scale(0)`,
        opacity: 0
      }
    ], {
      duration: 500 + Math.random() * 200,
      easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)'
    }).onfinish = () => particle.remove();
  }
}

function createScorePopup(x, y, score) {
  const popup = document.createElement('div');
  popup.className = 'score-popup';
  popup.textContent = '+' + score;
  popup.style.left = x + 'px';
  popup.style.top = y + 'px';
  popup.style.position = 'fixed';
  popup.style.fontSize = '24px';
  popup.style.fontWeight = '900';
  popup.style.color = '#ffd700';
  popup.style.textShadow = '0 0 20px rgba(255, 215, 0, 0.8)';
  popup.style.pointerEvents = 'none';
  popup.style.zIndex = '9999';
  popup.style.transform = 'translate(-50%, -50%)';
  
  document.body.appendChild(popup);
  
  popup.animate([
    { 
      transform: 'translate(-50%, -50%) scale(0.5)',
      opacity: 0
    },
    { 
      transform: 'translate(-50%, -70px) scale(1.2)',
      opacity: 1,
      offset: 0.3
    },
    { 
      transform: 'translate(-50%, -120px) scale(1)',
      opacity: 0
    }
  ], {
    duration: 1000,
    easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)'
  }).onfinish = () => popup.remove();
}

function getTileColor(value) {
  const colors = {
    2: '#00eaff',
    4: '#00ff99',
    8: '#ff00ff',
    16: '#ff0066',
    32: '#ffaa00',
    64: '#ff0000',
    128: '#5f00ff',
    256: '#00ffea',
    512: '#ff00aa',
    1024: '#00ffaa',
    2048: '#ffd700'
  };
  return colors[value] || '#00eaff';
}

