got these errors [{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-semicolonexpected",
	"severity": 8,
	"message": "semi-colon expected",
	"source": "css",
	"startLineNumber": 36,
	"startColumn": 22,
	"endLineNumber": 36,
	"endColumn": 28
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 37,
	"startColumn": 11,
	"endLineNumber": 37,
	"endColumn": 12
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 38,
	"startColumn": 12,
	"endLineNumber": 38,
	"endColumn": 13
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-ruleorselectorexpected",
	"severity": 8,
	"message": "at-rule or selector expected",
	"source": "css",
	"startLineNumber": 39,
	"startColumn": 3,
	"endLineNumber": 39,
	"endColumn": 4
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-semicolonexpected",
	"severity": 8,
	"message": "semi-colon expected",
	"source": "css",
	"startLineNumber": 51,
	"startColumn": 26,
	"endLineNumber": 51,
	"endColumn": 32
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 52,
	"startColumn": 12,
	"endLineNumber": 52,
	"endColumn": 13
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 53,
	"startColumn": 14,
	"endLineNumber": 53,
	"endColumn": 15
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 54,
	"startColumn": 8,
	"endLineNumber": 54,
	"endColumn": 9
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 55,
	"startColumn": 20,
	"endLineNumber": 55,
	"endColumn": 21
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 56,
	"startColumn": 16,
	"endLineNumber": 56,
	"endColumn": 17
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 57,
	"startColumn": 16,
	"endLineNumber": 57,
	"endColumn": 17
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 58,
	"startColumn": 14,
	"endLineNumber": 58,
	"endColumn": 15
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#1",
	"code": {
		"value": "compat-api/css",
		"target": {
			"$mid": 1,
			"path": "/docs/Web/CSS/user-select",
			"scheme": "https",
			"authority": "developer.mozilla.org"
		}
	},
	"severity": 8,
	"message": "'user-select' is not supported by Safari, Safari on iOS. Add '-webkit-user-select' to support Safari 3+, Safari on iOS 3+.",
	"source": "Microsoft Edge Tools",
	"startLineNumber": 59,
	"startColumn": 5,
	"endLineNumber": 59,
	"endColumn": 16
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 59,
	"startColumn": 16,
	"endLineNumber": 59,
	"endColumn": 17
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 60,
	"startColumn": 16,
	"endLineNumber": 60,
	"endColumn": 17
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-ruleorselectorexpected",
	"severity": 8,
	"message": "at-rule or selector expected",
	"source": "css",
	"startLineNumber": 61,
	"startColumn": 3,
	"endLineNumber": 61,
	"endColumn": 4
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#1",
	"code": {
		"value": "compat-api/css",
		"target": {
			"$mid": 1,
			"path": "/docs/Web/CSS/user-select",
			"scheme": "https",
			"authority": "developer.mozilla.org"
		}
	},
	"severity": 8,
	"message": "'user-select' is not supported by Safari, Safari on iOS. Add '-webkit-user-select' to support Safari 3+, Safari on iOS 3+.",
	"source": "Microsoft Edge Tools",
	"startLineNumber": 101,
	"startColumn": 5,
	"endLineNumber": 101,
	"endColumn": 16
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-semicolonexpected",
	"severity": 8,
	"message": "semi-colon expected",
	"source": "css",
	"startLineNumber": 113,
	"startColumn": 16,
	"endLineNumber": 113,
	"endColumn": 22
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 114,
	"startColumn": 15,
	"endLineNumber": 114,
	"endColumn": 16
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 119,
	"startColumn": 19,
	"endLineNumber": 119,
	"endColumn": 20
},{
	"resource": "/c:/Users/glenn/Downloads/3DVRGameHelper/Test.html",
	"owner": "_generated_diagnostic_collection_name_#4",
	"code": "css-lcurlyexpected",
	"severity": 8,
	"message": "{ expected",
	"source": "css",
	"startLineNumber": 120,
	"startColumn": 14,
	"endLineNumber": 120,
	"endColumn": 15
}] give me the css code snippet to fix it <!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>A Thousand British Raggers - Enhanced Prototype</title>
  <style> 
   /* RESET & Base */
