-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
578 lines (499 loc) · 22.8 KB
/
Copy pathindex.html
File metadata and controls
578 lines (499 loc) · 22.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>IONSTORM — WebGPU Arcade</title>
<meta name="description" content="IONSTORM — a neon WebGPU arcade shooter with escalating boss fights, daily seeded challenges, SURGE overdrive, and roguelite run upgrades.">
<meta name="theme-color" content="#04070f">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="IONSTORM">
<link rel="manifest" href="manifest.webmanifest">
<link rel="apple-touch-icon" href="ionstorm-icon.svg">
<meta property="og:title" content="IONSTORM — WebGPU Arcade">
<meta property="og:description" content="Defend the Veil. Ride the Surge.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://ionstorm.vercel.app/">
<meta property="og:image" content="https://ionstorm.vercel.app/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="IONSTORM — Defend the Veil. Ride the Surge.">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="IONSTORM — WebGPU Arcade">
<meta name="twitter:description" content="Defend the Veil. Ride the Surge.">
<meta name="twitter:image" content="https://ionstorm.vercel.app/og-image.png">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚡</text></svg>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@500;700;900&family=Rajdhani:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="src/styles.css">
</head>
<body>
<canvas id="view">IONSTORM requires a browser with HTML canvas support.</canvas>
<div id="fx-scan" aria-hidden="true"></div>
<div id="fx-vig" aria-hidden="true"></div>
<div id="fx-roll" aria-hidden="true"></div>
<div id="fx-bloom" aria-hidden="true"></div>
<div id="flash" aria-hidden="true"></div>
<header id="hud" class="hidden" aria-label="Mission status" inert>
<div class="hudbox panel hudscore">
<div class="lbl">SCORE</div>
<div class="val" id="hScore">0000000</div>
</div>
<div class="hudbox panel hudmid hudwave">
<div class="lbl">WAVE <span id="hMode" class="hudMode hidden">DAILY</span></div>
<div class="val" id="hWave">01</div>
</div>
<div class="hudright">
<div class="hudbox panel hudbest">
<div class="lbl">BEST</div>
<div class="val" id="hHi">0000000</div>
</div>
<div class="hudbox panel hudhull">
<div class="lbl">HULL</div>
<div id="hLives" role="img" aria-label="Hull status"></div>
</div>
<button type="button" class="panel hudbtn" id="sndBtn" title="Toggle sound" aria-label="Toggle sound" aria-pressed="false">
<span class="dot" aria-hidden="true"></span>
<span class="hudbtnLabel">SOUND</span>
</button>
<button type="button" class="panel hudbtn" id="pauseBtn" title="Pause" aria-label="Pause or resume">
<span class="hudbtnIcon" aria-hidden="true">❚❚</span>
<span class="hudbtnLabel">PAUSE</span>
</button>
</div>
</header>
<div id="combo" class="panel hidden" inert>
<div class="row">
<span class="lbl">COMBO</span>
<span id="hMult">×1</span>
</div>
<div id="comboBar"><i></i></div>
</div>
<div id="levelHud" class="panel hidden" aria-label="Run level progress" inert>
<div class="row">
<span class="lbl">LEVEL <b id="hLevel">01</b></span>
<span id="hXp">0 / 220</span>
</div>
<div id="xpBar"><i></i></div>
</div>
<div id="eventHud" class="panel hidden" aria-label="Wave event" inert>
<div class="eventKicker">WAVE EVENT</div>
<div id="eventName">ELITE HUNT</div>
<div id="eventDesc">COMMAND FRAMES DETECTED</div>
</div>
<button type="button" id="surge" class="panel hidden" aria-label="Surge charging" disabled inert>
<span class="row">
<span class="lbl">SURGE</span>
<span id="surgePct">0%</span>
</span>
<span id="surgeBar"><i></i></span>
</button>
<div id="boss" class="panel hidden" inert>
<div class="row">
<span id="bossName">DREADNOUGHT</span>
<span id="bossPhase">PHASE 1</span>
</div>
<div id="bossBar"><i></i></div>
<div id="bossMeta">
<span id="bossStatus">CORE SHIELDED</span>
<span id="bossAttack">AIMED BARRAGE</span>
<span id="bossRage">RAGE 0%</span>
</div>
</div>
<div id="chips" class="hidden" inert>
<div class="chip tri panel hidden" id="cTri">
TRIPLE<span class="bar"><i></i></span>
</div>
<div class="chip panel hidden" id="cRap">
RAPID<span class="bar"><i></i></span>
</div>
<div class="chip mis panel hidden" id="cMis">
SEEKER<span class="bar"><i></i></span>
</div>
<div class="chip pierce panel hidden" id="cPierce">
PIERCE<span class="bar"><i></i></span>
</div>
<div class="chip mag panel hidden" id="cMag">
MAGNET<span class="bar"><i></i></span>
</div>
<div class="chip slow panel hidden" id="cSlow">
TIME-SLOW<span class="bar"><i></i></span>
</div>
<div class="chip shd panel hidden" id="cShd">
SHIELD ◈<span id="cShdN">1</span>
</div>
</div>
<div id="fps"></div>
<div id="banner" aria-live="polite"></div>
<div id="toasts" role="status" aria-live="polite"></div>
<!-- TITLE SCREEN -->
<section id="ovTitle" class="ov on" aria-labelledby="titleLogo">
<div class="titleShell">
<header class="titleHero">
<div class="badge panel" id="badge">
<span class="pulse" aria-hidden="true"></span>
<span id="badgeTxt">PILOT NETWORK // ONLINE</span>
</div>
<p class="eyebrow">TACTICAL ARCADE // SECTOR 07</p>
<h1 class="logo" id="titleLogo">ION<b>STORM</b></h1>
<p class="tag">DEFEND THE VEIL · RIDE THE SURGE</p>
</header>
<main class="mainMenu panel" aria-label="Main menu">
<div class="menuMission">
<div class="panelHeading">
<span>CHOOSE DEPLOYMENT</span>
<span class="missionCode">VEIL-01</span>
</div>
<div class="playChoices">
<button type="button" class="modeCard modeCampaign" id="startPrompt">
<span class="modeKicker">CAMPAIGN</span>
<span class="modeTitle">PLAY</span>
<span class="modeDesc">Survive escalating waves and break the Dreadnought line.</span>
<span class="modeAction">
<span>LAUNCH MISSION</span>
<span class="desktopOnly">ENTER / SPACE</span>
<span class="mobileOnly">TAP TO DEPLOY</span>
</span>
</button>
<button type="button" class="modeCard modeDaily" id="dailyPrompt">
<span class="modeKicker">DAILY CHALLENGE</span>
<span class="modeTitle" id="dailyName">SYNCING…</span>
<span class="modeDesc" id="dailyDesc">Loading today's seeded combat profile.</span>
<span class="modeAction">
<span>START DAILY RUN</span>
<span id="dailyDate">— UTC</span>
</span>
</button>
</div>
<div class="dailyBrief panel" aria-label="Daily challenge local best">
<span>DAILY LOCAL BEST</span>
<b id="dailyBest">—</b>
</div>
</div>
<div class="meta pilotStatus" role="group" aria-label="Pilot status">
<span class="metaItem">
<small>HI-SCORE</small>
<b id="tHi">0000000</b>
</span>
<span class="metaItem">
<small>SCRAP</small>
<b id="tScrap">0</b>
</span>
<span class="metaItem">
<small>ACTIVE SHIP</small>
<b id="tShip">VANGUARD</b>
</span>
</div>
<nav class="titleNav" id="titleNav" aria-label="Game menu">
<button type="button" class="cham secondary menuNavButton" id="hangarBtn">HANGAR</button>
<button type="button" class="cham secondary menuNavButton" id="settingsBtn">SETTINGS</button>
<button type="button" class="cham secondary menuNavButton installAction hidden" id="installPrompt">INSTALL</button>
</nav>
<div class="quickControls desktopCtrls" aria-label="Quick controls">
<span><kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd> / POINTER TO MOVE</span>
<span>AUTO-FIRE</span>
<span><kbd>SPACE</kbd> SURGE</span>
<span><kbd>P</kbd> PAUSE</span>
</div>
<div class="quickControls mobileCtrls" aria-label="Mobile controls">
<span>DRAG TO STEER</span>
<span>AUTO-FIRE</span>
<span>TAP SURGE WHEN READY</span>
</div>
<div class="debugTelemetry" id="debugTelemetry" aria-hidden="true">
<span id="gpuinfo">INITIALIZING…</span>
</div>
</main>
</div>
</section>
<!-- HANGAR / META PROGRESSION -->
<section id="ovHangar" class="ov" role="dialog" aria-modal="true" aria-labelledby="hangarTitle" inert>
<div class="panel wrap">
<div class="hangarTop panel">
<div>
<span class="eyebrow">FLEET OPERATIONS // META PROGRESSION</span>
<h2 id="hangarTitle">HANGAR</h2>
<p>Choose a frame, install permanent upgrades, and customize your fleet.</p>
</div>
<div class="scrapCounter">
<span>AVAILABLE SCRAP</span>
<b id="hScrap">0</b>
</div>
</div>
<div class="hangarTabs" role="tablist" aria-label="Hangar sections">
<button type="button" class="hangarTab active" id="hangarTabShips" role="tab" aria-selected="true" aria-controls="hangarPanelShips" data-hangar-tab="ships">SHIPS</button>
<button type="button" class="hangarTab" id="hangarTabUpgrades" role="tab" aria-selected="false" aria-controls="hangarPanelUpgrades" data-hangar-tab="upgrades" tabindex="-1">UPGRADES</button>
<button type="button" class="hangarTab" id="hangarTabCosmetics" role="tab" aria-selected="false" aria-controls="hangarPanelCosmetics" data-hangar-tab="cosmetics" tabindex="-1">COSMETICS</button>
<button type="button" class="hangarTab" id="hangarTabAchievements" role="tab" aria-selected="false" aria-controls="hangarPanelAchievements" data-hangar-tab="achievements" tabindex="-1">ACHIEVEMENTS</button>
</div>
<div class="hangarBody">
<section class="hangarSection hangarPanel active" id="hangarPanelShips" role="tabpanel" aria-labelledby="hangarTabShips" data-hangar-panel="ships">
<div class="sectionHeading">
<div>
<h3 id="shipSelectHeading">SHIP SELECT</h3>
<p>Each frame changes speed, hull strength, and firing cadence.</p>
</div>
</div>
<div id="shipGrid"></div>
</section>
<section class="hangarSection hangarPanel" id="hangarPanelUpgrades" role="tabpanel" aria-labelledby="hangarTabUpgrades" data-hangar-panel="upgrades" hidden>
<div class="sectionHeading">
<div>
<h3 id="upgradeHeading">UPGRADES</h3>
<p>Permanent improvements apply to every future deployment.</p>
</div>
</div>
<div id="upGrid"></div>
</section>
<section class="hangarSection hangarPanel" id="hangarPanelCosmetics" role="tabpanel" aria-labelledby="hangarTabCosmetics" data-hangar-panel="cosmetics" hidden>
<div class="sectionHeading">
<div>
<h3 id="cosmeticsHeading">COSMETICS BAY</h3>
<p>Equip achievement-earned colors, trails, engine signatures, and victory effects.</p>
</div>
</div>
<div id="cosmeticsGrid"></div>
</section>
<section class="hangarSection hangarPanel" id="hangarPanelAchievements" role="tabpanel" aria-labelledby="hangarTabAchievements" data-hangar-panel="achievements" hidden>
<div class="sectionHeading">
<div>
<h3 id="achievementHeading">ACHIEVEMENTS</h3>
<p>Track milestones and see which rewards are still waiting to be unlocked.</p>
</div>
</div>
<div id="achGrid"></div>
</section>
</div>
<div class="hangarBtns">
<button type="button" class="cham secondary" id="hangarBackBtn">BACK</button>
<button type="button" class="cham" id="hangarLaunchBtn">LAUNCH</button>
</div>
</div>
</section>
<!-- SETTINGS -->
<section id="ovSettings" class="ov" role="dialog" aria-modal="true" aria-labelledby="settingsTitle" inert>
<div class="panel settingsWrap">
<div class="settingsTop panel">
<div>
<span class="eyebrow">SYSTEM CONFIGURATION</span>
<h2 id="settingsTitle">SETTINGS</h2>
<p>Adjust audio, accessibility, performance, and flight response.</p>
</div>
</div>
<div class="settingsBody">
<section class="settingsSection" aria-labelledby="gameSettingsHeading">
<div class="sectionHeading">
<div>
<h3 id="gameSettingsHeading">GAME OPTIONS</h3>
<p>Preferences are saved automatically on this device.</p>
</div>
</div>
<div id="settingsGrid">
<button type="button" class="setting panel" id="settingSound" aria-pressed="true">
<span class="settingName">SOUND & MUSIC</span>
<span class="settingDesc">Procedural combat audio and soundtrack</span>
<span class="settingState" id="settingSoundState">ON</span>
</button>
<button type="button" class="setting panel" id="settingFlash" aria-pressed="false">
<span class="settingName">REDUCED FLASH</span>
<span class="settingDesc">Suppress impact flashes and reduce bloom</span>
<span class="settingState" id="settingFlashState">OFF</span>
</button>
<button type="button" class="setting panel" id="settingShake" aria-pressed="false">
<span class="settingName">REDUCED SHAKE</span>
<span class="settingDesc">Limit camera shake and chromatic impact</span>
<span class="settingState" id="settingShakeState">OFF</span>
</button>
<button type="button" class="setting panel" id="settingQuality" aria-pressed="false">
<span class="settingName">LOW QUALITY</span>
<span class="settingDesc">Lower render resolution for slower devices</span>
<span class="settingState" id="settingQualityState">OFF</span>
</button>
<div class="setting settingRange panel" id="settingResponse">
<div class="settingRangeTop">
<div>
<span class="settingName">INPUT RESPONSE</span>
<span class="settingDesc">Tune touch, pointer, and keyboard steering speed</span>
</div>
<output class="settingState" id="settingResponseState" for="settingResponseRange">125%</output>
</div>
<input
type="range"
class="settingRangeControl"
id="settingResponseRange"
min="75"
max="175"
step="5"
value="125"
aria-label="Input response"
aria-valuemin="75"
aria-valuemax="175"
aria-valuenow="125"
aria-valuetext="125%"
>
<div class="settingScale" aria-hidden="true">
<span>PRECISE</span>
<span>FAST</span>
</div>
</div>
</div>
</section>
<section class="settingsSection controlReference" aria-labelledby="controlReferenceHeading">
<div class="sectionHeading">
<div>
<h3 id="controlReferenceHeading">CONTROLS</h3>
<p>The cannons fire automatically while you focus on movement and SURGE timing.</p>
</div>
</div>
<div class="controlReferenceGrid">
<div class="controlReferenceItem panel"><span>MOVE</span><b>WASD / ARROWS / POINTER / DRAG</b></div>
<div class="controlReferenceItem panel"><span>SURGE</span><b>SPACE / ON-SCREEN CONTROL</b></div>
<div class="controlReferenceItem panel"><span>PAUSE</span><b>P / ESCAPE</b></div>
<div class="controlReferenceItem panel"><span>SOUND</span><b>M / SETTINGS</b></div>
</div>
</section>
</div>
<div class="settingsBtns">
<button type="button" class="cham secondary" id="settingsBackBtn">BACK TO MENU</button>
</div>
</div>
</section>
<!-- IN-RUN UPGRADE CHOICE -->
<section
id="ovUpgrade"
class="ov"
role="dialog"
aria-modal="true"
aria-labelledby="upgradeTitle"
aria-describedby="upgradeCopy"
inert
>
<div class="upgradePanel panel">
<div class="overlayStatus upgradeStatus"><i aria-hidden="true"></i> RUN SYSTEMS // LEVEL UP</div>
<div class="upgradeTitleRow">
<div>
<h2 class="big hold" id="upgradeTitle">CHOOSE YOUR SYSTEM</h2>
<p class="overlayCopy" id="upgradeCopy">The run is paused. Install one temporary upgrade before returning to the Veil.</p>
</div>
<div class="upgradeLevelBadge">
<span>LEVEL</span>
<b id="upgradeLevelValue">02</b>
</div>
</div>
<div class="upgradeXpLabel">
<span>RUN XP</span>
<span id="upgradeXpValue">0 / 220 XP</span>
</div>
<div class="upgradeXpBar" aria-hidden="true"><i></i></div>
<div id="upgradeCards" class="upgradeCards" aria-label="Available temporary upgrades"></div>
<p class="hint upgradeHint">
<span class="desktopOnly"><kbd>1</kbd>–<kbd>3</kbd> SELECT SYSTEM</span>
<span class="mobileOnly">TAP A SYSTEM TO INSTALL IT</span>
</p>
</div>
</section>
<!-- PAUSE -->
<section id="ovPause" class="ov" role="dialog" aria-modal="true" aria-labelledby="pauseTitle" inert>
<div class="overlayCard panel">
<div class="overlayStatus"><i aria-hidden="true"></i> MISSION SUSPENDED</div>
<h2 class="big hold" id="pauseTitle">STANDBY</h2>
<p class="overlayCopy">Your run is paused. Resume when you are ready to re-enter the Veil.</p>
<div class="overlayActions">
<button type="button" class="cham" id="resumeBtn">RESUME</button>
<button type="button" class="cham secondary" id="pauseSoundBtn">SOUND ON</button>
<button type="button" class="cham danger" id="pauseRestartBtn">RESTART</button>
</div>
<p class="hint desktopOnly">
<kbd>P</kbd> RESUME <span>·</span> <kbd>M</kbd> SOUND <span>·</span> <kbd>R</kbd> RESTART
</p>
</div>
</section>
<!-- GAME OVER -->
<section id="ovOver" class="ov" role="dialog" aria-modal="true" aria-labelledby="gameOverTitle" inert>
<div class="overlayCard resultCard panel">
<div class="overlayStatus dangerStatus"><i aria-hidden="true"></i> PILOT LINK TERMINATED</div>
<h2 class="big lose" id="gameOverTitle">SIGNAL LOST</h2>
<div id="newRec" class="hidden">★ NEW RECORD ★</div>
<div id="dailyResult" class="dailyResult hidden" aria-live="polite">
<span id="dailyResultDate">DAILY // —</span>
<span>LOCAL BEST <b id="sDailyBest">—</b></span>
</div>
<div class="stats">
<span class="lbl">FINAL SCORE</span>
<span class="val" id="sScore">0</span>
<span class="lbl">BEST</span>
<span class="val" id="sBest">0</span>
<span class="lbl">WAVE REACHED</span>
<span class="val" id="sWave">1</span>
<span class="lbl">KILLS</span>
<span class="val" id="sKills">0</span>
<span class="lbl">MAX COMBO</span>
<span class="val" id="sCombo">0</span>
<span class="lbl">SCRAP EARNED</span>
<span class="val" id="sScrap">0</span>
<span class="lbl">TOTAL SCRAP</span>
<span class="val" id="sTotalScrap">0</span>
</div>
<div class="runBreakdown" aria-label="Run breakdown">
<div class="runMetric panel">
<span class="runMetricLabel">SURVIVAL</span>
<b id="sTime">00:00</b>
</div>
<div class="runMetric panel">
<span class="runMetricLabel">ACCURACY</span>
<b id="sAccuracy">0%</b>
</div>
<div class="runMetric panel">
<span class="runMetricLabel">DAMAGE</span>
<b id="sDamage">0</b>
</div>
<div class="runMetric panel">
<span class="runMetricLabel">ELITES</span>
<b id="sElites">0</b>
</div>
<div class="runMetric panel">
<span class="runMetricLabel">BOSSES</span>
<b id="sBosses">0</b>
</div>
<div class="runMetric panel">
<span class="runMetricLabel">SYSTEMS</span>
<b id="sSystems">0</b>
</div>
</div>
<div class="overlayActions gameOverActions">
<button type="button" class="cham" id="relaunchBtn">RELAUNCH</button>
<button type="button" class="cham secondary" id="overHangarBtn">HANGAR</button>
<button type="button" class="cham secondary" id="shareScoreBtn">SHARE SCORE</button>
</div>
<p class="hint desktopOnly"><kbd>ENTER</kbd> RELAUNCH <span>·</span> <kbd>H</kbd> HANGAR</p>
</div>
</section>
<!-- FATAL ERROR -->
<section id="ovFatal" class="ov" role="alertdialog" aria-modal="true" aria-labelledby="fatalTitle" inert>
<div class="panel fatalBox">
<div class="overlayStatus dangerStatus"><i aria-hidden="true"></i> VISUAL SYSTEM OFFLINE</div>
<h2 class="big lose fatalTitle" id="fatalTitle">SYSTEM FAULT</h2>
<p class="why" id="fatalWhy">—</p>
<p>
Enable browser hardware acceleration, update your graphics drivers,
or try the latest version of Chrome, Edge, Firefox, or Safari.
</p>
<button type="button" class="cham" onclick="location.reload()">RETRY</button>
</div>
</section>
<noscript>
<div class="noscript">
JavaScript required.
</div>
</noscript>
<script src="src/game.js"></script>
<script src="src/profile.js"></script>
<!-- Supabase is an optional enhancement; account.js keeps guest mode fully local if it is unavailable. -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script src="src/account-config.js"></script>
<script src="src/account.js"></script>
</body>
</html>