{"id":27,"date":"2026-05-27T13:06:38","date_gmt":"2026-05-27T10:06:38","guid":{"rendered":"https:\/\/urasuzay.com\/?page_id=27"},"modified":"2026-08-17T22:09:19","modified_gmt":"2026-08-17T19:09:19","slug":"korku-evi-2","status":"publish","type":"page","link":"https:\/\/urasuzay.com\/index.php\/korku-evi-2\/","title":{"rendered":"korku evi"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"27\" class=\"elementor elementor-27\">\n\t\t\t\t<div class=\"elementor-element elementor-element-197a507 e-con e-atomic-element e-flexbox-base \" data-id=\"197a507\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"197a507\">\n    \t\t\t<p class=\"e-6bd3e31-a476f7a e-paragraph-base\" data-interaction-id=\"6bd3e31\"><a href=\"https:\/\/urasuzay.com\/\" target=\"_self\" class=\"e-paragraph-link-base\">\n\t\tAna Sayfa\n\t<\/a><\/p>\n\t\t\n<\/div>\n<div class=\"elementor-element elementor-element-e7c3e5d e-flex e-con-boxed e-con e-parent\" data-id=\"e7c3e5d\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-507312a elementor-widget elementor-widget-html\" data-id=\"507312a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"tr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n<title>Backrooms Labirent - Uras Uzay<\/title>\n<style>\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Share+Tech+Mono&family=Roboto:wght@300;400;700&display=swap');\n*{margin:0;padding:0;box-sizing:border-box;user-select:none}\nbody{background:#000;overflow:hidden;font-family:'Roboto',sans-serif;color:#ddd;cursor:none}\n#game-container{position:relative;width:100vw;height:100vh;background:#000}\ncanvas{display:block;width:100%;height:100%}\n\n\/* Film grain overlay *\/\n#grain{position:absolute;inset:0;pointer-events:none;z-index:70;opacity:.12;mix-blend-mode:overlay;\nbackground-image:url(\"data:image\/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http:\/\/www.w3.org\/2000\/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'\/%3E%3C\/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'\/%3E%3C\/svg%3E\");\nanimation:grainShift .4s steps(2) infinite}\n@keyframes grainShift{0%{transform:translate(0,0)}100%{transform:translate(-2%,1%)}}\n\n\/* Chromatic aberration edge *\/\n#chroma{position:absolute;inset:0;pointer-events:none;z-index:71;opacity:.15;\nbackground:linear-gradient(90deg,rgba(255,0,0,.08),transparent 8%,transparent 92%,rgba(0,100,255,.08))}\n\n#main-menu{position:absolute;inset:0;background:radial-gradient(ellipse at center,#1a1810 0%,#0a0908 60%,#000 100%);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:1000;transition:opacity 1.2s}\n#main-menu.hidden{opacity:0;pointer-events:none}\n.menu-title{font-family:'Share Tech Mono',monospace;font-size:clamp(1.8rem,5vw,3.2rem);color:#c8b060;text-shadow:0 0 20px rgba(200,176,96,.4);letter-spacing:6px;margin-bottom:6px}\n.menu-sub{font-family:'Share Tech Mono',monospace;font-size:.85rem;color:#666;margin-bottom:36px;letter-spacing:3px}\n.menu-btn{background:transparent;border:1px solid #6a5a30;color:#bbb;font-family:'Share Tech Mono',monospace;font-size:1rem;padding:12px 40px;margin:8px;cursor:pointer;transition:all .3s;letter-spacing:2px}\n.menu-btn:hover{background:rgba(200,176,96,.12);border-color:#c8b060;color:#eee;box-shadow:0 0 20px rgba(200,176,96,.2)}\n\n#hud{position:absolute;inset:0;pointer-events:none;z-index:100;display:none}\n#hud.visible{display:block}\n.hud-top{position:absolute;top:12px;left:12px;right:12px;display:flex;justify-content:space-between}\n.stat-box{background:rgba(10,10,8,.85);border:1px solid #3a3520;padding:6px 11px;font-family:'Share Tech Mono',monospace;font-size:.78rem;min-width:105px;margin-bottom:4px}\n.stat-label{color:#666;font-size:.58rem;letter-spacing:1px}\n.stat-value{color:#ccc;font-size:.9rem}\n.stat-bar{width:100%;height:3px;background:#222;margin-top:3px;overflow:hidden}\n.stat-bar-fill{height:100%;transition:width .2s}\n.health-fill{background:#8b3030}.battery-fill{background:#4a8b30}.sanity-fill{background:#6a4a8b}.stamina-fill{background:#8b7a30}\n#objective{position:absolute;top:12px;left:50%;transform:translateX(-50%);background:rgba(10,10,8,.88);border:1px solid #3a3520;padding:8px 18px;font-family:'Share Tech Mono',monospace;font-size:.82rem;color:#aaa;text-align:center;max-width:420px}\n#objective .obj-title{color:#c8b060;font-size:.58rem;letter-spacing:2px;margin-bottom:2px}\n#crosshair{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:16px;height:16px}\n#crosshair::before,#crosshair::after{content:'';position:absolute;background:rgba(200,180,100,.35)}\n#crosshair::before{width:1px;height:100%;left:50%;transform:translateX(-50%)}\n#crosshair::after{height:1px;width:100%;top:50%;transform:translateY(-50%)}\n#interact-prompt{position:absolute;bottom:95px;left:50%;transform:translateX(-50%);background:rgba(10,10,8,.9);border:1px solid #4a4030;padding:7px 16px;font-family:'Share Tech Mono',monospace;font-size:.85rem;color:#ccc;opacity:0;transition:opacity .25s}\n#interact-prompt.visible{opacity:1}\n#interact-prompt kbd{background:#2a2820;padding:1px 5px;border:1px solid #4a4030;margin-right:4px;color:#c8b060}\n#inventory-bar{position:absolute;bottom:12px;left:50%;transform:translateX(-50%);display:flex;gap:5px}\n.inv-slot{width:46px;height:46px;background:rgba(10,10,8,.85);border:1px solid #3a3520;display:flex;align-items:center;justify-content:center;font-size:1.2rem;position:relative}\n.inv-slot.selected{border-color:#c8b060;box-shadow:0 0 10px rgba(200,176,96,.3)}\n.inv-slot .slot-key{position:absolute;bottom:1px;right:2px;font-size:.48rem;color:#555;font-family:'Share Tech Mono',monospace}\n#note-viewer{position:absolute;inset:0;background:rgba(0,0,0,.92);display:none;align-items:center;justify-content:center;z-index:200;pointer-events:auto}\n#note-viewer.visible{display:flex}\n.note-paper{background:#1a1810;border:1px solid #4a4030;width:min(90vw,440px);max-height:74vh;padding:30px;font-family:'Courier New',monospace;color:#c0b080;line-height:1.55;overflow-y:auto;position:relative}\n.note-paper h3{color:#c8b060;margin-bottom:12px;font-size:1rem;border-bottom:1px solid #3a3520;padding-bottom:6px}\n.note-paper p{margin-bottom:10px;font-size:.86rem}\n.note-close{position:absolute;top:8px;right:12px;background:none;border:none;color:#665;font-size:1.3rem;cursor:pointer}\n#story-text{position:absolute;bottom:85px;left:50%;transform:translateX(-50%);width:min(90vw,600px);background:rgba(10,10,8,.92);border-left:2px solid #c8b060;padding:14px 20px;font-size:.92rem;line-height:1.45;color:#ccc;opacity:0;transition:opacity .4s;pointer-events:none;z-index:150}\n#story-text.visible{opacity:1}\n#overlay-screen{position:absolute;inset:0;background:#000;display:none;flex-direction:column;align-items:center;justify-content:center;z-index:500}\n#overlay-screen.visible{display:flex}\n.overlay-title{font-family:'Share Tech Mono',monospace;font-size:2.4rem;color:#c8b060;letter-spacing:4px;margin-bottom:14px}\n.overlay-msg{font-family:'Share Tech Mono',monospace;color:#666;margin-bottom:28px;font-size:.9rem;text-align:center;max-width:400px;line-height:1.5}\n#loading{position:absolute;inset:0;background:#0a0908;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:2000}\n#loading.hidden{opacity:0;pointer-events:none;transition:opacity .9s}\n.loader-bar{width:240px;height:3px;background:#222;margin-top:20px;overflow:hidden}\n.loader-fill{height:100%;width:0%;background:#c8b060;transition:width .25s}\n#vignette{position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at center,transparent 18%,rgba(0,0,0,.82) 100%);z-index:50;opacity:.9}\n#blood-overlay{position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at center,transparent 28%,rgba(80,10,10,.5) 100%);z-index:51;opacity:0;transition:opacity .35s}\n#sanity-overlay{position:absolute;inset:0;pointer-events:none;background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(80,60,20,.03) 2px,rgba(80,60,20,.03) 4px);z-index:52;opacity:0;transition:opacity .8s}\n#pause-menu{position:absolute;inset:0;background:rgba(0,0,0,.94);display:none;flex-direction:column;align-items:center;justify-content:center;z-index:300;pointer-events:auto}\n#pause-menu.visible{display:flex}\n#controls-hint{position:absolute;bottom:20px;right:20px;background:rgba(10,10,8,.8);padding:9px 12px;font-family:'Share Tech Mono',monospace;font-size:.62rem;color:#555;line-height:1.6;border:1px solid #2a2820}\n#controls-hint kbd{background:#1a1810;padding:1px 4px;border:1px solid #3a3520;color:#888;margin-right:2px}\n#jumpscare{position:absolute;inset:0;background:#0a0800;opacity:0;pointer-events:none;z-index:400;display:flex;align-items:center;justify-content:center;transition:opacity .03s}\n#jumpscare.active{opacity:1}\n.js-face{font-size:15rem;filter:contrast(1.8) sepia(.3);animation:jsShake .08s infinite}\n@keyframes jsShake{0%{transform:translate(0,0) scale(1)}25%{transform:translate(-18px,14px) scale(1.14)}50%{transform:translate(16px,-12px) scale(1.2)}75%{transform:translate(-14px,16px) scale(1.1)}100%{transform:translate(0,0) scale(1)}}\n#scanlines{position:absolute;inset:0;pointer-events:none;background:repeating-linear-gradient(0deg,transparent,transparent 1px,rgba(0,0,0,.15) 1px,rgba(0,0,0,.15) 2px);z-index:60;opacity:.4}\n#lore-counter{position:absolute;top:70px;right:12px;background:rgba(10,10,8,.85);border:1px solid #3a3520;padding:5px 9px;font-family:'Share Tech Mono',monospace;font-size:.68rem;color:#777}\n#safe-indicator{position:absolute;top:70px;left:12px;background:rgba(10,10,8,.85);border:1px solid #3a3520;padding:5px 9px;font-family:'Share Tech Mono',monospace;font-size:.68rem;color:#666}\n#safe-indicator.safe{color:#8c8;border-color:#2a4a2a}\n#settings-panel{display:none;flex-direction:column;gap:11px;background:rgba(15,14,10,.97);border:1px solid #4a4030;padding:22px 30px;max-width:350px}\n#settings-panel.visible{display:flex}\n.setting-row{display:flex;justify-content:space-between;align-items:center;gap:12px;font-family:'Share Tech Mono',monospace;font-size:.8rem}\n.setting-row label{color:#999}\n.setting-row input[type=range]{width:125px;accent-color:#c8b060}\n#monster-scream-flash{position:absolute;inset:0;background:rgba(40,30,0,.35);opacity:0;pointer-events:none;z-index:53;transition:opacity .08s}\n#info-box{position:absolute;bottom:75px;left:12px;background:rgba(10,10,8,.85);border:1px solid #2a4a2a;padding:7px 11px;font-family:'Share Tech Mono',monospace;font-size:.65rem;color:#6a8a6a;max-width:190px;line-height:1.35;display:none}\n#info-box.visible{display:block}\n#exit-compass{position:absolute;top:100px;left:50%;transform:translateX(-50%);display:none;flex-direction:column;align-items:center;z-index:110;pointer-events:none}\n#exit-compass.visible{display:flex}\n#exit-arrow{width:0;height:0;border-left:10px solid transparent;border-right:10px solid transparent;border-bottom:18px solid #44ff66;filter:drop-shadow(0 0 6px #44ff66);transition:transform .15s linear}\n#exit-compass-label{font-family:'Share Tech Mono',monospace;font-size:.7rem;color:#6f6;margin-top:4px;text-shadow:0 0 8px #2a4}\n#exit-dist{font-family:'Share Tech Mono',monospace;font-size:.65rem;color:#8a8}\n<\/style>\n<\/head>\n<body>\n<div id=\"game-container\">\n  <div id=\"loading\">\n    <div class=\"menu-title\" style=\"font-size:1.6rem\">BACKROOMS<\/div>\n    <div style=\"color:#555;margin-top:8px;font-family:'Share Tech Mono',monospace;font-size:.8rem\">Seviye y\u00fckleniyor...<\/div>\n    <div class=\"loader-bar\"><div class=\"loader-fill\" id=\"loader-fill\"><\/div><\/div>\n    <div id=\"load-status\" style=\"color:#444;margin-top:10px;font-size:.7rem;font-family:'Share Tech Mono',monospace\">Ba\u015flat\u0131l\u0131yor<\/div>\n  <\/div>\n  <div id=\"main-menu\">\n    <div class=\"menu-title\">BACKROOMS<\/div>\n    <div class=\"menu-sub\">TERK ED\u0130LM\u0130\u015e KOR\u0130DORLAR \u2022 URAS UZAY<\/div>\n    <button class=\"menu-btn\" id=\"btn-start\">OYUNA BA\u015eLA<\/button>\n    <button class=\"menu-btn\" id=\"btn-settings\">AYARLAR<\/button>\n    <button class=\"menu-btn\" id=\"btn-controls\">KONTROLLER<\/button>\n    <div id=\"settings-panel\">\n      <div class=\"setting-row\"><label>Fare<\/label><input type=\"range\" id=\"sens-slider\" min=\"0.5\" max=\"3\" step=\"0.1\" value=\"1.25\"><\/div>\n      <div class=\"setting-row\"><label>Ses<\/label><input type=\"range\" id=\"vol-slider\" min=\"0\" max=\"1\" step=\"0.05\" value=\"0.85\"><\/div>\n      <div class=\"setting-row\"><label>Jumpscare<\/label><input type=\"range\" id=\"js-vol-slider\" min=\"0.3\" max=\"1\" step=\"0.05\" value=\"1\"><\/div>\n      <button class=\"menu-btn\" id=\"btn-settings-back\" style=\"margin-top:10px\">GER\u0130<\/button>\n    <\/div>\n    <div style=\"position:absolute;bottom:18px;color:#333;font-size:.65rem;font-family:'Share Tech Mono',monospace\">urasuzay.com \u2022 G\u00fcvenli oda \u2022 K\u0131rp\u0131\u015fan lambalar<\/div>\n  <\/div>\n  <div id=\"hud\">\n    <div class=\"hud-top\">\n      <div>\n        <div class=\"stat-box\"><div class=\"stat-label\">CAN<\/div><div class=\"stat-value\" id=\"health-text\">100<\/div><div class=\"stat-bar\"><div class=\"stat-bar-fill health-fill\" id=\"health-bar\" style=\"width:100%\"><\/div><\/div><\/div>\n        <div class=\"stat-box\"><div class=\"stat-label\">FENER<\/div><div class=\"stat-value\" id=\"battery-text\">100%<\/div><div class=\"stat-bar\"><div class=\"stat-bar-fill battery-fill\" id=\"battery-bar\" style=\"width:100%\"><\/div><\/div><\/div>\n        <div class=\"stat-box\"><div class=\"stat-label\">AKIL<\/div><div class=\"stat-value\" id=\"sanity-text\">100<\/div><div class=\"stat-bar\"><div class=\"stat-bar-fill sanity-fill\" id=\"sanity-bar\" style=\"width:100%\"><\/div><\/div><\/div>\n      <\/div>\n      <div><div class=\"stat-box\"><div class=\"stat-label\">DAYANIKLILIK<\/div><div class=\"stat-value\" id=\"stamina-text\">100<\/div><div class=\"stat-bar\"><div class=\"stat-bar-fill stamina-fill\" id=\"stamina-bar\" style=\"width:100%\"><\/div><\/div><\/div><\/div>\n    <\/div>\n    <div id=\"objective\"><div class=\"obj-title\">G\u00d6REV<\/div><div id=\"objective-text\">\u00c7\u0131k\u0131\u015f kart\u0131n\u0131 bul. G\u00fcvenli odaya s\u0131\u011f\u0131nabilirsin.<\/div><\/div>\n    <div id=\"lore-counter\">Kay\u0131t: <span id=\"lore-count\">0<\/span>\/6<\/div>\n    <div id=\"safe-indicator\">B\u00f6lge: <span id=\"safe-text\">Koridor<\/span><\/div>\n    <div id=\"crosshair\"><\/div>\n    <div id=\"interact-prompt\"><kbd>E<\/kbd> Etkile\u015fim<\/div>\n    <div id=\"inventory-bar\">\n      <div class=\"inv-slot\" data-slot=\"0\"><span class=\"slot-key\">1<\/span><\/div>\n      <div class=\"inv-slot\" data-slot=\"1\"><span class=\"slot-key\">2<\/span><\/div>\n      <div class=\"inv-slot\" data-slot=\"2\"><span class=\"slot-key\">3<\/span><\/div>\n      <div class=\"inv-slot\" data-slot=\"3\"><span class=\"slot-key\">4<\/span><\/div>\n      <div class=\"inv-slot\" data-slot=\"4\"><span class=\"slot-key\">5<\/span><\/div>\n    <\/div>\n    <div id=\"controls-hint\"><kbd>WASD<\/kbd> Hareket<br><kbd>SHIFT<\/kbd> Ko\u015f<br><kbd>F<\/kbd> Fener<br><kbd>E<\/kbd> Etkile\u015fim<br><kbd>C<\/kbd> E\u011fil<br><kbd>ESC<\/kbd> Duraklat<\/div>\n    <div id=\"info-box\">G\u00dcVENL\u0130 ODA \u2014 Pe\u015findeki varl\u0131klar yok olur, uzaklarda yeniden belirir.<\/div>\n    <div id=\"exit-compass\">\n      <div id=\"exit-arrow\"><\/div>\n      <div id=\"exit-compass-label\">\u00c7IKI\u015e<\/div>\n      <div id=\"exit-dist\">\u2014<\/div>\n    <\/div>\n  <\/div>\n  <div id=\"story-text\"><\/div>\n  <div id=\"note-viewer\"><div class=\"note-paper\"><button class=\"note-close\" id=\"note-close\">\u00d7<\/button><h3 id=\"note-title\">Kay\u0131t<\/h3><div id=\"note-body\"><\/div><\/div><\/div>\n  <div id=\"pause-menu\">\n    <div class=\"menu-title\" style=\"font-size:1.8rem\">DURAKLATILDI<\/div>\n    <button class=\"menu-btn\" id=\"btn-resume\">DEVAM<\/button>\n    <button class=\"menu-btn\" id=\"btn-restart\">YEN\u0130DEN<\/button>\n    <button class=\"menu-btn\" id=\"btn-mainmenu\">MEN\u00dc<\/button>\n  <\/div>\n  <div id=\"overlay-screen\">\n    <div class=\"overlay-title\" id=\"overlay-title\">KAYBOLDUN<\/div>\n    <div class=\"overlay-msg\" id=\"overlay-msg\">Backrooms seni yuttu.<\/div>\n    <button class=\"menu-btn\" id=\"btn-retry\">TEKRAR<\/button>\n    <button class=\"menu-btn\" id=\"btn-to-menu\">MEN\u00dc<\/button>\n  <\/div>\n  <div id=\"vignette\"><\/div>\n  <div id=\"blood-overlay\"><\/div>\n  <div id=\"sanity-overlay\"><\/div>\n  <div id=\"scanlines\"><\/div>\n  <div id=\"grain\"><\/div>\n  <div id=\"chroma\"><\/div>\n  <div id=\"monster-scream-flash\"><\/div>\n  <div id=\"jumpscare\"><div class=\"js-face\">\ud83d\udc41<\/div><\/div>\n<\/div>\n\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r128\/three.min.js\"><\/script>\n<script>\n\/**\n * BACKROOMS LAB\u0130RENT \u2014 Terk edilmi\u015f hastane \/ ofis koridorlar\u0131\n * Mod\u00fcler par\u00e7alar, k\u0131rp\u0131\u015fan floresan, g\u00fcvenli oda, dar FOV\n * urasuzay.com\n *\/\n(function(){\n'use strict';\n\nconst CONFIG = {\n  PLAYER_SPEED: 4.0, PLAYER_RUN_SPEED: 7.0, PLAYER_CROUCH_SPEED: 1.9,\n  PLAYER_HEIGHT: 1.65, PLAYER_CROUCH_HEIGHT: 0.95, PLAYER_RADIUS: 0.3,\n  JUMP_FORCE: 6.8, GRAVITY: 22, MOUSE_SENSITIVITY: 1.25,\n  FLASHLIGHT_RANGE: 12, FLASHLIGHT_ANGLE: 0.4,\n  BATTERY_DRAIN: 0.45, SANITY_DRAIN_DARK: 1.6, SANITY_DRAIN_NEAR: 7,\n  SANITY_REGEN: 3.2, STAMINA_DRAIN: 14, STAMINA_REGEN: 12,\n  MONSTER_SPEED: 2.9, MONSTER_CHASE_SPEED: 5.0, MONSTER_DETECT: 12,\n  MONSTER_ATTACK: 1.9, MONSTER_MIN_DIST: 1.4, MONSTER_HEAR: 10,\n  MONSTER_LOSE: 4.5, MONSTER_ATTACK_COOLDOWN: 3.2,\n  MONSTER_TELEPORT_AFTER_ATTACK: 0.7, \/\/ %70 sald\u0131r\u0131 sonras\u0131 \u0131\u015f\u0131nlan\n  SAFE_RADIUS: 3.8,\n  INTERACT_RANGE: 2.4,\n  FOV: 58,\n  GUN_DAMAGE: 40, GUN_RANGE: 14, GUN_COOLDOWN: 0.45\n};\n\n\/\/ Prosed\u00fcrel labirent (DFS) \u2014 her y\u00fcklemede farkl\u0131\nconst CELL = 3.4;\nlet MAZE = [], MW = 23, MH = 23;\nlet OX = 0, OZ = 0;\nlet spawnCell = {gx:11,gz:12};\nlet phantoms = []; \/\/ hall\u00fcsinasyon g\u00f6lgeleri\nlet radioGainNode = null, radioFilter = null, radioOsc = null;\nlet lastPhantomTime = 0, lastReverseFoot = 0;\n\nfunction generateMaze(w, h){\n  \/\/ Tek say\u0131 boyut (duvar-koridor deseni)\n  w = w|1; h = h|1;\n  const maze = Array.from({length:h}, ()=>Array(w).fill(1));\n  const dirs = [[0,2],[0,-2],[2,0],[-2,0]];\n  function shuffle(a){ for(let i=a.length-1;i>0;i--){ const j=Math.floor(Math.random()*(i+1)); [a[i],a[j]]=[a[j],a[i]]; } return a; }\n  function carve(x,y){\n    maze[y][x]=0;\n    for(const [dx,dy] of shuffle(dirs.slice())){\n      const nx=x+dx, ny=y+dy;\n      if(nx>0&&ny>0&&nx<w-1&&ny<h-1&&maze[ny][nx]===1){\n        maze[y+dy\/2][x+dx\/2]=0;\n        carve(nx,ny);\n      }\n    }\n  }\n  carve(1,1);\n  \/\/ Merkez g\u00fcvenli oda 3x3\n  const cx=Math.floor(w\/2), cy=Math.floor(h\/2);\n  for(let dy=-1;dy<=1;dy++) for(let dx=-1;dx<=1;dx++){\n    const x=cx+dx, y=cy+dy;\n    if(x>0&&y>0&&x<w-1&&y<h-1) maze[y][x]=2;\n  }\n  \/\/ G\u00fcvenli odaya koridor ba\u011fla\n  for(let y=cy;y>=1;y--){ if(maze[y][cx]===1) maze[y][cx]=0; if(maze[y][cx]===2) break; }\n  for(let y=cy;y<h-1;y++){ if(maze[y][cx]===1) maze[y][cx]=0; if(maze[y][cx]===2) break; }\n  \/\/ Birka\u00e7 ekstra ge\u00e7it (daha az \u00e7\u0131kmaz)\n  for(let i=0;i<Math.floor(w*h*0.04);i++){\n    const x=1+Math.floor(Math.random()*(w-2));\n    const y=1+Math.floor(Math.random()*(h-2));\n    if(maze[y][x]===1){\n      let openN=0;\n      [[0,1],[0,-1],[1,0],[-1,0]].forEach(([dx,dy])=>{ if(maze[y+dy]&&maze[y+dy][x+dx]!==1) openN++; });\n      if(openN>=1) maze[y][x]=0;\n    }\n  }\n  return maze;\n}\nfunction findOpenCells(excludeSafe){\n  const cells=[];\n  for(let gz=1;gz<MH-1;gz++) for(let gx=1;gx<MW-1;gx++){\n    if(MAZE[gz][gx]===0 || (!excludeSafe && MAZE[gz][gx]===2)) cells.push({gx,gz});\n  }\n  return cells;\n}\nfunction randomOpenCell(excludeSafe){\n  const cells=findOpenCells(excludeSafe!==false);\n  return cells[Math.floor(Math.random()*cells.length)] || {gx:1,gz:1};\n}\nfunction initMaze(){\n  MW=23; MH=23;\n  MAZE=generateMaze(MW,MH);\n  OX=-(MW*CELL)\/2; OZ=-(MH*CELL)\/2;\n  \/\/ Spawn = g\u00fcvenli oda merkezi\n  spawnCell={gx:Math.floor(MW\/2), gz:Math.floor(MH\/2)};\n}\n\nconst GameState = { menu:true, playing:false, paused:false, dead:false, won:false, loading:true, readingNote:false, sensitivity:1.25, volume:0.85, jsVolume:1 };\nconst Player = {\n  health:100, battery:100, sanity:100, stamina:100,\n  flashlightOn:true, isRunning:false, isCrouching:false, velocityY:0,\n  keys:{}, inventory:[null,null,null,null,null], selectedSlot:0,\n  hasKeycard:false, notesFound:[], inSafeZone:false, footTimer:0,\n  hasGun:false, ammo:0, gunCooldown:0\n};\n\nconst NOTES = {\n  n1:{title:\"G\u00fcvenlik Kayd\u0131 #441\", body:\"<p>Floresanlar yine s\u00f6nd\u00fc. Koridorun sonu g\u00f6r\u00fcnm\u00fcyor. Bir \u015fey ayak seslerimi takip ediyor.<\/p><p>G\u00fcvenli oda h\u00e2l\u00e2 \u00e7al\u0131\u015f\u0131yor \u2014 k\u0131rm\u0131z\u0131 \u00e7izginin i\u00e7inde kal.<\/p>\"},\n  n2:{title:\"Duvar Yaz\u0131s\u0131\", body:\"<p>BU ODA DE\u011e\u0130L<\/p><p>BU B\u0130R YER DE\u011e\u0130L<\/p><p>\u00c7IKI\u015e YOK \u2014 SADECE DAHA FAZLA KOR\u0130DOR<\/p>\"},\n  n3:{title:\"Personel Notu\", body:\"<p>Asans\u00f6r \u00e7al\u0131\u015fm\u0131yor. Merdiven yok. Sadece sar\u0131 duvarlar ve \u0131slak hal\u0131.<\/p><p>Anahtar kart\u0131 do\u011fu kanad\u0131nda, kilitli dolapta olmal\u0131.<\/p>\"},\n  n4:{title:\"Ses Kayd\u0131 \u00c7\u00f6z\u00fcm\u00fc\", body:\"<p>[statik] ...arkamda... [nefes] ...floresan k\u0131rp\u0131\u015f\u0131yor... [uzun sessizlik] ...g\u00fcl\u00fcyor.<\/p>\"},\n  n5:{title:\"Son Mesaj\", body:\"<p>G\u00fcvenli odaya kilitledim kendimi. Pil bitmek \u00fczere. O kap\u0131n\u0131n arkas\u0131nda bekliyor.<\/p><p>E\u011fer kart\u0131 bulursan kuzeydeki EXIT kap\u0131s\u0131na git. Asla geri bakma.<\/p>\"},\n  n6:{title:\"Kurallar\", body:\"<p>1. Floresan\u0131 takip etme \u2014 yalan s\u00f6yler.<\/p><p>2. Ko\u015fma. O duyar.<\/p><p>3. G\u00fcvenli oda senin tek dostun.<\/p><p>4. Islak hal\u0131ya basma \u00e7ok uzun s\u00fcre.<\/p>\"}\n};\n\nlet scene, camera, renderer, flashlight;\nlet monsters=[]; \/\/ birden fazla canavar\nlet colliders=[], interactables=[], flickerLights=[];\nlet direction=new THREE.Vector3();\nlet canJump=true, isPointerLocked=false, prevTime=performance.now();\nlet patrolPoints=[];\nlet audioCtx=null, masterGain=null, screamGain=null;\nlet lastProximityScream=0;\nlet safeZoneCenter=new THREE.Vector3(0,0,0);\nlet wallMat, floorMat, ceilMat, safeMat;\nlet wasInSafeZone=false; \/\/ g\u00fcvenli odaya yeni giri\u015f tespiti\nlet exitPos=new THREE.Vector3(0,0,0);\nlet exitDoorMesh=null, exitSignMesh=null, exitBeacon=null, exitMarkerLight=null;\nlet exitRevealed=false;\n\nconst dom={};\nfunction cacheDOM(){\n  ['loader-fill','load-status','main-menu','hud','health-text','health-bar','battery-text','battery-bar',\n   'sanity-text','sanity-bar','stamina-text','stamina-bar','objective-text','lore-count','safe-text',\n   'interact-prompt','story-text','note-viewer','note-title','note-body','pause-menu','overlay-screen',\n   'overlay-title','overlay-msg','blood-overlay','sanity-overlay','jumpscare','settings-panel',\n   'monster-scream-flash','info-box','safe-indicator'].forEach(id=>{\n    const el=document.getElementById(id);\n    if(el) dom[id.replace(\/-([a-z])\/g,g=>g[1].toUpperCase())]=el;\n  });\n  dom.loaderFill=document.getElementById('loader-fill');\n  dom.loadStatus=document.getElementById('load-status');\n  dom.mainMenu=document.getElementById('main-menu');\n  dom.hud=document.getElementById('hud');\n  dom.healthText=document.getElementById('health-text');\n  dom.healthBar=document.getElementById('health-bar');\n  dom.batteryText=document.getElementById('battery-text');\n  dom.batteryBar=document.getElementById('battery-bar');\n  dom.sanityText=document.getElementById('sanity-text');\n  dom.sanityBar=document.getElementById('sanity-bar');\n  dom.staminaText=document.getElementById('stamina-text');\n  dom.staminaBar=document.getElementById('stamina-bar');\n  dom.objectiveText=document.getElementById('objective-text');\n  dom.loreCount=document.getElementById('lore-count');\n  dom.safeText=document.getElementById('safe-text');\n  dom.safeIndicator=document.getElementById('safe-indicator');\n  dom.interactPrompt=document.getElementById('interact-prompt');\n  dom.storyText=document.getElementById('story-text');\n  dom.noteViewer=document.getElementById('note-viewer');\n  dom.noteTitle=document.getElementById('note-title');\n  dom.noteBody=document.getElementById('note-body');\n  dom.pauseMenu=document.getElementById('pause-menu');\n  dom.overlayScreen=document.getElementById('overlay-screen');\n  dom.overlayTitle=document.getElementById('overlay-title');\n  dom.overlayMsg=document.getElementById('overlay-msg');\n  dom.bloodOverlay=document.getElementById('blood-overlay');\n  dom.sanityOverlay=document.getElementById('sanity-overlay');\n  dom.jumpscare=document.getElementById('jumpscare');\n  dom.settingsPanel=document.getElementById('settings-panel');\n  dom.screamFlash=document.getElementById('monster-scream-flash');\n  dom.infoBox=document.getElementById('info-box');\n  dom.invSlots=document.querySelectorAll('.inv-slot');\n}\n\n\/\/ ===== SES (y\u00f6nsel yakla\u015f\u0131m) =====\n\/\/ ===== GEL\u0130\u015eM\u0130\u015e SES SENTEZ\u0130 =====\nfunction makeNoiseBuffer(dur){\n  const len=Math.floor(audioCtx.sampleRate*dur);\n  const buf=audioCtx.createBuffer(1,len,audioCtx.sampleRate);\n  const d=buf.getChannelData(0);\n  for(let i=0;i<len;i++) d[i]=Math.random()*2-1;\n  return buf;\n}\nfunction noiseSrc(dur, filterType, freq, q){\n  const src=audioCtx.createBufferSource();\n  src.buffer=makeNoiseBuffer(dur);\n  const f=audioCtx.createBiquadFilter();\n  f.type=filterType||'lowpass';\n  f.frequency.value=freq||800;\n  if(q) f.Q.value=q;\n  src.connect(f);\n  return {src, filter:f};\n}\nfunction panToNearest(){\n  const pan=audioCtx.createStereoPanner();\n  const nm=nearestMonster();\n  if(nm&&camera){\n    const dx=nm.mesh.position.x-camera.position.x;\n    const dz=nm.mesh.position.z-camera.position.z;\n    const ang=Math.atan2(dx,dz)-camera.rotation.y;\n    pan.pan.value=Math.max(-1,Math.min(1,Math.sin(ang)));\n  }\n  return pan;\n}\n\nfunction initAudio(){\n  try{\n    audioCtx=new (window.AudioContext||window.webkitAudioContext)();\n    masterGain=audioCtx.createGain(); masterGain.gain.value=GameState.volume; masterGain.connect(audioCtx.destination);\n    screamGain=audioCtx.createGain(); screamGain.gain.value=GameState.jsVolume; screamGain.connect(audioCtx.destination);\n    \/\/ Floresan hum \u2014 iki katman\n    const hum1=audioCtx.createOscillator(), hg1=audioCtx.createGain();\n    hum1.type='sine'; hum1.frequency.value=60;\n    hg1.gain.value=0.025;\n    hum1.connect(hg1); hg1.connect(masterGain); hum1.start();\n    const hum2=audioCtx.createOscillator(), hg2=audioCtx.createGain();\n    hum2.type='sine'; hum2.frequency.value=120;\n    hg2.gain.value=0.012;\n    hum2.connect(hg2); hg2.connect(masterGain); hum2.start();\n    \/\/ Hafif oda g\u00fcr\u00fclt\u00fcs\u00fc\n    const amb=noiseSrc(2,'lowpass',400);\n    amb.src.loop=true;\n    const ag=audioCtx.createGain(); ag.gain.value=0.018;\n    amb.filter.connect(ag); ag.connect(masterGain);\n    amb.src.start();\n    setInterval(()=>{ if(GameState.playing&&!GameState.paused&&Math.random()>0.55) playBuzz(); },3500);\n    setInterval(()=>{ if(GameState.playing&&!GameState.paused&&Math.random()>0.65) playDistantFoot(); },7000);\n  }catch(e){}\n}\nfunction playBuzz(){\n  if(!audioCtx)return;\n  const t=audioCtx.currentTime;\n  \/\/ Floresan \u00e7at\u0131rt\u0131s\u0131 \u2014 noise burst\n  const n=noiseSrc(0.15,'bandpass',2500,4);\n  const g=audioCtx.createGain();\n  g.gain.setValueAtTime(0.08*GameState.volume,t);\n  g.gain.exponentialRampToValueAtTime(0.001,t+0.12);\n  n.filter.connect(g); g.connect(masterGain);\n  n.src.start(t); n.src.stop(t+0.15);\n  \/\/ Ton d\u00fc\u015f\u00fc\u015f\u00fc\n  const o=audioCtx.createOscillator(), og=audioCtx.createGain();\n  o.type='sine'; o.frequency.setValueAtTime(90,t); o.frequency.exponentialRampToValueAtTime(40,t+0.2);\n  og.gain.setValueAtTime(0.05*GameState.volume,t); og.gain.exponentialRampToValueAtTime(0.001,t+0.2);\n  o.connect(og); og.connect(masterGain); o.start(t); o.stop(t+0.2);\n}\nfunction nearestMonster(){\n  if(!monsters.length||!camera) return null;\n  let best=null, bestD=1e9;\n  for(const m of monsters){\n    if(!m.mesh||!m.mesh.visible) continue;\n    const d=camera.position.distanceTo(m.mesh.position);\n    if(d<bestD){ bestD=d; best=m; }\n  }\n  return best;\n}\nfunction playDistantFoot(){\n  if(!audioCtx)return;\n  const t=audioCtx.currentTime;\n  const pan=panToNearest();\n  pan.connect(masterGain);\n  \/\/ Islak hal\u0131 \u2014 noise + bass\n  const n=noiseSrc(0.18,'lowpass',280);\n  const g=audioCtx.createGain();\n  g.gain.setValueAtTime(0.14*GameState.volume,t);\n  g.gain.exponentialRampToValueAtTime(0.001,t+0.16);\n  n.filter.connect(g); g.connect(pan);\n  n.src.start(t); n.src.stop(t+0.18);\n  const o=audioCtx.createOscillator(), og=audioCtx.createGain();\n  o.type='sine'; o.frequency.value=55+Math.random()*15;\n  og.gain.setValueAtTime(0.1*GameState.volume,t); og.gain.exponentialRampToValueAtTime(0.001,t+0.12);\n  o.connect(og); og.connect(pan); o.start(t); o.stop(t+0.12);\n}\nfunction playFootstep(){\n  if(!audioCtx||Player.isCrouching)return;\n  const t=audioCtx.currentTime;\n  const n=noiseSrc(0.09,'lowpass',350+Math.random()*80);\n  const g=audioCtx.createGain();\n  const vol=(Player.isRunning?0.16:0.1)*GameState.volume;\n  g.gain.setValueAtTime(vol,t);\n  g.gain.exponentialRampToValueAtTime(0.001,t+0.08);\n  n.filter.connect(g); g.connect(masterGain);\n  n.src.start(t); n.src.stop(t+0.09);\n  const o=audioCtx.createOscillator(), og=audioCtx.createGain();\n  o.type='triangle'; o.frequency.value=70+Math.random()*25;\n  og.gain.setValueAtTime(vol*0.7,t); og.gain.exponentialRampToValueAtTime(0.001,t+0.06);\n  o.connect(og); og.connect(masterGain); o.start(t); o.stop(t+0.06);\n}\nfunction playMonsterScream(loud=true){\n  if(!audioCtx)return;\n  const t=audioCtx.currentTime;\n  const vol=loud?0.9*GameState.jsVolume:0.32*GameState.jsVolume;\n  const pan=panToNearest();\n  pan.connect(screamGain);\n  \/\/ Katman 1: bo\u011fuk g\u00fcrleme (noise)\n  const n=noiseSrc(loud?1.1:0.6,'bandpass',400+Math.random()*200,1.5);\n  const ng=audioCtx.createGain();\n  ng.gain.setValueAtTime(vol*0.7,t);\n  ng.gain.exponentialRampToValueAtTime(0.001,t+(loud?1.0:0.55));\n  n.filter.connect(ng); ng.connect(pan);\n  n.src.start(t); n.src.stop(t+(loud?1.1:0.6));\n  \/\/ Katman 2: ini\u015fli \u00e7\u0131k\u0131\u015fl\u0131 \u00e7\u0131\u011fl\u0131k tonu\n  const o1=audioCtx.createOscillator(), g1=audioCtx.createGain();\n  o1.type='sawtooth';\n  o1.frequency.setValueAtTime(280+Math.random()*80,t);\n  o1.frequency.exponentialRampToValueAtTime(60,t+0.9);\n  g1.gain.setValueAtTime(vol*0.55,t);\n  g1.gain.exponentialRampToValueAtTime(0.001,t+0.95);\n  const f1=audioCtx.createBiquadFilter(); f1.type='lowpass'; f1.frequency.value=1200;\n  o1.connect(f1); f1.connect(g1); g1.connect(pan);\n  o1.start(t); o1.stop(t+1.0);\n  \/\/ Katman 3: tiz \u0131sl\u0131k \/ \u00e7\u0131\u011fl\u0131k\n  if(loud){\n    const o2=audioCtx.createOscillator(), g2=audioCtx.createGain();\n    o2.type='square';\n    o2.frequency.setValueAtTime(900,t);\n    o2.frequency.exponentialRampToValueAtTime(200,t+0.7);\n    g2.gain.setValueAtTime(vol*0.25,t);\n    g2.gain.exponentialRampToValueAtTime(0.001,t+0.7);\n    const f2=audioCtx.createBiquadFilter(); f2.type='bandpass'; f2.frequency.value=1500; f2.Q.value=2;\n    o2.connect(f2); f2.connect(g2); g2.connect(pan);\n    o2.start(t); o2.stop(t+0.75);\n  }\n  \/\/ Sub-bass vurgu\n  const o3=audioCtx.createOscillator(), g3=audioCtx.createGain();\n  o3.type='sine'; o3.frequency.value=35;\n  g3.gain.setValueAtTime(vol*0.5,t);\n  g3.gain.exponentialRampToValueAtTime(0.001,t+0.4);\n  o3.connect(g3); g3.connect(pan);\n  o3.start(t); o3.stop(t+0.4);\n  if(loud&&dom.screamFlash){ dom.screamFlash.style.opacity='1'; setTimeout(()=>dom.screamFlash.style.opacity='0',130); }\n}\nfunction playJumpscareSound(){\n  if(!audioCtx)return;\n  const t=audioCtx.currentTime;\n  \/\/ Ani stinger\n  const n=noiseSrc(0.35,'highpass',800);\n  const ng=audioCtx.createGain();\n  ng.gain.setValueAtTime(0.95*GameState.jsVolume,t);\n  ng.gain.exponentialRampToValueAtTime(0.001,t+0.3);\n  n.filter.connect(ng); ng.connect(screamGain);\n  n.src.start(t); n.src.stop(t+0.35);\n  playMonsterScream(true);\n  \/\/ Metalik vuru\u015f\n  const o=audioCtx.createOscillator(), g=audioCtx.createGain();\n  o.type='square'; o.frequency.setValueAtTime(150,t); o.frequency.exponentialRampToValueAtTime(30,t+0.25);\n  g.gain.setValueAtTime(0.6*GameState.jsVolume,t); g.gain.exponentialRampToValueAtTime(0.001,t+0.25);\n  o.connect(g); g.connect(screamGain); o.start(t); o.stop(t+0.25);\n}\nfunction playPickup(){\n  if(!audioCtx)return;\n  const t=audioCtx.currentTime;\n  \/\/ Yumu\u015fak dijital bip\n  [660,880,1100].forEach((freq,i)=>{\n    const o=audioCtx.createOscillator(), g=audioCtx.createGain();\n    o.type='sine'; o.frequency.value=freq;\n    g.gain.setValueAtTime(0,t+i*0.05);\n    g.gain.linearRampToValueAtTime(0.12*GameState.volume,t+i*0.05+0.01);\n    g.gain.exponentialRampToValueAtTime(0.001,t+i*0.05+0.12);\n    o.connect(g); g.connect(masterGain);\n    o.start(t+i*0.05); o.stop(t+i*0.05+0.12);\n  });\n}\nfunction playHeartbeat(){\n  if(!audioCtx)return;\n  const t=audioCtx.currentTime;\n  [0,0.16].forEach((off,i)=>{\n    const o=audioCtx.createOscillator(), g=audioCtx.createGain();\n    o.type='sine'; o.frequency.value=i===0?45:38;\n    g.gain.setValueAtTime(0,t+off);\n    g.gain.linearRampToValueAtTime((i===0?0.28:0.18)*GameState.volume,t+off+0.025);\n    g.gain.exponentialRampToValueAtTime(0.001,t+off+0.2);\n    o.connect(g); g.connect(masterGain);\n    o.start(t+off); o.stop(t+off+0.2);\n    \/\/ Sub thump noise\n    const n=noiseSrc(0.08,'lowpass',80);\n    const ng=audioCtx.createGain();\n    ng.gain.setValueAtTime(0.12*GameState.volume,t+off);\n    ng.gain.exponentialRampToValueAtTime(0.001,t+off+0.07);\n    n.filter.connect(ng); ng.connect(masterGain);\n    n.src.start(t+off); n.src.stop(t+off+0.08);\n  });\n}\n\n\/\/ ===== TEXTURE \/ MATERYAL (Backrooms sar\u0131-kirli) =====\nfunction makeWallTex(){\n  const c=document.createElement('canvas'); c.width=c.height=256;\n  const ctx=c.getContext('2d');\n  \/\/ Sar\u0131ms\u0131 kirli duvar\n  ctx.fillStyle='#c4b070'; ctx.fillRect(0,0,256,256);\n  for(let i=0;i<800;i++){\n    const n=Math.random()*30-15;\n    ctx.fillStyle=`rgb(${180+n},${160+n},${90+n})`;\n    ctx.fillRect(Math.random()*256,Math.random()*256,2+Math.random()*4,2+Math.random()*4);\n  }\n  \/\/ Rutubet lekeleri\n  for(let i=0;i<12;i++){\n    const grd=ctx.createRadialGradient(Math.random()*256,Math.random()*256,5,Math.random()*256,Math.random()*256,30+Math.random()*40);\n    grd.addColorStop(0,'rgba(60,70,40,0.25)'); grd.addColorStop(1,'transparent');\n    ctx.fillStyle=grd; ctx.fillRect(0,0,256,256);\n  }\n  \/\/ Kan \/ pas izi\n  for(let i=0;i<5;i++){\n    ctx.fillStyle=`rgba(${80+Math.random()*40},20,10,${0.15+Math.random()*0.2})`;\n    ctx.beginPath();\n    const x=Math.random()*256, y=Math.random()*100;\n    ctx.moveTo(x,y);\n    for(let j=0;j<8;j++) ctx.lineTo(x+(Math.random()-0.5)*20, y+j*12+Math.random()*8);\n    ctx.lineWidth=3+Math.random()*4; ctx.strokeStyle=ctx.fillStyle; ctx.stroke();\n  }\n  const tex=new THREE.CanvasTexture(c);\n  tex.wrapS=tex.wrapT=THREE.RepeatWrapping; tex.repeat.set(1.5,1.5);\n  return tex;\n}\nfunction makeFloorTex(){\n  const c=document.createElement('canvas'); c.width=c.height=256;\n  const ctx=c.getContext('2d');\n  ctx.fillStyle='#3a3830'; ctx.fillRect(0,0,256,256);\n  \/\/ Hal\u0131 deseni\n  for(let y=0;y<256;y+=8){\n    for(let x=0;x<256;x+=8){\n      const v=Math.random()*20;\n      ctx.fillStyle=`rgb(${50+v},${48+v},${40+v})`;\n      ctx.fillRect(x,y,8,8);\n    }\n  }\n  \/\/ Islak leke\n  for(let i=0;i<6;i++){\n    const grd=ctx.createRadialGradient(Math.random()*256,Math.random()*256,5,Math.random()*256,Math.random()*256,40);\n    grd.addColorStop(0,'rgba(30,40,50,0.35)'); grd.addColorStop(1,'transparent');\n    ctx.fillStyle=grd; ctx.fillRect(0,0,256,256);\n  }\n  const tex=new THREE.CanvasTexture(c);\n  tex.wrapS=tex.wrapT=THREE.RepeatWrapping; tex.repeat.set(2,2);\n  return tex;\n}\nfunction makeCeilTex(){\n  const c=document.createElement('canvas'); c.width=c.height=128;\n  const ctx=c.getContext('2d');\n  ctx.fillStyle='#e8e0c0'; ctx.fillRect(0,0,128,128);\n  \/\/ Floresan panel \u00e7izgileri\n  ctx.strokeStyle='rgba(0,0,0,0.15)'; ctx.lineWidth=1;\n  for(let i=0;i<128;i+=32){ ctx.beginPath(); ctx.moveTo(i,0); ctx.lineTo(i,128); ctx.stroke(); }\n  for(let i=0;i<128;i+=32){ ctx.beginPath(); ctx.moveTo(0,i); ctx.lineTo(128,i); ctx.stroke(); }\n  const tex=new THREE.CanvasTexture(c);\n  tex.wrapS=tex.wrapT=THREE.RepeatWrapping; tex.repeat.set(2,2);\n  return tex;\n}\n\nfunction gridToWorld(gx,gz){\n  return { x: OX+gx*CELL+CELL\/2, z: OZ+gz*CELL+CELL\/2 };\n}\n\nfunction buildBackrooms(){\n  wallMat=new THREE.MeshStandardMaterial({ map:makeWallTex(), roughness:0.88, metalness:0.05, color:0xddddcc });\n  floorMat=new THREE.MeshStandardMaterial({ map:makeFloorTex(), roughness:0.95, metalness:0.02, color:0x999990 });\n  ceilMat=new THREE.MeshStandardMaterial({ map:makeCeilTex(), roughness:0.7, metalness:0.1, color:0xeeeedd, emissive:0x222218, emissiveIntensity:0.15 });\n  safeMat=new THREE.MeshStandardMaterial({ color:0x2a3a2a, roughness:0.8, metalness:0.1, emissive:0x0a1a0a, emissiveIntensity:0.3 });\n\n  const wallH=3.0;\n  const wallGeo=new THREE.BoxGeometry(CELL,wallH,CELL);\n  const floorGeo=new THREE.BoxGeometry(CELL,0.15,CELL);\n  const ceilGeo=new THREE.BoxGeometry(CELL,0.12,CELL);\n\n  let safeCells=[];\n  for(let gz=0;gz<MH;gz++){\n    for(let gx=0;gx<MW;gx++){\n      const {x,z}=gridToWorld(gx,gz);\n      const cell=MAZE[gz][gx];\n      if(cell===1){\n        const w=new THREE.Mesh(wallGeo, wallMat);\n        w.position.set(x, wallH\/2, z);\n        w.castShadow=true; w.receiveShadow=true;\n        scene.add(w); colliders.push(w);\n      } else {\n        const fl=new THREE.Mesh(floorGeo, cell===2?safeMat:floorMat);\n        fl.position.set(x, -0.07, z); fl.receiveShadow=true; scene.add(fl);\n        const cl=new THREE.Mesh(ceilGeo, ceilMat);\n        cl.position.set(x, wallH, z); scene.add(cl);\n        if(cell===2) safeCells.push({x,z,gx,gz});\n      }\n    }\n  }\n\n  \/\/ G\u00fcvenli oda merkezi\n  if(safeCells.length){\n    let sx=0,sz=0;\n    safeCells.forEach(c=>{ sx+=c.x; sz+=c.z; });\n    safeZoneCenter.set(sx\/safeCells.length, 0, sz\/safeCells.length);\n  }\n\n  \/\/ Floresan lambalar (k\u0131rp\u0131\u015fan) \u2014 seyrek\n  for(let gz=1;gz<MH-1;gz+=3){\n    for(let gx=1;gx<MW-1;gx+=3){\n      if(MAZE[gz][gx]!==1){\n        const {x,z}=gridToWorld(gx,gz);\n        \/\/ Lamba g\u00f6vdesi\n        const fixture=new THREE.Mesh(\n          new THREE.BoxGeometry(1.2,0.08,0.35),\n          new THREE.MeshStandardMaterial({ color:0xddddcc, emissive:0xffffee, emissiveIntensity:0.4, roughness:0.4 })\n        );\n        fixture.position.set(x, 2.9, z); scene.add(fixture);\n        const light=new THREE.PointLight(0xfff5d0, 0.35, 8);\n        light.position.set(x, 2.75, z); scene.add(light);\n        flickerLights.push({ light, fixture, base:0.35, phase:Math.random()*Math.PI*2, broken:Math.random()>0.65 });\n      }\n    }\n  }\n\n  \/\/ G\u00fcvenli oda daha parlak\n  const safeLight=new THREE.PointLight(0x88ff88, 1.2, 10);\n  safeLight.position.set(safeZoneCenter.x, 2.5, safeZoneCenter.z);\n  scene.add(safeLight);\n  \/\/ Ye\u015fil halka ipucu\n  const ring=new THREE.Mesh(\n    new THREE.RingGeometry(CONFIG.SAFE_RADIUS-0.2, CONFIG.SAFE_RADIUS, 40),\n    new THREE.MeshBasicMaterial({ color:0x44ff44, transparent:true, opacity:0.1, side:THREE.DoubleSide })\n  );\n  ring.rotation.x=-Math.PI\/2; ring.position.set(safeZoneCenter.x, 0.05, safeZoneCenter.z);\n  scene.add(ring);\n\n  \/\/ A\u00e7\u0131k h\u00fccrelerden rastgele yerle\u015fim (prosed\u00fcrel)\n  const open=findOpenCells(true);\n  function pickFar(fromGx,fromGz,minDist){\n    const far=open.filter(c=>Math.hypot(c.gx-fromGx,c.gz-fromGz)>=minDist);\n    const pool=far.length?far:open;\n    return pool[Math.floor(Math.random()*pool.length)];\n  }\n  \/\/ \u00c7\u0131k\u0131\u015f \u2014 kenara yak\u0131n a\u00e7\u0131k h\u00fccre\n  let exitCell=open.filter(c=>c.gz<=2||c.gz>=MH-3||c.gx<=2||c.gx>=MW-3);\n  if(!exitCell.length) exitCell=open;\n  const ec=exitCell[Math.floor(Math.random()*exitCell.length)];\n  const exitP=gridToWorld(ec.gx,ec.gz);\n  addExit(exitP.x, exitP.z);\n\n  \/\/ Anahtar kart \u2014 \u00e7\u0131k\u0131\u015ftan uzak\n  const kc=pickFar(ec.gx,ec.gz,6);\n  const keyP=gridToWorld(kc.gx,kc.gz);\n  addItem(keyP.x, 0.35, keyP.z, 'keycard', 0xff4444);\n\n  \/\/ Notlar\n  const noteIds=['n1','n2','n3','n4','n5','n6'];\n  const usedNotes=new Set([kc.gx+','+kc.gz, ec.gx+','+ec.gz]);\n  noteIds.forEach(id=>{\n    let c, tries=0;\n    do{ c=open[Math.floor(Math.random()*open.length)]; tries++; }\n    while(usedNotes.has(c.gx+','+c.gz)&&tries<30);\n    usedNotes.add(c.gx+','+c.gz);\n    const p=gridToWorld(c.gx,c.gz);\n    addNote(p.x, 0.3, p.z, id);\n  });\n\n  \/\/ Pil \/ medkit\n  for(let i=0;i<3;i++){\n    const c=open[Math.floor(Math.random()*open.length)];\n    const p=gridToWorld(c.gx,c.gz);\n    addItem(p.x, 0.3, p.z, Math.random()>0.5?'battery':'medkit', Math.random()>0.5?0x44ff44:0xff3333);\n  }\n\n  \/\/ Silah (1) ve mermi\n  const gc=pickFar(spawnCell.gx,spawnCell.gz,4);\n  const gp=gridToWorld(gc.gx,gc.gz);\n  addItem(gp.x, 0.35, gp.z, 'gun', 0x888899);\n  for(let i=0;i<5;i++){\n    const c=open[Math.floor(Math.random()*open.length)];\n    const p=gridToWorld(c.gx,c.gz);\n    addItem(p.x, 0.3, p.z, 'ammo', 0xccaa44);\n  }\n\n  \/\/ \u00c7\u00f6km\u00fc\u015f tavan par\u00e7alar\u0131 (mod\u00fcler detay)\n  for(let i=0;i<8;i++){\n    const gx=2+Math.floor(Math.random()*(MW-4));\n    const gz=2+Math.floor(Math.random()*(MH-4));\n    if(MAZE[gz][gx]===0){\n      const p=gridToWorld(gx,gz);\n      const debris=new THREE.Mesh(\n        new THREE.BoxGeometry(0.8+Math.random(),0.15,0.6+Math.random()),\n        new THREE.MeshStandardMaterial({ color:0xb0a080, roughness:0.9 })\n      );\n      debris.position.set(p.x+(Math.random()-0.5), 0.2, p.z+(Math.random()-0.5));\n      debris.rotation.y=Math.random()*Math.PI;\n      scene.add(debris);\n    }\n  }\n\n  \/\/ Patrol\n  patrolPoints=[];\n  for(let gz=1;gz<MH-1;gz++){\n    for(let gx=1;gx<MW-1;gx++){\n      if(MAZE[gz][gx]===0){\n        const p=gridToWorld(gx,gz);\n        const d=Math.hypot(p.x-safeZoneCenter.x, p.z-safeZoneCenter.z);\n        if(d>CONFIG.SAFE_RADIUS+2.5) patrolPoints.push(new THREE.Vector3(p.x,0,p.z));\n      }\n    }\n  }\n  for(let i=patrolPoints.length-1;i>0;i--){\n    const j=Math.floor(Math.random()*(i+1));\n    [patrolPoints[i],patrolPoints[j]]=[patrolPoints[j],patrolPoints[i]];\n  }\n  patrolPoints=patrolPoints.slice(0,18);\n}\n\nfunction addExit(x,z){\n  const g=new THREE.Group();\n  const door=new THREE.Mesh(\n    new THREE.BoxGeometry(2.0,2.6,0.2),\n    new THREE.MeshStandardMaterial({ color:0x4a3a20, roughness:0.6, metalness:0.3, emissive:0x1a1000, emissiveIntensity:0.2 })\n  );\n  door.position.y=1.3; g.add(door);\n  const sign=new THREE.Mesh(\n    new THREE.BoxGeometry(0.9,0.3,0.05),\n    new THREE.MeshStandardMaterial({ color:0x22aa22, emissive:0x114411, emissiveIntensity:0.6 })\n  );\n  sign.position.set(0,2.4,0.15); g.add(sign);\n  g.position.set(x,0,z); scene.add(g);\n  interactables.push({ mesh:g, type:'exit', interactable:true });\n  exitPos.set(x,0,z);\n  exitDoorMesh=door;\n  exitSignMesh=sign;\n\n  \/\/ Anahtar al\u0131nana kadar gizli i\u015faret\u00e7i (kapal\u0131)\n  exitBeacon=new THREE.Mesh(\n    new THREE.CylinderGeometry(0.08,0.25,8,8),\n    new THREE.MeshBasicMaterial({ color:0x44ff66, transparent:true, opacity:0.55 })\n  );\n  exitBeacon.position.set(x,4,z);\n  exitBeacon.visible=false;\n  scene.add(exitBeacon);\n\n  exitMarkerLight=new THREE.PointLight(0x44ff66,0,18);\n  exitMarkerLight.position.set(x,3,z);\n  scene.add(exitMarkerLight);\n\n  \/\/ Yerde halka\n  const ring=new THREE.Mesh(\n    new THREE.RingGeometry(0.6,0.85,24),\n    new THREE.MeshBasicMaterial({ color:0x44ff66, transparent:true, opacity:0.5, side:THREE.DoubleSide })\n  );\n  ring.rotation.x=-Math.PI\/2;\n  ring.position.set(x,0.08,z);\n  ring.visible=false;\n  ring.name='exitRing';\n  scene.add(ring);\n  exitBeacon.userData.ring=ring;\n}\n\nfunction revealExitLocation(){\n  if(exitRevealed) return;\n  exitRevealed=true;\n  if(exitBeacon){\n    exitBeacon.visible=true;\n    if(exitBeacon.userData.ring) exitBeacon.userData.ring.visible=true;\n  }\n  if(exitMarkerLight) exitMarkerLight.intensity=1.8;\n  if(exitDoorMesh){\n    exitDoorMesh.material.emissive.setHex(0x226622);\n    exitDoorMesh.material.emissiveIntensity=0.55;\n  }\n  if(exitSignMesh){\n    exitSignMesh.material.emissive.setHex(0x44ff44);\n    exitSignMesh.material.emissiveIntensity=1.2;\n  }\n  \/\/ HUD pusula\n  const compass=document.getElementById('exit-compass');\n  if(compass) compass.classList.add('visible');\n  if(dom.objectiveText) dom.objectiveText.textContent='\u00c7\u0131k\u0131\u015f i\u015faretlendi! Ye\u015fil \u0131\u015f\u0131\u011f\u0131 \/ pusulay\u0131 takip et.';\n}\n\nfunction updateExitCompass(){\n  if(!exitRevealed||!GameState.playing) return;\n  const arrow=document.getElementById('exit-arrow');\n  const distEl=document.getElementById('exit-dist');\n  if(!arrow||!distEl) return;\n\n  const dx=exitPos.x-camera.position.x;\n  const dz=exitPos.z-camera.position.z;\n  const dist=Math.sqrt(dx*dx+dz*dz);\n  \/\/ D\u00fcnya a\u00e7\u0131s\u0131 \u2192 kamera g\u00f6reli a\u00e7\u0131\n  const worldAngle=Math.atan2(dx,dz);\n  const rel=worldAngle-camera.rotation.y;\n  \/\/ Ok yukar\u0131 bak\u0131yor; rotasyon derece\n  const deg=(rel*180\/Math.PI);\n  arrow.style.transform=`rotate(${deg}deg)`;\n  distEl.textContent=dist<3 ? 'YAKINDA' : (Math.round(dist)+' m');\n\n  \/\/ Beacon nab\u0131z\n  if(exitBeacon){\n    const pulse=0.4+Math.sin(performance.now()*0.005)*0.2;\n    exitBeacon.material.opacity=pulse;\n    exitBeacon.rotation.y+=0.02;\n  }\n  if(exitMarkerLight){\n    exitMarkerLight.intensity=1.4+Math.sin(performance.now()*0.006)*0.5;\n  }\n}\nfunction addNote(x,y,z,nid){\n  const m=new THREE.Mesh(new THREE.BoxGeometry(0.18,0.012,0.25), new THREE.MeshStandardMaterial({ color:0xc8b890, roughness:0.9 }));\n  m.position.set(x,y,z); m.rotation.x=-Math.PI\/2+0.08; scene.add(m);\n  interactables.push({ mesh:m, type:'note', noteId:nid, collected:false, interactable:true });\n}\nfunction addItem(x,y,z,itype,color){\n  let geo;\n  if(itype==='keycard') geo=new THREE.BoxGeometry(0.16,0.02,0.1);\n  else if(itype==='medkit') geo=new THREE.BoxGeometry(0.24,0.12,0.16);\n  else if(itype==='gun') geo=new THREE.BoxGeometry(0.35,0.12,0.08);\n  else if(itype==='ammo') geo=new THREE.BoxGeometry(0.14,0.1,0.14);\n  else geo=new THREE.BoxGeometry(0.08,0.14,0.08);\n  const m=new THREE.Mesh(geo, new THREE.MeshStandardMaterial({ color, roughness:0.45, metalness:itype==='gun'?0.7:0.3 }));\n  m.position.set(x,y,z); scene.add(m);\n  const l=new THREE.PointLight(color,0.45,2.2); l.position.copy(m.position); scene.add(l);\n  interactables.push({ mesh:m, light:l, type:'item', itemType:itype, collected:false, interactable:true });\n}\n\n\/\/ Canavar t\u00fcrleri: entity (klasik), stalker (daha h\u0131zl\u0131 ince), brute (yava\u015f ama hasarl\u0131)\nfunction createOneMonster(type, startPos){\n  const g=new THREE.Group();\n  let color=0x1a1810, emissive=0x2a1500, eyeColor=0xff2200, scale=1, speedMul=1, dmg=22, detect=1;\n  if(type==='stalker'){ color=0x0a1218; emissive=0x001a2a; eyeColor=0x00aaff; scale=0.9; speedMul=1.2; dmg=14; detect=1.1; }\n  else if(type==='brute'){ color=0x1a0a0a; emissive=0x2a0000; eyeColor=0xff4400; scale=1.25; speedMul=0.7; dmg=32; detect=0.85; }\n\n  const bodyMat=new THREE.MeshStandardMaterial({\n    color, roughness:0.95, metalness:0.05, emissive, emissiveIntensity:0.3\n  });\n  const torso=new THREE.Mesh(new THREE.CylinderGeometry(0.22*scale,0.35*scale,1.7*scale,6), bodyMat);\n  torso.position.y=1.4*scale; torso.rotation.z=0.12; g.add(torso);\n  const head=new THREE.Mesh(new THREE.SphereGeometry(0.3*scale,6,6), bodyMat);\n  head.position.y=2.4*scale; head.scale.set(1.15,1.4,0.8); g.add(head);\n  const socketMat=new THREE.MeshBasicMaterial({ color:0x000000 });\n  const sL=new THREE.Mesh(new THREE.SphereGeometry(0.08*scale,5,5), socketMat); sL.position.set(-0.1*scale,2.45*scale,0.22*scale); g.add(sL);\n  const sR=new THREE.Mesh(new THREE.SphereGeometry(0.08*scale,5,5), socketMat); sR.position.set(0.1*scale,2.45*scale,0.22*scale); g.add(sR);\n  const eyeMat=new THREE.MeshBasicMaterial({ color:eyeColor });\n  const eL=new THREE.Mesh(new THREE.SphereGeometry(0.035*scale,4,4), eyeMat); eL.position.set(-0.1*scale,2.45*scale,0.28*scale); g.add(eL);\n  const eR=new THREE.Mesh(new THREE.SphereGeometry(0.035*scale,4,4), eyeMat); eR.position.set(0.1*scale,2.45*scale,0.28*scale); g.add(eR);\n  const armGeo=new THREE.CylinderGeometry(0.05*scale,0.025*scale,2.0*scale,4);\n  const aL=new THREE.Mesh(armGeo, bodyMat); aL.position.set(-0.4*scale,1.3*scale,0); aL.rotation.z=0.55; g.add(aL);\n  const aR=new THREE.Mesh(armGeo, bodyMat); aR.position.set(0.4*scale,1.3*scale,0); aR.rotation.z=-0.55; g.add(aR);\n  const legGeo=new THREE.CylinderGeometry(0.08*scale,0.04*scale,1.2*scale,4);\n  const lL=new THREE.Mesh(legGeo, bodyMat); lL.position.set(-0.12*scale,0.5*scale,0); g.add(lL);\n  const lR=new THREE.Mesh(legGeo, bodyMat); lR.position.set(0.12*scale,0.5*scale,0); g.add(lR);\n  const glow=new THREE.PointLight(eyeColor,0.45,4); glow.position.y=2*scale; g.add(glow);\n\n  g.position.copy(startPos||new THREE.Vector3(10,0,10));\n  scene.add(g);\n\n  const maxHp = type==='brute' ? 120 : (type==='stalker' ? 70 : 90);\n  return {\n    mesh:g, type, state:'patrol', patrolIdx:Math.floor(Math.random()*Math.max(1,patrolPoints.length)),\n    loseTimer:0, attackCooldown:0, speedMul, dmg, detect,\n    hp:maxHp, maxHp,\n    userData:{ eL,eR,aL,aR,glow },\n    lastPlayerPos:new THREE.Vector3(),\n    dead:false\n  };\n}\n\nfunction getFarPatrolPoint(fromPos){\n  if(!patrolPoints.length) return new THREE.Vector3(12,0,12);\n  let best=patrolPoints[0], bestD=-1;\n  for(const p of patrolPoints){\n    const d=fromPos.distanceTo(p);\n    if(d>bestD && !isInSafeZone(p)){ bestD=d; best=p; }\n  }\n  \/\/ Biraz rastgelelik: en uzak 5 noktadan biri\n  const far=patrolPoints.filter(p=>fromPos.distanceTo(p)>bestD*0.6 && !isInSafeZone(p));\n  if(far.length) return far[Math.floor(Math.random()*far.length)].clone();\n  return best.clone();\n}\n\nfunction teleportMonsterAway(m){\n  const dest=getFarPatrolPoint(camera.position);\n  m.mesh.position.set(dest.x, 0, dest.z);\n  m.state='patrol';\n  m.loseTimer=0;\n  m.attackCooldown=1.5;\n  m.userData.glow.intensity=0.4;\n  \/\/ K\u0131sa g\u00f6r\u00fcnmezlik efekti (kaybolma hissi)\n  m.mesh.visible=false;\n  setTimeout(()=>{ if(m.mesh) m.mesh.visible=true; }, 400);\n}\n\nfunction createAllMonsters(){\n  monsters=[];\n  const types=['entity','stalker','brute'];\n  \/\/ Farkl\u0131 ba\u015flang\u0131\u00e7 noktalar\u0131\n  const used=[];\n  for(let i=0;i<types.length;i++){\n    let idx=Math.floor(Math.random()*Math.max(1,patrolPoints.length));\n    \/\/ Ayn\u0131 yere koymamaya \u00e7al\u0131\u015f\n    let tries=0;\n    while(used.includes(idx) && tries<20){ idx=(idx+3)%Math.max(1,patrolPoints.length); tries++; }\n    used.push(idx);\n    const pos=patrolPoints[idx] ? patrolPoints[idx].clone() : new THREE.Vector3(8+i*4,0,8);\n    monsters.push(createOneMonster(types[i], pos));\n  }\n}\n\nfunction isInSafeZone(pos){\n  return Math.hypot(pos.x-safeZoneCenter.x, pos.z-safeZoneCenter.z)<CONFIG.SAFE_RADIUS;\n}\n\n\/\/ ===== KONTROL \/ AI \/ OYUNCU \u2014 \u00f6nceki mant\u0131k (g\u00fcvenli b\u00f6lge korumal\u0131) =====\nfunction setupControls(){\n  document.addEventListener('keydown',onKeyDown);\n  document.addEventListener('keyup',e=>Player.keys[e.code]=false);\n  document.addEventListener('mousemove',onMouseMove);\n  document.addEventListener('click',()=>{\n    if(GameState.playing&&!GameState.paused&&!isPointerLocked){\n      document.body.requestPointerLock();\n      return;\n    }\n    if(GameState.playing&&!GameState.paused&&isPointerLocked) tryShoot();\n  });\n  document.addEventListener('pointerlockchange',()=>{ isPointerLocked=document.pointerLockElement===document.body; });\n}\nfunction playGunShot(){\n  if(!audioCtx) return;\n  const t=audioCtx.currentTime;\n  \/\/ Patlama \u2014 k\u0131sa white noise burst\n  const n=noiseSrc(0.2,'lowpass',3000);\n  const ng=audioCtx.createGain();\n  ng.gain.setValueAtTime(0.55*GameState.volume,t);\n  ng.gain.exponentialRampToValueAtTime(0.001,t+0.15);\n  n.filter.connect(ng); ng.connect(masterGain);\n  n.src.start(t); n.src.stop(t+0.2);\n  \/\/ Body \u2014 d\u00fc\u015f\u00fck ton\n  const o=audioCtx.createOscillator(), g=audioCtx.createGain();\n  o.type='sawtooth';\n  o.frequency.setValueAtTime(220,t); o.frequency.exponentialRampToValueAtTime(45,t+0.12);\n  g.gain.setValueAtTime(0.4*GameState.volume,t); g.gain.exponentialRampToValueAtTime(0.001,t+0.12);\n  const f=audioCtx.createBiquadFilter(); f.type='lowpass'; f.frequency.value=900;\n  o.connect(f); f.connect(g); g.connect(masterGain);\n  o.start(t); o.stop(t+0.12);\n  \/\/ Sub kick\n  const o2=audioCtx.createOscillator(), g2=audioCtx.createGain();\n  o2.type='sine'; o2.frequency.setValueAtTime(90,t); o2.frequency.exponentialRampToValueAtTime(30,t+0.1);\n  g2.gain.setValueAtTime(0.35*GameState.volume,t); g2.gain.exponentialRampToValueAtTime(0.001,t+0.1);\n  o2.connect(g2); g2.connect(masterGain); o2.start(t); o2.stop(t+0.1);\n}\nfunction tryShoot(){\n  if(!Player.hasGun||Player.ammo<=0||Player.gunCooldown>0||GameState.readingNote) return;\n  if(!Player.hasGun){ showStory('Silah\u0131n yok.',1500); return; }\n  Player.ammo--;\n  Player.gunCooldown=CONFIG.GUN_COOLDOWN;\n  playGunShot();\n  updateAmmoHUD();\n\n  \/\/ Raycast canavarlara\n  const dir=new THREE.Vector3(0,0,-1).applyQuaternion(camera.quaternion);\n  let hit=null, hitDist=CONFIG.GUN_RANGE;\n  for(const m of monsters){\n    if(m.dead||!m.mesh.visible) continue;\n    const toM=m.mesh.position.clone().add(new THREE.Vector3(0,1.5,0)).sub(camera.position);\n    const dist=toM.length();\n    if(dist>CONFIG.GUN_RANGE) continue;\n    const nd=toM.normalize();\n    const dot=nd.dot(dir);\n    \/\/ Yakla\u015f\u0131k ni\u015fan (koni)\n    if(dot>0.92 && dist<hitDist){ hit=m; hitDist=dist; }\n  }\n  if(hit){\n    hit.hp-=CONFIG.GUN_DAMAGE;\n    \/\/ Vurulunca geri tepme\n    const push=hit.mesh.position.clone().sub(camera.position).normalize();\n    hit.mesh.position.x+=push.x*0.8;\n    hit.mesh.position.z+=push.z*0.8;\n    playMonsterScream(false);\n    if(hit.hp<=0){\n      hit.dead=true;\n      hit.mesh.visible=false;\n      showStory('Varl\u0131k yok edildi.',2000);\n      \/\/ Bir s\u00fcre sonra ba\u015fka yerde yeniden do\u011fsun\n      setTimeout(()=>{\n        if(!hit) return;\n        hit.dead=false; hit.hp=hit.maxHp;\n        teleportMonsterAway(hit);\n        hit.mesh.visible=true;\n        hit.state='patrol';\n      }, 12000+Math.random()*8000);\n    } else {\n      \/\/ Hasar al\u0131nca ka\u00e7ma \u015fans\u0131\n      if(Math.random()<0.45){\n        teleportMonsterAway(hit);\n        showStory('Varl\u0131k isabet ald\u0131 ve ka\u00e7t\u0131.',1800);\n      } else {\n        hit.state='chase';\n        showStory('\u0130sabet! ('+Math.ceil(hit.hp)+' can)',1200);\n      }\n    }\n  }\n  if(Player.ammo<=0) showStory('Mermi bitti!',1800);\n}\nfunction onKeyDown(e){\n  if(GameState.menu||GameState.dead||GameState.won)return;\n  if(GameState.readingNote){ if(e.code==='Escape'||e.code==='KeyE')closeNote(); return; }\n  Player.keys[e.code]=true;\n  if(e.code==='KeyF')toggleFlash();\n  if(e.code==='KeyE')tryInteract();\n  if(e.code==='KeyC')Player.isCrouching=!Player.isCrouching;\n  if(e.code==='Escape')togglePause();\n  if(e.code==='Digit1')selectSlot(0); if(e.code==='Digit2')selectSlot(1);\n  if(e.code==='Digit3')selectSlot(2); if(e.code==='Digit4')selectSlot(3); if(e.code==='Digit5')selectSlot(4);\n  if(e.code==='Space'&&canJump&&!Player.isCrouching){ Player.velocityY=CONFIG.JUMP_FORCE; canJump=false; }\n}\nfunction onMouseMove(e){\n  if(!isPointerLocked||GameState.paused||!GameState.playing)return;\n  const s=CONFIG.MOUSE_SENSITIVITY*GameState.sensitivity*0.002;\n  camera.rotation.y-=e.movementX*s; camera.rotation.x-=e.movementY*s;\n  camera.rotation.x=Math.max(-1.3,Math.min(1.3,camera.rotation.x));\n}\nfunction toggleFlash(){\n  if(Player.battery<=0){ Player.flashlightOn=false; showStory('Fener s\u00f6nd\u00fc.',1800); return; }\n  Player.flashlightOn=!Player.flashlightOn;\n  flashlight.visible=Player.flashlightOn; flashlight.intensity=Player.flashlightOn?1.6:0;\n}\nfunction togglePause(){\n  if(!GameState.playing||GameState.dead||GameState.won)return;\n  GameState.paused=!GameState.paused;\n  dom.pauseMenu.classList.toggle('visible',GameState.paused);\n  if(GameState.paused)document.exitPointerLock(); else document.body.requestPointerLock();\n}\nfunction selectSlot(i){\n  Player.selectedSlot=i;\n  dom.invSlots.forEach((s,idx)=>s.classList.toggle('selected',idx===i));\n  const item=Player.inventory[i];\n  if(item==='medkit'&&Player.health<100){ Player.health=Math.min(100,Player.health+45); Player.inventory[i]=null; updateInvUI(); showStory('Medkit.',1800); playPickup(); }\n  else if(item==='battery'){ Player.battery=Math.min(100,Player.battery+50); Player.inventory[i]=null; updateInvUI(); showStory('Pil tak\u0131ld\u0131.',1800); playPickup(); }\n}\nfunction tryInteract(){\n  if(!GameState.playing||GameState.paused)return;\n  let closest=null, minD=CONFIG.INTERACT_RANGE;\n  for(const inter of interactables){\n    if(!inter.interactable||inter.collected)continue;\n    const pos=new THREE.Vector3(); inter.mesh.getWorldPosition(pos);\n    const d=camera.position.distanceTo(pos);\n    if(d<minD){ minD=d; closest=inter; }\n  }\n  if(closest)handleInteract(closest);\n}\nfunction handleInteract(obj){\n  if(obj.type==='note'){\n    openNote(obj.noteId);\n    if(!obj.collected){ obj.collected=true; obj.mesh.visible=false;\n      if(!Player.notesFound.includes(obj.noteId)){ Player.notesFound.push(obj.noteId); dom.loreCount.textContent=Player.notesFound.length; } }\n    playPickup();\n  } else if(obj.type==='item'){\n    const empty=Player.inventory.findIndex(s=>s===null);\n    if(empty===-1){ showStory('Envanter dolu.',1600); return; }\n    Player.inventory[empty]=obj.itemType; obj.collected=true; obj.mesh.visible=false;\n    if(obj.light)obj.light.visible=false; updateInvUI(); playPickup();\n    if(obj.itemType==='keycard'){\n      Player.hasKeycard=true;\n      revealExitLocation();\n      showStory('Anahtar kart al\u0131nd\u0131! \u00c7\u0131k\u0131\u015f kap\u0131s\u0131 ye\u015fil i\u015faretlendi \u2014 pusulay\u0131 takip et.',4000);\n    }\n    else if(obj.itemType==='gun'){\n      Player.hasGun=true;\n      Player.ammo+=6;\n      \/\/ Envanterde tutmaya gerek yok \u2014 direkt ku\u015fan\u0131l\u0131r\n      const idx=Player.inventory.indexOf('gun');\n      if(idx>=0) Player.inventory[idx]=null;\n      updateInvUI(); updateAmmoHUD();\n      showStory('Tabanca bulundu! T\u0131kla = ate\u015f. Mermi: '+Player.ammo,3500);\n    }\n    else if(obj.itemType==='ammo'){\n      Player.ammo+=5;\n      const idx=Player.inventory.indexOf('ammo');\n      if(idx>=0) Player.inventory[idx]=null;\n      updateInvUI(); updateAmmoHUD();\n      showStory('Mermi kutusu (+5). Toplam: '+Player.ammo,2500);\n    }\n    else if(obj.itemType==='medkit')showStory('Medkit.',1800);\n    else if(obj.itemType==='battery')showStory('Pil.',1800);\n  } else if(obj.type==='exit'){\n    if(!Player.hasKeycard){ showStory('Kart okuyucu k\u0131rm\u0131z\u0131. Anahtar kart laz\u0131m.',2400); return; }\n    showStory('Kap\u0131 a\u00e7\u0131ld\u0131. Backrooms geride kal\u0131yor...',2800);\n    setTimeout(()=>triggerWin(),2000);\n  }\n}\nfunction openNote(id){\n  const n=NOTES[id]; if(!n)return;\n  GameState.readingNote=true; dom.noteTitle.textContent=n.title; dom.noteBody.innerHTML=n.body;\n  dom.noteViewer.classList.add('visible'); document.exitPointerLock();\n}\nfunction closeNote(){\n  GameState.readingNote=false; dom.noteViewer.classList.remove('visible');\n  if(GameState.playing&&!GameState.paused)document.body.requestPointerLock();\n}\nfunction updateInvUI(){\n  const icons={keycard:'\ud83e\udeaa',medkit:'\ud83d\udc8a',battery:'\ud83d\udd0b',gun:'\ud83d\udd2b',ammo:'\ud83d\udce6'};\n  dom.invSlots.forEach((slot,i)=>{\n    const key=slot.querySelector('.slot-key'); slot.innerHTML=''; if(key)slot.appendChild(key);\n    if(Player.inventory[i]){ const s=document.createElement('span'); s.textContent=icons[Player.inventory[i]]||'?'; s.style.fontSize='1.15rem'; slot.insertBefore(s,key); }\n  });\n}\nfunction showStory(text,dur=3200){\n  dom.storyText.textContent=text; dom.storyText.classList.add('visible');\n  clearTimeout(showStory._t); showStory._t=setTimeout(()=>dom.storyText.classList.remove('visible'),dur);\n}\n\n\/\/ Canavar duvar \u00e7arp\u0131\u015fmas\u0131 \u2014 duvar i\u00e7inden ge\u00e7emez\nconst MONSTER_RADIUS=0.4;\nfunction monsterBlocked(x,z){\n  for(const wall of colliders){\n    const box=new THREE.Box3().setFromObject(wall);\n    box.min.x-=MONSTER_RADIUS; box.max.x+=MONSTER_RADIUS;\n    box.min.z-=MONSTER_RADIUS; box.max.z+=MONSTER_RADIUS;\n    box.min.y=-5; box.max.y=10;\n    if(box.containsPoint(new THREE.Vector3(x,1,z))) return true;\n  }\n  return false;\n}\n\/\/ Eksensel kayma: \u00f6nce X+Z, olmazsa sadece X, olmazsa sadece Z\nfunction moveMonster(m, nx, nz){\n  if(isInSafeZone({x:nx,z:nz})) return false;\n  const ox=m.mesh.position.x, oz=m.mesh.position.z;\n  if(!monsterBlocked(nx,nz)){ m.mesh.position.x=nx; m.mesh.position.z=nz; return true; }\n  if(!monsterBlocked(nx,oz)){ m.mesh.position.x=nx; return true; }\n  if(!monsterBlocked(ox,nz)){ m.mesh.position.z=nz; return true; }\n  return false;\n}\n\nfunction updateOneMonster(m, dt, pPos, playerSafe, t){\n  if(m.dead||!m.mesh) return;\n  if(!m.mesh.visible && m.state!=='patrol') return;\n  const mPos=m.mesh.position.clone(); mPos.y=0;\n  let dist=pPos.distanceTo(mPos);\n\n  \/\/ Animasyon\n  m.userData.aL.rotation.z=0.55+Math.sin(t*3.5+m.patrolIdx)*0.4;\n  m.userData.aR.rotation.z=-0.55-Math.sin(t*3.3+m.patrolIdx)*0.4;\n  m.mesh.position.y=Math.sin(t*2.8+m.patrolIdx)*0.07;\n  m.userData.eL.scale.setScalar(1+Math.sin(t*10)*0.2);\n  m.userData.eR.scale.setScalar(1+Math.sin(t*10+1)*0.2);\n  if(m.attackCooldown>0) m.attackCooldown-=dt;\n\n  \/\/ G\u00fcvenli b\u00f6lgeye giremez \u2014 d\u0131\u015far\u0131 it\n  if(isInSafeZone(mPos)){\n    const away=mPos.clone().sub(safeZoneCenter).normalize();\n    moveMonster(m, m.mesh.position.x+away.x*CONFIG.MONSTER_SPEED*1.8*dt, m.mesh.position.z+away.z*CONFIG.MONSTER_SPEED*1.8*dt);\n    if(m.state==='chase'||m.state==='attack') m.state='patrol';\n  }\n\n  const detectRange=CONFIG.MONSTER_DETECT*m.detect;\n  const canSee=dist<detectRange && !playerSafe;\n  const canHear=Player.isRunning && dist<CONFIG.MONSTER_HEAR*m.detect && !playerSafe;\n\n  if(!playerSafe && dist<5){\n    Player.sanity=Math.max(0, Player.sanity-CONFIG.SANITY_DRAIN_NEAR*dt*0.7);\n    if(dist<2.8 && Math.random()<0.03) playHeartbeat();\n    if(dist<CONFIG.MONSTER_ATTACK+0.9 && performance.now()-lastProximityScream>2500){\n      playMonsterScream(false); lastProximityScream=performance.now(); triggerMiniScare();\n    }\n  }\n\n  if(m.state==='patrol'){\n    if(canSee||canHear){\n      m.state='chase'; m.loseTimer=CONFIG.MONSTER_LOSE;\n      playMonsterScream(true); triggerMiniScare();\n    } else if(patrolPoints.length){\n      const target=patrolPoints[m.patrolIdx % patrolPoints.length];\n      if(isInSafeZone(target)){ m.patrolIdx++; return; }\n      const dir=target.clone().sub(mPos).normalize();\n      const next=mPos.clone().addScaledVector(dir, CONFIG.MONSTER_SPEED*m.speedMul*dt);\n      const moved=moveMonster(m, next.x, next.z);\n      \/\/ Duvara tak\u0131ld\u0131ysa sonraki patrol noktas\u0131na ge\u00e7\n      if(!moved) m.patrolIdx++;\n      m.mesh.lookAt(target.x, m.mesh.position.y+1.5, target.z);\n      if(mPos.distanceTo(target)<2) m.patrolIdx++;\n    }\n  } else if(m.state==='chase'){\n    if(playerSafe){\n      teleportMonsterAway(m);\n      return;\n    }\n    const dir=pPos.clone().sub(mPos).normalize();\n    let spd=CONFIG.MONSTER_CHASE_SPEED*m.speedMul;\n    if(dist<3.2) spd*=0.45;\n    if(dist<CONFIG.MONSTER_MIN_DIST+0.3) spd*=0.25;\n    if(dist>CONFIG.MONSTER_MIN_DIST){\n      const next=mPos.clone().addScaledVector(dir, spd*dt);\n      if(!moveMonster(m, next.x, next.z)){\n        \/\/ Duvar engelliyorsa yan kayma dene\n        const tan=new THREE.Vector3(-dir.z,0,dir.x);\n        moveMonster(m, mPos.x+tan.x*CONFIG.MONSTER_SPEED*0.7*dt, mPos.z+tan.z*CONFIG.MONSTER_SPEED*0.7*dt);\n      }\n    } else {\n      const side=new THREE.Vector3(-dir.z,0,dir.x);\n      moveMonster(m, mPos.x+side.x*CONFIG.MONSTER_SPEED*0.35*dt, mPos.z+side.z*CONFIG.MONSTER_SPEED*0.35*dt);\n    }\n    m.mesh.lookAt(pPos.x, m.mesh.position.y+1.5, pPos.z);\n    m.userData.glow.intensity=1.4;\n    \/\/ G\u00fcncel mesafe (hareket sonras\u0131)\n    dist=pPos.distanceTo(new THREE.Vector3(m.mesh.position.x,0,m.mesh.position.z));\n    if(dist<CONFIG.MONSTER_ATTACK && m.attackCooldown<=0 && !playerSafe){\n      m.state='attack'; m.attackCooldown=CONFIG.MONSTER_ATTACK_COOLDOWN;\n      damagePlayer(m.dmg); triggerJumpscare();\n      if(Math.random()<CONFIG.MONSTER_TELEPORT_AFTER_ATTACK){\n        setTimeout(()=>{\n          if(m && !m.dead && m.state!=='patrol'){\n            teleportMonsterAway(m);\n            showStory('Varl\u0131k kayboldu... uzak bir koridora \u00e7ekildi.', 2200);\n          }\n        }, 500);\n      }\n    }\n    if(!canSee&&!canHear){\n      m.loseTimer-=dt;\n      if(m.loseTimer<=0){ m.state='search'; m.lastPlayerPos.copy(pPos); m.userData.glow.intensity=0.4; }\n    } else m.loseTimer=CONFIG.MONSTER_LOSE;\n    if(Math.random()<0.008) playMonsterScream(true);\n  } else if(m.state==='search'){\n    if(playerSafe){ teleportMonsterAway(m); return; }\n    const dir=m.lastPlayerPos.clone().sub(mPos).normalize();\n    const next=mPos.clone().addScaledVector(dir, CONFIG.MONSTER_SPEED*m.speedMul*0.5*dt);\n    if(!moveMonster(m, next.x, next.z)) m.state='patrol';\n    if(mPos.distanceTo(m.lastPlayerPos)<2) m.state='patrol';\n    if(canSee||canHear){ m.state='chase'; m.loseTimer=CONFIG.MONSTER_LOSE; playMonsterScream(true); }\n  } else if(m.state==='attack'){\n    const dir=pPos.clone().sub(mPos).normalize();\n    if(dist<CONFIG.MONSTER_MIN_DIST){\n      moveMonster(m, mPos.x-dir.x*2*dt, mPos.z-dir.z*2*dt);\n    }\n    m.attackCooldown=Math.max(m.attackCooldown, 0.5);\n    if(m.attackCooldown<=CONFIG.MONSTER_ATTACK_COOLDOWN-0.65) m.state='chase';\n  }\n}\n\nfunction updateMonsters(dt){\n  if(GameState.dead||GameState.won||!monsters.length) return;\n  const pPos=camera.position.clone(); pPos.y=0;\n  const playerSafe=isInSafeZone(pPos);\n  const t=performance.now()*0.001;\n\n  \/\/ G\u00fcvenli odaya YEN\u0130 girildi\u011finde: pe\u015findeki t\u00fcm canavarlar yok olsun\n  if(playerSafe && !wasInSafeZone){\n    let anyChasing=false;\n    for(const m of monsters){\n      if(m.state==='chase'||m.state==='attack'||m.state==='search'){\n        teleportMonsterAway(m);\n        anyChasing=true;\n      }\n    }\n    if(anyChasing){\n      showStory('G\u00fcvenli odaya s\u0131\u011f\u0131nd\u0131n. Varl\u0131klar da\u011f\u0131ld\u0131... ba\u015fka koridorlarda bekliyorlar.', 3500);\n      playMonsterScream(false);\n    }\n  }\n  wasInSafeZone=playerSafe;\n\n  for(const m of monsters) updateOneMonster(m, dt, pPos, playerSafe, t);\n}\n\nfunction damagePlayer(amt){\n  if(Player.inSafeZone)return;\n  Player.health=Math.max(0,Player.health-amt);\n  dom.bloodOverlay.style.opacity='0.7'; setTimeout(()=>dom.bloodOverlay.style.opacity='0',420);\n  playHeartbeat();\n  if(Player.health<=0)triggerDeath();\n}\nfunction triggerJumpscare(){\n  dom.jumpscare.classList.add('active'); playJumpscareSound();\n  const orig=camera.position.clone(); let sh=0;\n  const sk=setInterval(()=>{ camera.position.x=orig.x+(Math.random()-0.5)*0.3; camera.position.y=orig.y+(Math.random()-0.5)*0.18; sh++; if(sh>12){ camera.position.copy(orig); clearInterval(sk); } },22);\n  setTimeout(()=>dom.jumpscare.classList.remove('active'),300);\n}\nfunction triggerMiniScare(){ dom.screamFlash.style.opacity='0.45'; setTimeout(()=>dom.screamFlash.style.opacity='0',80); }\nfunction triggerDeath(){\n  GameState.dead=true; GameState.playing=false; document.exitPointerLock();\n  dom.hud.classList.remove('visible');\n  dom.overlayTitle.textContent='KAYBOLDUN';\n  dom.overlayMsg.textContent='Backrooms seni sonsuza dek tuttu. Koridorlar hi\u00e7 bitmiyor...';\n  dom.overlayScreen.classList.add('visible'); playJumpscareSound();\n}\nfunction triggerWin(){\n  GameState.won=true; GameState.playing=false; document.exitPointerLock();\n  dom.hud.classList.remove('visible');\n  dom.overlayTitle.textContent='\u00c7IKI\u015e';\n  dom.overlayMsg.textContent=`Kart okundu. Kap\u0131 kapand\u0131. Kay\u0131tlar: ${Player.notesFound.length}\/6`;\n  dom.overlayScreen.classList.add('visible');\n}\n\nfunction updatePlayer(dt){\n  if(!GameState.playing||GameState.paused||GameState.readingNote)return;\n  const speed=Player.isCrouching?CONFIG.PLAYER_CROUCH_SPEED:((Player.keys['ShiftLeft']||Player.keys['ShiftRight'])&&Player.stamina>0)?CONFIG.PLAYER_RUN_SPEED:CONFIG.PLAYER_SPEED;\n  Player.isRunning=(Player.keys['ShiftLeft']||Player.keys['ShiftRight'])&&Player.stamina>0&&!Player.isCrouching;\n  direction.set(0,0,0);\n  if(Player.keys['KeyW']||Player.keys['ArrowUp'])direction.z-=1;\n  if(Player.keys['KeyS']||Player.keys['ArrowDown'])direction.z+=1;\n  if(Player.keys['KeyA']||Player.keys['ArrowLeft'])direction.x-=1;\n  if(Player.keys['KeyD']||Player.keys['ArrowRight'])direction.x+=1;\n  direction.normalize();\n  const yaw=new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,1,0),camera.rotation.y);\n  const forward=new THREE.Vector3(0,0,-1).applyQuaternion(yaw);\n  const right=new THREE.Vector3(1,0,0).applyQuaternion(yaw);\n  const move=new THREE.Vector3().addScaledVector(forward,-direction.z*speed*dt).addScaledVector(right,direction.x*speed*dt);\n  const newPos=camera.position.clone().add(move);\n  let canMove=true;\n  for(const wall of colliders){\n    const box=new THREE.Box3().setFromObject(wall);\n    box.min.x-=CONFIG.PLAYER_RADIUS; box.max.x+=CONFIG.PLAYER_RADIUS;\n    box.min.z-=CONFIG.PLAYER_RADIUS; box.max.z+=CONFIG.PLAYER_RADIUS;\n    box.min.y=-5; box.max.y=10;\n    if(box.containsPoint(new THREE.Vector3(newPos.x,1,newPos.z))){ canMove=false; break; }\n  }\n  if(canMove){ camera.position.x=newPos.x; camera.position.z=newPos.z; }\n  Player.velocityY-=CONFIG.GRAVITY*dt; camera.position.y+=Player.velocityY*dt;\n  const th=Player.isCrouching?CONFIG.PLAYER_CROUCH_HEIGHT:CONFIG.PLAYER_HEIGHT;\n  if(camera.position.y<=th){ camera.position.y=th; Player.velocityY=0; canJump=true; }\n\n  Player.inSafeZone=isInSafeZone(camera.position);\n  if(Player.inSafeZone){\n    dom.safeText.textContent='G\u00dcVENL\u0130 ODA'; dom.safeIndicator.classList.add('safe');\n    dom.infoBox.classList.add('visible');\n    Player.sanity=Math.min(100,Player.sanity+CONFIG.SANITY_REGEN*1.8*dt);\n  } else {\n    dom.safeText.textContent='Koridor'; dom.safeIndicator.classList.remove('safe');\n    dom.infoBox.classList.remove('visible');\n  }\n\n  if(Player.isRunning&&direction.length()>0)Player.stamina=Math.max(0,Player.stamina-CONFIG.STAMINA_DRAIN*dt);\n  else Player.stamina=Math.min(100,Player.stamina+CONFIG.STAMINA_REGEN*dt);\n  if(Player.flashlightOn&&Player.battery>0){\n    Player.battery=Math.max(0,Player.battery-CONFIG.BATTERY_DRAIN*dt);\n    if(Player.battery<=0){ Player.flashlightOn=false; flashlight.visible=false; showStory('Fener s\u00f6nd\u00fc.',2200); }\n  }\n  if(!Player.flashlightOn&&!Player.inSafeZone)Player.sanity=Math.max(0,Player.sanity-CONFIG.SANITY_DRAIN_DARK*dt);\n  else if(Player.flashlightOn)Player.sanity=Math.min(100,Player.sanity+CONFIG.SANITY_REGEN*dt);\n\n  flashlight.position.copy(camera.position);\n  const look=new THREE.Vector3(0,0,-1).applyQuaternion(camera.quaternion);\n  flashlight.target.position.copy(camera.position).add(look); flashlight.target.updateMatrixWorld();\n\n  if(direction.length()>0&&canJump){ Player.footTimer-=dt; if(Player.footTimer<=0){ playFootstep(); Player.footTimer=Player.isRunning?0.3:0.5; } }\n\n  let showP=false;\n  for(const inter of interactables){\n    if(!inter.interactable||inter.collected)continue;\n    const pos=new THREE.Vector3(); inter.mesh.getWorldPosition(pos);\n    if(camera.position.distanceTo(pos)<CONFIG.INTERACT_RANGE){ showP=true; break; }\n  }\n  dom.interactPrompt.classList.toggle('visible',showP);\n  dom.sanityOverlay.style.opacity=Math.max(0,(100-Player.sanity)\/100*0.6);\n  if(Player.health<30&&Math.random()<0.015)playHeartbeat();\n  if(Player.gunCooldown>0) Player.gunCooldown=Math.max(0, Player.gunCooldown-dt);\n  updateHUD();\n}\nfunction updateHUD(){\n  dom.healthText.textContent=Math.ceil(Player.health); dom.healthBar.style.width=Player.health+'%';\n  dom.batteryText.textContent=Math.ceil(Player.battery)+'%'; dom.batteryBar.style.width=Player.battery+'%';\n  dom.sanityText.textContent=Math.ceil(Player.sanity); dom.sanityBar.style.width=Player.sanity+'%';\n  dom.staminaText.textContent=Math.ceil(Player.stamina); dom.staminaBar.style.width=Player.stamina+'%';\n}\nfunction updateAmmoHUD(){\n  let el=document.getElementById('ammo-hud');\n  if(!el){\n    el=document.createElement('div');\n    el.id='ammo-hud';\n    el.style.cssText='position:absolute;bottom:70px;right:16px;background:rgba(10,10,8,.85);border:1px solid #3a3520;padding:6px 12px;font-family:Share Tech Mono,monospace;font-size:.8rem;color:#ccc;display:none';\n    document.getElementById('hud').appendChild(el);\n  }\n  if(Player.hasGun){\n    el.style.display='block';\n    el.innerHTML='\ud83d\udd2b Mermi: <b style=\"color:#c8b060\">'+Player.ammo+'<\/b>';\n  } else el.style.display='none';\n}\nfunction updateFlicker(dt){\n  const t=performance.now()*0.001;\n  flickerLights.forEach(fl=>{\n    if(fl.broken){\n      if(Math.random()<0.03) fl.light.intensity=fl.base*(Math.random()>0.5?0.05:1.1);\n      fl.fixture.material.emissiveIntensity=fl.light.intensity>0.2?0.5:0.05;\n    } else {\n      fl.light.intensity=fl.base*(0.85+Math.sin(t*2+fl.phase)*0.15+Math.random()*0.05);\n    }\n  });\n}\n\n\/\/ ===== TELSIZ PARAZ\u0130T\u0130 =====\nfunction startRadio(){\n  if(!audioCtx) return;\n  try{\n    if(radioOsc){ try{radioOsc.stop();}catch(e){} }\n    radioOsc=audioCtx.createOscillator();\n    radioFilter=audioCtx.createBiquadFilter();\n    radioGainNode=audioCtx.createGain();\n    radioOsc.type='sawtooth';\n    radioOsc.frequency.value=80;\n    radioFilter.type='bandpass';\n    radioFilter.frequency.value=900;\n    radioFilter.Q.value=0.7;\n    radioGainNode.gain.value=0.001;\n    radioOsc.connect(radioFilter);\n    radioFilter.connect(radioGainNode);\n    radioGainNode.connect(masterGain);\n    radioOsc.start();\n  }catch(e){}\n}\nfunction updateRadio(){\n  if(!radioGainNode||!audioCtx||!GameState.playing) return;\n  const nm=nearestMonster();\n  let proximity=0;\n  if(nm&&nm.mesh){\n    const d=camera.position.distanceTo(nm.mesh.position);\n    proximity=Math.max(0, 1-d\/14); \/\/ 14m i\u00e7inde artar\n  }\n  \/\/ Ak\u0131l d\u00fc\u015f\u00fckse de c\u0131z\u0131rt\u0131\n  const sanityNoise=(100-Player.sanity)\/100*0.35;\n  const level=(proximity*0.22 + sanityNoise*0.12)*GameState.volume;\n  radioGainNode.gain.setTargetAtTime(Math.max(0.001, level), audioCtx.currentTime, 0.08);\n  if(radioOsc) radioOsc.frequency.setTargetAtTime(60+proximity*140+Math.random()*30, audioCtx.currentTime, 0.05);\n  if(radioFilter) radioFilter.frequency.setTargetAtTime(400+proximity*1200, audioCtx.currentTime, 0.1);\n}\n\n\/\/ ===== AKIL HALL\u00dcS\u0130NASYONLARI =====\nfunction spawnPhantom(){\n  if(!scene||phantoms.length>4) return;\n  const dir=new THREE.Vector3((Math.random()-0.5)*2, 0, (Math.random()-0.5)*2).normalize();\n  const dist=4+Math.random()*7;\n  const pos=camera.position.clone().add(dir.multiplyScalar(dist));\n  pos.y=0;\n  if(isInSafeZone(pos)||monsterBlocked(pos.x,pos.z)) return;\n\n  const g=new THREE.Group();\n  const mat=new THREE.MeshBasicMaterial({ color:0x111108, transparent:true, opacity:0.55 });\n  const body=new THREE.Mesh(new THREE.CylinderGeometry(0.15,0.25,1.5,5), mat);\n  body.position.y=1.2; g.add(body);\n  const head=new THREE.Mesh(new THREE.SphereGeometry(0.22,5,5), mat);\n  head.position.y=2.1; g.add(head);\n  g.position.copy(pos);\n  scene.add(g);\n  phantoms.push({ mesh:g, life:1.2+Math.random()*1.5, mat });\n}\nfunction updateHallucinations(dt){\n  const sanity=Player.sanity;\n  const now=performance.now();\n\n  \/\/ D\u00fc\u015f\u00fck ak\u0131l \u2192 fantom g\u00f6lge\n  if(sanity<55 && now-lastPhantomTime > (sanity<25?2500:5000)){\n    if(Math.random()<0.4) spawnPhantom();\n    lastPhantomTime=now;\n  }\n  \/\/ Fantomlar\u0131 solukla\u015ft\u0131r \/ yok et\n  for(let i=phantoms.length-1;i>=0;i--){\n    const p=phantoms[i];\n    p.life-=dt;\n    if(p.mat) p.mat.opacity=Math.max(0, p.life\/2*0.55);\n    \/\/ Hafif oyuncuya bak\n    if(p.mesh) p.mesh.lookAt(camera.position.x, p.mesh.position.y, camera.position.z);\n    if(p.life<=0){\n      scene.remove(p.mesh);\n      phantoms.splice(i,1);\n    }\n  }\n\n  \/\/ Ters ayak sesi (yanl\u0131\u015f y\u00f6n)\n  if(sanity<40 && now-lastReverseFoot>3000 && Math.random()<0.25){\n    lastReverseFoot=now;\n    if(audioCtx){\n      try{\n        const pan=audioCtx.createStereoPanner();\n        pan.pan.value=(Math.random()>0.5?1:-1)*(0.6+Math.random()*0.4);\n        pan.connect(masterGain);\n        const o=audioCtx.createOscillator(), g=audioCtx.createGain(), f=audioCtx.createBiquadFilter();\n        f.type='lowpass'; f.frequency.value=120;\n        o.type='triangle'; o.frequency.value=35+Math.random()*25;\n        g.gain.setValueAtTime(0.14*GameState.volume, audioCtx.currentTime);\n        g.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime+0.25);\n        o.connect(f); f.connect(g); g.connect(pan);\n        o.start(); o.stop(audioCtx.currentTime+0.25);\n      }catch(e){}\n    }\n  }\n\n  \/\/ \u00c7ok d\u00fc\u015f\u00fck ak\u0131l \u2192 sis yo\u011funla\u015f\u0131r, vignette artar\n  if(scene.fog){\n    const base=0.055;\n    scene.fog.density=base+(100-sanity)\/100*0.04;\n  }\n  if(dom.sanityOverlay){\n    dom.sanityOverlay.style.opacity=Math.max(0,(100-sanity)\/100*0.7);\n  }\n}\n\nfunction animate(){\n  requestAnimationFrame(animate);\n  const time=performance.now();\n  const dt=Math.min((time-prevTime)\/1000,0.1);\n  prevTime=time;\n  if(GameState.playing&&!GameState.paused&&!GameState.dead&&!GameState.won){\n    updatePlayer(dt); updateMonsters(dt); updateFlicker(dt); updateExitCompass();\n    updateRadio(); updateHallucinations(dt);\n  }\n  renderer.render(scene,camera);\n}\n\nfunction init(){\n  cacheDOM();\n  scene=new THREE.Scene();\n  scene.background=new THREE.Color(0x1a1810);\n  scene.fog=new THREE.FogExp2(0x1a1810, 0.055); \/\/ hacimsel sis hissi\n\n  camera=new THREE.PerspectiveCamera(CONFIG.FOV, innerWidth\/innerHeight, 0.1, 45);\n  camera.rotation.order='YXZ';\n\n  renderer=new THREE.WebGLRenderer({ antialias:true, powerPreference:'high-performance' });\n  renderer.setSize(innerWidth,innerHeight);\n  renderer.setPixelRatio(Math.min(devicePixelRatio,2));\n  renderer.shadowMap.enabled=true;\n  renderer.shadowMap.type=THREE.PCFSoftShadowMap;\n  renderer.toneMapping=THREE.ACESFilmicToneMapping;\n  renderer.toneMappingExposure=0.75; \/\/ daha karanl\u0131k, klostrofobik\n  document.getElementById('game-container').insertBefore(renderer.domElement, document.getElementById('game-container').firstChild);\n\n  scene.add(new THREE.AmbientLight(0x3a3828, 0.2));\n  scene.add(new THREE.HemisphereLight(0x4a4838, 0x1a1810, 0.15));\n\n  flashlight=new THREE.SpotLight(0xfff0d0, 1.6, CONFIG.FLASHLIGHT_RANGE, CONFIG.FLASHLIGHT_ANGLE, 0.45, 1.4);\n  flashlight.castShadow=true; flashlight.shadow.mapSize.set(1024,1024);\n  scene.add(flashlight); scene.add(flashlight.target);\n\n  updateLoad(15,'Labirent \u00fcretiliyor...');\n  initMaze();\n  updateLoad(35,'Koridorlar olu\u015fuyor...');\n  buildBackrooms();\n  updateLoad(65,'Varl\u0131klar uyan\u0131yor...');\n  createAllMonsters();\n  const spawn=gridToWorld(spawnCell.gx,spawnCell.gz);\n  camera.position.set(spawn.x, CONFIG.PLAYER_HEIGHT, spawn.z);\n  updateLoad(85,'Sistemler...');\n  setupControls(); setupMenu();\n  updateLoad(100,'Haz\u0131r');\n  setTimeout(()=>{ document.getElementById('loading').classList.add('hidden'); GameState.loading=false; },450);\n  window.addEventListener('resize',()=>{ camera.aspect=innerWidth\/innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth,innerHeight); });\n  animate();\n}\nfunction updateLoad(pct,status){ dom.loaderFill.style.width=pct+'%'; dom.loadStatus.textContent=status; }\n\nfunction setupMenu(){\n  document.getElementById('btn-start').onclick=startGame;\n  document.getElementById('btn-resume').onclick=()=>{ GameState.paused=false; dom.pauseMenu.classList.remove('visible'); document.body.requestPointerLock(); };\n  document.getElementById('btn-restart').onclick=()=>location.reload();\n  document.getElementById('btn-mainmenu').onclick=()=>location.reload();\n  document.getElementById('btn-retry').onclick=()=>location.reload();\n  document.getElementById('btn-to-menu').onclick=()=>location.reload();\n  document.getElementById('note-close').onclick=closeNote;\n  document.getElementById('btn-settings').onclick=()=>{\n    dom.settingsPanel.classList.add('visible');\n    ['btn-start','btn-settings','btn-controls'].forEach(id=>document.getElementById(id).style.display='none');\n  };\n  document.getElementById('btn-settings-back').onclick=()=>{\n    dom.settingsPanel.classList.remove('visible');\n    ['btn-start','btn-settings','btn-controls'].forEach(id=>document.getElementById(id).style.display='');\n  };\n  document.getElementById('sens-slider').oninput=e=>{ GameState.sensitivity=parseFloat(e.target.value); };\n  document.getElementById('vol-slider').oninput=e=>{ GameState.volume=parseFloat(e.target.value); if(masterGain)masterGain.gain.value=GameState.volume; };\n  document.getElementById('js-vol-slider').oninput=e=>{ GameState.jsVolume=parseFloat(e.target.value); if(screamGain)screamGain.gain.value=GameState.jsVolume; };\n  document.getElementById('btn-controls').onclick=()=>showStory('WASD | SHIFT ko\u015f | F fener | E al | TIKLA ate\u015f | C e\u011fil | ESC | G\u00fcvenli oda = ye\u015fil',5500);\n}\n\nfunction startGame(){\n  initAudio();\n  if(audioCtx&&audioCtx.state==='suspended')audioCtx.resume();\n  GameState.menu=false; GameState.playing=true;\n  dom.mainMenu.classList.add('hidden'); dom.hud.classList.add('visible');\n  const spawn=gridToWorld(spawnCell.gx,spawnCell.gz);\n  camera.position.set(spawn.x,CONFIG.PLAYER_HEIGHT,spawn.z); camera.rotation.set(0,0,0);\n  Player.health=100; Player.battery=100; Player.sanity=100; Player.stamina=100;\n  Player.flashlightOn=true; flashlight.visible=true; flashlight.intensity=1.6;\n  Player.hasGun=false; Player.ammo=0; updateAmmoHUD();\n  startRadio();\n  showStory('Bu labirent her seferinde farkl\u0131. Telsiz varl\u0131k yakla\u015f\u0131nca c\u0131z\u0131rdar. Ak\u0131l d\u00fc\u015f\u00fcnce hall\u00fcsinasyon ba\u015flar.',5500);\n  setTimeout(()=>document.body.requestPointerLock(),350);\n}\n\ninit();\n})();\n<\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Ana Sayfa Backrooms Labirent &#8211; Uras Uzay BACKROOMS Seviye y\u00fckleniyor&#8230; Ba\u015flat\u0131l\u0131yor BACKROOMS TERK ED\u0130LM\u0130\u015e KOR\u0130DORLAR \u2022 URAS UZAY OYUNA BA\u015eLA AYARLAR KONTROLLER Fare Ses Jumpscare GER\u0130 urasuzay.com \u2022 G\u00fcvenli oda \u2022 K\u0131rp\u0131\u015fan lambalar CAN100 FENER100% AKIL100 DAYANIKLILIK100 G\u00d6REV\u00c7\u0131k\u0131\u015f kart\u0131n\u0131 bul. G\u00fcvenli odaya s\u0131\u011f\u0131nabilirsin. Kay\u0131t: 0\/6 B\u00f6lge: Koridor E Etkile\u015fim 1 2 3 4 5 WASD [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-27","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/urasuzay.com\/index.php\/wp-json\/wp\/v2\/pages\/27","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/urasuzay.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/urasuzay.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/urasuzay.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/urasuzay.com\/index.php\/wp-json\/wp\/v2\/comments?post=27"}],"version-history":[{"count":22,"href":"https:\/\/urasuzay.com\/index.php\/wp-json\/wp\/v2\/pages\/27\/revisions"}],"predecessor-version":[{"id":204,"href":"https:\/\/urasuzay.com\/index.php\/wp-json\/wp\/v2\/pages\/27\/revisions\/204"}],"wp:attachment":[{"href":"https:\/\/urasuzay.com\/index.php\/wp-json\/wp\/v2\/media?parent=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}