My Tic-Tac-Toe Game

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Tic-Tac-Toe</title>
  <style>
    :root { --green:#4CAF50; --blue:#2196F3; --gray:#ccc; }
    body { font-family: sans-serif; text-align: center; background:#f4f4f4; margin:0; padding:40px 16px; }
    h1 { margin: 0 0 10px; }
    .board {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      gap: 0;
      margin: 20px auto;
      background: #fff;
      border: 20px solid var(--gray);
      box-shadow: 0 0 10px rgba(0,0,0,.1);
      width: min(90vw, 420px);
      height: min(90vw, 420px);
      max-width: 420px;
      max-height: 420px;
      user-select: none;
    }
    .cell {
      border: 3px solid var(--gray);
      display: flex; align-items: center; justify-content: center;
      font-size: clamp(2.2rem, 10vw, 3.5rem);
      cursor: pointer; transition: background-color .15s ease;
      box-sizing: border-box;
    }
    .cell:hover { background:#eee; }
    .cell.x { background: var(--green); color:#fff; }
    .cell.o { background: var(--blue); color:#fff; }
    .cell.disabled { pointer-events: none; cursor: not-allowed; opacity:.6; }

    .score { margin-top: 10px; font-size: 1.2rem; color:#333; display:flex; gap:16px; justify-content:center; }
    .meta { margin-top: 10px; color:#555; min-height: 1.4em; }
    .controls { margin-top: 16px; display:flex; gap:10px; justify-content:center; }
    .btn {
      padding: 10px 18px; background: var(--green); color:#fff; border:none; border-radius:6px; cursor:pointer;
    }
    .btn:hover { filter: brightness(.95); }
    .btn.secondary { background:#666; }
  </style>
</head>
<body>
  <h1 id="game-title">Tic-Tac-Toe</h1>

  <div class="score">
    <p id="player-x-score">Player X: 0</p>
    <p id="player-o-score">Player O: 0</p>
  </div>
  <div class="meta" id="status">X to move</div>

  <div class="board" id="board">
    <div class="cell" data-index="0"></div>
    <div class="cell" data-index="1"></div>
    <div class="cell" data-index="2"></div>
    <div class="cell" data-index="3"></div>
    <div class="cell" data-index="4"></div>
    <div class="cell" data-index="5"></div>
    <div class="cell" data-index="6"></div>
    <div class="cell" data-index="7"></div>
    <div class="cell" data-index="8"></div>
  </div>

  <div class="controls">
    <button class="btn" id="reset-round">New Round</button>
    <button class="btn secondary" id="reset-scores">Reset Scores</button>
  </div>

  <script>
    const boardEl = document.getElementById('board');
    const cells = Array.from(boardEl.querySelectorAll('.cell'));
    const statusEl = document.getElementById('status');
    const playerXScoreEl = document.getElementById('player-x-score');
    const playerOScoreEl = document.getElementById('player-o-score');
    const resetRoundBtn = document.getElementById('reset-round');
    const resetScoresBtn = document.getElementById('reset-scores');

    let boardState = Array(9).fill('');
    let currentPlayer = 'X';
    let gameActive = true;
    let scoreX = 0;
    let scoreO = 0;

    const winningLines = [
      [0,1,2], [3,4,5], [6,7,8],     // rows
      [0,3,6], [1,4,7], [2,5,8],     // cols
      [0,4,8], [2,4,6]               // diagonals
    ];

    function updateScoreUI() {
      playerXScoreEl.textContent = `Player X: ${scoreX}`;
      playerOScoreEl.textContent = `Player O: ${scoreO}`;
    }

    function setStatus(msg) {
      statusEl.textContent = msg;
    }

    function clearBoardUI() {
      cells.forEach(c => {
        c.textContent = '';
        c.classList.remove('x', 'o', 'disabled');
      });
    }

    function newRound() {
      boardState = Array(9).fill('');
      gameActive = true;
      currentPlayer = 'X';
      clearBoardUI();
      setStatus(`${currentPlayer} to move`);
    }

    function resetScores() {
      scoreX = 0;
      scoreO = 0;
      updateScoreUI();
      newRound();
    }

    function determineWinner() {
      for (const [a,b,c] of winningLines) {
        const va = boardState[a], vb = boardState[b], vc = boardState[c];
        if (va && va === vb && vb === vc) return va; // 'X' or 'O'
      }
      return null;
    }

    function isBoardFull() {
      return boardState.every(v => v !== '');
    }

    function endGame(message) {
      gameActive = false;
      // disable remaining cells
      cells.forEach((cell, idx) => {
        if (!boardState[idx]) cell.classList.add('disabled');
      });
      setStatus(message);
    }

    // Single event listener (no duplicates on reset)
    boardEl.addEventListener('click', (e) => {
      if (!gameActive) return;
      const cell = e.target.closest('.cell');
      if (!cell || !boardEl.contains(cell)) return;

      const idx = Number(cell.dataset.index);
      if (boardState[idx]) return; // already played

      // Commit move
      boardState[idx] = currentPlayer;
      cell.textContent = currentPlayer;
      cell.classList.add(currentPlayer.toLowerCase()); // 'x' or 'o'

      // Check outcome
      const winner = determineWinner();
      if (winner) {
        if (winner === 'X') scoreX++; else scoreO++;
        updateScoreUI();
        endGame(`Player ${winner} wins!`);
        return;
      }

      if (isBoardFull()) {
        endGame(`It's a tie!`);
        return;
      }

      // Next turn
      currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
      setStatus(`${currentPlayer} to move`);
    });

    resetRoundBtn.addEventListener('click', newRound);
    resetScoresBtn.addEventListener('click', resetScores);

    // Init
    updateScoreUI();
    newRound();
  </script>
</body>
</html>