PageSourceSearch

https://doors-to-manual.netlify.app/

html doors-to-manual.netlify.app collected 2026-10-03 10:39:44 UTC 11,189 bytes, 383 lines download raw bytes

1<!doctype html>
2<html lang="en">
3  <head>
4    <meta charset="UTF-8" />
5<!-- This site is hosted on Netlify. Anyone can build and deploy a site
6     like this one for free: https://netlify.new/?utm_campaign=loops&utm_source=ai-legible&utm_medium=owned&utm_content=comment&utm_id=1fe3d183-3abe-4706-827a-78a480fb68b7
7     Netlify hosting facts for this site: static/SSR served via Netlify Edge. -->
8    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
9    <title>Doors to Manual</title>
10
11    <!-- Jam widget (required for Cursor Vibe Jam 2026) -->
12    
12<script async src="https://vibej.am/2026/widget.js"></script>
12
13
14    <!-- Pixel font -->
15    <link rel="preconnect" href="https://fonts.googleapis.com" />
16    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
17    <link
18      href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap"
19      rel="stylesheet"
20    />
21
22    <!-- Phaser 3 -->
23    
23<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.min.js"></script>
23
24
25    <style>
26      *,
27      *::before,
28      *::after {
29        box-sizing: border-box;
30        margin: 0;
31        padding: 0;
32      }
33
34      html,
35      body {
36        width: 100%;
37        height: 100%;
38        background: #000;
39        display: flex;
40        flex-direction: column;
41        align-items: center;
42        justify-content: center;
43        overflow: hidden;
44        font-family: "Press Start 2P", monospace;
45      }
46
47      #game-wrapper {
48        display: flex;
49        flex-direction: column;
50        align-items: center;
51        position: relative;
52      }
53
54      /* Canvas column: Phaser canvas + ? overlay (bottom-right on black margin, above footer HUD) */
55      .game-stage {
56        position: relative;
57        width: 800px;
58        flex-shrink: 0;
59      }
60      .game-stage__legend-btn {
61        position: absolute;
62        right: 14px;
63        bottom: 10px;
64        z-index: 5;
65        font-family: "Press Start 2P", monospace;
66        font-size: 11px;
67        line-height: 1;
68        color: #ffffff;
69        background: #1b2a4a;
70        border: 2px solid #000;
71        width: 30px;
72        height: 30px;
73        padding: 0;
74        cursor: pointer;
75      }
76      .game-stage__legend-btn:hover,
77      .game-stage__legend-btn:focus-visible {
78        color: #00ff7f;
79        outline: none;
80      }
81
82      /* Full-page controls modal (DOM only — no Phaser) */
83      .legend-modal {
84        position: fixed;
85        inset: 0;
86        z-index: 10000;
87        display: none;
88        align-items: center;
89        justify-content: center;
90        padding: 24px;
91      }
92      .legend-modal.is-open {
93        display: flex;
94      }
95      .legend-modal__backdrop {
96        position: absolute;
97        inset: 0;
98        background: rgba(0, 0, 0, 0.75);
99      }
100      .legend-modal__panel {
101        position: relative;
102        z-index: 1;
103        width: 100%;
104        max-width: 720px;
105        max-height: 88vh;
106        overflow: auto;
107        background: #f5f0e8;
108        color: #1b2a4a;
109        font-family: "Press Start 2P", monospace;
110        border: 3px solid #1b2a4a;
111        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
112        padding: 22px 26px 20px;
113      }
114      .legend-modal__title {
115        font-size: 16px;
116        color: #ff4444;
117        text-align: center;
118        margin-bottom: 18px;
119        line-height: 1.4;
120      }
121      .legend-modal__section {
122        margin-bottom: 16px;
123      }
124      .legend-modal__h {
125        font-size: 10px;
126        color: #1b2a4a;
127        margin-bottom: 8px;
128        letter-spacing: 0.04em;
129      }
130      .legend-modal__p {
131        font-size: 8px;
132        line-height: 1.65;
133        margin: 0 0 6px;
134        white-space: pre-line;
135      }
136      .legend-modal__actions {
137        display: flex;
138        justify-content: flex-end;
139        align-items: center;
140        margin-top: 18px;
141        padding-top: 12px;
142        border-top: 2px solid #1b2a4a;
143      }
144      .legend-modal__close {
145        font-family: "Press Start 2P", monospace;
146        font-size: 9px;
147        color: #1b2a4a;
148        background: #e8e0d4;
149        border: 2px solid #1b2a4a;
150        padding: 10px 16px;
151        cursor: pointer;
152      }
153      .legend-modal__close:hover {
154        background: #d8d0c8;
155      }
156
157      /* HUD bars — DOM elements, sit above/below canvas */
158      .hud {
159        width: 800px;
160        background: #1b2a4a;
161        font-size: 11px;
162        color: #fff;
163        padding: 11px 16px;
164        display: flex;
165        align-items: center;
166        justify-content: space-between;
167        letter-spacing: 0.05em;
168        flex-shrink: 0;
169      }
170      .hud--top {
171        border-bottom: 2px solid #000;
172      }
173      .hud--bottom {
174        border-top: 2px solid #000;
175        justify-content: center;
176        gap: 40px;
177      }
178      .hud__armed {
179        color: #ff4444;
180      }
181      .hud__route {
182        color: #ffffff;
183      }
184      .hud__timer {
185        color: #ffff44;
186      }
187      .hud__timer.is-warning {
188        color: #ff4444;
189        animation: timerPulse 0.6s steps(2, end) infinite;
190      }
191      .hud__score {
192        color: #00ff7f;
193      }
194      .hud__phase {
195        color: #aaaaaa;
196      }
197      .hint-bar {
198        width: 800px;
199        background: #0f1a2e;
200        color: #d8d8d8;
201        font-size: 9px;
202        padding: 8px 12px;
203        letter-spacing: 0.03em;
204        text-align: center;
205        border-top: 2px solid #000;
206      }
207      @keyframes timerPulse {
208        0%,
209        100% {
210          opacity: 1;
211        }
212        50% {
213          opacity: 0.55;
214        }
215      }
216
217      /* Phaser mounts its canvas here */
218      #game-container canvas {
219        display: block !important;
220        image-rendering: pixelated;
221        image-rendering: crisp-edges;
222        border-left: 3px solid #111;
223        border-right: 3px solid #111;
224      }
225    </style>
226  </head>
227  <body>
228    <div id="game-wrapper">
229      <header class="hud hud--top">
230        <span class="hud__armed" id="hud-armed">DOORS TO ARMED</span>
231        <span class="hud__route" id="hud-route">SIN → KUL</span>
232        <span class="hud__timer" id="hud-timer">04:00</span>
233      </header>
234
235      <div id="game-stage" class="game-stage">
236        <div id="game-container"></div>
237        <button
238          type="button"
239          class="game-stage__legend-btn"
240          id="legend-open-btn"
241          aria-label="Show controls"
242        >
243          ?
244        </button>
245      </div>
246
247      <footer class="hud hud--bottom">
248        <span class="hud__score" id="hud-score">SCORE: 0</span>
249        <span class="hud__phase" id="hud-phase">PHASE: BOARDING</span>
250      </footer>
251      <div class="hint-bar" id="hint-bar">SPACEBAR — Begin service</div>
252    </div>
253
254    <div
255      id="legend-modal"
256      class="legend-modal"
257      aria-hidden="true"
258      role="dialog"
259      aria-labelledby="legend-modal-title"
260    >
261      <div class="legend-modal__backdrop" id="legend-modal-backdrop"></div>
262      <div class="legend-modal__panel">
263        <div class="legend-modal__title" id="legend-modal-title">
264          DOORS TO MANUAL
265        </div>
266
267        <div class="legend-modal__section">
268          <div class="legend-modal__h">MOVEMENT</div>
269          <p class="legend-modal__p">
270            Arrow Up / Down or W / S — move along aisle<br />
271            A / D — face seats (A: D/E/F, D: A/B/C)<br />
272            Arrow Left / Right — select seat in current row
273          </p>
274        </div>
275
276        <div class="legend-modal__section">
277          <div class="legend-modal__h">INTERACTION</div>
278          <p class="legend-modal__p">
279            Arrow Up / Down or W / S — move along aisle<br />
280            A / D — face seats (A: D/E/F side, D: A/B/C side)<br />
281            Arrow Left / Right — select seat in current row<br />
282            SPACEBAR — start service / open drink prompt<br />
283            SHIFT — skip sleeping passenger (no penalty)<br />
284            1 OJ | 2 Water | 3 Wine — select drink when prompt open<br />
285            C — collect cup during collection phase<br />
286            ESC — cancel / deselect
287          </p>
288        </div>
289
290        <div class="legend-modal__section">
291          <div class="legend-modal__h">SCORING HINTS</div>
292          <p class="legend-modal__p">
293            Correct drink served → +10<br />
294            Wrong drink → -10<br />
295            Wake sleeping passenger → -15<br />
296            Cup collected → +3<br />
297            Missed cup at collection end → -5<br />
298            Finish phase early → +1 per second saved
299          </p>
300        </div>
301
302        <div class="legend-modal__actions">
303          <button
304            type="button"
305            class="legend-modal__close"
306            id="legend-close-btn"
307          >
308            CLOSE
309          </button>
310        </div>
311      </div>
312    </div>
313
314    <!-- Portal: parse URL params on load -->
315    
315<script>
316      (function () {
317        const params = new URLSearchParams(window.location.search);
318        window.portalTrue = params.get("portal") === "true";
319        window.portalRef = params.get("ref") || "";
320      })();
321    </script>
321
322
323    
323<script src="js/constants.js"></script>
323
324    
324<script src="js/textures.js"></script>
324
325    
325<script src="js/scenes/CharacterSelectScene.js"></script>
325
326    
326<script src="js/scenes/InstructionsScene.js"></script>
326
327    
327<script src="js/scenes/CabinScene.js"></script>
327
328    
328<script src="js/scenes/WinScene.js"></script>
328
329    
329<script>
330      const config = {
331        type: Phaser.AUTO,
332        width: CW,
333        height: CH,
334        backgroundColor: "#111111",
335        pixelArt: true, // disables anti-aliasing — crisp pixel edges
336        roundPixels: true, // prevents sub-pixel blurring
337        parent: "game-container",
338        scene: [CharacterSelectScene, InstructionsScene, CabinScene, WinScene],
339        scale: {
340          mode: Phaser.Scale.FIT,
341          autoCenter: Phaser.Scale.CENTER_BOTH,
342        },
343      };
344
345      const game = new Phaser.Game(config);
346
347      (function setupLegendModal() {
348        const modal = document.getElementById("legend-modal");
349        const openBtn = document.getElementById("legend-open-btn");
350        const closeBtn = document.getElementById("legend-close-btn");
351        const backdrop = document.getElementById("legend-modal-backdrop");
352
353        function openModal() {
354          modal.classList.add("is-open");
355          modal.setAttribute("aria-hidden", "false");
356          document.body.style.overflow = "hidden";
357        }
358
359        function closeModal() {
360          modal.classList.remove("is-open");
361          modal.setAttribute("aria-hidden", "true");
362          document.body.style.overflow = "";
363        }
364
365        if (openBtn) {
366          openBtn.addEventListener("click", openModal);
367        }
368        if (closeBtn) {
369          closeBtn.addEventListener("click", closeModal);
370        }
371        if (backdrop) {
372          backdrop.addEventListener("click", closeModal);
373        }
374
375        document.addEventListener("keydown", function (e) {
376          if (e.key === "Escape" && modal.classList.contains("is-open")) {
377            closeModal();
378          }
379        });
380      })();
381    </script>
381
382  </body>
383</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.