<!-- SOLID CITY · part 1917 -->
ain" style="margin-left:10px;text-decoration:none;display:inline-block">← RETURN TO SOLID CITY</a>
    </div>
  </section>

<script>
(function(){
  'use strict';
  var WORLD={w:2400,h:1600}, SPEED_TARGET=340;
  var views=[document.querySelector('#view0'),document.querySelector('#view1')];
  var canvases=views.map(function(v){return v.querySelector('canvas')});
  var ctxs=canvases.map(function(c){return c.getContext('2d')});
  var armEl=document.querySelector('#arm'), clockEl=document.querySelector('#clock'), waveEl=document.querySelector('#waveText'),flightStateEl=document.querySelector('#flightState'),objectiveEl=document.querySelector('#objective'),speedometerEl=document.querySelector('#speedometer'),speedValueEl=document.querySelector('#speedValue'),speedBarEl=document.querySelector('#speedBar');
  var intro=document.querySelector('#intro'), debrief=document.querySelector('#debrief'),levelBeat=document.querySelector('#levelBeat');
  var running=false,last=0,elapsed=0,levelElapsed=0,wave=1,level=1,spawnT=0,meteorT=0,enemyShotT=0,nextId=1,transitioning=false,runEnding=false;
  var ships=[],enemies=[],shots=[],bolts=[],meteors=[],sparks=[],pickups=[],muzzles=[],stars=[],nebula=[],rings=[],hazards=[],corridorThreats=[],corridorShots=[],corridorPickups=[],corridorStars=[];
  var progression={componentIndex:0,speedHold:0,expansionStage:1,levelKills:0,boss:null,pursuer:null,corridorCleared:0,corridorRunT:0,corridorSequence:0};
  var levelInfo=[null,{name:'SOLIDIVISM',copy:'The doctrine of solidity: experience makes each fragile ship SOLID — unbreakable and whole — through plating, cannons, thrusters, and biological adaptations.',button:'BEGIN SOLIDIVISM'},{name:'SPEED',copy:'Bank velocity through glowing speed rings. The pursuer cannot be outgunned — both ships must hold target speed together.',button:'ENTER SPEED TRIAL'},{name:'EXPANSION',copy:'Push outward. Each cleared sector pulls the camera back, unlocks a new hazard, and extends weapons and radar.',button:'REACH OUTWARD'},{name:'CONVERGENCE',copy:'Return to the original view at full intensity — threats arrive immediately. Expanded awareness enables AUTO-LOCK only while both ships hold formation. Togetherness is the weapon system.',button:'BEGIN CONVERGENCE'},{name:'DEPTH FLIGHT',copy:'The corridor carries both ships forward. Rise ABOVE or dive BELOW incoming attack runs; lateral movement is now fine positioning. Thread the three bands together.',button:'ENTER THE CORRIDOR'}];
  var flight={mode:'formation',wasSeparated:false,reunionUntil:0,lastDistance:0};
  var indicators=[{until:0},{until:0}], keys={}, controls=[makeControl(),makeControl()],friendlyHitGuard={};
  var fireControl={active:false,pointer:null},fireEl=document.querySelector('#fire'),metrics;
  var sessionBest={score:0,kills:0,level:1,time:0,formation:0,reunions:0,rescues:0,shield:0,friendly:0};
  function makeControl(){return {active:false,x:0,y:0,startX:0,startY:0,pointer:null,lastRelease:0,resumePending:false,keyActive:false}}
  function resetMetrics(){metrics={avoided:0,meteorHits:0,shieldHits:0,friendlyFire:0,kills:0,formationTime:0,separations:0,reunions:0,rescues:0,coordinated:0,reunionBonus:0,defenseSaved:0,latencies:[],handoffs:[],assists:[],assistChecks:0,assistContinuity:0,threats:{}};flight={mode:'formation',wasSeparated:false,reunionUntil:0,lastDistance:0}}
  function stamp(){var s=Math.max(0,elapsed);return String(Math.floor(s/60)).padStart(2,'0')+':'+String(Math.floor(s%60)).padStart(2,'0')}
  function logH(text){metrics.handoffs.push(stamp()+'  '+text)}
  function logA(text){metrics.assists.push(stamp()+'  '+text)}
  function notify(i,text,ms){var el=document.querySelector('#ind'+i);el.textContent=text;el.classList.add('show');indicators[i].until=performance.now()+(ms||900)}
  function resize(){canvases.forEach(function(c){var r=c.getBoundingClientRect(),d=Math.min(devicePixelRatio||1,2);c.width=Math.max(1,Math.floor(r.width*d));c.height=Math.max(1,Math.floor(r.height*d));c._w=r.width;c._h=r.height;c._d=d})}
  addEventListener('resize',resize); if(window.visualViewport) visualViewport.addEventListener('resize',resize);
  function makeShip(x,y,color,label){return {x:x,y:y,vx:0,vy:0,a:0,color:color,label:label,hull:100,maxHull:100,alive:true,respawn:0,fire:0,manualFire:0,score:0,actionTick:0,assistVX:0,assistVY:0,assistUntil:0,coveringTarget:null,coverBroke:false,coverNotice:0,shieldCharges:0,shieldUntil:0,shieldHitUntil:0,shieldRingUntil:0,shieldShatterUntil:0,spreadUntil:0,rapidUntil:0,repairUntil:0,build:{hull:0,cannon:0,thruster:0,bio:0},ringScore:0,speedBank:0,altitude:0,corridorX:0}}
  function init(){
    ships=[makeShip(1100,800,'#ffc84a','YOU'),makeShip(1280,840,'#44e1d0','AI')];
    enemies=[];shots=[];bolts=[];meteors=[];sparks=[];pickups=[];muzzles=[];rings=[];hazards=[];corridorThreats=[];corridorShots=[];corridorPickups=[];corridorStars=[];elapsed=0;levelElapsed=0;wave=1;level=1;spawnT=0;meteorT=2;enemyShotT=1;nextId=1;transitioning