SpaceCities / index.html
Claude
Boot the game in a real browser in CI — the one thing 2502 tests cannot see
778e159 unverified
Raw History Blame
5.86 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Stellar Frontier: RTS</title>
<!-- Inline SVG data URI, not a file: every browser requests /favicon.ico unprompted, and with
nothing declared here that is a guaranteed 404 on every single page load. Harmless, but it
puts a permanent error in the console, which makes "the console is clean" useless as a signal
— tools/smoke.js asserts exactly that. A data URI fixes it with no binary asset to store, no
extra request, and nothing for the no-build-step rule to object to. -->
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='6' fill='%230b1020'/%3E%3Ccircle cx='16' cy='16' r='7' fill='none' stroke='%2355ccff' stroke-width='2.5'/%3E%3Ccircle cx='16' cy='16' r='2.5' fill='%2355ccff'/%3E%3C/svg%3E" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="app">
<!-- Two FIXED rows so the control buttons never jump: the info row (line 1) stays a single line
(the resource readout scrolls sideways rather than wrapping), and the controls row (line 2)
is pinned below it regardless of how long the commodity list gets. -->
<header id="topbar">
<div class="topbar-row topbar-info">
<span class="title">STELLAR FRONTIER: RTS</span>
<span id="appVersion" class="app-version" title="App version"></span>
<div id="resources" class="resources"></div>
<div id="matchClock" class="clock">0:00</div>
<div id="scoreBar" class="score-bar hidden" title="The score tiebreak that decides the match if neither Command Center falls first"></div>
<button id="idleWorkers" class="idle-workers hidden" title="Idle workers — click to select the next one (`)"></button>
<button id="idleProduction" class="idle-workers hidden" title="Idle production buildings — click to select the next one"></button>
<span id="factionChip" class="faction-chip hidden" title="Your faction vs the opponent's — each side's passive trait bonus."></span>
</div>
<div class="topbar-row topbar-controls">
<span id="seedChip" class="seed-chip hidden" title="Match seed — click to copy. Enter it on the setup screen to replay this map."></span>
<input id="volume" class="volume" type="range" min="0" max="100" value="90" title="Sound volume" aria-label="Sound volume">
<button id="muteBtn" class="mute-btn" title="Mute sound" aria-pressed="false">🔊</button>
<button id="pauseBtn" class="chip-btn hidden" title="Pause / resume (P)">⏸ Pause</button>
<button id="starmapBtn" class="chip-btn hidden" title="Galaxy map (M)">🗺 Galaxy</button>
<button id="observerBtn" class="chip-btn hidden" title="Observer Mode: free-look every world, fog revealed, no orders (O)">🔭 Observe</button>
<button id="techChartBtn" class="chip-btn" title="Tech &amp; Industry chart (T)">📊 Tech Chart</button>
<button id="saveBtn" class="chip-btn" title="Save game to a file (download). Your progress also autosaves for Continue.">⭳ Save</button>
<button id="loadBtn" class="chip-btn" title="Load a game from a file">⭱ Load</button>
<button id="homeBtn" class="chip-btn" title="Return to the menu">⌂ Home</button>
<button id="helpBtn" class="help-btn" title="Controls &amp; help (F1)" aria-label="Help">?</button>
</div>
</header>
<main id="main">
<div id="view">
<canvas id="field"></canvas>
<div id="underAttackAlert" class="under-attack hidden" title="Click to jump to the attack">⚠ Under Attack ▸</div>
<div id="gateChip" class="gate-chip hidden" title="Click to jump to the Antimatter Gate"></div>
<div id="galaxyToast" class="galaxy-toast-stack hidden"></div>
<div id="groupChips" class="group-chips hidden"></div>
<div id="uiHint" class="ui-hint hidden"></div>
<div id="starmap" class="starmap-overlay hidden"></div>
<div id="observerBanner" class="observer-banner hidden"></div>
<!-- The spectate controls for a WATCHED AI-vs-AI match (observerPanel.js): speed, the
exhibition-only disclosure, and the way back to the Competition screen. Its own
element rather than part of #observerBanner above, which is deliberately
pointer-events:none (nothing on it is ever clickable) — these controls must be. -->
<div id="spectateBar" class="spectate-bar hidden"></div>
<div id="observerPanel" class="observer-panel hidden"></div>
<div id="techChart" class="techchart-overlay hidden"></div>
<div id="objectives" class="objectives hidden"></div>
<div id="scenarioBar" class="scenario-bar hidden">
<span id="scenarioBanner" class="scenario-banner"></span>
<span id="scenarioStatus" class="scenario-status"></span>
<button id="repairBtn" class="scenario-btn hidden"></button>
<button id="departBtn" class="scenario-btn hidden">Depart ▸</button>
</div>
<canvas id="minimap" class="minimap"></canvas>
<button id="sheetToggle" class="sheet-toggle" title="Show or hide the panel" aria-label="Show or hide the panel">▾</button>
<button id="panelToggle" class="panel-toggle" title="Show or hide the side panel" aria-label="Show or hide the side panel">▸</button>
<div id="gameOver" class="overlay hidden"></div>
</div>
<aside id="selectionPanel" class="panel"></aside>
</main>
</div>
<div id="helpOverlay" class="overlay help-overlay hidden"></div>
<div id="mapSelect" class="map-select"></div>
<script type="module" src="main.js"></script>
</body>
</html>