THE LAST WATCH — Ultimate
by LunarPanda23626 lines36.9 KB
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>THE LAST WATCH — Ultimate</title>
<style>
:root{--bg:#070b12;--panel:#111b28;--line:#40546a;--text:#eaf3ff;--red:#ff4256;--green:#63efad;--gold:#ffdc8a}
*{box-sizing:border-box}
html,body{margin:0;width:100%;height:100%;overflow:hidden}
body{background:#05070b;color:var(--text);font-family:Arial,sans-serif;user-select:none}
button{font:inherit;cursor:pointer;color:inherit}
button:disabled{opacity:.35;cursor:not-allowed}
.hidden{display:none!important}
#game{height:100dvh;width:100%;min-height:430px;position:relative;overflow:hidden;background:#080d14}
#hud{height:59px;position:absolute;z-index:30;top:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;padding:6px 13px;gap:8px;background:linear-gradient(#030509,#0a1019);border-bottom:1px solid #39485b}
.logo{font-weight:1000;font-size:13px;letter-spacing:2px}
.logo span{color:#ff5366}
.sub{font-size:8px;color:#8598ad;letter-spacing:2px;margin-top:4px}
.stats{display:flex;gap:6px}
.stat{min-width:64px;padding:5px 7px;text-align:center;background:#101925;border:1px solid #35465a;border-radius:3px}
.stat small{font-size:8px;color:#8d9fb5;display:block}
.stat strong{font-size:13px;display:block;margin-top:3px}
#powerValue{color:var(--green)}
#usage{display:flex;justify-content:center;gap:3px;margin-top:4px}
.usage i{height:4px;width:7px;background:#3b4858}
.usage i.on{background:#64f0ae}.usage i.hot{background:#ff4356}
/* OFFICE */
#office{position:absolute;inset:59px 0 0;overflow:hidden;background:radial-gradient(ellipse at 50% 42%,#2b3642 0,#161e29 35%,#080c13 78%)}
#office:before{content:"";position:absolute;inset:0;pointer-events:none;background:repeating-linear-gradient(90deg,transparent 0 90px,#ffffff04 91px 92px)}
.ceiling{position:absolute;top:0;left:14%;right:14%;height:15%;background:linear-gradient(#3a4551,#171f2a);clip-path:polygon(12% 0,88% 0,100% 100%,0 100%);border-bottom:2px solid #526171}
.lamp{position:absolute;top:5%;left:50%;transform:translateX(-50%);width:18%;height:7px;background:#c5d9e8;box-shadow:0 0 28px 12px #9ccfff22}
.backwall{position:absolute;top:12%;bottom:17%;left:15%;right:15%;border:2px solid #344252;background:linear-gradient(90deg,#151e28,#27323e 50%,#151e28);box-shadow:inset 0 0 65px #0009}
.wallpanel{position:absolute;top:23%;height:27%;width:11%;background:#111923;border:2px solid #39495a;box-shadow:inset 0 0 20px #000}
.wallpanel.l{left:18%}.wallpanel.r{right:18%}
.warning{position:absolute;top:19%;left:50%;transform:translateX(-50%);padding:7px 12px;border:1px solid #65583c;background:#211e18;color:#dfc58c;font-size:9px;letter-spacing:1px;white-space:nowrap}
.monitor{position:absolute;top:40%;left:50%;transform:translateX(-50%);width:15%;min-width:80px;height:16%;border:7px solid #090d13;background:radial-gradient(ellipse,#314958,#0a121b 75%);box-shadow:0 0 0 2px #4b5c6b;display:flex;flex-direction:column;justify-content:center;align-items:center}
.monitor small{font-size:8px;color:#8fbad4;letter-spacing:2px}
.monitor strong{font-size:22px;margin-top:4px}
.floor{position:absolute;bottom:0;left:0;right:0;height:27%;clip-path:polygon(12% 0,88% 0,100% 100%,0 100%);border-top:3px solid #485664;background:repeating-linear-gradient(90deg,transparent 0 75px,#0005 76px 79px),repeating-linear-gradient(0deg,#202a35 0 29px,#111821 30px 32px)}
.desk{position:absolute;bottom:0;left:27%;right:27%;height:15%;z-index:7;clip-path:polygon(8% 0,92% 0,100% 100%,0 100%);background:linear-gradient(#566372,#1b242e 22%,#080b10);border-top:3px solid #71808d}
.desk:before{content:"";position:absolute;top:0;left:10%;right:10%;height:8px;background:#81909b}
.deskScreen{position:absolute;z-index:8;bottom:7%;left:50%;transform:translateX(-50%);min-width:75px;padding:7px;border:5px solid #101720;background:#0c1922;color:#82d9ff;text-align:center;font-size:8px;letter-spacing:2px}
/* Separate doors at the outer corners; short windows beside them */
.side{position:absolute;z-index:10;top:20%;bottom:20%;width:37%;display:flex;gap:9px;align-items:stretch}
.side.west{left:0;flex-direction:row}
.side.east{right:0;flex-direction:row}
.bay{position:relative;min-width:0;display:flex;flex-direction:column}
.doorBay{flex:1.08}
.windowBay{flex:.78;justify-content:center}
.bayLabel{text-align:center;font-size:8px;color:#9aacc0;letter-spacing:1px;height:20px;display:flex;align-items:center;justify-content:center;white-space:nowrap}
.frame{position:relative;flex:1;min-height:0;padding:6px;background:linear-gradient(135deg,#758493,#273544 22%,#101721 75%,#667887);border:2px solid #566879;box-shadow:0 0 0 2px #06090d,inset 0 0 0 2px #111720}
.inner{position:relative;width:100%;height:100%;overflow:hidden;border:3px solid #080c12;background:#030609}
.doorFrame{background:linear-gradient(135deg,#768696,#283746 25%,#101721 80%,#627383)}
.doorLeaf{position:absolute;z-index:4;inset:0;transform:translateX(105%);transition:transform .23s;background:repeating-linear-gradient(0deg,transparent 0 40px,#0004 41px 44px),linear-gradient(90deg,#172330,#465767 30%,#283745 68%,#111923);border:3px solid #82919c;box-shadow:inset 0 0 0 4px #111923,inset 0 0 20px #000}
.doorLeaf.closed{transform:translateX(0)}
.doorLeaf:before{content:"";position:absolute;inset:7%;border:2px solid #17222e;box-shadow:inset 0 0 0 2px #586b7c}
.doorLeaf:after{content:"";position:absolute;right:10%;top:49%;width:7px;height:7px;border-radius:50%;background:#f5d17c;box-shadow:0 0 7px #f5d17c}
.doorNumber{position:absolute;top:10px;left:0;right:0;text-align:center;font-size:9px;color:#8295a8;letter-spacing:2px}
.windowBay .frame{height:72%;flex:none;align-self:center;width:100%}
.glass{position:absolute;inset:0;overflow:hidden;background:radial-gradient(ellipse at 50% 45%,#263643,#0c141d 65%,#030609);transition:filter .1s}
.glass:before{content:"";position:absolute;inset:0;background:linear-gradient(90deg,transparent 48%,#080d14 49% 51%,transparent 52%),linear-gradient(0deg,transparent 48%,#080d14 49% 51%,transparent 52%);z-index:5}
.glass:after{content:"";position:absolute;inset:0;background:linear-gradient(115deg,transparent 30%,#bde4ff12 34% 36%,transparent 40%)}
.windowStatus{position:absolute;z-index:7;top:5px;left:5px;right:5px;font-size:7px;color:#95a8bb;display:flex;justify-content:space-between}
.glow{position:absolute;z-index:2;inset:0;opacity:0;background:radial-gradient(ellipse at 50% 50%,#fff6c9,#fff6 50%,transparent 78%);transition:opacity .1s}
.windowBay.lit .glow{opacity:1}
.windowBay.lit .glass{background:radial-gradient(ellipse at 50% 45%,#9ba6a5,#4b5a61 55%,#222d36)}
/* light spills across the whole side, including door area */
.sideLight{position:absolute;z-index:1;inset:-15px;pointer-events:none;opacity:0;background:radial-gradient(ellipse at 65% 48%,#fff2bd38,transparent 67%);transition:opacity .12s}
.side.lit .sideLight{opacity:1}
.creatureSlot{position:absolute;z-index:3;bottom:2%;left:50%;width:86%;height:85%;transform:translateX(-50%);opacity:0;transition:opacity .12s;filter:drop-shadow(0 0 10px #ff1e37aa)}
.windowBay.lit .creatureSlot.present{opacity:1}
.creature{position:absolute;inset:0}
.body{position:absolute;left:20%;right:20%;bottom:-5%;height:55%;background:linear-gradient(90deg,#10151b,#505961,#10151b);border:2px solid #070a0e;border-radius:45% 45% 5% 5%}
.head{position:absolute;left:17%;right:17%;top:8%;height:43%;background:linear-gradient(140deg,#78818a,#303942 55%,#080c11);border:3px solid #080b10;border-radius:42% 42% 28% 28%}
.eye{position:absolute;top:40%;height:9%;width:17%;background:#ff243b;box-shadow:0 0 10px 4px #ff243b;border-radius:50%}
.eye:first-child{left:17%}.eye:nth-child(2){right:17%}
.mouth{position:absolute;left:25%;right:25%;bottom:9%;height:23%;background:#030406;border:2px solid #090c10;border-radius:2px 2px 45% 45%}
.horn{position:absolute;top:-9%;width:20%;height:26%;background:#35414b;border:2px solid #080b10;clip-path:polygon(50% 0,100% 100%,0 100%)}
.horn.left{left:8%}.horn.right{right:8%}
.arm{position:absolute;top:47%;width:24%;height:43%;background:linear-gradient(90deg,#10151b,#545e65,#11161c);border:2px solid #080b10;border-radius:15px}
.arm.left{left:0;transform:rotate(14deg)}.arm.right{right:0;transform:rotate(-14deg)}
.grinner .head{background:linear-gradient(140deg,#b79b67,#4e3927,#14100c);border-radius:48% 48% 20% 20%}
.grinner .body{background:linear-gradient(90deg,#281b12,#796345,#1b140e)}
.grinner .eye{background:#ffe58d;box-shadow:0 0 12px 5px #ffbd3d}
.grinner .mouth{height:28%;border-radius:0;background:repeating-linear-gradient(90deg,#090909 0 4px,#d9c7a4 5px 7px)}
.stalker .head{background:linear-gradient(140deg,#3d607a,#142130,#03070c);border-radius:50% 50% 35% 35%}
.stalker .body{background:linear-gradient(90deg,#07121c,#2b5065,#07121c)}
.stalker .eye{height:5%;background:#67ddff;box-shadow:0 0 12px 5px #32bfff}
.stalker .mouth{left:39%;right:39%;height:26%}
.runner .head{background:linear-gradient(140deg,#9b3a44,#3b121b,#0b080c);border-radius:25% 25% 40% 40%}
.runner .body{background:linear-gradient(90deg,#210b11,#762633,#1a0910)}
.runner .eye{background:#ffb24a;box-shadow:0 0 12px 5px #ff6a22}
.runner .horn{height:17%;top:-12%}
.warden .head{background:linear-gradient(140deg,#858b94,#343b45,#10141a);border-radius:34% 34% 18% 18%}
.warden .body{background:linear-gradient(90deg,#15191f,#606771,#161a20)}
.warden .mouth{height:30%;border-radius:0 0 45% 45%;background:repeating-linear-gradient(90deg,#080a0d 0 5px,#c3cbd2 6px 8px)}
/* controls mounted directly over each door */
.controlDock{height:31px;display:flex;gap:4px;position:absolute;top:-34px;left:0;right:0;z-index:20}
.control{flex:1;min-width:0;border:1px solid #50647a;border-radius:3px;background:linear-gradient(#293a4d,#101923);font-size:8px;font-weight:900;box-shadow:0 3px 0 #030508;padding:0 2px}
.control.active.doorControl{background:linear-gradient(#b82e42,#55131e);border-color:#ff6979}
.control.active.lightControl{background:linear-gradient(#c8a75e,#5a4724);border-color:#ffe3a1;color:#fff9df}
/* camera monitor */
#cameraButton{position:absolute;z-index:35;bottom:10px;left:50%;transform:translateX(-50%);padding:10px 18px;min-width:175px;background:linear-gradient(#293d51,#101a27);border:1px solid #718aa2;border-radius:3px;box-shadow:0 4px 0 #030508;font-size:10px;font-weight:900;letter-spacing:1px}
#cams{position:absolute;z-index:25;inset:59px 0 0;background:#060a10;display:flex;flex-direction:column;border-top:2px solid #536a80}
.camHead{height:43px;flex-shrink:0;display:flex;align-items:center;justify-content:space-between;padding:6px 10px;background:#111a25;border-bottom:1px solid #34485b}
.camTitle{font-size:11px;font-weight:900;letter-spacing:2px}
.camSub{font-size:8px;color:#91a4b9;margin-top:3px}
#closeCams{padding:7px 10px;background:#25374a;border:1px solid #657b91;font-size:9px}
.camArea{flex:1;min-height:0;padding:8px 8px 5px;display:flex}
#camScreen{position:relative;flex:1;min-width:0;min-height:0;overflow:hidden;border:3px solid #3c5368;background:radial-gradient(ellipse at 50% 40%,#33434f,#101923 60%,#03060b);box-shadow:inset 0 0 35px #000}
#camScreen.stage{background:radial-gradient(ellipse at 50% 30%,#573239,#26151d 55%,#06070b)}
#camScreen.storage{background:radial-gradient(ellipse at 50% 40%,#454747,#1b2024 60%,#05070a)}
#camScreen.service{background:radial-gradient(ellipse at 50% 35%,#2b4a50,#111d25 60%,#04070b)}
#camScreen:before{content:"";position:absolute;z-index:10;inset:0;pointer-events:none;background:repeating-linear-gradient(0deg,transparent 0 4px,#0004 5px 6px)}
.camLabel{position:absolute;z-index:12;top:9px;left:9px;padding:7px;background:#05080cdd;border:1px solid #536a80;font-size:9px;letter-spacing:1px}
.rec{position:absolute;z-index:12;top:12px;right:12px;color:#ff5367;font-size:10px;font-weight:900}
.rec:before{content:"●";margin-right:5px;animation:blink 1s infinite}
@keyframes blink{50%{opacity:.25}}
.camProps{position:absolute;inset:0}
.camPipes{position:absolute;top:0;bottom:20%;left:10%;width:10%;border-left:7px solid #52616d;border-right:5px solid #2b3946}
.camPipes.r{left:auto;right:10%}
.camDoor{position:absolute;top:16%;bottom:20%;left:39%;width:22%;border:8px solid #465968;background:#06090e;box-shadow:inset 0 0 20px #000}
.camCrate{position:absolute;bottom:20%;left:12%;width:20%;height:18%;background:linear-gradient(135deg,#454b4e,#171b1f);border:3px solid #0a0d11;box-shadow:inset 0 0 0 2px #606669}
.camCrate.r{left:auto;right:12%;height:25%}
.camFloor{position:absolute;bottom:0;left:0;right:0;height:20%;border-top:2px solid #566675;background:repeating-linear-gradient(90deg,#202b35 0 55px,#101820 56px 59px)}
.camPoster{position:absolute;top:25%;left:30%;width:14%;height:18%;border:3px solid #4d5e6b;background:#141e28;display:grid;place-items:center;color:#8ba3b7;font-size:8px}
.camMonster{position:absolute;z-index:8;bottom:15%;left:50%;width:24%;height:57%;transform:translateX(-50%);filter:drop-shadow(0 0 14px #ff273b88)}
.camEmpty{position:absolute;z-index:12;bottom:8px;left:9px;font-size:9px;color:#91a3b5;background:#060a10b8;padding:5px}
.camNoise{position:absolute;z-index:11;inset:0;pointer-events:none;opacity:.1;background:repeating-linear-gradient(0deg,transparent 0 2px,#d6e9ff 3px 4px);animation:noise .16s infinite}
@keyframes noise{0%{transform:translateY(-2px)}100%{transform:translateY(2px)}}
/* Camera switching controls live at the bottom only */
#camFooter{height:65px;flex-shrink:0;display:flex;align-items:center;gap:5px;padding:7px;background:#101923;border-top:1px solid #3c5064;overflow-x:auto}
.camPick{flex:1;min-width:42px;max-width:105px;height:42px;background:#1a2939;border:1px solid #40566d;border-radius:3px;font-size:9px;font-weight:900;white-space:nowrap}
.camPick.active{background:#345b78;border-color:#c0e7ff;box-shadow:0 0 12px #6abaff22}
.camPick.close{background:#4a2029;border-color:#8f4451}
.camPick span{display:block;font-size:7px;color:#8fa4b9;margin-top:3px}
.camPick.active span{color:#e2f4ff}
/* menus */
.overlay{position:absolute;z-index:100;inset:0;display:flex;align-items:center;justify-content:center;padding:14px;background:radial-gradient(ellipse,#131e2add,#030509f5)}
.card{width:min(600px,100%);max-height:94%;overflow:auto;padding:clamp(17px,4vw,32px);position:relative;background:linear-gradient(145deg,#192535,#090e15);border:1px solid #485d73;box-shadow:0 20px 80px #000b,inset 0 0 0 4px #080c12}
.card:before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,transparent,#c1e4ff,transparent)}
.eyebrow{font-size:9px;letter-spacing:3px;color:#9cb1c9}
.title{font-size:clamp(30px,7vw,51px);font-weight:1000;letter-spacing:2px;margin:10px 0 5px}
.title em{font-style:normal;color:#ff5367}
.desc{font-size:12px;line-height:1.8;color:#9aacc0}
.divider{height:1px;background:#34465a;margin:16px 0}
.nights{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;margin-top:10px}
.night{padding:11px 2px;border:1px solid #3a4e63;background:#121d2a;text-align:center;border-radius:3px}
.night strong{display:block;font-size:17px}
.night small{display:block;font-size:8px;color:#8fa2b8;margin-top:4px}
.night.selected{background:#2c4964;border-color:#c2e4ff}
.night.locked{opacity:.3}
.primary,.secondary{width:100%;padding:13px;margin-top:10px;border-radius:3px;font-weight:900;letter-spacing:1px}
.primary{background:linear-gradient(#e4f3ff,#91bad8);border:1px solid #c6e4ff;color:#101a25}
.secondary{background:#172435;border:1px solid #455a70;color:#c2d3e6;font-size:11px}
.tip{font-size:10px;line-height:1.8;color:#8397ae;margin-top:13px}
.resultTitle{font-size:36px;font-weight:1000;letter-spacing:2px}
.win{color:#72efb0}.lose{color:#ff6878}
.resultText{font-size:12px;line-height:1.9;color:#a9b9cd;margin:10px 0}
#toast{position:absolute;z-index:60;top:69px;left:50%;transform:translateX(-50%);padding:9px 12px;max-width:90%;text-align:center;background:#101a25ee;border:1px solid #657b91;font-size:10px;pointer-events:none}
#blackout{position:absolute;z-index:80;inset:0;background:#000;display:grid;place-items:center;text-align:center;letter-spacing:4px}
#scare{position:absolute;z-index:200;inset:0;background:#020204;display:grid;place-items:center;overflow:hidden}
#scare:before{content:"";position:absolute;inset:-20%;background:repeating-linear-gradient(0deg,transparent 0 5px,#ff1d3520 6px 8px);animation:noise .08s infinite}
#scareArt{position:relative;width:min(70vw,420px);height:min(75vh,480px);filter:drop-shadow(0 0 25px #ff182d);animation:shake .07s infinite alternate}
#scareArt .eye{background:#ff002e;box-shadow:0 0 30px 14px #ff002e}
#scareText{position:absolute;bottom:8%;font-size:clamp(20px,5vw,38px);color:#ff344d;font-weight:1000;letter-spacing:5px;text-shadow:0 0 18px #f00}
@keyframes shake{from{transform:translate(-5px,3px) rotate(-2deg) scale(1.02)}to{transform:translate(6px,-4px) rotate(2deg) scale(1.08)}}
#game.shaking #office,#game.shaking #hud{animation:screenShake .08s infinite alternate}
@keyframes screenShake{from{transform:translate(2px,-2px)}to{transform:translate(-2px,2px)}}
@media(max-width:650px){
#hud{height:53px;padding:5px 7px;gap:4px}
.logo{font-size:10px;letter-spacing:1px}.sub{font-size:7px;letter-spacing:1px}
.stats{gap:3px}.stat{min-width:48px;padding:4px}
.stat small{font-size:7px}.stat strong{font-size:11px}
#office{inset:53px 0 0}
.side{width:41%;top:22%;bottom:22%;gap:5px}
.bayLabel{height:17px;font-size:6px;letter-spacing:.3px}
.frame{padding:4px}.controlDock{top:-29px;height:25px;gap:2px}
.control{font-size:6px;padding:0}
.windowBay .frame{height:65%}
.warning{font-size:6px;padding:5px 7px}
.monitor{min-width:56px;width:18%;height:13%}
.monitor small{font-size:6px;letter-spacing:1px}.monitor strong{font-size:16px}
.desk{left:21%;right:21%;height:14%}
.deskScreen{min-width:60px;font-size:7px}
#cameraButton{bottom:7px;padding:9px 12px;min-width:145px;font-size:9px}
#cams{inset:53px 0 0}
.camHead{height:39px;padding:5px 7px}
.camTitle{font-size:9px}.camSub{font-size:7px}
.camArea{padding:5px}
#camFooter{height:59px;padding:5px;gap:4px}
.camPick{height:40px;min-width:38px;font-size:8px}
.camPick span{font-size:6px}
}
@media(max-width:390px){
.sub{display:none}
.side{width:43%}
.control{font-size:5.5px}
.camPick{min-width:34px;font-size:7px}
}
@media(max-height:520px){
.side{top:21%;bottom:19%}
.windowBay .frame{height:62%}
.desk{height:12%}
#cameraButton{bottom:4px;padding:7px 10px}
#camFooter{height:53px}
.camPick{height:36px}
}
</style>
</head>
<body>
<div id="game">
<header id="hud">
<div>
<div class="logo">THE LAST <span>WATCH</span></div>
<div class="sub">NIGHT SECURITY SYSTEM</div>
</div>
<div class="stats">
<div class="stat"><small>TIME</small><strong id="clock">12 AM</strong></div>
<div class="stat"><small>POWER</small><strong id="powerValue">100%</strong><div id="usage"><i class="on"></i><i></i><i></i><i></i></div></div>
<div class="stat"><small>NIGHT</small><strong id="nightValue">01 / 05</strong></div>
</div>
</header>
<main id="office">
<div class="ceiling"></div><div class="lamp"></div>
<div class="backwall"></div>
<div class="wallpanel l"></div><div class="wallpanel r"></div>
<div class="warning">AUTHORIZED PERSONNEL ONLY</div>
<div class="monitor"><small>SYSTEM ONLINE</small><strong id="systemNumber">01</strong></div>
<div class="floor"></div>
<!-- WEST: door at the OUTER LEFT edge, short independent window beside it -->
<section class="side west" id="westSide">
<div class="sideLight"></div>
<div class="bay doorBay">
<div class="controlDock">
<button class="control doorControl" id="westDoorBtn">🔒 DOOR</button>
<button class="control lightControl" id="westLightBtn">☼ LIGHT</button>
</div>
<div class="bayLabel">WEST DOOR</div>
<div class="frame doorFrame"><div class="inner">
<div class="doorNumber">W-01</div><div class="doorLeaf" id="westDoorLeaf"></div>
</div></div>
</div>
<div class="bay windowBay" id="westWindowBay">
<div class="bayLabel">WEST WINDOW</div>
<div class="frame"><div class="inner glass">
<div class="windowStatus"><span>W-02</span><span id="westStatus">DARK</span></div>
<div class="glow"></div><div class="creatureSlot" id="westCreature"></div>
</div></div>
</div>
</section>
<!-- EAST: short window first, door at the OUTER RIGHT edge -->
<section class="side east" id="eastSide">
<div class="sideLight"></div>
<div class="bay windowBay" id="eastWindowBay">
<div class="bayLabel">EAST WINDOW</div>
<div class="frame"><div class="inner glass">
<div class="windowStatus"><span>E-02</span><span id="eastStatus">DARK</span></div>
<div class="glow"></div><div class="creatureSlot" id="eastCreature"></div>
</div></div>
</div>
<div class="bay doorBay">
<div class="controlDock">
<button class="control doorControl" id="eastDoorBtn">DOOR 🔒</button>
<button class="control lightControl" id="eastLightBtn">LIGHT ☼</button>
</div>
<div class="bayLabel">EAST DOOR</div>
<div class="frame doorFrame"><div class="inner">
<div class="doorNumber">E-01</div><div class="doorLeaf" id="eastDoorLeaf"></div>
</div></div>
</div>
</section>
<div class="desk"></div><div class="deskScreen">SECURITY</div>
</main>
<button id="cameraButton">▣ OPEN SECURITY CAMERAS</button>
<section id="cams" class="hidden">
<div class="camHead">
<div><div class="camTitle">▣ SECURITY MONITOR</div><div class="camSub" id="camSub">CAM 01 — MAIN HALL</div></div>
<button id="closeCams">✕ CLOSE</button>
</div>
<div class="camArea">
<div id="camScreen">
<div class="camProps">
<div class="camPipes"></div><div class="camPipes r"></div>
<div class="camDoor"></div><div class="camPoster">STAFF<br>ONLY</div>
<div class="camCrate"></div><div class="camCrate r"></div><div class="camFloor"></div>
</div>
<div class="camLabel" id="camLabel">CAM 01 / MAIN HALL</div>
<div class="rec">● REC</div>
<div class="camMonster hidden" id="camMonster"></div>
<div class="camEmpty" id="camEmpty">NO MOVEMENT DETECTED</div>
<div class="camNoise"></div>
</div>
</div>
<div id="camFooter">
<button class="camPick active" data-cam="01">01<span>HALL</span></button>
<button class="camPick" data-cam="02">02<span>EAST</span></button>
<button class="camPick" data-cam="03">03<span>STAGE</span></button>
<button class="camPick" data-cam="04">04<span>STORE</span></button>
<button class="camPick" data-cam="05">05<span>WEST</span></button>
<button class="camPick" data-cam="06">06<span>SERVICE</span></button>
<button class="camPick" data-cam="07">07<span>REPAIR</span></button>
<button class="camPick" data-cam="08">08<span>PARTS</span></button>
<button class="camPick" data-cam="09">09<span>REAR</span></button>
<button class="camPick close" id="camCloseBottom">✕</button>
</div>
</section>
<div id="toast" class="hidden"></div>
<div id="menu" class="overlay">
<div class="card">
<div class="eyebrow">AN ORIGINAL SURVIVAL HORROR GAME</div>
<div class="title">THE LAST <em>WATCH</em></div>
<div class="desc">חמש משמרות. ארבע מפלצות. משרד אבטחה אחד.<br>בדוק את המצלמות, נהל את החשמל ושרוד עד 6 בבוקר.</div>
<div class="divider"></div>
<div style="font-size:10px;letter-spacing:2px;color:#a8bad0">CHOOSE NIGHT</div>
<div class="nights" id="nightGrid"></div>
<button class="primary" id="startBtn">START NIGHT 1</button>
<button class="secondary" id="continueBtn">CONTINUE PROGRESS</button>
<div class="tip">במחשב: A/D — דלתות, Q/E — אורות, C — מצלמות, 1–9 — בחירת מצלמה כשהמסך פתוח. אל תשאיר דלתות ואורות מופעלים ללא צורך.</div>
</div>
</div>
<div id="result" class="overlay hidden">
<div class="card" style="text-align:center;max-width:470px">
<div class="eyebrow" id="resultEyebrow">SHIFT REPORT</div>
<div class="resultTitle win" id="resultTitle">6 AM</div>
<div class="resultText" id="resultText"></div>
<button class="primary" id="resultPrimary">CONTINUE</button>
<button class="secondary" id="resultMenu">MAIN MENU</button>
</div>
</div>
<div id="blackout" class="hidden"><div><div style="font-size:25px;margin-bottom:12px">POWER FAILURE</div><small>SECURITY SYSTEM OFFLINE</small></div></div>
<div id="scare" class="hidden"><div id="scareArt"></div><div id="scareText">TOO LATE.</div></div>
</div>
<script>
"use strict";
const $=id=>document.getElementById(id);
const SAVE="lastwatch-ultimate-save";
const rooms={
"01":{name:"MAIN HALL",kind:"hall"},
"02":{name:"EAST CORRIDOR",kind:"hall"},
"03":{name:"PERFORMANCE STAGE",kind:"stage"},
"04":{name:"STORAGE ROOM",kind:"storage"},
"05":{name:"WEST CORRIDOR",kind:"hall"},
"06":{name:"SERVICE HALL",kind:"service"},
"07":{name:"MAINTENANCE",kind:"storage"},
"08":{name:"PARTS ROOM",kind:"storage"},
"09":{name:"REAR PASSAGE",kind:"hall"}
};
const templates=[
{id:"warden",name:"THE WARDEN",art:"warden",side:"WEST",path:["03","01","08","05","WEST"],speed:1},
{id:"grinner",name:"THE GRINNER",art:"grinner",side:"EAST",path:["08","04","02","06","EAST"],speed:1.1},
{id:"stalker",name:"THE STALKER",art:"stalker",side:"WEST",path:["07","09","05","WEST"],speed:1.22},
{id:"runner",name:"THE RUNNER",art:"runner",side:"EAST",path:["03","01","06","EAST"],speed:1.35}
];
let highest=1,selectedNight=1,night=1,active=false,ended=false,camOpen=false;
let currentCam="01",power=100,elapsed=0,duration=180,last=0;
let monsters=[],doors={WEST:false,EAST:false},lights={WEST:false,EAST:false};
let loop=null,powerTimer=0,blackoutTimer=0,toastTimer=0,audio=null;
function loadSave(){
try{highest=Math.max(1,Math.min(5,Number(JSON.parse(localStorage.getItem(SAVE)||"{}").highest)||1))}
catch(e){highest=1}
selectedNight=highest;
}
function save(){try{localStorage.setItem(SAVE,JSON.stringify({highest}))}catch(e){}}
function renderNights(){
$("nightGrid").innerHTML="";
for(let n=1;n<=5;n++){
const b=document.createElement("button");
b.className="night"+(n>highest?" locked":"")+(n===selectedNight?" selected":"");
b.innerHTML=`<strong>${n>highest?"🔒":String(n).padStart(2,"0")}</strong><small>${n>highest?"LOCKED":"NIGHT "+n}</small>`;
b.disabled=n>highest;
b.onclick=()=>{selectedNight=n;renderNights();$("startBtn").textContent="START NIGHT "+n};
$("nightGrid").appendChild(b);
}
$("continueBtn").textContent="CONTINUE — NIGHT "+highest;
}
function initAudio(){
if(!audio){const A=window.AudioContext||window.webkitAudioContext;if(A)audio=new A()}
if(audio&&audio.state==="suspended")audio.resume().catch(()=>{});
}
function tone(f=440,d=.12,type="sine",v=.03,slide=0){
if(!audio)return;
const o=audio.createOscillator(),g=audio.createGain(),t=audio.currentTime;
o.type=type;o.frequency.setValueAtTime(f,t);
if(slide)o.frequency.linearRampToValueAtTime(Math.max(20,f+slide),t+d);
g.gain.setValueAtTime(v,t);g.gain.exponentialRampToValueAtTime(.001,t+d);
o.connect(g);g.connect(audio.destination);o.start();o.stop(t+d);
}
function noise(d=.3,v=.08){
if(!audio)return;
const b=audio.createBuffer(1,Math.floor(audio.sampleRate*d),audio.sampleRate),a=b.getChannelData(0);
for(let i=0;i<a.length;i++)a[i]=(Math.random()*2-1)*(1-i/a.length);
const s=audio.createBufferSource(),g=audio.createGain();s.buffer=b;g.gain.value=v;s.connect(g);g.connect(audio.destination);s.start();
}
function clickSound(){tone(650,.05,"square",.02,-170)}
function doorSound(){tone(110,.2,"sawtooth",.04,-45);noise(.12,.025)}
function showToast(s,ms=1600){
$("toast").textContent=s;$("toast").classList.remove("hidden");
clearTimeout(toastTimer);toastTimer=setTimeout(()=>$("toast").classList.add("hidden"),ms);
}
function makeCreature(art){
const d=document.createElement("div");d.className="creature "+art;
d.innerHTML='<div class="horn left"></div><div class="horn right"></div><div class="arm left"></div><div class="arm right"></div><div class="body"></div><div class="head"><i class="eye"></i><i class="eye"></i><div class="mouth"></div></div>';
return d;
}
function startNight(n){
initAudio();night=Math.max(1,Math.min(highest,n));
selectedNight=night;active=true;ended=false;camOpen=false;
power=100;elapsed=0;powerTimer=0;blackoutTimer=0;duration=Math.max(150,190-(night-1)*7);
doors={WEST:false,EAST:false};lights={WEST:false,EAST:false};currentCam="01";
monsters=templates.map((t,i)=>({...t,index:0,room:t.path[0],wait:7+i*2+Math.random()*3,attack:0,patience:0,
moveEvery:Math.max(4.8,11-(night-1)*1.2)/t.speed}));
$("menu").classList.add("hidden");$("result").classList.add("hidden");
$("scare").classList.add("hidden");$("blackout").classList.add("hidden");
$("cams").classList.add("hidden");$("cameraButton").classList.remove("hidden");
$("game").classList.remove("shaking");last=performance.now();
clearInterval(loop);renderWindows();renderCameras();updateUI();
showToast("NIGHT "+night+" — SURVIVE UNTIL 6 AM",2200);
loop=setInterval(tick,100);
}
function toggleDoor(side){
if(!active||power<=0)return;
doors[side]=!doors[side];doorSound();updateUI();
showToast(side+" DOOR "+(doors[side]?"CLOSED":"OPEN"),700);
}
function toggleLight(side){
if(!active||power<=0)return;
lights[side]=!lights[side];tone(820,.06,"square",.02,-260);
updateUI();
}
$("westDoorBtn").onclick=()=>toggleDoor("WEST");
$("eastDoorBtn").onclick=()=>toggleDoor("EAST");
$("westLightBtn").onclick=()=>toggleLight("WEST");
$("eastLightBtn").onclick=()=>toggleLight("EAST");
function atSide(side){return monsters.find(m=>m.room===side)}
function renderWindows(){
for(const x of [
{s:"WEST",side:"westSide",bay:"westWindowBay",slot:"westCreature",status:"westStatus",leaf:"westDoorLeaf"},
{s:"EAST",side:"eastSide",bay:"eastWindowBay",slot:"eastCreature",status:"eastStatus",leaf:"eastDoorLeaf"}
]){
const lit=lights[x.s],m=atSide(x.s),slot=$(x.slot);
$(x.side).classList.toggle("lit",lit);
$(x.bay).classList.toggle("lit",lit);
$(x.leaf).classList.toggle("closed",doors[x.s]);
slot.innerHTML="";slot.classList.remove("present");
$(x.status).textContent=lit?"LIGHT ON":"DARK";
if(lit&&m&&active&&power>0){
slot.appendChild(makeCreature(m.art));slot.classList.add("present");
$(x.status).textContent="MOVEMENT!";
}
}
}
function openCams(){
if(!active||power<=0)return;
camOpen=true;$("cams").classList.remove("hidden");$("cameraButton").classList.add("hidden");
clickSound();renderCameras();updateUI();
}
function closeCams(){
camOpen=false;$("cams").classList.add("hidden");$("cameraButton").classList.remove("hidden");
clickSound();updateUI();
}
$("cameraButton").onclick=openCams;
$("closeCams").onclick=closeCams;
$("camCloseBottom").onclick=closeCams;
document.querySelectorAll("[data-cam]").forEach(b=>b.onclick=()=>selectCam(b.dataset.cam));
function selectCam(id){if(!rooms[id])return;currentCam=id;clickSound();renderCameras()}
function renderCameras(){
const r=rooms[currentCam],screen=$("camScreen");
$("camSub").textContent="CAM "+currentCam+" — "+r.name;
$("camLabel").textContent="CAM "+currentCam+" / "+r.name;
screen.className=r.kind;
const m=monsters.find(x=>x.room===currentCam),slot=$("camMonster");
slot.innerHTML="";slot.classList.toggle("hidden",!m);
if(m)slot.appendChild(makeCreature(m.art));
$("camEmpty").textContent=m?"SIGNAL DISTORTION":"NO MOVEMENT DETECTED";
$("camEmpty").style.color=m?"#ff8b97":"#91a3b5";
document.querySelectorAll(".camPick[data-cam]").forEach(b=>b.classList.toggle("active",b.dataset.cam===currentCam));
}
function moveMonster(m){
if(!active||ended||power<=0)return;
if(m.room==="WEST"||m.room==="EAST"){
if(doors[m.room]){
m.index=Math.max(0,m.index-1);m.room=m.path[m.index];m.attack=0;
tone(100,.12,"triangle",.025,-25);
}else{
m.attack++;
if(m.attack>=Math.max(1.5,4.5-(night-1)*.6)){jumpscare(m);return}
}
renderWindows();if(camOpen)renderCameras();return;
}
let chance=Math.min(.95,.72+(night-1)*.055);
if(m.id==="runner")chance=Math.min(.98,chance+.12);
if(m.id==="stalker"&&camOpen&¤tCam===m.room)chance*=.82;
if(Math.random()<chance||night>=4&&Math.random()<.12){
m.index=Math.min(m.path.length-1,m.index+1);m.room=m.path[m.index];m.attack=0;
tone(70,.13,"triangle",.025,-20);
if(m.room==="WEST"||m.room==="EAST")showToast("SOUND DETECTED — CHECK THE SIDE WINDOWS",1100);
}
renderWindows();if(camOpen)renderCameras();
}
function tick(){
if(!active||ended)return;
const now=performance.now(),dt=Math.min(.2,Math.max(0,(now-last)/1000));last=now;
elapsed+=dt;
const drain=(.10+(Number(doors.WEST)+Number(doors.EAST))*.22+
(Number(lights.WEST)+Number(lights.EAST))*.17+(camOpen?.15:0))*(1+(night-1)*.05);
power=Math.max(0,power-drain*dt);
powerTimer+=dt;
if(powerTimer>=1){
powerTimer=0;
for(const m of monsters){
m.wait-=1;
if(m.wait<=0){moveMonster(m);m.wait=m.moveEvery*(.8+Math.random()*.55)/(.9+(night-1)*.1)}
}
}
if(power<=0){
if($("blackout").classList.contains("hidden")){
$("blackout").classList.remove("hidden");tone(125,.8,"sawtooth",.06,-110);
doors={WEST:false,EAST:false};lights={WEST:false,EAST:false};camOpen=false;
$("cams").classList.add("hidden");$("cameraButton").classList.add("hidden");
renderWindows();blackoutTimer=0;
}else{
blackoutTimer+=dt;
if(blackoutTimer>=5){
jumpscare(monsters.find(m=>m.room==="WEST"||m.room==="EAST")||monsters[0],true);return;
}
}
}
$("clock").textContent=elapsed>=duration?"6 AM":Math.min(5,Math.floor(elapsed/duration*6))+" AM";
if(elapsed>=duration){winNight();return}
updateUI();
}
function updateUI(){
$("powerValue").textContent=Math.ceil(power)+"%";
$("powerValue").style.color=power<25?"#ff596b":power<50?"#ffd277":"#63efad";
$("nightValue").textContent=String(night).padStart(2,"0")+" / 05";
$("systemNumber").textContent=String(night).padStart(2,"0");
const usage=1+Number(doors.WEST)+Number(doors.EAST)+Number(lights.WEST)+Number(lights.EAST)+Number(camOpen);
document.querySelectorAll("#usage i").forEach((e,i)=>{e.classList.toggle("on",i<usage);e.classList.toggle("hot",i>=3&&i<usage)});
for(const s of ["WEST","EAST"]){
const side=s==="WEST"?"west":"east";
$(side+"DoorBtn").classList.toggle("active",doors[s]);
$(side+"LightBtn").classList.toggle("active",lights[s]);
$(side+"DoorBtn").textContent=doors[s]?"🔒 CLOSED":"🔓 DOOR";
$(side+"LightBtn").textContent=lights[s]?"☼ ON":"☼ LIGHT";
$(side+"DoorBtn").disabled=power<=0;
$(side+"LightBtn").disabled=power<=0;
}
renderWindows();
}
function winNight(){
if(ended)return;ended=true;active=false;clearInterval(loop);closeCams();
$("blackout").classList.add("hidden");
tone(440,.2,"sine",.04);setTimeout(()=>tone(554,.25,"sine",.04),150);setTimeout(()=>tone(659,.4,"sine",.04),320);
highest=Math.max(highest,Math.min(5,night+1));save();renderNights();
$("resultEyebrow").textContent="SHIFT REPORT — NIGHT "+night;
$("resultTitle").textContent="6 AM";$("resultTitle").className="resultTitle win";
$("resultText").textContent=night===5?"שרדת את כל חמש המשמרות. המשמרת הסתיימה — אבל המצלמות עדיין קולטות רעש...":"שרדת את הלילה. הלילה הבא יהיה מהיר וקשה יותר.";
$("resultPrimary").textContent=night===5?"PLAY AGAIN":"START NIGHT "+(night+1);
$("resultPrimary").onclick=()=>startNight(night===5?1:night+1);
$("result").classList.remove("hidden");
}
function jumpscare(m,black=false){
if(ended)return;ended=true;active=false;clearInterval(loop);camOpen=false;
$("cams").classList.add("hidden");$("cameraButton").classList.add("hidden");$("blackout").classList.add("hidden");
$("game").classList.add("shaking");
$("scareArt").innerHTML="";$("scareArt").appendChild(makeCreature(m.art));
$("scareText").textContent=black?"POWER IS GONE":"TOO LATE.";
$("scare").classList.remove("hidden");
noise(.8,.2);tone(85,.8,"sawtooth",.15,400);tone(42,.8,"square",.1,-15);
if(navigator.vibrate)navigator.vibrate([100,60,180,60,250]);
setTimeout(()=>{
$("scare").classList.add("hidden");$("game").classList.remove("shaking");
$("resultEyebrow").textContent="SHIFT FAILED";
$("resultTitle").textContent="GAME OVER";$("resultTitle").className="resultTitle lose";
$("resultText").textContent=m.name+" הגיע למשרד. השתמש באורות כדי לבדוק את החלונות, עקוב אחר תנועות במצלמות וחסוך בחשמל.";
$("resultPrimary").textContent="RETRY NIGHT "+night;$("resultPrimary").onclick=()=>startNight(night);
$("result").classList.remove("hidden");
},1450);
}
function showMenu(){
active=false;ended=false;camOpen=false;clearInterval(loop);
$("menu").classList.remove("hidden");$("result").classList.add("hidden");$("scare").classList.add("hidden");
$("blackout").classList.add("hidden");$("cams").classList.add("hidden");$("cameraButton").classList.remove("hidden");
$("game").classList.remove("shaking");selectedNight=Math.min(highest,5);renderNights();
$("startBtn").textContent="START NIGHT "+selectedNight;
}
$("startBtn").onclick=()=>startNight(selectedNight);
$("continueBtn").onclick=()=>startNight(highest);
$("resultMenu").onclick=showMenu;
document.addEventListener("keydown",e=>{
if(!active||e.repeat)return;
const k=e.key.toLowerCase();
if(k==="a")toggleDoor("WEST");
if(k==="d")toggleDoor("EAST");
if(k==="q")toggleLight("WEST");
if(k==="e")toggleLight("EAST");
if(k==="c"||k===" "){e.preventDefault();camOpen?closeCams():openCams()}
if(k>="1"&&k<="9"&&camOpen)selectCam("0"+k);
if(k==="escape"&&camOpen)closeCams();
});
loadSave();renderNights();updateUI();
</script>
</body>
</html>
Game Source: THE LAST WATCH — Ultimate
Creator: LunarPanda23
Libraries: none
Complexity: complex (626 lines, 36.9 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: the-last-watch-ultimate-lunarpanda23" to link back to the original. Then publish at arcadelab.ai/publish.