<!-- SOLID CITY · part 1959 -->
st?progression.speedHold+dt:Math.max(0,progression.speedHold-dt*1.4);objectiveEl.textContent='RINGS '+Math.min(3,ships[0].ringScore)+'/3 + '+Math.min(3,ships[1].ringScore)+'/3 · HOLD '+progression.speedHold.toFixed(1)+'/3.0s';if(progression.speedHold>=3)completeLevel()
    }
    if(level===3){
      var stage=progression.levelKills>=12?3:progression.levelKills>=5?2:1;if(stage>progression.expansionStage){progression.expansionStage=stage;notify(0,stage===3?'REACH EXPANSION':'SECTOR '+stage+' OPEN',1500);notify(1,stage===3?'REACH EXPANSION':'SECTOR '+stage+' OPEN',1500);burst(ships[0].x,ships[0].y,'#b9a7ff',28);burst(ships[1].x,ships[1].y,'#b9a7ff',28)}objectiveEl.textContent=stage===3?'REACH EXPANSION · CLEAR THE FRONTIER '+progression.levelKills+'/18':'PUSH OUTWARD · SECTOR '+stage+' / 3';if(stage===3&&progression.levelKills>=18)completeLevel()
    }
    hazards.forEach(function(h){if(progression.expansionStage<h.stage)return;h.phase=(h.phase||0)+dt;ships.forEach(function(s,i){var d=distObj(h,s);if(d<h.r){if(h.type==='ion'){s.vx*=Math.pow(.965,dt*60);s.vy*=Math.pow(.965,dt*60)}else if(Math.sin(elapsed*3+i)>.985)damage(s,i,6,'rift')}})});
    if(level===4&&progression.boss){var locked=progression.expansionStage===3&&flight.mode==='formation';objectiveEl.textContent=(locked?'AUTO-LOCK · ':'LOCK LOST · ')+Math.max(0,Math.ceil(progression.boss.hull))+' / '+progression.boss.maxHull;if(locked){flightStateEl.textContent='FORMATION · LOCK';flightStateEl.className='flight-state formation'}if(progression.boss.hull<=0)completeLevel()}
  }
  function update(dt){
    elapsed+=dt;levelElapsed+=dt;if(level===5){updateCorridor(dt);updateHUD();return}wave=1+Math.floor(levelElapsed/18);spawnT-=dt;meteorT-=dt;
    if(spawnT<=0){spawnT=level===4?.38:level===3?Math.max(.42,1.45-wave*.1):Math.max(.58,2.05-wave*.12);spawnEnemy()}
    if(meteorT<=0){meteorT=level===4?.72:Math.max(1.1,3.1-wave*.17);spawnMeteor(level===4||Math.random()<.58)}
    var in0=humanInput(0);drive(ships[0],in0,dt);aiPilot(dt);assist(dt);
    ships.forEach(function(s,i){
      if(!s.alive){s.respawn-=dt;if(s.respawn<=0){s.alive=true;s.hull=s.maxHull;s.x=1150+i*130;s.y=800;burst(s.x,s.y,s.color,24);notify(i,'BACK IN THE FIGHT',900)}return}
      if(i===0&&s.assistUntil>performance.now()&&!in0.active){s.vx+=s.assistVX*dt;s.vy+=s.assistVY*dt;s.actionTick++}
      var now=performance.now();if(s.shieldCharges>0&&now>=s.shieldUntil)breakShield(s);if(s.build.bio>0&&s.hull<s.maxHull)s.hull=Math.min(s.maxHull,s.hull+dt*(.45+s.build.bio*.35));var max=270+s.build.thruster*30+s.speedBank,l=Math.hypot(s.vx,s.vy);if(l>max){s.vx=s.vx/l*max;s.vy=s.vy/l*max}s.vx*=Math.pow(.987,dt*60);s.vy*=Math.pow(.987,dt*60);s.speedBank=Math.max(0,s.speedBank-dt*(level===2?1.4:3));s.x=wrapX(s.x+s.vx*dt);s.y=wrapY(s.y+s.vy*dt);if(l>12)s.a=Math.atan2(s.vy,s.vx);autoFire(s,i,dt);if(i===0)manualFire(s,i,dt)
    });
    updateFlight(dt);updateLevelSystems(dt);
    enemies.forEach(function(e){var target=e.splitter?ships[e.id%2]:(distObj(e,ships[0])<distObj(e,ships[1])?ships[0]:ships[1]),liveIndex=target===ships[0]?0:1;if(e.targetIndex!==liveIndex){e.targetIndex=liveIndex;e.threatTargetIndex=-1;e.rescuePilot=-1;e.rescueBroke=false;if(ships[1].coveringTarget===e.id){ships[1].coveringTarget=null;ships[1].coverBroke=false}}var d=distObj(e,target);if(d<650)e.threatTargetIndex=e.targetIndex;else e.threatTargetIndex=-1;if(target.alive){if(d>210)steer(e,target.x,target.y,dt,80);else{var dx=delta(e.x,target.x,WORLD.w),dy=delta(e.y,target.y,WORLD.h);e.vx+=-dy/(d||1)*35*dt;e.vy+=dx/(d||1)*35*dt}e.a=Math.atan2(delta(target.y,e.y,WORLD.h),delta(target.x,e.x,WORLD.w));e.fire-=dt;if(e.fire<=0&&d<650){e.fire=Math.max(.85,2.2-wave*.12)+Math.random();var a=e.a;bolts.push({x:e.x,y:e.y,vx:Math.cos(a)*150,vy:Math.sin(a)*150,life:5})}}var l=Math.hypot(e.vx,e.vy);if(l>90){e.vx=e.vx/l*90;e.vy=e.vy/l*90}e.x=wrapX(e.x+e.vx*dt);e.y=wrapY(e.y+e.vy*dt)});
    meteors.forEach(function(m){m.x=wrapX(m.x+m.vx*dt);m.y=wrapY(m.y+m.vy*dt);m.rot+=m.spin*dt});
    pickups.forEach(function(p){p.life-=dt;p.phase+=dt*2.5;var pull=p.component?620:240,s=p.component&&ships[p.target].alive?ships[p.target]:nearest(p,ships.filter(function(q){return q.alive}),pull);if(s){var dx=delta(s.x,p.x,WORLD.w),dy=delta(s.y,p.y,WORLD.h),d=Math.hypot(dx,dy)||1,q=Math.max(0,(pull-d)/pull);p.vx+=dx/d*(100+q*700)*dt;p.vy+=dy/d*(100+q*700)*dt;if(d<25)collectPower(p,s,ships.indexOf(s))}p.vx*=Math.pow(.98,dt*60);p.vy*=Math.pow(.98,dt*60);p.x=wrapX(p.x+p.vx*dt);p.y=wrapY(p.y+p.vy*dt)});
    moveProjectiles(shots,dt);moveProjectiles(bolts,dt);collisions();
    sparks.forEach(function(p){p.x+=p.vx*dt;p.y+=p.vy*dt;p.life-=dt;p.vx*=.97;p.vy*=.97});sparks=sparks.filter(function(p){return p.life>0});muzzles.forEach(function(m){m.life-=dt});
    enemies=enemies.filter(function(e){return e.hull>0});shots=shots.filter(function(s){return s.life>0});bolts=bolts.filter(function(b){return b.life>0});meteors=meteors.filter(function(m){return !