* {
    box-sizing: border-box;
    outline: none;
  }
  body, html {
    margin: 0;
    padding: 0;
    overflow: hidden;
    background: linear-gradient(135deg, #0a0f12, #111a22);
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    -webkit-user-select: none; /* Safari 3+ */
    user-select: none;
    color: #0ff;
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  
  /* Canvas */
  #gameCanvas {
    background: #1c1c25;
    border-radius: 25px;
    box-shadow:
      0 0 40px #0ff,
      inset 0 0 60px #0ff99;
    cursor: crosshair;
    display: block;
  }
  
  /* UI Base */
  #ui, #mainMenu, #upgradeMenu {
    max-width: 1100px;
    width: 95vw;
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px); /* Safari 9+ */
    background: rgba(12, 15, 17, 0.75);
    border-radius: 26px;
    padding: 16px 30px;
    color: #0ff;
    box-shadow: 0 0 30px #0ffcc;
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    justify-content: center;
    font-family: 'Share Tech Mono', monospace;
    font-weight: 700;
    font-size: 1.2rem;
    user-select: none;
    text-shadow: 0 0 8px #0ff;
  }
  
  #mainMenu, #upgradeMenu {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 400px;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    display: none;
    z-index: 10;
    text-align: center;
  }
  
  #mainMenu.show, #upgradeMenu.show {
    display: flex;
    animation: fadeInScale 0.35s ease forwards;
  }
  
  @keyframes fadeInScale {
    0% {
      opacity: 0;
      transform: translate(-50%, -48%) scale(0.9);
    }
    100% {
      opacity: 1;
      transform: translate(-50%, -50%) scale(1);
    }
  }
  
  h1, h2 {
    font-family: 'Playfair Display', serif;
    margin-bottom: 10px;
    text-shadow: 0 0 12px #0ff;
  }
  
  /* Buttons */
  button {
    user-select: none;
    cursor: pointer;
    border: 2px solid #0ff;
    border-radius: 30px;
    background: rgba(0, 255, 255, 0.1);
    padding: 12px 36px;
    font-weight: 700;
    font-size: 1.15rem;
    color: #0ff;
    margin: 8px 0;
    box-shadow:
      inset 0 0 20px #0ff,
      0 0 30px #0ffbb;
    transition:
      background 0.3s ease,
      box-shadow 0.4s ease,
      color 0.3s ease,
      transform 0.22s ease;
    letter-spacing: 1.6px;
    min-width: 200px;
  }
  button:hover {
    background: #0ff;
    color: #0a0a0a;
    box-shadow:
      inset 0 0 40px #0ff,
      0 0 45px #0fffcc;
    transform: scale(1.06);
  }
  button:active {
    transform: scale(0.94);
    box-shadow: none;
  }
  button:disabled {
    opacity: 0.3;
    cursor: not-allowed;
    box-shadow: none !important;
    color: #0aa;
  }
  
  /* Panels */
  .panel {
    flex: 1 1 130px;
    min-width: 140px;
    background: rgba(0, 32, 48, 0.25);
    border-radius: 24px;
    box-shadow:
      inset 0 10px 16px #0ff3,
      0 0 12px #0ff8;
    padding: 18px 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    transition: background 0.25s ease;
    user-select: none;
  }
  .panel strong {
    font-size: 1.4rem;
    font-family: 'Playfair Display', serif;
    user-select: none;
    letter-spacing: 0.03em;
    margin-top: 6px;
    color: #07ffffee;
    text-shadow: 0 0 22px #0ff;
  }
  
  /* Scrollable log */
  #log {
    max-width: 1100px;
    width: 95vw;
    max-height: 170px;
    overflow-y: auto;
    background: rgba(0, 0, 0, 0.55);
    border-radius: 20px;
    padding: 16px 24px;
    font-family: 'Share Tech Mono', monospace;
    font-size: 14px;
    user-select: none;
    color: #0ff;
    margin-top: 22px;
    box-shadow:
      0 0 35px #0ffa inset,
      0 0 18px #0ffa;
    line-height: 1.25;
  }
  
  /* Scrollbar styles */
  #log::-webkit-scrollbar {
    width: 10px;
  }
  #log::-webkit-scrollbar-track {
    background: #071012b3;
    border-radius: 10px;
  }
  #log::-webkit-scrollbar-thumb {
    background: #0ff5;
    border-radius: 10px;
  }
  
  /* Weaponbar */
  #weaponBar {
    position: fixed;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 14px;
    background: rgba(0, 32, 50, 0.4);
    padding: 12px 20px;
    border-radius: 40px;
    box-shadow: 0 0 22px #00ffe620;
    z-index: 20;
    user-select: none;
  }
  .weaponSlot {
    border: 2.5px solid #0ff;
    width: 58px;
    height: 58px;
    border-radius: 18px;
    position: relative;
    cursor: pointer;
    transition: background 0.3s ease, box-shadow 0.3s ease;
    background: rgba(0, 150, 150, 0.2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 900;
    font-family: monospace;
    font-size: 22px;
    color: #0ff;
    text-shadow:
      0 0 9px #0ff,
      0 0 2px #0fff;
  }
  .weaponSlot.active {
    background: #0ff;
    color: #111;
    box-shadow:
      0 0 14px #0ff,
      inset 0 0 8px #0ff;
  }
  .weaponSlot .nameTip {
    position: absolute;
    bottom: 62px;
    left: 50%;
    transform: translateX(-50%);
    background: #036e7ccc;
    border-radius: 6px;
    padding: 4px 11px;
    font-size: 11px;
    color: #0ef;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
    text-shadow: 0 0 7px #0ff;
    user-select: none;
  }
  .weaponSlot:hover .nameTip {
    opacity: 1;
  }
  
  /* Upgrade menu item */
  .upgradeItem {
    background: rgba(0, 50, 75, 0.2);
    border-radius: 14px;
    box-shadow: inset 0 0 10px #0ff1;
    padding: 10px 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: nowrap;
    margin-bottom: 12px;
    border: 1.75px solid transparent;
    cursor: pointer;
    transition: border-color 0.3s ease;
  }
  .upgradeItem:hover {
    border-color: #0ff8;
    background: rgba(0, 100, 160, 0.3);
  }
  .upgradeItem.locked {
    opacity: 0.5;
    cursor: not-allowed;
    border-color: transparent !important;
  }
  .upgradeItem > .text {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex-grow: 1;
    font-size: 14px;
    color: #affe;
    text-shadow: 0 0 8px #06ff;
    user-select: none;
  }
  .upgradeItem > .cost {
    font-weight: 900;
    font-size: 18px;
    color: #0ff;
    user-select: none;
    min-width: 60px;
    text-align: right;
  }
  .upgradeItem button {
    background: transparent;
    border: none;
    color: #0ff;
    font-weight: 800;
    font-size: 1.35rem;
    cursor: pointer;
    user-select: none;
    transition: color 0.3s ease;
  }
  .upgradeItem button:hover {
    color: #0ffcaa;
  }
  
  /* Animations */
  
  .fadeIn {
    animation: fadeIn 0.35s ease forwards;
  }
  .fadeOut {
    animation: fadeOut 0.35s ease forwards;
  }
  
  @keyframes fadeIn {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
  @keyframes fadeOut {
    from {
      opacity: 1;
    }
    to {
      opacity: 0;
    }
  }
  
  /* Visibly smooth transition for opacity */
  #upgradeMenu, #mainMenu, #ui {
    transition: opacity 0.3s ease;
  }

  </style>
</head>
<body>
  <canvas id="gameCanvas" width="1040" height="720" tabindex="0"></canvas>

  <!-- Main Menu -->
  <div id="mainMenu" class="show" role="dialog" aria-modal="true" aria-labelledby="titleMainMenu">
    <h1 id="titleMainMenu" style="font-family:'Playfair Display', serif; font-weight: 900; font-size: 3rem;">A Thousand British Raggers</h1>
    <button id="btnStart">Start Game</button>
    <button id="btnUpgrades">Upgrades & Weapons</button>
    <button id="btnInstructions">How to Play</button>
  </div>

  <!-- Upgrade & Weapon Menu -->
  <div id="upgradeMenu" role="dialog" aria-modal="true" aria-labelledby="titleUpgradeMenu">
    <h2 id="titleUpgradeMenu" style="margin-bottom:12px;">Upgrades & Weapon Unlocks</h2>
    <div style="height: 420px; overflow-y: auto; width: 100%;">
      <div id="upgradeItems"></div>
    </div>
    <button id="closeUpgrade">Back</button>
  </div>

  <!-- Game UI -->
  <div id="ui" style="display:none;">
    <div class="panel">Level <br /><strong id="level">1</strong></div>
    <div class="panel">XP <br /><strong id="xp">0</strong></div>
    <div class="panel">P Coins <br /><strong id="coins">0</strong></div>
    <div class="panel">Wave <br /><strong id="wave">1</strong></div>
    <div class="panel" style="min-width: 220px;">Class <br /><strong id="class">Recruit</strong></div>
    <button id="upgradeBenchBtn">Upgrade Coin Drop Chance (Cost: 50)</button>
    <button id="buySoldierBtn" disabled>Buy Soldier (Cost: 100 P)</button>
  </div>

  <!-- Weapon quick slots bar -->
  <div id="weaponBar" aria-label="Weapon quick switch bar" role="list" style="display:none;"></div>

  <!-- Game Log -->
  <div id="log" aria-live="polite" aria-atomic="true"></div>

<script>
(() => {
  "use strict";

  const canvas = document.getElementById('gameCanvas');
  const ctx = canvas.getContext('2d');

  // --- Dimensions & Map ---
  const WIDTH = canvas.width;
  const HEIGHT = canvas.height;

  const MAP_WIDTH = 2400;
  const MAP_HEIGHT = 1800;
  const BOX = { // Player movement box
    x: (MAP_WIDTH - 1200) / 2,
    y: (MAP_HEIGHT - 900) / 2,
    width: 1200,
    height: 900,
  };

  // --- DOM elements ---
  const UI = {
    level: document.getElementById('level'),
    xp: document.getElementById('xp'),
    coins: document.getElementById('coins'),
    wave: document.getElementById('wave'),
    playerClass: document.getElementById('class'),
    upgradeBenchBtn: document.getElementById('upgradeBenchBtn'),
    buySoldierBtn: document.getElementById('buySoldierBtn'),
    log: document.getElementById('log'),
    mainMenu: document.getElementById('mainMenu'),
    upgradeMenu: document.getElementById('upgradeMenu'),
    upgradeItems: document.getElementById('upgradeItems'),
    closeUpgrade: document.getElementById('closeUpgrade'),
    btnStart: document.getElementById('btnStart'),
    btnUpgrades: document.getElementById('btnUpgrades'),
    btnInstructions: document.getElementById('btnInstructions'),
    weaponBar: document.getElementById('weaponBar'),
    uiContainer: document.getElementById('ui'),
  };

  // --- Utilities ---
  function clamp(v, a, b) { return v < a ? a : v > b ? b : v; }
  function length(x, y) { return Math.sqrt(x * x + y * y); }
  function normalize(x, y) {
    let len = length(x, y); if (len === 0) return [0, 0];
    return [x / len, y / len];
  }
  function lerp(a, b, t) { return a + (b - a) * t; }
  function randRange(min, max) { return Math.random() * (max - min) + min; }
  function chance(p) { return Math.random() < p; }

  // Format XP with suffixes
  function formatXP(xp) {
    if (xp < 1000) return xp.toFixed(0);
    if (xp < 10000) return (xp / 1000).toFixed(1) + 'k';
    if (xp < 1000000) return (xp / 1000).toFixed(0) + 'k';
    else return (xp / 1000000).toFixed(1) + 'M';
  }

  // Log helper
  function log(msg, type = "INFO") {
    UI.log.innerHTML = `[${type}] ${msg}<br />` + UI.log.innerHTML;
    if (UI.log.innerHTML.length > 8000) UI.log.innerHTML = UI.log.innerHTML.substring(0, 7000);
  }

  // --- Camera ---
  class Camera {
    constructor() {
      this.x = 0; this.y = 0;
      this.shakeTime = 0;
      this.shakeIntensity = 0;
    }
    update(targetX, targetY) {
      let cx = clamp(targetX - WIDTH / 2, 0, MAP_WIDTH - WIDTH);
      let cy = clamp(targetY - HEIGHT / 2, 0, MAP_HEIGHT - HEIGHT);
      if (this.shakeTime > 0) {
        const s = this.shakeIntensity;
        const shakeX = (Math.random() * 2 - 1) * s;
        const shakeY = (Math.random() * 2 - 1) * s;
        cx += shakeX; cy += shakeY;
        this.shakeIntensity *= 0.8;
        this.shakeTime--;
      }
      this.x = cx; this.y = cy;
    }
    shake(intensity = 7, time = 10) {
      this.shakeIntensity = intensity;
      this.shakeTime = time;
    }
  }
  const camera = new Camera();

  // --- Classes ---
  class Particle {
    constructor(x, y, vx, vy, radius, color, life, glow=false){
      this.x = x; this.y = y;
      this.vx = vx; this.vy = vy;
      this.radius = radius; 
      this.color = color;
      this.life = life;
      this.glow = glow;
      this.alpha = 1;
    }
    update(){
      this.x += this.vx;
      this.y += this.vy;
      this.life--;
      this.alpha = Math.max(0, this.alpha - 0.04);
    }
    draw(ctx, cam){
      const cx = this.x - cam.x;
      const cy = this.y - cam.y;
      ctx.save();
      if(this.glow) {
        ctx.shadowColor = this.color;
        ctx.shadowBlur = this.radius * 4;
      }
      ctx.fillStyle = `rgba(${this.color},${this.alpha})`;
      ctx.beginPath();
      ctx.arc(cx, cy, this.radius, 0, Math.PI * 2);
      ctx.fill();
      ctx.restore();
    }
    isDead(){ return this.life <= 0 || this.alpha <= 0; }
  }

  // Player, enemy, mini soldier, weapons and upgrades defined below...

  // --- Player class ---
  class Player {
    constructor(){
      this.x = MAP_WIDTH/2;
      this.y = MAP_HEIGHT/2;
      this.radius = 25;
      this.baseSpeed = 3.6;
      this.speedBoost = false;
      this.speed = this.baseSpeed;
      this.vx = 0;
      this.vy = 0;
      this.level = 1;
      this.xp = 0;
      this.coins = 0;
      this.wave = 1;
      this.classRank = 'Recruit';
      this.canShoot = true;
      this.shootCooldownBase = 280;
      this.shootCooldown = this.shootCooldownBase;
      this.shootTimer = 0;
      // Weapon inventory
      this.weaponsUnlocked = {};
      this.weaponOrder = []; // To keep weapon keying order
      this.currentWeaponIndex = 0;
      this.weapon = 'Fist';

      // Upgrade flags
      this.pocketSandUnlocked = false;
      this.barnettAttachment = false;
      this.hasScope = false;
      this.miniSoldierAI = false;

      // Soldiers
      this.soldiers = 0;
      this.coinDropChance = 0.25;
    }

    move(keys){
      // Direction vector calculation
      let vx = (keys.a ? -1 : 0) + (keys.d ? 1 : 0);
      let vy = (keys.w ? -1 : 0) + (keys.s ? 1 : 0);
      if (vx === 0 && vy === 0) {
        this.vx = 0;
        this.vy = 0;
        return;
      }
      let len = Math.sqrt(vx * vx + vy * vy);
      vx /= len; vy /= len;
      this.speed = this.baseSpeed * (this.speedBoost ? 1.65 : 1);
      this.vx = vx * this.speed;
      this.vy = vy * this.speed;

      this.x += this.vx;
      this.y += this.vy;

      // Clamp inside box
      this.x = clamp(this.x, BOX.x + this.radius, BOX.x + BOX.width - this.radius);
      this.y = clamp(this.y, BOX.y + this.radius, BOX.y + BOX.height - this.radius);
    }

    updateShootCooldown(delta){
      if(this.shootTimer > 0){
        this.shootTimer -= delta;
        if(this.shootTimer < 0) this.shootTimer = 0;
      }
    }

    addWeapon(name, damage, desc, category='weapon'){
      if(!this.weaponsUnlocked[name]){
        this.weaponsUnlocked[name] = {damage, desc, category};
        this.weaponOrder.push(name);
        if(this.weaponOrder.length === 1){
          this.setWeapon(name);
          addLog(`New weapon unlocked: ${name}`, "UNLOCK");
        }
      }
    }

    setWeapon(nameOrIndex){
      if(typeof nameOrIndex === "number"){
        if(nameOrIndex >= 0 && nameOrIndex < this.weaponOrder.length){
          this.currentWeaponIndex = nameOrIndex;
          this.weapon = this.weaponOrder[nameOrIndex];
        }
      } else if(typeof nameOrIndex === "string"){
        if(this.weaponsUnlocked[nameOrIndex]){
          this.weapon = nameOrIndex;
          this.currentWeaponIndex = this.weaponOrder.indexOf(nameOrIndex);
        }
      }
    }

    nextWeapon() {
      this.currentWeaponIndex++;
      if(this.currentWeaponIndex >= this.weaponOrder.length) this.currentWeaponIndex = 0;
      this.weapon = this.weaponOrder[this.currentWeaponIndex];
    }
    prevWeapon() {
      this.currentWeaponIndex--;
      if(this.currentWeaponIndex < 0) this.currentWeaponIndex = this.weaponOrder.length - 1;
      this.weapon = this.weaponOrder[this.currentWeaponIndex];
    }

    shoot(mouseX, mouseY){
      if(this.shootTimer === 0 && this.weapon){
        let dmg = this.weaponsUnlocked[this.weapon].damage || 1;
        shootBullet(this.x, this.y, mouseX, mouseY, dmg, this.weapon);
        this.shootTimer = this.shootCooldown;
        camera.shake(7, 10);
      }
    }

    addXP(amount){
      this.xp += amount;
      // Level up check is outside this class
    }

    addCoins(amount){
      this.coins += amount;
    }

    levelUp(){
      // XP thresholds demo logic
      if(this.level === 1 && this.xp >= 100){
        this.level = 2;
        this.classRank = "Private";
        this.addWeapon("Flintlock", 5, "Classic flintlock pistol.");
        this.addWeapon("Musket", 6, "Standard musket.");
        this.setWeapon("Flintlock");
        addLog('Reached Private! Flintlock and Musket added to inventory.', 'LEVELUP');
      } else if(this.level === 2 && this.xp >= 500){
        this.level = 3;
        this.classRank = "Lutenit First Class";
        this.hasScope = true;
        this.barnettAttachment = true;
        this.addWeapon("Musket (Barnett)", 7, "Musket with Barnett attachment.");
        this.addWeapon("Flintlock (Scoped)", 5, "Flintlock with scope attachment.");
        this.setWeapon("Musket (Barnett)");
        addLog('Ranked Lutenit First Class! Attachments unlocked.', 'LEVELUP');
      } else if(this.level === 3 && this.xp >= 1000){
        this.level = 4;
        this.classRank = "Lutenit Second Class";
        if(chance(0.01)) {
          this.pocketSandUnlocked = true;
          this.addWeapon("Pocket Sand", 0, "Throw sand at close foes!");
          addLog("Pocket Sand unlocked! Use to blind nearby enemies.", 'LEVELUP');
          this.setWeapon("Pocket Sand");
        } else {
          this.addWeapon("Musket (Upgraded)", 7.7, "Upgraded musket for more damage.");
          this.addWeapon("Flintlock (Upgraded)", 7, "Upgraded flintlock.");
          this.setWeapon("Musket (Upgraded)");
          addLog("Upgraded Musket and Flintlock unlocked.", 'LEVELUP');
          this.pocketSandUnlocked = false;
        }
      } else if(this.level ===4 && this.wave >= 15){
        this.level = 5;
        this.classRank = "Commander Second Class";
        this.speedBoost = true;
        this.miniSoldierAI = true;
        if(miniSoldiers.length < 1){
          miniSoldiers.push(new MiniSoldier());
          addLog('Commander Second Class! Speed boost activated, mini soldier deployed.');
        }
      } else if(this.level === 5 && this.wave >= 25){
        this.level = 6;
        this.classRank = "Command First Charge";
        for(let i=0; i<5; i++) miniSoldiers.push(new MiniSoldier());
        this.soldiers += 5;
        addLog('Command First Charge! +5 mini soldiers added to your squad.');
      }
    }
  }

  // --- Enemy ---
  class Enemy {
    constructor(side){
      this.radius = 18+Math.random()*6;
      this.side = side;
      this.x = side === 'left' ? BOX.x - this.radius*3 : BOX.x + BOX.width + this.radius*3;
      this.y = BOX.y + Math.random()*BOX.height;
      this.speed = randRange(1.0, 1.7);
      this.vx = 0;
      this.vy = 0;
      this.hpMax = 20 + Math.random()*10;
      this.hp = this.hpMax;
      this.dead = false;
      this.state = 'chase';
      this.attackRange = 40 + this.radius;
      this.attackCooldown = 0;
      this.attackCooldownBase = 800;
      this.colorHue = randRange(350, 10);
      this.isStunned = false;
      this.stunTimeout = 0;
    }
    update(dt, player){
      if(this.dead) return;

      if(this.isStunned){
        this.stunTimeout -= dt;
        if(this.stunTimeout <= 0){
          this.isStunned = false;
          addLog('Enemy recovered from pocket sand.');
        }
        return;
      }

      let dx = player.x - this.x;
      let dy = player.y - this.y;
      let distToPlayer = length(dx, dy);

      if(distToPlayer < this.attackRange){
        this.state = 'attack';
      } else {
        this.state = 'chase';
      }

      if(this.state === 'chase'){
        let [nx, ny] = normalize(dx, dy);
        this.vx = nx * this.speed;
        this.vy = ny * this.speed;
        this.x += this.vx;
        this.y += this.vy;

        this.x = clamp(this.x, BOX.x + this.radius, BOX.x + BOX.width - this.radius);
        this.y = clamp(this.y, BOX.y + this.radius, BOX.y + BOX.height - this.radius);
      }
      else if(this.state === 'attack'){
        if(this.attackCooldown <= 0){
          playerTakeDamage(1);
          this.attackCooldown = this.attackCooldownBase;
          camera.shake(12, 12);
          addLog(`Enemy attacked you!`, "DAMAGE");
        } else {
          this.attackCooldown -= dt;
        }
      }
    }
    draw(ctx, cam){
      let cx = this.x - cam.x;
      let cy = this.y - cam.y;

      ctx.save();
      ctx.translate(cx, cy);

      ctx.shadowColor = `hsl(${this.colorHue}, 80%, 60%)`;
      ctx.shadowBlur = 25;
      ctx.fillStyle = `hsl(${this.colorHue}, 70%, 48%)`;
      ctx.beginPath();
      ctx.ellipse(0, 8, this.radius * 1.3, this.radius * 1.7, 0, 0, 2 * Math.PI);
      ctx.fill();

      ctx.shadowBlur = 0;
      ctx.fillStyle = '#f4d1b6';
      ctx.beginPath();
      ctx.ellipse(0, -this.radius * 1.2, this.radius * 1.15, this.radius, 0, 0, 2 * Math.PI);
      ctx.fill();

      ctx.fillStyle = '#ffffff';
      ctx.beginPath();
      ctx.ellipse(-this.radius * 0.4, -this.radius * 1.3, this.radius * 0.5, this.radius * 0.7, 0, 0, 2 * Math.PI);
      ctx.ellipse(this.radius * 0.4, -this.radius * 1.3, this.radius * 0.5, this.radius * 0.7, 0, 0, 2 * Math.PI);
      ctx.fill();

      ctx.fillStyle = '#111';
      ctx.beginPath();
      ctx.ellipse(-this.radius * 0.4, -this.radius * 1.25, this.radius * 0.3, this.radius * 0.5, 0, 0, 2 * Math.PI);
      ctx.ellipse(this.radius * 0.4, -this.radius * 1.25, this.radius * 0.3, this.radius * 0.5, 0, 0, 2 * Math.PI);
      ctx.fill();

      ctx.fillStyle = '#6b3030';
      ctx.fillRect(-this.radius * 0.6, -this.radius * 0.65, this.radius * 1.2, this.radius * 0.25);

      ctx.fillStyle = '#3a3a3a';
      ctx.fillRect(-this.radius*0.1, 10, this.radius*1.6, 6);
      ctx.fillStyle = '#bfbf5a';
      if(this.isStunned){
        ctx.fillStyle = '#ffec4d';
      }
      ctx.beginPath();
      ctx.moveTo(this.radius * 1.5, 10);
      ctx.lineTo(this.radius * 1.6 + 6, 19);
      ctx.lineTo(this.radius * 0.9, 34);
      ctx.closePath();
      ctx.fill();

      let hpRatio = this.hp / this.hpMax;
      const barWidth = this.radius * 2.7;
      ctx.fillStyle = '#222';
      ctx.fillRect(-barWidth/2, this.radius * 1.8, barWidth, 10);
      ctx.fillStyle = hpRatio > 0.6 ? '#1aff0b' : (hpRatio > 0.3 ? '#e6e60b' : '#ff1300');
      ctx.fillRect(-barWidth/2, this.radius * 1.8, barWidth * hpRatio, 10);

      ctx.restore();
    }
  }

  // --- MiniSoldier allies ---
  class MiniSoldier {
    constructor(){
      this.radius = 14;
      this.x = Player.x + randRange(20, 60);
      this.y = Player.y + randRange(20, 60);
      this.speed = 3.2;
      this.hp = 30;
      this.attackPower = 1.1;
      this.targetEnemy = null;
      this.color = '#44ffaa';
      this.anglePhase = Math.random()*Math.PI*2;
    }
    update(enemies){
      if(!this.targetEnemy || this.targetEnemy.hp <= 0){
        let minDist = 9999;
        this.targetEnemy = null;
        for(const e of enemies){
          let d = length(e.x - this.x, e.y - this.y);
          if(d < minDist){
            minDist = d;
            this.targetEnemy = e;
          }
        }
      }
      if(this.targetEnemy){
        let dx = this.targetEnemy.x - this.x;
        let dy = this.targetEnemy.y - this.y;
        let dist = length(dx, dy);
        if(dist > this.radius + this.targetEnemy.radius + 5){
          let [nx, ny] = normalize(dx, dy);
          this.x += nx * this.speed;
          this.y += ny * this.speed;
        } else {
          this.targetEnemy.hp -= this.attackPower * 0.4;
          if(this.targetEnemy.hp <= 0) this.targetEnemy = null;
        }
      } else {
        let angle = performance.now()/1000 + this.anglePhase;
        this.x = lerp(this.x, Player.x + 40 * Math.cos(angle), 0.1);
        this.y = lerp(this.y, Player.y + 40 * Math.sin(angle), 0.1);
      }
    }
    draw(ctx, cam){
      let cx = this.x - cam.x;
      let cy = this.y - cam.y;

      ctx.save();
      ctx.translate(cx, cy);
      ctx.shadowColor = this.color;
      ctx.shadowBlur = 14;
      ctx.fillStyle = this.color;

      ctx.beginPath();
      ctx.ellipse(0, 0, this.radius * 0.7, this.radius * 1.3, 0, 0, 2 * Math.PI);
      ctx.fill();

      ctx.shadowBlur = 0;
      ctx.fillStyle = '#33aa77';
      ctx.beginPath();
      ctx.arc(0, -this.radius * 0.8, this.radius * 0.55, 0, 2 * Math.PI);
      ctx.fill();

      ctx.fillStyle = '#d3fff8';
      ctx.beginPath();
      ctx.ellipse(-5, -this.radius * 0.85, 3.6, 5, 0, 0, 2 * Math.PI);
      ctx.ellipse(5, -this.radius * 0.85, 3.6, 5, 0, 0, 2 * Math.PI);
      ctx.fill();

      ctx.fillStyle = '#111';
      ctx.beginPath();
      ctx.ellipse(-5, -this.radius * 0.82, 2, 3, 0, 0, 2 * Math.PI);
      ctx.ellipse(5, -this.radius * 0.82, 2, 3, 0, 0, 2 * Math.PI);
      ctx.fill();

      ctx.fillStyle = '#006633';
      ctx.fillRect(-this.radius*0.2, -6, 20, 6);

      ctx.restore();

      let hpRatio = Math.min(1, this.hp / 30);
      let barWidth = this.radius * 1.3;

      ctx.fillStyle = '#111';
      ctx.fillRect(cx - barWidth/2, cy + this.radius + 8, barWidth, 6);
      ctx.fillStyle = '#0ff';
      ctx.fillRect(cx - barWidth/2, cy + this.radius + 8, barWidth * hpRatio, 6);
    }
  }

  // --- Bullet ---
  class Bullet {
    constructor(x, y, dx, dy, damage, _type){
      this.x = x;
      this.y = y;
      this.dx = dx;
      this.dy = dy;
      this.speed = 18;
      this.radius = 7;
      this.life = 40;
      this.damage = damage || 1;
      this.type = _type || "bullet";
      this.color = "0,255,255";
      this.glowColor = "aqua";
      this.exploded = false;
    }
    update(){
      this.x += this.dx * this.speed;
      this.y += this.dy * this.speed;
      this.life--;
    }
    draw(ctx, cam){
      let cx = this.x - cam.x;
      let cy = this.y - cam.y;
      ctx.save();
      ctx.shadowColor = `rgba(${this.color},0.8)`;
      ctx.shadowBlur = 18;
      ctx.fillStyle = `rgba(${this.color},0.98)`;
      ctx.beginPath();
      ctx.ellipse(cx, cy, this.radius, this.radius * 0.7, 0, 0, Math.PI * 2);
      ctx.fill();
      ctx.restore();
    }
  }

  // --- Globals ---
  const keys = {w:false, a:false, s:false, d:false};
  let mousePos = {x: WIDTH/2, y: HEIGHT/2};
  let mouseDown = false;

  const enemies = [];
  const bullets = [];
  const miniSoldiers = [];
  const particles = [];

  const Player = new Player();

  // Movement and input
  window.addEventListener('keydown', e => {
    if(e.repeat) return;
    const k = e.key.toLowerCase();
    if(k in keys) keys[k] = true;
    if('123456789'.indexOf(e.key) >= 0){
      const idx = parseInt(e.key) -1;
      if(Player.weaponOrder.length > idx){
        Player.setWeapon(idx);
        updateWeaponBar();
        addLog(`Switched weapon to: ${Player.weapon}`, 'WEAPON');
      }
    }
  });
  window.addEventListener('keyup', e=> {
    const k = e.key.toLowerCase();
    if(k in keys) keys[k] = false;
  });
  canvas.addEventListener('mousemove', e=>{
    const rect = canvas.getBoundingClientRect();
    mousePos.x = e.clientX - rect.left;
    mousePos.y = e.clientY - rect.top;
  });
  canvas.addEventListener('mousedown', e=>{
    if(e.button === 0) mouseDown = true;
  });
  canvas.addEventListener('mouseup', e=>{
    if(e.button === 0) mouseDown = false;
  });

  // --- Game functions ---
  function shootBullet(x, y, mouseX, mouseY, damage, weaponType){
    const dx = mouseX + camera.x - x;
    const dy = mouseY + camera.y - y;
    const [nx, ny] = normalize(dx, dy);
    if(nx ===0 && ny ===0) return;
    bullets.push(new Bullet(x + nx*20, y + ny*20, nx, ny, damage, weaponType));
    spawnShootParticles(x + nx*20, y + ny*20, nx, ny);
  }

  function spawnShootParticles(x, y, dx, dy){
    for(let i=0; i<6; i++){
      const angle = Math.atan2(dy, dx) + randRange(-0.3, 0.3);
      const speed = randRange(2.5, 5.5);
      const vx = Math.cos(angle)*speed;
      const vy = Math.sin(angle)*speed;
      particles.push(new Particle(x, y, vx, vy, randRange(2,5), '0,255,255', 20, true));
    }
  }

  // Explosion particles
  function spawnExplosion(x, y){
    let colors = ['0,255,255', '100,255,100', '255,255,100'];
    for(let i=0; i<20; i++){
      const angle = randRange(0, Math.PI*2);
      const speed = randRange(1, 8);
      const vx = Math.cos(angle)*speed;
      const vy = Math.sin(angle)*speed;
      const color = colors[Math.floor(Math.random()*colors.length)];
      particles.push(new Particle(x, y, vx, vy, randRange(2,6), color, 50, true));
    }
  }

  let playerHealth = 100;
  let playerInvulnerableTimer = 0;

  function playerTakeDamage(amount){
    if(playerInvulnerableTimer > 0) return;
    playerHealth -= amount;
    playerInvulnerableTimer = 1000;
    if(playerHealth < 0) playerHealth = 0;
    addLog(`You took ${amount} damage! HP: ${playerHealth}`, "DAMAGE");
  }

  function pocketSandAttack(enemy){
    if(!Player.pocketSandUnlocked) return false;
    const d = length(Player.x - enemy.x, Player.y - enemy.y);
    if(d < Player.radius + enemy.radius + 20){
      enemy.hp -= 5;
      enemy.isStunned = true;
      enemy.stunTimeout = 1500;
      camera.shake(12, 15);
      addLog("Pocket Sand blinded enemy!", "EFFECT");
      return true;
    }
    return false;
  }

  function upgradeCoinDropChance(){
    if(Player.coins < 50) {
      addLog("Not enough P coins to upgrade coin drop chance!");
      return;
    }
    Player.coins -= 50;
    Player.coinDropChance += 0.035;
    if(Player.coinDropChance > 1) Player.coinDropChance = 1;
    addLog(`Coin drop chance increased to ${(Player.coinDropChance*100).toFixed(1)}%!`);
  }

  function buyMiniSoldier(){
    if(Player.coins < 100){
      addLog("Not enough P coins to buy mini soldier!");
      return;
    }
    Player.coins -= 100;
    Player.soldiers++;
    miniSoldiers.push(new MiniSoldier());
    addLog("Mini soldier bought and deployed!");
  }

  function spawnWave(){
    const count = chance(0.25) ? 20 : 10;
    for(let i=0; i<count; i++){
      enemies.push(new Enemy(chance(0.5)? 'left':'right'));
    }
    addLog(`Wave ${Player.wave} started with ${count} raggers!`);
    UI.buySoldierBtn.disabled = Player.coins < 100;
  }

  function update(delta){
    Player.move(keys);
    Player.updateShootCooldown(delta);
    if(mouseDown) Player.shoot(mousePos.x, mousePos.y);

    for(let i=bullets.length-1; i>=0; i--){
      const b = bullets[i];
      b.update();
      if(b.life < 0 || b.x < 0 || b.x > MAP_WIDTH || b.y<0 || b.y>MAP_HEIGHT){
        bullets.splice(i, 1);
        continue;
      }
      for(let j = enemies.length-1; j>=0; j--){
        let e = enemies[j];
        if(!e.dead && length(b.x - e.x, b.y - e.y) < e.radius + b.radius){
          e.hp -= b.damage;
          camera.shake(10, 10);
          if(b.type === "Musket (Barnett)" || b.type.includes("Musket")){
            spawnExplosion(b.x, b.y);
          }
          bullets.splice(i, 1);
          if(e.hp <= 0) {
            e.dead = true;
            camera.shake(18, 15);
            spawnExplosion(e.x, e.y);
            Player.addXP(15);
            if(chance(Player.coinDropChance)){
              Player.coins += 10;
              addLog("Enemy dropped 10 P coins!");
            }
            enemies.splice(j, 1);
            if(enemies.length === 0){
              Player.wave++;
              Player.coins += 50;
              addLog(`Wave cleared! Earned 50 P coins.`);
              spawnWave();
              UI.buySoldierBtn.disabled = Player.coins < 100;
            }
            Player.levelUp();
          }
          break;
        }
      }
    }

    if(Player.miniSoldierAI){
      miniSoldiers.forEach(s => s.update(enemies));
    }

    enemies.forEach(e => {
      e.update(delta, Player);
      if(Player.pocketSandUnlocked) pocketSandAttack(e);
    });

    for(let i=particles.length-1; i >= 0; i--){
      particles[i].update();
      if(particles[i].isDead()) particles.splice(i, 1);
    }

    if(playerInvulnerableTimer > 0) playerInvulnerableTimer -= delta;
  }

  function draw(){
    const bgGradient = ctx.createRadialGradient(WIDTH/2, HEIGHT/2, HEIGHT/6, WIDTH/2, HEIGHT/2, HEIGHT*1.5);
    bgGradient.addColorStop(0, '#0ff9');
    bgGradient.addColorStop(1, '#001122');
    ctx.fillStyle = bgGradient;
    ctx.fillRect(0, 0, WIDTH, HEIGHT);

    ctx.save();
    ctx.shadowColor = '#0ffcc';
    ctx.shadowBlur = 36;
    ctx.strokeStyle = '#00ffaacc';
    ctx.lineWidth = 7;
    ctx.strokeRect(BOX.x - camera.x, BOX.y - camera.y, BOX.width, BOX.height);
    ctx.restore();

    const boxFloorGradient = ctx.createLinearGradient(BOX.x, BOX.y, BOX.x + BOX.width, BOX.y + BOX.height);
    boxFloorGradient.addColorStop(0, '#003333ee');
    boxFloorGradient.addColorStop(1, '#005555cc');
    ctx.fillStyle = boxFloorGradient;
    ctx.fillRect(BOX.x - camera.x, BOX.y - camera.y, BOX.width, BOX.height);

    // Draw player and other entities
    drawPlayer();
    enemies.forEach(e => e.draw(ctx, camera));
    miniSoldiers.forEach(s => s.draw(ctx, camera));
    bullets.forEach(b => b.draw(ctx, camera));
    particles.forEach(p => p.draw(ctx, camera));

    drawCrosshair(mousePos.x, mousePos.y);
    drawPlayerHealth();
    updateWeaponBar();
  }

  let playerAnimAngle = 0;
  function drawPlayer(){
    let px = Player.x - camera.x;
    let py = Player.y - camera.y;

    playerAnimAngle += 0.06;

    ctx.save();
    ctx.translate(px, py);
    ctx.rotate(Math.sin(playerAnimAngle)*0.05);

    ctx.shadowBlur = 36;
    ctx.shadowColor = '#00ffffaa';
    ctx.fillStyle = '#c74545';
    ctx.beginPath();
    ctx.ellipse(0, 12, 26, 38, 0, 0, Math.PI*2);
    ctx.fill();

    ctx.shadowBlur = 0;
    ctx.fillStyle = '#f9d9ba';
    ctx.beginPath();
    ctx.ellipse(0, -28, 20, 26, 0, 0, Math.PI*2);
    ctx.fill();

    ctx.fillStyle = '#220000';
    ctx.beginPath();
    ctx.moveTo(-28, -20);
    ctx.lineTo(0, -52);
    ctx.lineTo(28, -20);
    ctx.closePath();
    ctx.fill();

    ctx.fillStyle = '#0f0f0f';
    ctx.beginPath();
    ctx.ellipse(-8, -26, 6, 8, 0, 0, Math.PI * 2);
    ctx.ellipse(8, -26, 6, 8, 0, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = '#e5e9f0';
    ctx.beginPath();
    ctx.ellipse(-8, -25, 3.5, 4.5, 0, 0, Math.PI * 2);
    ctx.ellipse(8, -25, 3.5, 4.5, 0, 0, Math.PI * 2);
    ctx.fill();

    ctx.lineWidth = 3;
    ctx.strokeStyle = '#222';
    ctx.fillStyle = '#777';

    if(Player.weapon.includes('Musket')){
      ctx.fillRect(12, 14, 38, 11);
      if(Player.barnettAttachment){
        ctx.fillStyle = '#bfbf2a';
        ctx.beginPath();
        ctx.moveTo(46, 14);
        ctx.lineTo(56, 25);
        ctx.lineTo(42, 40);
        ctx.closePath();
        ctx.fill();
      }
      if(Player.hasScope){
        ctx.strokeStyle = '#0ff';
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(22, 10);
        ctx.lineTo(46, 10);
        ctx.stroke();
      }
    } else if(Player.weapon.includes('Flintlock')){
      ctx.fillRect(20,16,30,17);
      ctx.fillStyle = '#222';
      ctx.beginPath();
      ctx.arc(45, 22, 12, 0, Math.PI*2);
      ctx.fill();

      if(Player.hasScope){
        ctx.strokeStyle = '#0ff';
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(25, 10);
        ctx.lineTo(52, 10);
        ctx.stroke();
      }
    } else if(Player.weapon === 'Pocket Sand'){
      ctx.fillStyle = '#fff79e';
      ctx.beginPath();
      ctx.arc(42, 25, 18, 0, Math.PI*2);
      ctx.fill();
    } else {
      ctx.fillStyle = '#d15050';
      ctx.beginPath();
      ctx.arc(38, 26, 20, 0, Math.PI * 2);
      ctx.fill();
    }

    ctx.restore();
  }

  function drawCrosshair(x, y){
    ctx.save();
    ctx.strokeStyle = '#0ff';
    ctx.lineWidth = 2;
    ctx.shadowColor = '#0ff';
    ctx.shadowBlur = 7;
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI * 2);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(x - 15, y);
    ctx.lineTo(x + 15, y);
    ctx.moveTo(x, y - 15);
    ctx.lineTo(x, y + 15);
    ctx.stroke();
    ctx.restore();
  }

  function drawPlayerHealth(){
    ctx.save();
    let hpPercent = playerHealth / 100;
    let barWidth = 250;
    let barHeight = 24;
    let padding = 18;

    ctx.shadowColor = '#0ff';
    ctx.shadowBlur = 20;

    ctx.fillStyle = '#003311cc';
    ctx.fillRect(padding, HEIGHT - barHeight - padding, barWidth, barHeight);

    ctx.fillStyle = hpPercent > 0.6 ? '#22ff22bb' : hpPercent > 0.3 ? '#ffff22bb' : '#ff2222bb';
    ctx.fillRect(padding, HEIGHT - barHeight - padding, barWidth * hpPercent, barHeight);

    ctx.strokeStyle = '#0ff';
    ctx.lineWidth = 3;
    ctx.strokeRect(padding, HEIGHT - barHeight - padding, barWidth, barHeight);

    ctx.fillStyle = '#0ff';
    ctx.font = 'bold 18px monospace';
    ctx.textBaseline = "middle";
    ctx.fillText(`HP: ${Math.round(playerHealth)} / 100`, padding + 8, HEIGHT - barHeight/2 - padding);
    ctx.restore();
  }

  function updateWeaponBar(){
    UI.weaponBar.innerHTML = "";
    if(!UI.uiContainer || !UI.uiContainer.style.display || UI.uiContainer.style.display === 'none') return;
    UI.weaponBar.style.display = 'flex';
    Player.weaponOrder.forEach((w, idx) => {
      const slot = document.createElement("div");
      slot.className = "weaponSlot";
      if(idx === Player.currentWeaponIndex) slot.classList.add("active");
      slot.textContent = `${idx + 1}`;
      const tip = document.createElement("div");
      tip.className = "nameTip";
      tip.textContent = w;
      slot.appendChild(tip);
      slot.onclick = () => {
        Player.setWeapon(idx);
        addLog(`Switched weapon to: ${w}`, 'WEAPON');
        updateWeaponBar();
      };
      UI.weaponBar.appendChild(slot);
    });
  }

  // --- Game Loop Setup ---
  let lastTime = performance.now();
  let running = false;

  function loop(time){
    if(!running) return;
    let dt = time - lastTime;
    lastTime = time;

    update(dt);
    draw();

    requestAnimationFrame(loop);
  }

  function startGame(){
    Player.x = MAP_WIDTH/2;
    Player.y = MAP_HEIGHT/2;
    Player.level = 1;
    Player.xp = 0;
    Player.coins = 0;
    Player.wave = 1;
    Player.classRank = "Recruit";
    Player.weaponOrder = [];
    Player.weaponsUnlocked = {};
    Player.currentWeaponIndex = 0;
    Player.soldiers = 0;
    Player.pocketSandUnlocked = false;
    Player.barnettAttachment = false;
    Player.hasScope = false;
    Player.miniSoldierAI = false;
    playerHealth = 100;

    Player.addWeapon('Fist', 1, 'Bare hands');
    Player.setWeapon('Fist');

    enemies.length = 0;
    bullets.length = 0;
    miniSoldiers.length = 0;
    particles.length = 0;
    running = true;

    spawnWave();
    updateUI();
    updateWeaponBar();

    requestAnimationFrame(loop);
  }

  // UI events wiring
  UI.btnStart.addEventListener('click', () => {
    UI.mainMenu.classList.remove('show');
    UI.uiContainer.style.display = 'flex';
    UI.weaponBar.style.display = 'flex';
    startGame();
  });
  UI.btnUpgrades.addEventListener('click', () => {
    UI.mainMenu.classList.remove('show');
    updateUpgradeMenu();
    UI.upgradeMenu.classList.add('show');
  });
  UI.closeUpgrade.addEventListener('click', () => {
    UI.upgradeMenu.classList.remove('show');
    UI.mainMenu.classList.add('show');
  });
  UI.btnInstructions.addEventListener('click', () => {
    alert(`How to play:
- WASD to move.
- Left click to shoot.
- Press keys 1-9 to switch weapons.
- Defeat waves of enemies and earn XP, P coins.
- Open Upgrades menu from main menu to purchase upgrades and unlock weapons.
- Buy mini soldiers with P coins, upgrade your coin drop.
- Survive waves and unlock higher classes and weapons.
Have fun!`);
  });

  UI.upgradeBenchBtn.addEventListener('click', () => {
    upgradeCoinDropChance();
    updateUI();
  });
  UI.buySoldierBtn.addEventListener('click', () => {
    buyMiniSoldier();
    updateUI();
  });

  // Upgrades and weapons for upgrade menu
  const upgrades = [
    {
      id: "boost_speed", name: "Speed Boost", desc: "Increase player speed by 30%.",
      cost: 200, unlocked: false,
      apply() { Player.speedBoost = true; }
    },
    {
      id: "barnett_attachment", name: "Barnett Attachment", desc: "Barnett hook for your musket.",
      cost: 400, unlocked: false,
      apply() { Player.barnettAttachment = true; }
    },
    {
      id: "musket_scope", name: "Musket Scope", desc: "Add telescopic scope to musket.",
      cost: 750, unlocked: false,
      apply() { Player.hasScope = true; }
    },
    {
      id: "pocket_sand", name: "Pocket Sand", desc: "Blinds close enemies.",
      cost: 1500, unlocked: false,
      apply() { Player.pocketSandUnlocked = true; }
    },
    {
      id: "soldier_ai", name: "Mini Soldier AI", desc: "Summon mini soldiers to fight for you.",
      cost: 650, unlocked: false,
      apply() {
        Player.miniSoldierAI = true;
        if(miniSoldiers.length === 0) miniSoldiers.push(new MiniSoldier());
      }
    }
  ];

  const weaponUnlocks = [
    {name:'Flintlock', damage:5, cost:300, unlocked:false, desc:'Classic flintlock pistol.'},
    {name:'Musket', damage:6, cost:400, unlocked:false, desc:'Standard musket.'},
    {name:'Musket (Barnett)', damage:7, cost:700, unlocked:false, desc:'Musket with Barnett.'},
    {name:'Flintlock (Scoped)', damage:5, cost:700, unlocked:false, desc:'Flintlock with scope.'},
    {name:'Musket (Upgraded)', damage:7.7, cost:1200, unlocked:false, desc:'Upgraded musket.'},
    {name:'Flintlock (Upgraded)', damage:7, cost:1200, unlocked:false, desc:'Upgraded flintlock.'},
    {name:'Pocket Sand', damage:0, cost:2500, unlocked:false, desc:'Throw sand to blind enemies.'}
  ];

  function updateUpgradeMenu(){
    UI.upgradeItems.innerHTML = '';

    upgrades.forEach(upg => {
      const div = document.createElement('div');
      div.className = 'upgradeItem' + (upg.unlocked ? '' : ' locked');
      let txt = document.createElement('div');
      txt.className = 'text';
      txt.innerHTML = `<strong>${upg.name}</strong><span>${upg.desc}</span>`;
      div.appendChild(txt);

      if(!upg.unlocked){
        const cost = document.createElement('div');
        cost.className = 'cost';
        cost.textContent = upg.cost;
        div.appendChild(cost);
        const buybtn = document.createElement('button');
        buybtn.textContent = 'Buy';
        buybtn.onclick = () => {
          if(Player.coins >= upg.cost){
            Player.coins -= upg.cost;
            upg.unlocked = true;
            upg.apply();
            updateUI();
            addLog(`Upgrade "${upg.name}" purchased!`);
            updateUpgradeMenu();
          } else {
            addLog('Not enough P coins for '+upg.name);
          }
        };
        div.appendChild(buybtn);
      } else {
        const bought = document.createElement('div');
        bought.className = 'cost';
        bought.textContent = 'Owned';
        div.appendChild(bought);
      }

      UI.upgradeItems.appendChild(div);
    });

    weaponUnlocks.forEach(wpn => {
      const div = document.createElement('div');
      div.className = 'upgradeItem' + (wpn.unlocked ? '' : ' locked');
      let txt = document.createElement('div');
      txt.className = 'text';
      txt.innerHTML = `<strong>${wpn.name}</strong><span>${wpn.desc}</span>`;
      div.appendChild(txt);

      if(!wpn.unlocked){
        const cost = document.createElement('div');
        cost.className = 'cost';
        cost.textContent = wpn.cost;
        div.appendChild(cost);
        const buybtn = document.createElement('button');
        buybtn.textContent = 'Unlock';
        buybtn.onclick = () => {
          if(Player.coins >= wpn.cost){
            Player.coins -= wpn.cost;
            wpn.unlocked = true;
            Player.addWeapon(wpn.name, wpn.damage, wpn.desc);
            updateUI();
            addLog(`Weapon "${wpn.name}" unlocked!`);
            updateUpgradeMenu();
          } else {
            addLog('Not enough P coins for '+wpn.name);
          }
        };
        div.appendChild(buybtn);
      } else {
        const unlocked = document.createElement('div');
        unlocked.className = 'cost';
        unlocked.textContent = 'Unlocked';
        div.appendChild(unlocked);
      }

      UI.upgradeItems.appendChild(div);
    });
  }

  function updateUI(){
    UI.level.textContent = Player.level;
    UI.xp.textContent = formatXP(Player.xp);
    UI.coins.textContent = Player.coins;
    UI.wave.textContent = Player.wave;
    UI.playerClass.textContent = Player.classRank;
    UI.buySoldierBtn.disabled = Player.coins < 100;
    UI.upgradeBenchBtn.textContent = `Upgrade Coin Drop Chance (Cost: 50) - Current: ${(Player.coinDropChance*100).toFixed(1)}%`;
  }

  // Initial display setup
  UI.uiContainer.style.display = 'none';
  UI.weaponBar.style.display = 'none';

  // Show main menu on load
  UI.mainMenu.classList.add('show');

})();
</script>

</body>
</html>