fxkvpi (html, doesn't expire)
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>HYPERSTITION: SHENZHEN</title>
<style>
  * { 
    box-sizing: border-box; 
    touch-action: manipulation;
  }
  html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: #020206;
    color: #00ffcc;
    font-family: 'Courier New', 'PingFang SC', 'Microsoft YaHei', monospace;
    margin: 0;
    padding: 6px;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    user-select: none;
    -webkit-user-select: none;
  }
  
  #game-wrapper {
    position: relative;
    width: 100%;
    max-width: 380px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    justify-content: flex-start;
  }

  /* CYBERPUNK CHINESE TITLE SCREEN */
  #title-screen {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: radial-gradient(circle at center, #0e051c 0%, #020208 100%);
    border: 2px solid #ff0055;
    box-shadow: inset 0 0 30px rgba(255, 0, 85, 0.5), 0 0 20px rgba(0, 255, 204, 0.3);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 500;
    padding: 15px;
    text-align: center;
    overflow: hidden;
  }

  /* CRT Scanline Overlay Effect */
  #title-screen::before {
    content: " ";
    display: block;
    position: absolute;
    top: 0; left: 0; bottom: 0; right: 0;
    background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.35) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.05), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.05));
    z-index: 2;
    background-size: 100% 3px, 6px 100%;
    pointer-events: none;
  }

  /* Watermark Chinese Characters in Background */
  .title-bg-kanji {
    position: absolute;
    font-size: 110px;
    color: rgba(255, 0, 85, 0.05);
    font-weight: 900;
    z-index: 1;
    pointer-events: none;
    line-height: 0.9;
    letter-spacing: -5px;
  }

  .title-main-box {
    z-index: 3;
    border-top: 1.5px solid #00ffcc;
    border-bottom: 1.5px solid #00ffcc;
    padding: 12px 10px;
    width: 100%;
    background: rgba(8, 3, 18, 0.75);
    box-shadow: 0 0 15px rgba(0, 255, 204, 0.15);
  }

  .title-kanji-top {
    font-size: 13px;
    color: #ffcc00;
    letter-spacing: 5px;
    text-shadow: 0 0 8px #ffcc00;
    margin-bottom: 4px;
    font-weight: bold;
  }

  .title-glitch {
    font-size: 21px;
    font-weight: 900;
    color: #ff0055;
    text-shadow: 3px 0 #00ffcc, -2px 0 #ffcc00;
    letter-spacing: 2px;
    line-height: 1.1;
    animation: glitch 1.6s infinite alternate;
  }

  .title-sub {
    font-size: 11px;
    color: #00ffcc;
    margin-top: 6px;
    letter-spacing: 2px;
    text-shadow: 0 0 8px #00ffcc;
    font-weight: bold;
  }

  .title-tags {
    display: flex;
    gap: 6px;
    margin: 12px 0 6px 0;
    z-index: 3;
  }

  .tag-badge {
    font-size: 8px;
    background: #160829;
    border: 1px solid #ff0055;
    color: #ff0055;
    padding: 2px 6px;
    border-radius: 2px;
    letter-spacing: 1px;
  }

  .title-info {
    z-index: 3;
    font-size: 8px;
    color: #8899a6;
    margin: 10px 0 18px 0;
    line-height: 1.5;
    border-left: 2px solid #00ffcc;
    padding-left: 8px;
    text-align: left;
    background: rgba(0, 0, 0, 0.4);
    width: 100%;
  }

  .start-btn {
    z-index: 3;
    background: #ff0055;
    border: 1.5px solid #00ffcc;
    color: #020208;
    font-family: inherit;
    font-weight: 900;
    font-size: 11px;
    padding: 10px 22px;
    cursor: pointer;
    box-shadow: 0 0 15px rgba(255, 0, 85, 0.8);
    letter-spacing: 1.5px;
    animation: pulse 1.2s infinite alternate;
  }
  .start-btn:active {
    background: #00ffcc;
    color: #000;
    box-shadow: 0 0 20px #00ffcc;
  }

  /* GAME UI */
  #ui-stats {
    width: 100%;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 2px;
    font-weight: bold;
    color: #ff0055;
    font-size: 9px;
    background: #08030f;
    padding: 4px;
    border: 1px solid #ff0055;
    box-shadow: 0 0 6px rgba(255, 0, 85, 0.3);
  }
  #ui-stats div { text-align: center; white-space: nowrap; }
  
  #game-container {
    position: relative;
    width: 100%;
  }

  #map {
    background: #000;
    border: 1.5px solid #ff0055;
    box-shadow: 0 0 8px rgba(255, 0, 85, 0.25);
    padding: 2px;
    width: 100%;
    height: 250px;
    display: grid;
    grid-template-columns: repeat(22, 1fr);
    grid-template-rows: repeat(14, 1fr);
    align-items: center;
    justify-items: center;
  }

  .t {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: bold;
    line-height: 1;
  }

  /* AIMING SKILL-CHECK MODAL */
  #aim-modal {
    display: none;
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 88%;
    background: rgba(6, 2, 14, 0.95);
    border: 2px solid #00ffcc;
    box-shadow: 0 0 20px rgba(0, 255, 204, 0.6);
    padding: 10px;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    z-index: 200;
    cursor: pointer;
  }
  #aim-title {
    color: #ff0055;
    font-size: 10px;
    font-weight: bold;
    letter-spacing: 1px;
  }
  #aim-bar-container {
    width: 100%;
    height: 22px;
    background: #000;
    border: 1px solid #00ffcc;
    position: relative;
    overflow: hidden;
  }
  #aim-target-zone {
    position: absolute;
    top: 0; bottom: 0;
    background: rgba(0, 255, 204, 0.35);
    border-left: 2px solid #00ffcc;
    border-right: 2px solid #00ffcc;
  }
  #aim-cursor {
    position: absolute;
    top: 0; bottom: 0;
    width: 4px;
    background: #ff0055;
    box-shadow: 0 0 8px #ff0055, 0 0 12px #ff0055;
  }
  #aim-instruction {
    font-size: 9px;
    color: #ffcc00;
    font-weight: bold;
    letter-spacing: 1px;
  }

  #shop-modal {
    display: none;
    position: absolute;
    top: 4px; left: 4px; right: 4px; bottom: 4px;
    background: rgba(4, 2, 10, 0.98);
    border: 1.5px solid #ffcc00;
    box-shadow: 0 0 15px rgba(255, 204, 0, 0.4);
    padding: 6px;
    flex-direction: column;
    z-index: 100;
  }
  #shop-title {
    color: #ffcc00;
    font-size: 10px;
    font-weight: bold;
    text-align: center;
    border-bottom: 1px dashed #ffcc00;
    padding-bottom: 2px;
    margin-bottom: 4px;
  }
  .shop-items {
    display: flex;
    flex-direction: column;
    gap: 4px;
    overflow-y: auto;
    flex: 1;
  }
  .shop-btn {
    background: #0a0a1a;
    border: 1px solid #00ffcc;
    color: #00ffcc;
    padding: 4px 6px;
    font-size: 9px;
    font-family: inherit;
    cursor: pointer;
    text-align: left;
    display: flex;
    justify-content: space-between;
  }
  .shop-btn:active { background: #00ffcc; color: #000; }
  .close-shop {
    margin-top: 4px;
    background: #ff0055;
    color: #fff;
    border: none;
    padding: 5px;
    font-weight: bold;
    cursor: pointer;
    text-align: center;
    font-size: 10px;
  }

  #action-panel, #inventory-panel {
    width: 100%;
    display: flex;
    gap: 3px;
  }
  .action-btn, .inv-slot {
    flex: 1;
    background: #0f0a1c;
    border: 1px solid #00ffcc;
    color: #ffcc00;
    font-size: 9px;
    padding: 5px 1px;
    text-align: center;
    cursor: pointer;
    border-radius: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: bold;
  }
  .action-btn { background: #240a18; border-color: #ff0055; color: #ff0055; }
  .action-btn:active, .inv-slot:active { background: #00ffcc; color: #000; }
  
  #log {
    width: 100%;
    height: 42px;
    background: #05020c;
    border: 1px solid #222;
    color: #ffcc00;
    font-size: 9px;
    padding: 3px 5px;
    overflow-y: auto;
    line-height: 1.2;
  }

  .controls-wrapper {
    display: flex;
    justify-content: center;
    margin-top: 2px;
  }

  .controls {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
    width: 170px;
  }
  .btn {
    background: #0f0f24;
    color: #00ffcc;
    border: 1px solid #00ffcc;
    padding: 7px 0;
    font-size: 12px;
    font-weight: bold;
    text-align: center;
    border-radius: 3px;
    cursor: pointer;
  }
  .btn:active { background: #00ffcc; color: #000; }
  
  .p-player { color: #00ffcc; }
  .p-psychotic { color: #ff0055; animation: blink 0.4s infinite; }
  .e-triad { color: #ff3333; }
  .e-ministry { color: #ffcc00; }
  .e-drone { color: #ff00ff; }
  .i-vendor { color: #ffcc00; text-shadow: 0 0 5px #ffcc00; }
  .i-item { color: #00ff66; }
  .i-exit { color: #00ffcc; text-shadow: 0 0 6px #00ffcc; font-size: 12px; }
  .tile-wall { color: #3d1c3d; }
  .tile-floor { color: #160f24; }
  .fog-hidden { color: #000000; }
  .fog-explored { color: #12081c; }
  .stunned { color: #777777 !important; }

  @keyframes glitch {
    0% { transform: skew(0deg); }
    80% { transform: skew(0deg); }
    85% { transform: skew(3deg); }
    90% { transform: skew(-3deg); }
    100% { transform: skew(0deg); }
  }

  @keyframes pulse {
    0% { transform: scale(1); box-shadow: 0 0 10px rgba(255, 0, 85, 0.6); }
    100% { transform: scale(1.04); box-shadow: 0 0 20px rgba(255, 0, 85, 0.9); }
  }

  @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0.2; } 100% { opacity: 1; } }
</style>
</head>
<body>

<div id="game-wrapper">

  <!-- CHINESE CYBERPUNK TITLE SCREEN -->
  <div id="title-screen">
    <div class="title-bg-kanji">超迷信<br>深圳</div>
    
    <div class="title-main-box">
      <div class="title-kanji-top">【 超 迷 信 】</div>
      <div class="title-glitch">HYPERSTITION</div>
      <div class="title-sub">SHENZHEN // 深圳</div>
    </div>

    <div class="title-tags">
      <span class="tag-badge">加速主义</span>
      <span class="tag-badge">赛博朋克</span>
      <span class="tag-badge">特区 S-01</span>
    </div>

    <div class="title-info">
      > SYSTEM: NEURAL INTERFACE ONLINE<br>
      > LOCATION: SHENZHEN SEZ [深圳特区]<br>
      > WARNING: 人性流失 (HUMANITY DEPLETION)
    </div>

    <button class="start-btn" onclick="startGame()">[ 网络接入 // ACCESS ]</button>
  </div>

  <!-- GAME INTERFACE -->
  <div id="ui-stats">
    <div id="stat-level">ZONE: S-01</div>
    <div id="stat-hp">INT: 35</div>
    <div id="stat-ram">RAM: 4/4</div>
    <div id="stat-psyche">HUM: 100%</div>
    <div id="stat-food">CAL: 100%</div>
    <div id="stat-ammo">AMMO: 8</div>
    <div id="stat-atk">GUN: 4</div>
    <div id="stat-cred">¥50</div>
  </div>

  <div id="game-container">
    <div id="map"></div>
    
    <!-- AIMING SKILL CHECK OVERLAY -->
    <div id="aim-modal" onclick="resolveShot()">
      <div id="aim-title">=== ZIELERFASSUNG // LOCK-ON ===</div>
      <div id="aim-bar-container">
        <div id="aim-target-zone"></div>
        <div id="aim-cursor"></div>
      </div>
      <div id="aim-instruction">[F] / [SPACE] / TIPPE ZUM FEUERN</div>
    </div>

    <div id="shop-modal">
      <div id="shop-title">=== SHENZHEN TAOBAO-LOOM [¥] ===</div>
      <div class="shop-items">
        <button class="shop-btn" onclick="buyShopItem('Sheng-Stim', 35, 0)"><span>[1] Sheng-Stim (+20 Int)</span><span>¥35</span></button>
        <button class="shop-btn" onclick="buyShopItem('Synth-Baozi', 15, 0)"><span>[2] Synth-Baozi (+50% Cal)</span><span>¥15</span></button>
        <button class="shop-btn" onclick="buyShopItem('Mag-Rounds', 25, 0)"><span>[3] Kinetic-Mag (+6 Ammo)</span><span>¥25</span></button>
        <button class="shop-btn" onclick="buyShopItem('Xeno-Blade', 110, 25)"><span>[4] Xeno-Blade (+3 ATK)</span><span>¥110 (-25% H)</span></button>
        <button class="shop-btn" onclick="buyShopItem('Subdermal-Weave', 110, 25)"><span>[5] Subdermal (+15 HP)</span><span>¥110 (-25% H)</span></button>
        <button class="shop-btn" onclick="buyShopItem('Teleoplex-Chip', 110, 25)"><span>[6] Teleoplex (+2 RAM)</span><span>¥110 (-25% H)</span></button>
      </div>
      <div class="close-shop" onclick="closeShop()">TRENNEN [Ø]</div>
    </div>
  </div>

  <div id="action-panel">
    <div class="action-btn" onclick="shootNearest()">[F] KINETIK-SCHUSS</div>
    <div class="action-btn" onclick="hackEnemy()">[H] OVERLOAD</div>
  </div>

  <div id="inventory-panel">
    <div class="inv-slot" onclick="useItem(0)" id="inv-0">[1] -</div>
    <div class="inv-slot" onclick="useItem(1)" id="inv-1">[2] -</div>
    <div class="inv-slot" onclick="useItem(2)" id="inv-2">[3] -</div>
    <div class="inv-slot" onclick="useItem(3)" id="inv-3">[4] -</div>
  </div>

  <div id="log"></div>

  <div class="controls-wrapper">
    <div class="controls">
      <div></div>
      <div class="btn" onclick="handleInput(0, -1)"></div>
      <div></div>
      <div class="btn" onclick="handleInput(-1, 0)"></div>
      <div class="btn" onclick="handleInput(0, 0)">Wait</div>
      <div class="btn" onclick="handleInput(1, 0)"></div>
      <div></div>
      <div class="btn" onclick="handleInput(0, 1)"></div>
      <div></div>
    </div>
  </div>
</div>

<script>
const WIDTH = 22;
const HEIGHT = 14;
const MAX_INV = 4;
const VISIBILITY_RADIUS = 6;

let audioCtx = null;

function initAudio() {
  if (!audioCtx) {
    audioCtx = new (window.AudioContext || window.webkitAudioContext)();
  }
  if (audioCtx.state === 'suspended') {
    audioCtx.resume();
  }
}

function startGame() {
  initAudio();
  playSfx('exit');
  document.getElementById('title-screen').style.display = 'none';
}

function playSfx(type) {
  initAudio();
  if (!audioCtx) return;

  const now = audioCtx.currentTime;
  const osc = audioCtx.createOscillator();
  const gain = audioCtx.createGain();
  osc.connect(gain);
  gain.connect(audioCtx.destination);

  if (type === 'move') {
    osc.type = 'triangle';
    osc.frequency.setValueAtTime(110, now);
    osc.frequency.exponentialRampToValueAtTime(40, now + 0.04);
    gain.gain.setValueAtTime(0.04, now);
    gain.gain.exponentialRampToValueAtTime(0.001, now + 0.04);
    osc.start(now);
    osc.stop(now + 0.04);
  } else if (type === 'shoot') {
    osc.type = 'sawtooth';
    osc.frequency.setValueAtTime(700, now);
    osc.frequency.exponentialRampToValueAtTime(60, now + 0.12);
    gain.gain.setValueAtTime(0.12, now);
    gain.gain.exponentialRampToValueAtTime(0.001, now + 0.12);
    osc.start(now);
    osc.stop(now + 0.12);
  } else if (type === 'hit') {
    osc.type = 'square';
    osc.frequency.setValueAtTime(140, now);
    osc.frequency.exponentialRampToValueAtTime(30, now + 0.18);
    gain.gain.setValueAtTime(0.15, now);
    gain.gain.exponentialRampToValueAtTime(0.001, now + 0.18);
    osc.start(now);
    osc.stop(now + 0.18);
  } else if (type === 'item') {
    osc.type = 'square';
    osc.frequency.setValueAtTime(440, now);
    osc.frequency.setValueAtTime(880, now + 0.06);
    gain.gain.setValueAtTime(0.08, now);
    gain.gain.exponentialRampToValueAtTime(0.001, now + 0.18);
    osc.start(now);
    osc.stop(now + 0.18);
  } else if (type === 'buy') {
    osc.type = 'square';
    osc.frequency.setValueAtTime(523, now);
    osc.frequency.setValueAtTime(659, now + 0.06);
    osc.frequency.setValueAtTime(783, now + 0.12);
    gain.gain.setValueAtTime(0.08, now);
    gain.gain.exponentialRampToValueAtTime(0.001, now + 0.22);
    osc.start(now);
    osc.stop(now + 0.22);
  } else if (type === 'hack') {
    osc.type = 'sawtooth';
    osc.frequency.setValueAtTime(220, now);
    osc.frequency.linearRampToValueAtTime(880, now + 0.08);
    osc.frequency.linearRampToValueAtTime(330, now + 0.16);
    gain.gain.setValueAtTime(0.1, now);
    gain.gain.exponentialRampToValueAtTime(0.001, now + 0.18);
    osc.start(now);
    osc.stop(now + 0.18);
  } else if (type === 'exit') {
    // 8-Bit Chiptune Warp / Level Clear Sound
    osc.type = 'square';
    const notes = [261.63, 329.63, 392.00, 523.25, 659.25, 783.99, 1046.50];
    const step = 0.035;
    notes.forEach((freq, i) => {
      osc.frequency.setValueAtTime(freq, now + i * step);
    });
    gain.gain.setValueAtTime(0.1, now);
    gain.gain.exponentialRampToValueAtTime(0.001, now + notes.length * step);
    osc.start(now);
    osc.stop(now + notes.length * step);
  } else if (type === 'gameover') {
    osc.type = 'sawtooth';
    osc.frequency.setValueAtTime(300, now);
    osc.frequency.exponentialRampToValueAtTime(30, now + 0.5);
    gain.gain.setValueAtTime(0.2, now);
    gain.gain.exponentialRampToValueAtTime(0.001, now + 0.5);
    osc.start(now);
    osc.stop(now + 0.5);
  }
}

let player = {
  x: 0, y: 0,
  hp: 35, maxHp: 35,
  ram: 4, maxRam: 4,
  humanity: 100,
  hunger: 100,
  ammo: 8,
  atk: 4,
  creds: 50,
  level: 1,
  noise: 0,
  inventory: ['Sheng-Stim', 'Synth-Baozi']
};

let map = [];
let visibleMap = [];
let exploredMap = [];
let enemies = [];
let items = [];
let vendors = [];
let exitGate = { x: 0, y: 0 };
let turnCounter = 0;
let inShop = false;

// AIMING SKILL CHECK VARIABLES
let isAiming = false;
let aimPos = 0;
let aimDir = 1;
let aimSpeed = 2.5;
let aimAnimFrame = null;
let currentAimTargetIdx = -1;

function log(msg) {
  const logBox = document.getElementById('log');
  if (logBox) {
    logBox.innerHTML += `> ${msg}<br>`;
    logBox.scrollTop = logBox.scrollHeight;
  }
}

function initGame() {
  log("SONDERWIRTSCHAFTSZONE LÄDT... NETZWERK GENERIERT.");
  generateCitySector();
  updateVision();
  render();

  document.addEventListener('keydown', e => {
    initAudio();

    if (isAiming) {
      if (e.key === 'f' || e.key === 'F' || e.key === ' ' || e.key === 'Enter') {
        resolveShot();
      }
      return;
    }

    if (inShop) {
      if (e.key === 'Escape') closeShop();
      return;
    }

    if (e.key === 'ArrowUp' || e.key === 'w') handleInput(0, -1);
    if (e.key === 'ArrowDown' || e.key === 's') handleInput(0, 1);
    if (e.key === 'ArrowLeft' || e.key === 'a') handleInput(-1, 0);
    if (e.key === 'ArrowRight' || e.key === 'd') handleInput(1, 0);
    if (e.key === ' ') handleInput(0, 0);
    if (e.key === 'f' || e.key === 'F') shootNearest();
    if (e.key === 'h' || e.key === 'H') hackEnemy();
    if (e.key >= '1' && e.key <= '4') useItem(parseInt(e.key) - 1);
  });
}

function generateCitySector() {
  map = Array(HEIGHT).fill(null).map(() => Array(WIDTH).fill('▓'));
  exploredMap = Array(HEIGHT).fill(null).map(() => Array(WIDTH).fill(false));
  visibleMap = Array(HEIGHT).fill(null).map(() => Array(WIDTH).fill(false));
  enemies = [];
  items = [];
  vendors = [];

  let blocks = [];
  let attempts = 0;
  
  while (blocks.length < 7 && attempts < 120) {
    attempts++;
    let w = Math.floor(Math.random() * 3) + 3;
    let h = Math.floor(Math.random() * 3) + 3;
    let x = Math.floor(Math.random() * (WIDTH - w - 2)) + 1;
    let y = Math.floor(Math.random() * (HEIGHT - h - 2)) + 1;

    let overlap = blocks.some(b => !(x + w + 1 < b.x || x > b.x + b.w + 1 || y + h + 1 < b.y || y > b.y + b.h + 1));
    if (!overlap) {
      blocks.push({ x, y, w, h, center: { x: Math.floor(x + w/2), y: Math.floor(y + h/2) } });
      for (let rx = x; rx < x + w; rx++) {
        for (let ry = y; ry < y + h; ry++) map[ry][rx] = '·';
      }
    }
  }

  for (let i = 0; i < blocks.length; i++) {
    let distances = blocks
      .map((b, idx) => ({ idx, dist: Math.hypot(b.center.x - blocks[i].center.x, b.center.y - blocks[i].center.y) }))
      .filter(d => d.idx !== i)
      .sort((a, b) => a.dist - b.dist);

    let neighbors = distances.slice(0, 2);
    neighbors.forEach(n => {
      let c1 = blocks[i].center;
      let c2 = blocks[n.idx].center;
      let currX = c1.x, currY = c1.y;
      
      if (Math.random() < 0.5) {
        while (currX !== c2.x) { map[currY][currX] = '·'; currX += currX < c2.x ? 1 : -1; }
        while (currY !== c2.y) { map[currY][currX] = '·'; currY += currY < c2.y ? 1 : -1; }
      } else {
        while (currY !== c2.y) { map[currY][currX] = '·'; currY += currY < c2.y ? 1 : -1; }
        while (currX !== c2.x) { map[currY][currX] = '·'; currX += currX < c2.x ? 1 : -1; }
      }
    });
  }

  for (let k = 0; k < 3; k++) {
    let rx = Math.floor(Math.random() * (WIDTH - 6)) + 3;
    let ry = Math.floor(Math.random() * (HEIGHT - 6)) + 3;
    if (Math.random() < 0.5) {
      for (let len = 0; len < 5; len++) { if (rx + len < WIDTH - 1) map[ry][rx + len] = '·'; }
    } else {
      for (let len = 0; len < 5; len++) { if (ry + len < HEIGHT - 1) map[ry + len][rx] = '·'; }
    }
  }

  player.x = blocks[0].center.x;
  player.y = blocks[0].center.y;

  let sortedByDist = blocks.slice().sort((a, b) => {
    let dA = Math.hypot(a.center.x - player.x, a.center.y - player.y);
    let dB = Math.hypot(b.center.x - player.x, b.center.y - player.y);
    return dB - dA;
  });
  let furthestBlock = sortedByDist[0];
  exitGate = { x: furthestBlock.center.x, y: furthestBlock.center.y };

  let vendorCandidates = blocks.filter(b => b !== blocks[0] && b !== furthestBlock);
  if (vendorCandidates.length > 0) {
    let vBlock = vendorCandidates[0];
    vendors.push({ x: vBlock.center.x, y: vBlock.center.y, char: '¥' });
  } else if (blocks.length > 1) {
    vendors.push({ x: blocks[1].x + 1, y: blocks[1].y + 1, char: '¥' });
  }

  blocks.forEach((b) => {
    let rand = Math.random();
    
    let isReserved = (x, y) => (x === player.x && y === player.y) || 
                              (x === exitGate.x && y === exitGate.y) || 
                              vendors.some(v => v.x === x && v.y === y);

    let enemyX = b.x + 1;
    let enemyY = b.y + 1;
    if (!isReserved(enemyX, enemyY) && rand > 0.3) {
      let enemyType = rand < 0.6 ? 'triad' : (rand < 0.85 ? 'ministry' : 'drone');
      enemies.push({
        x: enemyX, y: enemyY,
        type: enemyType,
        char: enemyType === 'triad' ? '帮' : (enemyType === 'ministry' ? '官' : '∆'),
        hp: enemyType === 'triad' ? 10 : (enemyType === 'ministry' ? 16 : 8),
        atk: enemyType === 'triad' ? 4 : (enemyType === 'ministry' ? 7 : 8),
        range: enemyType === 'triad' ? 1.5 : (enemyType === 'ministry' ? 4 : 6),
        bounty: enemyType === 'triad' ? 25 : (enemyType === 'ministry' ? 45 : 60),
        stunned: 0
      });
    }

    let itemX = b.x + b.w - 2;
    let itemY = b.y + b.h - 2;
    if (!isReserved(itemX, itemY) && Math.random() > 0.35) {
      let itemRand = Math.random();
      let type = itemRand < 0.4 ? 'Sheng-Stim' : (itemRand < 0.7 ? 'Synth-Baozi' : 'Mag-Rounds');
      let char = type === 'Sheng-Stim' ? '生' : (type === 'Synth-Baozi' ? '包' : '⌖');
      items.push({ x: itemX, y: itemY, type, char });
    }
  });
}

function updateVision() {
  for (let y = 0; y < HEIGHT; y++) {
    for (let x = 0; x < WIDTH; x++) visibleMap[y][x] = false;
  }

  for (let angle = 0; angle < 360; angle += 5) {
    let rad = angle * (Math.PI / 180);
    let dx = Math.cos(rad);
    let dy = Math.sin(rad);
    let cx = player.x + 0.5;
    let cy = player.y + 0.5;

    for (let d = 0; d < VISIBILITY_RADIUS; d++) {
      let tileX = Math.floor(cx);
      let tileY = Math.floor(cy);

      if (tileX >= 0 && tileX < WIDTH && tileY >= 0 && tileY < HEIGHT) {
        visibleMap[tileY][tileX] = true;
        exploredMap[tileY][tileX] = true;
        if (map[tileY][tileX] === '▓') break;
      }
      cx += dx;
      cy += dy;
    }
  }
}

function handleInput(dx, dy) {
  initAudio();
  if (player.hp <= 0 || inShop || isAiming) return;

  let newX = player.x + dx;
  let newY = player.y + dy;

  if (map[newY][newX] !== '▓') {
    let enemyIdx = enemies.findIndex(e => e.x === newX && e.y === newY);
    let vendorIdx = vendors.findIndex(v => v.x === newX && v.y === newY);

    if (enemyIdx !== -1) {
      attackEnemyMelee(enemyIdx);
    } else if (vendorIdx !== -1) {
      openShop();
      return;
    } else {
      player.x = newX;
      player.y = newY;
      playSfx('move');
      checkItems();
      checkExit();
    }
    endTurn();
  }
}

function openShop() {
  inShop = true;
  playSfx('buy');
  document.getElementById('shop-modal').style.display = 'flex';
  log(`<span style="color:#ffcc00">Verbindung mit Automat [¥] hergestellt.</span>`);
}

function closeShop() {
  inShop = false;
  document.getElementById('shop-modal').style.display = 'none';
  render();
}

function buyShopItem(itemType, cost, humanityCost) {
  initAudio();
  if (player.creds < cost) {
    log(`<span style="color:#ff3333">FEHLER: Zu wenig Yuan! (¥${cost})</span>`);
    return;
  }

  playSfx('buy');

  if (humanityCost > 0) {
    player.creds -= cost;
    player.humanity = Math.max(0, player.humanity - humanityCost);

    if (itemType === 'Xeno-Blade') player.atk += 3;
    if (itemType === 'Subdermal-Weave') { player.maxHp += 15; player.hp += 15; }
    if (itemType === 'Teleoplex-Chip') { player.maxRam += 2; player.ram += 2; }

    log(`<span style="color:#ff00ff">CYBERWARE: ${itemType}. Menschlichkeit: ${player.humanity}%.</span>`);
    
    if (player.humanity <= 30) {
      log(`<span style="color:#ff0055; font-weight:bold;">HYPERSTITION: Cyber-Dämon [魔]!</span>`);
    }
  } else {
    if (itemType === 'Mag-Rounds') {
      player.creds -= cost;
      player.ammo += 6;
      log(`Magazin [⌖] erworben (+6 Ammo).`);
    } else {
      if (player.inventory.length < MAX_INV) {
        player.creds -= cost;
        player.inventory.push(itemType);
        log(`${itemType} verstaut.`);
      } else {
        log(`<span style="color:#ff3333">KAUF ABGEBROCHEN: Inventar voll!</span>`);
      }
    }
  }
  render();
}

function shootNearest() {
  initAudio();
  if (player.hp <= 0 || inShop || isAiming) return;
  if (player.ammo <= 0) {
    log(`<span style="color:#ff3333">MAGAZIN LEER!</span>`);
    return;
  }

  let targetIdx = -1;
  let minDistance = 999;

  enemies.forEach((e, idx) => {
    if (visibleMap[e.y][e.x]) {
      let dist = Math.hypot(e.x - player.x, e.y - player.y);
      if (dist < minDistance) {
        minDistance = dist;
        targetIdx = idx;
      }
    }
  });

  if (targetIdx !== -1) {
    currentAimTargetIdx = targetIdx;
    startAimMiniGame();
  } else {
    log(`Kein Ziel sichtbar.`);
  }
}

function startAimMiniGame() {
  isAiming = true;
  aimPos = 0;
  aimDir = 1;
  aimSpeed = 2.4 + Math.random() * 1.6;

  let zoneLeft = 30 + Math.floor(Math.random() * 25);
  let zoneWidth = 20;

  let targetZoneElem = document.getElementById('aim-target-zone');
  targetZoneElem.style.left = zoneLeft + '%';
  targetZoneElem.style.width = zoneWidth + '%';
  targetZoneElem.dataset.min = zoneLeft;
  targetZoneElem.dataset.max = zoneLeft + zoneWidth;

  document.getElementById('aim-modal').style.display = 'flex';
  updateAimLoop();
}

function updateAimLoop() {
  if (!isAiming) return;

  aimPos += aimSpeed * aimDir;
  if (aimPos >= 100) {
    aimPos = 100;
    aimDir = -1;
  } else if (aimPos <= 0) {
    aimPos = 0;
    aimDir = 1;
  }

  document.getElementById('aim-cursor').style.left = aimPos + '%';
  aimAnimFrame = requestAnimationFrame(updateAimLoop);
}

function resolveShot() {
  if (!isAiming) return;
  cancelAnimationFrame(aimAnimFrame);
  isAiming = false;
  document.getElementById('aim-modal').style.display = 'none';

  player.ammo--;
  player.noise += 3;

  let targetZoneElem = document.getElementById('aim-target-zone');
  let min = parseFloat(targetZoneElem.dataset.min);
  let max = parseFloat(targetZoneElem.dataset.max);
  let center = min + (max - min) / 2;

  let e = enemies[currentAimTargetIdx];

  if (!e) {
    endTurn();
    return;
  }

  if (aimPos >= min && aimPos <= max) {
    let isCrit = Math.abs(aimPos - center) <= 3.5;
    let bonusAtk = player.humanity <= 30 ? 6 : 0;
    let dmg = player.atk + bonusAtk + Math.floor(Math.random() * 4);
    if (isCrit) dmg = Math.floor(dmg * 1.6) + 4;

    playSfx('shoot');
    if (isCrit) {
      log(`<span style="color:#ffcc00; font-weight:bold;">CRITICAL LOCK! [${e.char}] kritisch getroffen für ${dmg} DMG!</span>`);
    } else {
      log(`<span style="color:#00ffcc">TREFFER! Schuss auf [${e.char}] für ${dmg} DMG!</span>`);
    }

    e.hp -= dmg;
    if (e.hp <= 0) {
      player.creds += e.bounty;
      log(`<span style="color:#00ffcc">[${e.char}] eliminiert! +¥${e.bounty}.</span>`);
      enemies.splice(currentAimTargetIdx, 1);
    }
  } else {
    playSfx('hit');
    log(`<span style="color:#ff0055">FEHLSCHUSS! Zielverfehlung (${Math.round(aimPos)}%).</span>`);
  }

  endTurn();
}

function hackEnemy() {
  initAudio();
  if (player.ram < 2 || inShop || isAiming) {
    log(`<span style="color:#ff3333">RAM ZU NIEDRIG! (2 K-RAM nötig)</span>`);
    return;
  }

  let targetIdx = -1;
  let minDistance = 999;

  enemies.forEach((e, idx) => {
    if (visibleMap[e.y][e.x] && e.stunned === 0) {
      let dist = Math.hypot(e.x - player.x, e.y - player.y);
      if (dist < minDistance) {
        minDistance = dist;
        targetIdx = idx;
      }
    }
  });

  if (targetIdx !== -1) {
    playSfx('hack');
    player.ram -= 2;
    let e = enemies[targetIdx];
    e.stunned = 3;
    log(`<span style="color:#ff00ff">OVERCLOCK auf [${e.char}]! 3 Züge gelähmt.</span>`);
    endTurn();
  } else {
    log(`Kein erfassbares Ziel.`);
  }
}

function attackEnemyMelee(idx) {
  playSfx('hit');
  let e = enemies[idx];
  let bonusAtk = player.humanity <= 30 ? 5 : 0;
  let dmg = Math.floor(player.atk * 0.7) + bonusAtk;
  e.hp -= dmg;
  log(`Nahkampf auf [${e.char}] für ${dmg} DMG.`);
  if (e.hp <= 0) {
    player.creds += e.bounty;
    log(`<span style="color:#00ffcc">[${e.char}] eliminiert! +¥${e.bounty}.</span>`);
    enemies.splice(idx, 1);
  }
}

function useItem(slot) {
  initAudio();
  if (player.hp <= 0 || slot >= player.inventory.length || inShop || isAiming) return;

  playSfx('item');
  let item = player.inventory[slot];
  if (item === 'Sheng-Stim') {
    player.hp = Math.min(player.maxHp, player.hp + 20);
    log(`<span style="color:#00ffcc">Sheng-Stim [生] (+20 HP).</span>`);
  } else if (item === 'Synth-Baozi') {
    player.hunger = Math.min(100, player.hunger + 50);
    player.hp = Math.min(player.maxHp, player.hp + 5);
    log(`<span style="color:#00ffcc">Synth-Baozi [包] (+50% Cal).</span>`);
  }

  player.inventory.splice(slot, 1);
  endTurn();
}

function checkItems() {
  let idx = items.findIndex(i => i.x === player.x && i.y === player.y);
  if (idx !== -1) {
    let item = items[idx];
    playSfx('item');
    if (item.type === 'Mag-Rounds') {
      player.ammo += 5;
      log(`Magazin [⌖] aufgesammelt (+5).`);
      items.splice(idx, 1);
    } else {
      if (player.inventory.length < MAX_INV) {
        player.inventory.push(item.type);
        log(`${item.type} [${item.char}] aufgesammelt.`);
        items.splice(idx, 1);
      } else {
        log(`<span style="color:#ff0055">Inventar voll für ${item.type}.</span>`);
      }
    }
  }
}

function checkExit() {
  if (player.x === exitGate.x && player.y === exitGate.y) {
    playSfx('exit');
    player.level++;
    log(`<span style="color:#00ffcc">ACCELERATING... Betrete Zone S-0${player.level} [门].</span>`);
    generateCitySector();
  }
}

function endTurn() {
  turnCounter++;
  updateVision();

  if (turnCounter % 3 === 0 && player.ram < player.maxRam) player.ram++;

  if (player.humanity <= 30 && Math.random() < 0.25) {
    let psychosisEffect = Math.random();
    if (psychosisEffect < 0.5) {
      player.hp -= 2;
      playSfx('hit');
      log(`<span style="color:#ff0055; font-weight:bold;">HYPERSTITION! (-2 HP).</span>`);
    } else {
      player.noise += 5;
      log(`<span style="color:#ff0055; font-weight:bold;">TIME-LOOP-PULSE!</span>`);
    }
  }

  if (player.noise > 0) player.noise--;

  if (turnCounter % 5 === 0 && player.hunger > 0) player.hunger--;
  if (player.hunger <= 0) {
    player.hp--;
    playSfx('hit');
    log(`<span style="color:#ff0055">METABOLISCHER KOLLAPS! -1 HP.</span>`);
  }

  enemies.forEach(e => {
    if (e.stunned > 0) {
      e.stunned--;
      return;
    }

    let isVisible = visibleMap[e.y][e.x];
    let dist = Math.hypot(e.x - player.x, e.y - player.y);

    if (isVisible || dist < player.noise) {
      if (dist <= e.range) {
        let dmg = Math.max(1, e.atk - Math.floor(Math.random() * 2));
        player.hp -= dmg;
        playSfx('hit');
        log(`<span style="color:#ff0055">[${e.char}] trifft dich für ${dmg} DMG!</span>`);
      } else {
        let dx = Math.sign(player.x - e.x);
        let dy = Math.sign(player.y - e.y);
        if (map[e.y + dy][e.x + dx] !== '▓' && !enemies.some(o => o.x === e.x + dx && o.y === e.y + dy)) {
          e.x += dx;
          e.y += dy;
        }
      }
    }
  });

  if (player.hp <= 0) {
    playSfx('gameover');
    log(`<span style="color:#ff0000; font-weight:bold;">FLATLINE: Vom Kapital vollständig reabsorbiert. Game Over.</span>`);
  }

  render();
}

function render() {
  document.getElementById('stat-level').innerText = `ZONE: S-0${player.level}`;
  document.getElementById('stat-hp').innerText = `INT: ${player.hp}/${player.maxHp}`;
  document.getElementById('stat-ram').innerText = `RAM: ${player.ram}/${player.maxRam}`;
  document.getElementById('stat-psyche').innerText = `HUM: ${player.humanity}%`;
  document.getElementById('stat-food').innerText = `CAL: ${player.hunger}%`;
  document.getElementById('stat-ammo').innerText = `AMMO: ${player.ammo}`;
  document.getElementById('stat-atk').innerText = `GUN: ${player.atk}`;
  document.getElementById('stat-cred').innerText = ${player.creds}`;

  for (let i = 0; i < MAX_INV; i++) {
    let slot = document.getElementById(`inv-${i}`);
    let name = player.inventory[i] || 'Leer';
    let icon = name === 'Sheng-Stim' ? '[生]' : (name === 'Synth-Baozi' ? '[包]' : (name === 'Mag-Rounds' ? '[⌖]' : ''));
    slot.innerText = `[${i+1}] ${name} ${icon}`;
  }

  let htmlMap = '';
  for (let y = 0; y < HEIGHT; y++) {
    for (let x = 0; x < WIDTH; x++) {
      let isVisible = visibleMap[y][x];
      let isExplored = exploredMap[y][x];

      if (!isExplored) {
        htmlMap += '<div class="t fog-hidden"></div>';
        continue;
      }

      if (x === player.x && y === player.y) {
        let pClass = player.humanity <= 30 ? 'p-psychotic' : 'p-player';
        let pChar = player.humanity <= 30 ? '魔' : '@';
        htmlMap += `<div class="t ${pClass}">${pChar}</div>`;
      } else if (x === exitGate.x && y === exitGate.y) {
        htmlMap += '<div class="t i-exit">门</div>';
      } else {
        let enemy = enemies.find(e => e.x === x && e.y === y);
        let item = items.find(i => i.x === x && i.y === y);
        let vendor = vendors.find(v => v.x === x && v.y === y);

        if (isVisible && enemy) {
          let cssClass = enemy.type === 'triad' ? 'e-triad' : (enemy.type === 'ministry' ? 'e-ministry' : 'e-drone');
          if (enemy.stunned > 0) cssClass += ' stunned';
          htmlMap += `<div class="t ${cssClass}">${enemy.char}</div>`;
        } else if (isVisible && vendor) {
          htmlMap += `<div class="t i-vendor">${vendor.char}</div>`;
        } else if (isVisible && item) {
          htmlMap += `<div class="t i-item">${item.char}</div>`;
        } else {
          let char = map[y][x];
          let cssClass = isVisible ? (char === '▓' ? 'tile-wall' : 'tile-floor') : 'fog-explored';
          htmlMap += `<div class="t ${cssClass}">${char}</div>`;
        }
      }
    }
  }
  document.getElementById('map').innerHTML = htmlMap;
}

initGame();
</script>
</body>
</html>